OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-note / test / unit / drive-manager.test.js

193 lines · javascript ref:
import test from 'brittle'
import fs from 'bare-fs'
import path from 'bare-path'
import os from 'bare-os'
import Corestore from 'corestore'
import Hyperbee from 'hyperbee'
import { DriveManager } from '../../lib/drive-manager.js'

function tmpSetup () {
  const dir = path.join(os.tmpdir(), 'hn-dm-' + Date.now() + '-' + Math.random().toString(36).slice(2))
  fs.mkdirSync(dir, { recursive: true })
  const store = new Corestore(dir)
  const registry = new Hyperbee(store.get({ name: 'registry' }), {
    keyEncoding: 'utf-8',
    valueEncoding: 'json'
  })
  const dm = new DriveManager(store, registry)
  return { store, registry, dm, dir }
}

test('createDrive — registers in registry and returns drive', async (t) => {
  const { store, registry, dm } = tmpSetup()
  await registry.ready()

  const drive = await dm.createDrive('work')
  t.ok(drive)
  t.ok(drive.key)

  const entry = await registry.get('notebook-drive:work')
  t.ok(entry)
  t.is(entry.value.slug, 'work')
  t.is(entry.value.isLocal, true)
  t.is(entry.value.isShared, false)
  t.is(entry.value.driveKey, drive.key.toString('hex'))

  await dm.closeAll()
  await store.close()
})

test('getDrive — returns cached drive', async (t) => {
  const { store, registry, dm } = tmpSetup()
  await registry.ready()

  const drive1 = await dm.createDrive('cached')
  const drive2 = await dm.getDrive('cached')

  t.is(drive1, drive2, 'returns same drive instance from cache')

  await dm.closeAll()
  await store.close()
})

test('getDrive — opens drive from registry after restart', async (t) => {
  const { store, registry, dm, dir } = tmpSetup()
  await registry.ready()

  const drive = await dm.createDrive('test')
  await drive.put('/hello.txt', Buffer.from('world'))

  await dm.closeAll()
  await store.close()

  const store2 = new Corestore(dir)
  const registry2 = new Hyperbee(store2.get({ name: 'registry' }), {
    keyEncoding: 'utf-8',
    valueEncoding: 'json'
  })
  await registry2.ready()
  const dm2 = new DriveManager(store2, registry2)

  const reopened = await dm2.getDrive('test')
  t.ok(reopened)
  const buf = await reopened.get('/hello.txt')
  t.is(buf.toString(), 'world')

  await dm2.closeAll()
  await store2.close()
})

test('getDrive — returns null for missing slug', async (t) => {
  const { store, registry, dm } = tmpSetup()
  await registry.ready()

  const result = await dm.getDrive('nonexistent')
  t.is(result, null)

  await dm.closeAll()
  await store.close()
})

test('deleteDrive — removes from registry and cache', async (t) => {
  const { store, registry, dm } = tmpSetup()
  await registry.ready()

  await dm.createDrive('doomed')
  await dm.deleteDrive('doomed')

  const entry = await registry.get('notebook-drive:doomed')
  t.is(entry, null)
  t.is(dm._cache.has('doomed'), false)

  const result = await dm.getDrive('doomed')
  t.is(result, null)

  await dm.closeAll()
  await store.close()
})

test('listDrives — returns all registered entries', { timeout: 10000 }, async (t) => {
  const { store, registry, dm } = tmpSetup()
  await registry.ready()

  await dm.createDrive('alpha')
  await dm.createDrive('beta')
  await dm.createDrive('gamma')

  const list = await dm.listDrives()
  t.is(list.length, 3)

  const slugs = list.map(e => e.slug).sort()
  t.alike(slugs, ['alpha', 'beta', 'gamma'])

  await dm.closeAll()
  await store.close()
})

test('addRemoteDrive — sets isLocal false', async (t) => {
  const srcDir = path.join(os.tmpdir(), 'hn-dmsrc-' + Date.now() + '-' + Math.random().toString(36).slice(2))
  fs.mkdirSync(srcDir, { recursive: true })
  const srcStore = new Corestore(srcDir)
  const srcReg = new Hyperbee(srcStore.get({ name: 'registry' }), {
    keyEncoding: 'utf-8', valueEncoding: 'json'
  })
  await srcReg.ready()
  const srcDm = new DriveManager(srcStore, srcReg)
  const srcDrive = await srcDm.createDrive('local')
  const keyHex = srcDrive.key.toString('hex')

  const { store, registry, dm } = tmpSetup()
  await registry.ready()

  const remote = await dm.addRemoteDrive(keyHex, 'remote-work')
  t.ok(remote)

  const info = await dm.getDriveInfo('remote-work')
  t.is(info.isLocal, false)
  t.is(info.slug, 'remote-work')
  t.is(info.driveKey, keyHex)

  t.is(dm.isLocal('remote-work'), false)
  t.is(dm.isRemote('remote-work'), true)

  await dm.closeAll()
  await store.close()
  await srcDm.closeAll()
  await srcStore.close()
})

test('isLocal / isRemote — correct flags', async (t) => {
  const { store, registry, dm } = tmpSetup()
  await registry.ready()

  await dm.createDrive('local-nb')
  t.is(dm.isLocal('local-nb'), true)
  t.is(dm.isRemote('local-nb'), false)

  t.is(dm.isLocal('unknown'), true)
  t.is(dm.isRemote('unknown'), false)

  await dm.closeAll()
  await store.close()
})

test('setShared — updates registry entry', async (t) => {
  const { store, registry, dm } = tmpSetup()
  await registry.ready()

  await dm.createDrive('shared-nb')

  let info = await dm.getDriveInfo('shared-nb')
  t.is(info.isShared, false)

  await dm.setShared('shared-nb', true)

  info = await dm.getDriveInfo('shared-nb')
  t.is(info.isShared, true)

  t.is(dm._cache.get('shared-nb').entry.isShared, true)

  await dm.closeAll()
  await store.close()
})