OverviewFilesCommitsIssuesDocsReleasesPeers

keet-daemon / test / probe-v3-router-integration.mjs

51 lines · javascript ref:
// P1 step-1 verify: the daemon (router → StateBaseV3) persists game state for a
// real keet room. Fresh /tmp identity (no real data touched). Creator path.
import { startDaemon } from '../index.js'
import Pipe from 'bare-pipe'
import fs from 'bare-fs'

const STORAGE = '/tmp/v3-router-int'
const SOCK = '/tmp/v3-router-int.sock'
try { fs.rmSync(STORAGE, { recursive: true, force: true }) } catch {}
const sleep = (ms) => new Promise(r => setTimeout(r, ms))
function rpc (method, params) {
  return new Promise((res) => {
    const p = new Pipe(SOCK); let b = Buffer.alloc(0); const id = Math.floor(Math.random() * 1e9)
    const f = Buffer.from(JSON.stringify({ id, method, params })); const l = Buffer.alloc(4); l.writeUInt32LE(f.length, 0)
    p.on('connect', () => p.write(Buffer.concat([l, f])))
    p.on('data', d => { b = Buffer.concat([b, d]); while (b.length >= 4) { const n = b.readUInt32LE(0); if (b.length < 4 + n) break; const m = JSON.parse(b.subarray(4, 4 + n)); b = b.subarray(4 + n); if (m.id === id) { p.destroy(); res(m) } } })
    p.on('error', e => res({ ok: false, error: 'pipe:' + e.message }))
    setTimeout(() => { try { p.destroy() } catch {} ; res({ ok: false, error: 'timeout' }) }, 25000)
  })
}
let pass = 0; let fail = 0
const ok = (c, m) => { if (c) { pass++; console.log('  ok  ' + m) } else { fail++; console.log('  FAIL ' + m) } }

async function main () {
  await startDaemon({ storage: STORAGE, socketPath: SOCK, debug: false })
  await sleep(12000) // keet-core boot + fresh identity

  const idr = await rpc('identity', {})
  ok(idr.ok && idr.data.memberId, 'fresh identity created (memberId=' + (idr.ok && idr.data.memberId ? idr.data.memberId.slice(0, 10) : '?') + ')')

  const cr = await rpc('room.create', { title: 'v3 integration test' })
  const roomId = cr.ok ? (cr.data.roomId || cr.data.id || cr.data) : null
  ok(roomId && typeof roomId === 'string', 'room.create → roomId=' + roomId)
  if (!roomId) { console.log('\n[probe] pass=' + pass + ' fail=' + (fail + 1)); return Bare.exit(1) }

  const info = await rpc('state.info', { roomId })
  ok(info.ok, 'state.info ok writable=' + (info.ok && info.data.writable) + ' key=' + (info.ok && info.data.stateBaseKey ? info.data.stateBaseKey.slice(0, 10) : '?'))
  ok(info.ok && info.data.writable === true, 'creator is WRITABLE (single-writer v3.0a)')

  const setr = await rpc('state.set', { roomId, key: 'world:players:self', value: '{"level":"town","x":5}' })
  ok(setr.ok, 'state.set ok (' + (setr.ok ? '' : setr.error) + ')')

  const listr = await rpc('state.list', { roomId })
  const keys = listr.ok ? Object.keys(listr.data.entries || {}) : []
  ok(listr.ok && keys.includes('world:players:self'), 'state.list returns the written key (' + JSON.stringify(keys) + ')')

  console.log('\n[probe] pass=' + pass + ' fail=' + fail)
  Bare.exit(fail ? 1 : 0)
}
main().catch((e) => { console.error('[probe] THREW:', e && e.stack ? e.stack : e); Bare.exit(2) })