OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-room / test / migration-readopt.test.js

56 lines · javascript ref:
// Re-adopt migration for the 'hyper-tps/state/v3' -> 'atproto-room/state/v3' namespace rename.
// A room created under the legacy namespace opens under the new one as an empty base sharing the
// same on-disk Corestore; StateBaseV3._migrateFromLegacyNamespace seeds the new base from the old.
// Run: bare test/migration-readopt.test.js  (aggregated in test/all.js)
import '../lib/bare-globals.js'
import test from 'brittle'
import crypto from 'hypercore-crypto'
import fs from 'bare-fs'
import { StateBaseV3 } from '../lib/state-base.js'

const LEGACY = Buffer.from('hyper-tps/state/v3', 'utf-8')
const tmp = () => { const d = '/tmp/atr-mig-' + Math.floor(Math.random() * 1e9); fs.mkdirSync(d, { recursive: true }); return d }

test('re-adopt: a renamed-namespace room seeds from the legacy base in the same dir', async (t) => {
  const dir = tmp()
  const roomKey = crypto.randomBytes(32)
  const roomSeed = crypto.randomBytes(32)
  const encryptionKey = crypto.randomBytes(32)
  const cfg = (gsNamespace) => ({ roomSeed, encryptionKey, network: false, ...(gsNamespace ? { gsNamespace } : {}) })

  // 1. Populate a LEGACY-namespace room: repo records + a firehose entry + a membership entry.
  const legacy = new StateBaseV3(dir, roomKey, cfg(LEGACY))
  await legacy.ready()
  await legacy.set('app.bsky.feed.post/aaa', { text: 'hello' })
  await legacy.set('app.bsky.feed.post/bbb', { text: 'world' })
  await legacy.set('__commit__/3abc', { rev: '3abc', commitCid: 'bafyfake' })
  await legacy.close() // release the fd-lock before reopening the same dir

  // 2. Open the RENAMED room on the SAME dir → migration fires (empty new base + legacy base present).
  const fresh = new StateBaseV3(dir, roomKey, cfg())
  await fresh.ready()
  t.alike(await fresh.get('app.bsky.feed.post/aaa'), { text: 'hello' }, 'repo record aaa migrated')
  t.alike(await fresh.get('app.bsky.feed.post/bbb'), { text: 'world' }, 'repo record bbb migrated')
  t.alike(await fresh.get('__commit__/3abc'), { rev: '3abc', commitCid: 'bafyfake' }, '__commit__ firehose entry migrated')
  const all = await fresh.list('')
  t.is(Object.keys(all).length, 3, 'exactly the 3 durable entries migrated (no transient/admission junk)')
  await fresh.close()

  // 3. Idempotent: reopening the renamed room again does not re-migrate or lose data.
  const again = new StateBaseV3(dir, roomKey, cfg())
  await again.ready()
  t.alike(await again.get('app.bsky.feed.post/aaa'), { text: 'hello' }, 'still present on 2nd reopen (idempotent)')
  t.is(Object.keys(await again.list('')).length, 3, 'still exactly 3 entries (no duplication)')
  await again.close()
})

test('re-adopt: a fresh renamed room with NO legacy base is untouched', async (t) => {
  const dir = tmp()
  const sb = new StateBaseV3(dir, crypto.randomBytes(32), { roomSeed: crypto.randomBytes(32), encryptionKey: crypto.randomBytes(32), network: false })
  await sb.ready()
  t.is(Object.keys(await sb.list('')).length, 0, 'no legacy base → nothing migrated, room is empty')
  await sb.set('app.bsky.feed.post/x', { text: 'new' })
  t.alike(await sb.get('app.bsky.feed.post/x'), { text: 'new' }, 'normal writes still work')
  await sb.close()
})