OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / test / unit / storage-service.test.js

178 lines · javascript ref:
import test from 'brittle'
import { StorageService } from 'p2p-hiveservices/builtin/storage-service.js'
import { PolicyGuard } from 'p2p-hiverelay/core/policy-guard.js'

// ─── Manifest ───

test('StorageService - manifest', (t) => {
  const svc = new StorageService()
  const m = svc.manifest()
  t.is(m.name, 'storage')
  t.is(m.version, '1.0.0')
  t.ok(m.capabilities.includes('drive-create'))
  t.ok(m.capabilities.includes('drive-write'))
  t.ok(m.capabilities.includes('drive-read'))
  t.ok(m.capabilities.includes('drive-delete'))
  t.ok(m.capabilities.includes('core-create'))
  t.ok(m.capabilities.includes('core-append'))
  t.ok(m.capabilities.includes('core-get'))
})

// ─── Constructor options ───

test('StorageService - accepts policyGuard and getAppTier', (t) => {
  const guard = new PolicyGuard()
  const svc = new StorageService({
    policyGuard: guard,
    getAppTier: () => 'public'
  })
  t.is(svc.policyGuard, guard)
  t.ok(typeof svc.getAppTier === 'function')
})

test('StorageService - defaults without options', (t) => {
  const svc = new StorageService()
  t.is(svc.policyGuard, null)
  t.is(svc.getAppTier, null)
  t.is(svc.maxDrives, 256)
})

// ─── _getDrive ───

test('StorageService - _getDrive throws for unknown key', (t) => {
  const svc = new StorageService()
  try {
    svc._getDrive('deadbeef')
    t.fail('should have thrown')
  } catch (err) {
    t.ok(err.message.includes('DRIVE_NOT_FOUND'))
    t.ok(err.message.includes('deadbeef'))
  }
})

// ─── PolicyGuard _checkPolicy ───

test('StorageService - _checkPolicy allows public tier', (t) => {
  const guard = new PolicyGuard()
  const svc = new StorageService({
    policyGuard: guard,
    getAppTier: () => 'public'
  })
  // Should not throw
  svc._checkPolicy('aabb', 'store-on-relay')
  t.pass('policy check passed for public tier')
})

test('StorageService - _checkPolicy blocks local-first store-on-relay', (t) => {
  const guard = new PolicyGuard()
  const svc = new StorageService({
    policyGuard: guard,
    getAppTier: () => 'local-first'
  })
  try {
    svc._checkPolicy('aabb', 'store-on-relay')
    t.fail('should have thrown')
  } catch (err) {
    t.ok(err.message.includes('POLICY_VIOLATION'))
  }
})

test('StorageService - _checkPolicy blocks p2p-only store-on-relay', (t) => {
  const guard = new PolicyGuard()
  const svc = new StorageService({
    policyGuard: guard,
    getAppTier: () => 'p2p-only'
  })
  try {
    svc._checkPolicy('aabb', 'store-on-relay')
    t.fail('should have thrown')
  } catch (err) {
    t.ok(err.message.includes('POLICY_VIOLATION'))
  }
})

test('StorageService - _checkPolicy skips when no guard', (t) => {
  const svc = new StorageService()
  // Should not throw even without a guard
  svc._checkPolicy('aabb', 'store-on-relay')
  t.pass('no guard, no check')
})

test('StorageService - _checkPolicy denies when tier unknown (fail-closed)', (t) => {
  const guard = new PolicyGuard()
  const svc = new StorageService({
    policyGuard: guard,
    getAppTier: () => null // unknown app
  })
  // Should deny unknown apps (fail-closed)
  try {
    svc._checkPolicy('aabb', 'store-on-relay', { remotePubkey: 'peer-a' })
    t.fail('should throw for unknown tier')
  } catch (err) {
    t.ok(err.message.includes('ACCESS_DENIED'), 'unknown tier denied')
  }
})

test('StorageService - _checkPolicy allows unknown tier for admin context', (t) => {
  const guard = new PolicyGuard()
  const svc = new StorageService({
    policyGuard: guard,
    getAppTier: () => null
  })
  // Admin should pass even for unknown apps
  svc._checkPolicy('aabb', 'store-on-relay', { role: 'local' })
  t.pass('admin passes unknown tier')
})

test('StorageService - _checkPolicy suspends app permanently', (t) => {
  const guard = new PolicyGuard()
  const svc = new StorageService({
    policyGuard: guard,
    getAppTier: () => 'local-first'
  })

  // First call suspends
  try { svc._checkPolicy('aabb', 'store-on-relay') } catch {}
  t.ok(guard.isSuspended('aabb'))

  // Second call still blocked (even if we change tier lookup)
  svc.getAppTier = () => 'public'
  try {
    svc._checkPolicy('aabb', 'store-on-relay')
    t.fail('should still be blocked')
  } catch (err) {
    t.ok(err.message.includes('POLICY_VIOLATION'))
  }
})

// ─── drive-list on empty ───

test('StorageService - drive-list empty', async (t) => {
  const svc = new StorageService()
  const result = await svc['drive-list']()
  t.is(result.length, 0)
})

// ─── drive limit ───

test('StorageService - drive-create respects maxDrives', (t) => {
  const svc = new StorageService()
  svc.maxDrives = 0
  // Manually check the limit logic
  t.is(svc.drives.size, 0)
  t.is(svc.maxDrives, 0)
  // Can't easily test without a real store, but the manifest test confirms the code loads
})

// ─── stop clears drives ───

test('StorageService - stop clears drives map', async (t) => {
  const svc = new StorageService()
  // Inject fake drives with close() method
  svc.drives.set('key1', { close: async () => {} })
  svc.drives.set('key2', { close: async () => {} })
  t.is(svc.drives.size, 2)
  await svc.stop()
  t.is(svc.drives.size, 0)
})