import { test, b4a, Hyperdrive, Corestore, mkdirSync, rmSync, readFile, readdir, path, fileURLToPath, PassThrough, XTERM_CLEAR_SCROLLBACK_AND_VIEWPORT, runKernelFromSource, runBinCommand, createGitFsFromVfs, runGitCli, createStreamLineReader, sanitizeInteractiveShellLine, createVfs, BARE_OS_PROC_FILE_TO_ID_HYPERCORE_PACK_HRPC_LIFECYCLE, parseHdmsPairArgv, hcCrypto, idEnc, decodeRwShareOffer, decodeShareOffer, HDMS_AUTOPASS_SHARE_KEY, HDMS_AUTOPASS_SHARE_RW_KEY, normalizeWriterSecretHex, buildBareOsHypercorePackHrpcLifecycleProcJson, buildBareOsPearCorestoreHrpcProcJson, buildBareOsPearInspectLoggerTlsProcJson, buildBareOsBareRuntimeProtoMuxProcJson, buildBareOsBootGraphProcJson, pathnameExpandShellWord, createBareOsIpc, BareOsSwarmConnectionManager, createBareOsLifecycleStateMachine, runTransactionalLifecycleHooks, bareOsRegisterCorestoreSuspendResumeHooks, bareOsInstallCorestoreSuspendResumeHooks, bareOsFindOrphanProcessRows, topologicalOrderKernelExtensions, resolveKernelExtensionsFull, createBareOsProtomuxAliasRegistry, bareOsHttpUrlAllowed, bareOsParseBareAclText, bareOsAclDeniesSubject, raceWithAbortAndTimeout, tokenize, expandWord, execShellLine, expandArgvAliases, defaultShellAliases, loadBarerc, BARERC_SKELETON, splitTokensBySemicolon, splitTokensByAndOr, bareOsShellAstSnapshot, planShellRedirections, buildShellExecutionGraph, dispatchShellTrapSignal, BARE_OS_EXIT_STATUS_ENV, syncBareOsExitStatusEnv, getBareOsPipelineLimits, DEFAULT_PIPELINE_MAX_STAGES, tokenizeBareShellLineDetailed, decodeBareOsDollarQuote, applyBareOsThemeFromEnv, bareOsListThemeNames, bareParseLsColors, bareSerializeLsColors, bareLsColorOpenSgrFromMap, bareDefaultDircolorsDatabase, bareParseDircolorsDatabase, BARE_OS_CTX_API_VERSION, buildBareOsRuntimeCaps, bareOsBareModulesEnabled, bareOsBareModuleManifestEmbeddedRef, buildBareCtxObjectFromHost, buildPearCtxObjectFromHost, loadBareModuleManifest, maybeMergeBareFromDrive, maybeBareOsBuildBinManifest, createFishReadLine, fuzzyMatch, stripAnsi, parseHistoryFile, formatHistoryFile, dedupeConsecutiveHistory, searchHistoryEntries, shouldPersistShellHistoryCommand, scrubShellHistoryEntries, SHELL_BUILTINS, resolveShellPromptHookSegment, parseCompletionContext, rankCompletionItems, suggestGhostFromHistory, suggestGhostFromFs, ghostReplaceCurrentWord, longestCommonCompletionPrefix, completeLine, levenshtein, fieldMatches, dowFieldMatches, parseCronLine, jobMatchesDate, bareInitdReadinessSnapshot, bareInitdShutdownActiveUnitsReverse, getBareServiceRuntime, registerBareInitdDisposer, registerKernelShutdownHook, runKernelShutdownHooks, startBareInitd, stopBareInitd, getLastBareInitdDagSnapshotJson, appendVarLog, ensureBareOsVarLogTree, KERNEL_CONSOLE_LOG, BOOT_LOG, bareOsKernelMetricsReset, bareOsKernelMetricsSnapshot, parseUnitDropInText, bareOsHyperswarmOptsFromEnv, bareOsBootJoinPeerHexFromEnv, bareOsBootInitPrefetchEnabled, bareOsBootWarmBinDownloadDiffEnabled, bareOsProcessTableSnapshot, buildBareOsSyscallsProcJson, bareOsParseSendmsgScmRights, wantPosixSocketScmRights, parseBareOsHrpcAllowlistJson, bareOsHrpcAllowlistDeniesRoute, buildBareOsProtomuxExtensionsProcJson, createBareOsDiskOsBridge, buildBareOsReplicationLiveSketch, evaluateBareOsPeerAdmission, bareOsFormatPeerAdmissionAuditEvent, bareOsPeerAdmissionAuditRateAllow, parseDelegateAllowSet, isDelegateKindAllowed, bareOsAuditAppend, bareOsAuditVerifyRows, bareOsDrainFcntlLockWaiters, buildBareOsReplicationOperatorSurfaceProcJson, DEFAULT_CURL_USER_AGENT, DEFAULT_WGET_USER_AGENT, filenameFromContentDisposition, encodeUstarHeader, runTarCli, require, __dirname, TAR_BLK, concatTarParts, headerFromInit, testCorestoreDir, testCtx, personalHomeBacking, readBuiltBin } from './test/_helpers.js' test('kernel_program proc JSON includes program metadata', async (t) => { const o = buildBareOsHypercorePackHrpcLifecycleProcJson( 'kernel_program', { BARE_OS_BOOT_SAFE_MODE: '1' } ) t.is(o.schema, 3) t.is(o.program, 'bare-os-kernel-program') t.ok(o.operatorSketches && typeof o.operatorSketches === 'object') t.ok(o.hooks && o.hooks.bootSafeMode === true) }) test('giant_phase_program proc id returns same builder as kernel_program', async (t) => { const a = buildBareOsHypercorePackHrpcLifecycleProcJson('kernel_program', {}) const b = buildBareOsHypercorePackHrpcLifecycleProcJson('giant_phase_program', {}) t.is(a.program, b.program) t.is(a.schema, b.schema) }) test('parseUnitDropInText parses ConditionPathExists and Restart keys', async (t) => { const d = parseUnitDropInText( '[Unit]\nConditionPathExists=/tmp/x\nRestart=on-failure\nRestartSec=2\n' ) t.is(d.conditionPathExists, '/tmp/x') t.is(d.restart, 'on-failure') t.is(d.restartSec, 2) }) test('bareOsIpc.signalProcessGroup pushes bareOsProcessGroupSignal to scoped channels', async (t) => { const ipc = createBareOsIpc() ipc.create('c1') ipc.create('c2') ipc.assignProcessGroup('c1', 7) ipc.assignProcessGroup('c2', 7) const p1 = ipc.takeJson('c1') const p2 = ipc.takeJson('c2') const out = ipc.signalProcessGroup(7, 'SIGUSR1') t.is(out.delivered, 2) const j1 = await p1 const j2 = await p2 t.is(j1.method, 'bareOsProcessGroupSignal') t.is(j1.signal, 'SIGUSR1') t.is(j2.pgid, 7) const st = ipc.stats() t.ok(st.processGroups && st.processGroups.byPgid) t.ok(st.processGroups.byPgid['pgid:7'].includes('c1')) }) test('kernel ext incremental reload runs only new scripts when hot reload env set', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) /** @type {string[]} */ const extDir = ['01-a.json'] /** @type {string[]} */ const ran = [] const vfsFiles = new Map() const drive = { async get(p) { if (p === '/etc/os-release') return b4a.from('ID=test\n') if (p === '/etc/motd') return b4a.from('') if (p === '/etc/bare-os/kernel.ext.d/01-a.json') { return b4a.from( JSON.stringify({ id: 'a', scripts: ['/lib/bare-os/extensions/a.js'] }) ) } if (p === '/etc/bare-os/kernel.ext.d/02-b.json') { return b4a.from( JSON.stringify({ id: 'b', scripts: ['/lib/bare-os/extensions/b.js'] }) ) } return null }, async *readdir(d) { if (d === '/etc/bare-os/kernel.ext.d') { for (const x of extDir) yield x } } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_BOOT_SKIP_STAGES: 'profile,rc,rc.d,rc.local,kernel.d,onboot,selftest', BARE_OS_KERNEL_EXT_D_HOT_RELOAD: '1' }, drive, b4a, vfs: { async readFile(p) { return vfsFiles.get(p) ?? null }, async writeFile(p, body) { vfsFiles.set( p, body instanceof Uint8Array ? body : b4a.from(String(body)) ) } }, console: { log() {}, error() {}, warn() {} }, readLine: async () => null, async execLine() { return 'ok' }, async bareOsRunImageScript(path) { ran.push(path) } } await runKernelFromSource(src, ctx) t.alike(ran, ['/lib/bare-os/extensions/a.js']) t.ok(typeof ctx.bareOsReloadKernelExtDropinsSafe === 'function') extDir.push('02-b.json') const out = await ctx.bareOsReloadKernelExtDropinsSafe() t.ok(out.ok) t.alike(out.ranScripts, ['/lib/bare-os/extensions/b.js']) t.alike(ran, [ '/lib/bare-os/extensions/a.js', '/lib/bare-os/extensions/b.js' ]) const jr = b4a.toString(vfsFiles.get('/run/bare-os/kernel-ext-reload.ndjson')) t.ok(jr.includes('incremental')) }) test('kernel.ext.d minCtxApiVersion skips drop-in when ctx API too low', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) /** @type {string[]} */ const ran = [] const drive = { async get(p) { if (p === '/etc/os-release') return b4a.from('ID=test\n') if (p === '/etc/motd') return b4a.from('') if (p === '/etc/bare-os/kernel.ext.d/01-hi.json') { return b4a.from( JSON.stringify({ id: 'hi', minCtxApiVersion: '99.0.0', scripts: ['/lib/bare-os/extensions/hi.js'] }) ) } return null }, async *readdir(d) { if (d === '/etc/bare-os/kernel.ext.d') yield '01-hi.json' } } const ctx = { bareOsSkipRepl: true, bareOsCtxApiVersion: '1.0.0', env: { BARE_OS_BOOT_SKIP_STAGES: 'profile,rc,rc.d,rc.local,kernel.d,onboot,selftest' }, drive, b4a, console: { log() {}, error() {}, warn() {} }, readLine: async () => null, async execLine() { return 'ok' }, async bareOsRunImageScript(path) { ran.push(path) } } await runKernelFromSource(src, ctx) t.is(ran.length, 0) }) test('kernel.ext.d conflictsWith strict skips extension scripts', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) /** @type {string[]} */ const ran = [] const drive = { async get(p) { if (p === '/etc/os-release') return b4a.from('ID=test\n') if (p === '/etc/motd') return b4a.from('') if (p === '/etc/bare-os/kernel.ext.d/01-a.json') { return b4a.from( JSON.stringify({ id: 'a', conflictsWith: ['b'], scripts: ['/lib/bare-os/extensions/a.js'] }) ) } if (p === '/etc/bare-os/kernel.ext.d/02-b.json') { return b4a.from( JSON.stringify({ id: 'b', scripts: ['/lib/bare-os/extensions/b.js'] }) ) } return null }, async *readdir(d) { if (d === '/etc/bare-os/kernel.ext.d') { yield '01-a.json' yield '02-b.json' } } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_BOOT_SKIP_STAGES: 'profile,rc,rc.d,rc.local,kernel.d,onboot,selftest', BARE_OS_BOOT_POLICY_STRICT: '1' }, drive, b4a, console: { log() {}, error() {}, warn() {} }, readLine: async () => null, async execLine() { return 'ok' }, async bareOsRunImageScript(p) { ran.push(p) } } await runKernelFromSource(src, ctx) t.is(ran.length, 0) }) test('kernel.ext.d dependency cycle strict skips extension scripts', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) /** @type {string[]} */ const ran = [] const drive = { async get(p) { if (p === '/etc/os-release') return b4a.from('ID=test\n') if (p === '/etc/motd') return b4a.from('') if (p === '/etc/bare-os/kernel.ext.d/01-a.json') { return b4a.from( JSON.stringify({ id: 'a', dependsOn: ['b'], scripts: ['/lib/bare-os/extensions/a.js'] }) ) } if (p === '/etc/bare-os/kernel.ext.d/02-b.json') { return b4a.from( JSON.stringify({ id: 'b', dependsOn: ['a'], scripts: ['/lib/bare-os/extensions/b.js'] }) ) } return null }, async *readdir(d) { if (d === '/etc/bare-os/kernel.ext.d') { yield '01-a.json' yield '02-b.json' } } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_BOOT_SKIP_STAGES: 'profile,rc,rc.d,rc.local,kernel.d,onboot,selftest', BARE_OS_BOOT_POLICY_STRICT: '1' }, drive, b4a, console: { log() {}, error() {}, warn() {} }, readLine: async () => null, async execLine() { return 'ok' }, async bareOsRunImageScript(p) { ran.push(p) } } await runKernelFromSource(src, ctx) t.is(ran.length, 0) }) test('stock kernel BARE_OS_BOOT_SAFE_MODE skips kernel.ext.d scripts', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) let extRan = false const drive = { async get(p) { if (p === '/etc/bare-os/kernel.ext.d/01-a.json') { return b4a.from( JSON.stringify({ id: 'a', scripts: ['/lib/bare-os/extensions/x.js'] }) ) } return null }, async *readdir(d) { if (d === '/etc/bare-os/kernel.ext.d') yield '01-a.json' } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_BOOT_SAFE_MODE: '1' }, drive, b4a, console: { log() {}, error() {} }, readLine: async () => null, async execLine() { return 'ok' }, async bareOsRunImageScript() { extRan = true } } await runKernelFromSource(src, ctx) t.is(extRan, false) }) test('boot.policy denySeedRpcMethods merges into kernel env deny list', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) const drive = { async get(p) { if (p === '/etc/os-release') return b4a.from('ID=test\n') if (p === '/etc/motd') return b4a.from('') if (p === '/etc/bare-os/boot.policy.json') { return b4a.from( JSON.stringify({ denySeedRpcMethods: ['replication_queue', 'capabilities'] }) ) } return null }, async *readdir() {} } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_BOOT_POLICY: '1', BARE_OS_BOOT_SKIP_STAGES: 'profile,rc,rc.d,rc.local,kernel.d,onboot,selftest', BARE_OS_BOOT_POLICY_DENY_SEED_RPC_METHODS: 'version,replication_queue' }, drive, b4a, console: { log() {}, error() {}, warn() {} }, readLine: async () => null, async execLine() { return 'ok' } } await runKernelFromSource(src, ctx) t.is( ctx.env.BARE_OS_BOOT_POLICY_DENY_SEED_RPC_METHODS, 'version,replication_queue,capabilities' ) }) test('runKernelFromSource invokes start(ctx)', async (t) => { const calls = [] const source = ` async function start(ctx) { ctx.calls.push('ok') } ` await runKernelFromSource(source, { calls }) t.is(calls[0], 'ok') }) test('stock kernel init.js onboot runs multiple BARE_OS_ONBOOT lines when SKIP_REPL', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) const execLines = [] const drive = { async get() { return null }, async *readdir() { /* empty */ } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_ONBOOT: 'echo one\n#c\n echo two' }, drive, b4a, console: { log() {}, error() {} }, readLine: async () => null, async execLine(line) { execLines.push(String(line).trim()) return 'ok' } } await runKernelFromSource(src, ctx) t.alike(execLines, ['echo one', 'echo two']) }) test('stock kernel init.js runs rc.local before onboot', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) const execLines = [] const drive = { async get(p) { if (p === '/etc/bare-os/rc.local') return b4a.from('echo rc-local') return null }, async *readdir() { /* empty */ } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_ONBOOT: 'echo onboot-line' }, drive, b4a, console: { log() {}, error() {} }, readLine: async () => null, async execLine(line) { execLines.push(String(line).trim()) return 'ok' } } await runKernelFromSource(src, ctx) t.is(execLines[0], 'echo rc-local') t.is(execLines[1], 'echo onboot-line') }) test('stock kernel init.js runs kernel.d after rc.local before onboot', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) const execLines = [] const drive = { async get(p) { if (p === '/etc/bare-os/rc.local') return b4a.from('echo rc-local') if (p === '/etc/bare-os/kernel.d/05-k.mod') return b4a.from('echo kmod') return null }, async *readdir(dir) { if (dir === '/etc/bare-os/kernel.d') yield '05-k.mod' } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_ONBOOT: 'echo onboot-line' }, drive, b4a, console: { log() {}, error() {} }, readLine: async () => null, async execLine(line) { execLines.push(String(line).trim()) return 'ok' } } await runKernelFromSource(src, ctx) t.is(execLines[0], 'echo rc-local') t.is(execLines[1], 'echo kmod') t.is(execLines[2], 'echo onboot-line') }) test('stock kernel init.js BARE_OS_BOOT_TRACE=json emits boot trace JSON on stderr', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) const stderr = [] const drive = { async get() { return null }, async *readdir() { /* empty */ } } const ctx = { bareOsSkipRepl: false, env: { BARE_OS_BOOT_TRACE: 'json' }, drive, b4a, console: { log() {}, error(...a) { stderr.push(a.join(' ')) } }, readLine: async () => null, async execLine() { return 'ok' } } await runKernelFromSource(src, ctx) const phases = stderr .map((l) => { try { return JSON.parse(l) } catch { return null } }) .filter(Boolean) const bootSteps = phases.filter( (o) => o && typeof o.ms === 'number' && o.type !== 'bootOutput' ) t.ok(bootSteps.length >= 3) t.ok(bootSteps.some((o) => o.phase === 'rc.local')) t.ok(bootSteps.some((o) => o.step === 'rc.local')) t.ok(bootSteps.some((o) => o.phase === 'kernel.d')) t.ok(bootSteps.some((o) => o.step === 'kernel.d')) t.ok(bootSteps.every((o) => o.bootTraceSchemaVersion === 2)) t.ok(bootSteps.every((o) => typeof o.ms === 'number')) t.ok( phases.some( (o) => o && o.type === 'bootOutput' && o.step === 'banner' ), 'bootOutput trace for guest-visible banner' ) }) test('stock kernel BARE_OS_RC_D_SKIP skips matching rc.d snippets', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) const execLines = [] const drive = { async get(p) { if (p === '/etc/bare-os/rc.d/05-skip.me') return b4a.from('echo skipped-should-not-run') if (p === '/etc/bare-os/rc.d/10-keep') return b4a.from('echo kept') return null }, async *readdir(dir) { if (dir === '/etc/bare-os/rc.d') { yield '05-skip.me' yield '10-keep' } } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_ONBOOT: 'echo tail', BARE_OS_RC_D_SKIP: '05-*' }, drive, b4a, console: { log() {}, error() {} }, readLine: async () => null, async execLine(line) { execLines.push(String(line).trim()) return 'ok' } } await runKernelFromSource(src, ctx) t.ok(!execLines.some((l) => l.includes('skipped'))) t.is(execLines[0], 'echo kept') t.is(execLines[1], 'echo tail') }) test('stock kernel BARE_OS_BOOT_STRICT stops boot after execLine throw', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) const execLines = [] let exitArg = null const drive = { async get(p) { if (p === '/etc/bare-os/rc') return b4a.from('echo first\n__throw__\necho third') return null }, async *readdir() { /* empty */ } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_BOOT_STRICT: '1' }, drive, b4a, console: { log() {}, error() {} }, readLine: async () => null, requestBooterExit(code) { exitArg = code }, async execLine(line) { const t0 = String(line).trim() if (t0 === '__throw__') throw new Error('boot-fail') execLines.push(t0) return 'ok' } } await runKernelFromSource(src, ctx) t.alike(execLines, ['echo first']) t.is(exitArg, 1) }) test('stock kernel BARE_OS_BOOT_DRY_RUN skips execLine and reports bootDryRun in boot proc', async (t) => { const src = await readFile( path.join(__dirname, '../../kernel/init.js'), 'utf8' ) /** @type {string[]} */ const errs = [] /** @type {string[]} */ const execCalls = [] const drive = { async get(p) { if (p === '/etc/os-release') return b4a.from('ID=test\n') if (p === '/etc/motd') return b4a.from('') if (p === '/etc/bare-os/rc') return b4a.from('echo dry-rc\n') if (p === '/etc/bare-os/onboot') return b4a.from('echo dry-onboot\n') return null }, async *readdir() { /* empty */ } } const ctx = { bareOsSkipRepl: true, env: { BARE_OS_BOOT_DRY_RUN: '1' }, drive, b4a, console: { log() {}, warn() {}, error: (...a) => errs.push(a.join(' ')) }, readLine: async () => null, async execLine(line) { execCalls.push(String(line || '')) return 'should-not-run' }, bareOsPublishBootReady(patch) { this._bootReady = patch } } await runKernelFromSource(src, ctx) t.is(execCalls.length, 0) t.ok( errs.some( (m) => m.includes('bootDryRunExecLine') || m.includes('bootDryRunOnboot') || m.includes('[boot-dry-run]') ) ) t.is(ctx._bootReady?.subsystems?.kernel?.programProc?.bootDryRun, true) }) test('runBinCommand runs /bin helper', async (t) => { const dir = testCorestoreDir('bin') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('p')) await drive.ready() await personal.ready() await drive.put( '/bin/hello', b4a.from(` async function run(ctx, argv) { ctx.out.push(argv.join(' ')) } `) ) const out = [] const ctx = testCtx(drive, personal) ctx.out = out await runBinCommand(ctx, ['hello', 'a', 'b']) t.is(out[0], 'hello a b') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand runs bare hello.js from cwd on personal drive', async (t) => { const dir = testCorestoreDir('barejs') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pj')) await drive.ready() await personal.ready() await personal.put( personalHomeBacking('/home/user', 'hello.js'), b4a.from(` async function run(ctx, argv) { ctx.out.push(argv.join(' ')) } `) ) const out = [] const ctx = testCtx(drive, personal) ctx.out = out await runBinCommand(ctx, ['hello.js', 'x', 'y']) t.is(out[0], 'hello.js x y') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand strips shebang from user script', async (t) => { const dir = testCorestoreDir('shebang') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('psh')) await drive.ready() await personal.ready() await personal.put( personalHomeBacking('/home/user', 'x.js'), b4a.from(`#!/usr/bin/env bare async function run(ctx) { ctx.out.push('ok') } `) ) const out = [] const ctx = testCtx(drive, personal) ctx.out = out await runBinCommand(ctx, ['./x.js']) t.is(out[0], 'ok') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand runs top-level user script without run()', async (t) => { const dir = testCorestoreDir('norun') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pnr')) await drive.ready() await personal.ready() await personal.put( personalHomeBacking('/home/user', 'plain.js'), b4a.from(`ctx.out.push('only-top')`) ) const out = [] const ctx = testCtx(drive, personal) ctx.out = out await runBinCommand(ctx, ['./plain.js']) t.is(out[0], 'only-top') t.is(ctx.exitCode, 0) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand runs top-level then run() when both present', async (t) => { const dir = testCorestoreDir('bothrun') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pbr')) await drive.ready() await personal.ready() await personal.put( personalHomeBacking('/home/user', 'hybrid.js'), b4a.from(`ctx.out.push('first') async function run(ctx) { ctx.out.push('second') } `) ) const out = [] const ctx = testCtx(drive, personal) ctx.out = out await runBinCommand(ctx, ['./hybrid.js']) t.alike(out, ['first', 'second']) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand user script error is caught and logged', async (t) => { const dir = testCorestoreDir('throwjs') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('ptj')) await drive.ready() await personal.ready() await personal.put( personalHomeBacking('/home/user', 'bad.js'), b4a.from(`async function run() { test() }`) ) const errs = [] const ctx = testCtx(drive, personal) ctx.console = { log: () => {}, error: (...a) => { errs.push(a.join(' ')) } } await runBinCommand(ctx, ['./bad.js']) t.ok(errs.length > 0) t.ok(errs.some((e) => /test|not defined|ReferenceError/i.test(e))) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ls hides dotfiles unless -a', async (t) => { const lsPath = path.join(__dirname, '../../kernel/bin/ls') const lsSrc = await readFile(lsPath, 'utf8') const dir = testCorestoreDir('lsdot') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pls')) await drive.ready() await personal.ready() await drive.put('/bin/ls', b4a.from(lsSrc)) await personal.put( personalHomeBacking('/home/user', 'shown.txt'), b4a.from('') ) await personal.put(personalHomeBacking('/home/user', '.hidden'), b4a.from('')) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await runBinCommand(ctx, ['ls']) const flat = lines.join('\n') t.ok(flat.includes('shown.txt')) t.ok(!flat.includes('hidden')) lines.length = 0 await runBinCommand(ctx, ['ls', '-a']) const flatA = lines.join('\n') t.ok(flatA.includes('hidden')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('createStreamLineReader yields lines after newline', async (t) => { const stdin = new PassThrough() const chunks = [] const stdout = { write(s) { chunks.push(String(s)) } } const readLine = createStreamLineReader(stdin, stdout) const p = readLine('> ') stdin.write('help\n') t.is(await p, 'help') t.ok(chunks.join('').includes('> ')) stdin.end() }) test('createStreamLineReader yields lines after carriage return (SSH PTY)', async (t) => { const stdin = new PassThrough() const stdout = { write() {} } const readLine = createStreamLineReader(stdin, stdout) const p = readLine('> ') stdin.write('pwd\r') t.is(await p, 'pwd') const p2 = readLine('> ') stdin.write('a\r\n') t.is(await p2, 'a') stdin.end() }) test('sanitizeInteractiveShellLine applies DEL and strips controls', async (t) => { t.is(sanitizeInteractiveShellLine('ls'), 'ls') t.is(sanitizeInteractiveShellLine('a\x7Fb'), 'b') t.is(sanitizeInteractiveShellLine('ab\x08'), 'a') t.is(sanitizeInteractiveShellLine('x\x01y'), 'xy') }) test('Hyperdrive roundtrips /boot/init.js on Corestore', async (t) => { const dir = testCorestoreDir('seed') const store = new Corestore(dir) const drive = new Hyperdrive(store) await drive.ready() await drive.put('/boot/init.js', b4a.from('async function start() {}')) const buf = await drive.get('/boot/init.js') t.ok(buf) t.is(b4a.toString(buf), 'async function start() {}') await drive.close() rmSync(dir, { recursive: true, force: true }) }) test('Hyperdrive checkout read-only boot probe', async (t) => { const dir = testCorestoreDir('seed-checkout-ro') const store = new Corestore(dir) const drive = new Hyperdrive(store) await drive.ready() await drive.put('/boot/init.js', b4a.from('async function start() { return 1 }')) const version = drive.version const ro = drive.checkout(version, { writable: false }) const buf = await ro.get('/boot/init.js') t.ok(buf) t.is(b4a.toString(buf), 'async function start() { return 1 }') await t.exception(async () => { await ro.put('/boot/init.js', b4a.from('mutate')) }) await ro.close() await drive.close() rmSync(dir, { recursive: true, force: true }) })