import test from 'brittle' import b4a from 'b4a' import Hyperdrive from 'hyperdrive' import Corestore from 'corestore' import { mkdirSync, rmSync } from 'node:fs' import { readFile, readdir } from 'node:fs/promises' import path from 'node:path' import { fileURLToPath } from 'node:url' import { PassThrough } from 'node:stream' import { runKernelFromSource, runBinCommand } from './lib/kernel-runner.js' import { createGitFsFromVfs } from './lib/git-fs-adapter.js' import { runGitCli } from './lib/git-cli.js' import { createStreamLineReader } from './lib/cli-readline.js' import { createVfs, BARE_OS_PROC_FILE_TO_ID_HYPERCORE_PACK_HRPC_LIFECYCLE } from './lib/vfs.js' import { buildBareOsHypercorePackHrpcLifecycleProcJson } from './lib/bare-os-proc-hypercore-pack-hrpc-lifecycle.js' import { createBareOsIpc } from './lib/bare-os-ipc.js' import { bareOsHttpUrlAllowed } from './lib/bare-os-http-policy.js' import { raceWithAbortAndTimeout } from './lib/bare-os-abort.js' import { tokenize, expandWord, execShellLine, expandArgvAliases, defaultShellAliases, loadBarerc, BARERC_SKELETON, splitTokensBySemicolon, splitTokensByAndOr, BARE_OS_EXIT_STATUS_ENV, syncBareOsExitStatusEnv, getBareOsPipelineLimits, DEFAULT_PIPELINE_MAX_STAGES } from './lib/shell.js' import { applyBareOsThemeFromEnv, bareOsListThemeNames } from './lib/bare-os-theme-presets.js' import { bareParseLsColors, bareSerializeLsColors, bareLsColorOpenSgrFromMap, bareDefaultDircolorsDatabase, bareParseDircolorsDatabase } from 'bare-os-lscolors' import { BARE_OS_CTX_API_VERSION } from './lib/bare-os-ctx-api.js' import { buildBareOsRuntimeCaps } from './lib/bare-os-runtime-caps.js' import { bareOsBareModulesEnabled, buildBareCtxObjectFromHost, loadBareModuleManifest, maybeMergeBareFromDrive } from './lib/bare-os-ctx-bare.js' import { fuzzyMatch, stripAnsi, parseHistoryFile, formatHistoryFile, dedupeConsecutiveHistory, searchHistoryEntries } from './lib/fish-readline.js' import { fieldMatches, dowFieldMatches, parseCronLine, jobMatchesDate } from './lib/bare-cron.js' import { getBareServiceRuntime, registerBareInitdDisposer, registerKernelShutdownHook, runKernelShutdownHooks, startBareInitd, stopBareInitd } from './lib/bare-initd.js' import { DEFAULT_CURL_USER_AGENT, DEFAULT_WGET_USER_AGENT } from './lib/http-fetch-url.js' import { filenameFromContentDisposition } from './lib/curl-cli.js' const __dirname = path.dirname(fileURLToPath(import.meta.url)) function headerFromInit(init, name) { if (!init?.headers) return undefined const h = init.headers if (typeof h.get === 'function') return h.get(name) return undefined } function testCorestoreDir(name) { const dir = path.join( __dirname, '.test-data', name + '-' + process.pid + '-' + Math.random().toString(36).slice(2) ) mkdirSync(path.dirname(dir), { recursive: true }) return dir } function testCtx(drive, personal, env) { const shellEnv = { HOME: '/home/user', PATH: '/bin', USER: 'user', UID: '1000', GID: '1000', PWD: '/home/user', BARE_OS_EXIT_STATUS: '0', ...env } const bareOsIpc = createBareOsIpc() const vfs = createVfs(drive, personal, shellEnv, null, { bareOsIpc }) const ctx = { drive, personalDrive: personal, vfs, bareOsIpc, env: shellEnv, console, b4a, async bareOsApplyTheme() { return applyBareOsThemeFromEnv(this) }, bareOsListThemes() { return bareOsListThemeNames() } } return ctx } /** Personal-drive path backing logical `/home//…` (matches `vfs.js`). */ function personalHomeBacking(homePath, rel = '') { const seg = homePath.replace(/^\/home\//, '').split('/')[0] || 'user' const r = String(rel).replace(/^\//, '') return r ? `/.bare-os/home/${seg}/${r}` : `/.bare-os/home/${seg}` } 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, 2) 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('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('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) t.ok(phases.length >= 3) t.ok(phases.some((o) => o.phase === 'rc.local')) t.ok(phases.some((o) => o.step === 'rc.local')) t.ok(phases.some((o) => o.phase === 'kernel.d')) t.ok(phases.some((o) => o.step === 'kernel.d')) t.ok(phases.every((o) => o.bootTraceSchemaVersion === 2)) t.ok(phases.every((o) => typeof o.ms === 'number')) }) 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('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('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('vfs lstat personal file includes mode uid user mtime', async (t) => { const dir = testCorestoreDir('lstatposix') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('lsp')) await sys.ready() await personal.ready() const vfs = createVfs(sys, personal, { HOME: '/home/user', PWD: '/home/user', PATH: '/bin', USER: 'alice', UID: '4242', GID: '4242' }) await vfs.writeFile('f', b4a.from('x')) const st = await vfs.lstat('/home/user/f') t.ok(st) t.is(st.type, 'file') t.is(st.user, 'alice') t.is(st.uid, 4242) t.ok((st.mode & 0o777) <= 0o777) t.ok((st.mode & 0o100000) === 0o100000) t.ok(typeof st.mtimeMs === 'number') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ls -l long listing uses session user and regular file mode', async (t) => { const lsPath = path.join(__dirname, '../../kernel/bin/ls') const lsSrc = await readFile(lsPath, 'utf8') const dir = testCorestoreDir('lslong') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pll')) await drive.ready() await personal.ready() await drive.put('/bin/ls', b4a.from(lsSrc)) const lines = [] const ctx = testCtx(drive, personal, { USER: 'carol', UID: '9001', GID: '9001' }) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await ctx.vfs.writeFile('shown.txt', b4a.from('')) await runBinCommand(ctx, ['ls', '-l', 'shown.txt']) const longLine = lines.find((l) => l.includes('shown.txt')) t.ok(longLine) t.ok(longLine.includes('carol')) t.ok(/^-rw/.test(longLine), 'expected regular file mode prefix') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ls --color=always colors directory blue and executable green', async (t) => { const lsPath = path.join(__dirname, '../../kernel/bin/ls') const lsSrc = await readFile(lsPath, 'utf8') const dir = testCorestoreDir('lscolor') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('plsc')) await drive.ready() await personal.ready() await drive.put('/bin/ls', b4a.from(lsSrc)) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await ctx.vfs.mkdir('subdir', { recursive: true }) await ctx.vfs.writeFile('xfile', b4a.from('')) await ctx.vfs.chmod('xfile', 0o755) await runBinCommand(ctx, ['ls', '--color=always']) const shortLine = lines.find( (l) => l.includes('subdir') && l.includes('xfile') ) t.ok(shortLine) t.ok( /\x1b\[[0-9;]*msubdir\x1b\[0m/.test(shortLine), 'directory uses LS_COLORS di SGR' ) t.ok( /\x1b\[[0-9;]*mxfile\x1b\[0m/.test(shortLine), 'executable uses LS_COLORS ex SGR' ) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ls honors NO_COLOR over --color=always', async (t) => { const lsPath = path.join(__dirname, '../../kernel/bin/ls') const lsSrc = await readFile(lsPath, 'utf8') const dir = testCorestoreDir('lscolornc') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('plsn')) await drive.ready() await personal.ready() await drive.put('/bin/ls', b4a.from(lsSrc)) const lines = [] const ctx = testCtx(drive, personal, { NO_COLOR: '1' }) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await ctx.vfs.mkdir('onlydir', { recursive: true }) await runBinCommand(ctx, ['ls', '--color=always']) const shortLine = lines.find((l) => l.includes('onlydir')) t.ok(shortLine) t.ok(!shortLine.includes('\x1b['), 'NO_COLOR strips ANSI') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ls rejects unknown long option', async (t) => { const lsPath = path.join(__dirname, '../../kernel/bin/ls') const lsSrc = await readFile(lsPath, 'utf8') const dir = testCorestoreDir('lsbadopt') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('plbo')) await drive.ready() await personal.ready() await drive.put('/bin/ls', b4a.from(lsSrc)) const errs = [] const ctx = testCtx(drive, personal) ctx.console = { log: () => {}, error: (...a) => errs.push(a.join(' ')) } await runBinCommand(ctx, ['ls', '--not-a-real-option']) t.is(ctx.exitCode, 2) t.ok(errs.some((e) => e.includes('unrecognized'))) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs readFile missing path in home does not throw (touch pattern)', async (t) => { const dir = testCorestoreDir('vfsreadmiss') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvrm')) await sys.ready() await personal.ready() const vfs = createVfs(sys, personal, { HOME: '/home/zed', PWD: '/home/zed', PATH: '/bin', USER: 'zed', UID: '7000', GID: '7000' }) const missing = await vfs.readFile('newfile') t.is(missing, null) await vfs.writeFile('newfile', b4a.from('ok')) t.is(b4a.toString(await vfs.readFile('newfile')), 'ok') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs routes HOME to personal drive', async (t) => { const dir = testCorestoreDir('vfs') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pv')) await sys.ready() await personal.ready() const env = { HOME: '/home/user', PWD: '/home/user', PATH: '/bin' } const vfs = createVfs(sys, personal, env) await vfs.writeFile('f.txt', b4a.from('hi')) const buf = await personal.get(personalHomeBacking('/home/user', 'f.txt')) t.ok(buf) t.is(b4a.toString(buf), 'hi') const sysTry = await sys.get('/home/user/f.txt') t.is(sysTry, null) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs chdir / and stat $HOME root (Hyperdrive rejects entry("/"))', async (t) => { const dir = testCorestoreDir('vfsroot') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pv2')) await sys.ready() await personal.ready() const env = { HOME: '/home/user', PWD: '/home/user', PATH: '/bin' } const vfs = createVfs(sys, personal, env) await vfs.chdir('/') t.is(vfs.getcwd(), '/') const st = await vfs.stat('/home/user') t.is(st.type, 'directory') await vfs.chdir('/home/user') t.is(vfs.getcwd(), '/home/user') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs expands ~ and ~/ to $HOME (not read-only /~)', async (t) => { const dir = testCorestoreDir('vfstilde') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pv3')) await sys.ready() await personal.ready() const env = { HOME: '/home/zuser', PWD: '/home/zuser', PATH: '/bin' } const vfs = createVfs(sys, personal, env) await vfs.chdir('/') await vfs.chdir('~') t.is(vfs.getcwd(), '/home/zuser') await vfs.writeFile('~/tilde.txt', b4a.from('ok')) const buf = await personal.get( personalHomeBacking('/home/zuser', 'tilde.txt') ) t.ok(buf) t.is(b4a.toString(buf), 'ok') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs lists virtual /home at root; /home shows only active session dir', async (t) => { const dir = testCorestoreDir('vfshomevirt') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvh')) await sys.ready() await personal.ready() const envGuest = { HOME: '/home/guest', PWD: '/home/guest', PATH: '/bin' } const vfsG = createVfs(sys, personal, envGuest) const rootG = await vfsG.readdir('/') t.ok(rootG.includes('home')) t.ok(rootG.includes('bin') || rootG.includes('boot') || rootG.length >= 1) t.alike(await vfsG.readdir('/home'), ['guest']) const envUser = { HOME: '/home/eeb18de988e9', PWD: '/home/eeb18de988e9', PATH: '/bin' } const vfsU = createVfs(sys, personal, envUser) t.alike(await vfsU.readdir('/home'), ['eeb18de988e9']) t.is(await vfsU.stat('/home/guest'), null) await vfsU.writeFile('/home/eeb18de988e9/x', b4a.from('1')) const buf = await personal.get(personalHomeBacking('/home/eeb18de988e9', 'x')) t.ok(buf) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs /proc /sys read-only pseudo files; write rejected', async (t) => { const dir = testCorestoreDir('vfsproc') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvproc')) await sys.ready() await personal.ready() const env = { HOME: '/home/guest', PWD: '/home/guest', PATH: '/bin', USER: 'guest', BARE_OS_CTX_API_VERSION: '9.9.9-test' } const mntMap = new Map() const bareOsIpc = createBareOsIpc() const vfs = createVfs( sys, personal, env, { getMounts: () => mntMap }, { procSnapshot: { version: '1.2.3-test', cmdline: 'unit-test' }, bootStartedMs: Date.now() - 4000, bootProfileText: () => 'mini\n', sessionText: () => 'test-session-id\n', initdRunText: () => 'demo-unit\tactive\t1\tdemo\n', procBareOsSwarmText: () => '{}\n', bareOsIpc } ) const root = await vfs.readdir('/') t.ok(root.includes('proc')) t.ok(root.includes('sys')) t.ok(root.includes('tmp')) t.ok(root.includes('run')) t.ok(root.includes('dev')) t.alike(await vfs.readdir('/proc').then((a) => [...a].sort()), [ 'bare_os', 'bare_os_activity_queue_depth.json', 'bare_os_async_hooks_lag.json', 'bare_os_autobase_writer_hint.json', 'bare_os_autopass_rotation_sketch.json', 'bare_os_autopass_session_sketch.json', 'bare_os_bare_addon_policy.json', 'bare_os_bare_boot_phase_map.json', 'bare_os_bare_crypto_policy.json', 'bare_os_bare_daemon_hooks.json', 'bare_os_bare_diagnostics_channel.json', 'bare_os_bare_inspect_policy.json', 'bare_os_bare_ipc_bridge.json', 'bare_os_bare_kit_bridge.json', 'bare_os_bare_logger_policy.json', 'bare_os_bare_module_resolution.json', 'bare_os_bare_net_interfaces.json', 'bare_os_bare_pack_cache.json', 'bare_os_bare_performance_counters.json', 'bare_os_bare_rpc_registry_sketch.json', 'bare_os_bare_signals_mask.json', 'bare_os_bare_signals_profile.json', 'bare_os_bare_storage_quota.json', 'bare_os_bare_stream_backpressure.json', 'bare_os_bare_thread_pool.json', 'bare_os_bare_timers_budget.json', 'bare_os_bare_timers_histogram.json', 'bare_os_bare_tls_session_hint.json', 'bare_os_bare_vm_sandbox_sketch.json', 'bare_os_bare_worker_pool.json', 'bare_os_bare_ws_gateway_sketch.json', 'bare_os_blind_pairing_sketch.json', 'bare_os_blind_relay_router.json', 'bare_os_bootstrap', 'bare_os_brittle_snapshot_ci.json', 'bare_os_broadcast_encryption_hint.json', 'bare_os_build_attestation_pointer.json', 'bare_os_bundle_preload_hint.json', 'bare_os_capabilities', 'bare_os_capabilities.json', 'bare_os_cellery_sidecar_hint.json', 'bare_os_compact_encoding_profile.json', 'bare_os_corestore_gc_hint.json', 'bare_os_debug.json', 'bare_os_delegate_red.json', 'bare_os_dht_status.json', 'bare_os_dns_map_active.json', 'bare_os_drive_resolve_cache.json', 'bare_os_drive_version_graph.json', 'bare_os_extensions.json', 'bare_os_features', 'bare_os_form_data_delegate_limits.json', 'bare_os_form_data_delegate_limits_v2.json', 'bare_os_giant_phase_program.json', 'bare_os_gip_transport_sketch.json', 'bare_os_git_delegate_stats.json', 'bare_os_git_lfs_budget.json', 'bare_os_git_lfs_pointer_stats.json', 'bare_os_hdms_health.json', 'bare_os_hdms_hints.json', 'bare_os_host_os.json', 'bare_os_hrpc_allowlist_sketch.json', 'bare_os_hrpc_bridge_health.json', 'bare_os_http_dht_proxy_route.json', 'bare_os_hyper_multisig_trust_pointer.json', 'bare_os_hypercore_lengths.json', 'bare_os_hypercore_repair_hint.json', 'bare_os_hypercore_replicate_budget.json', 'bare_os_hypercore_signing_status.json', 'bare_os_hyperdb_readonly_index.json', 'bare_os_hyperdrive_sparse_index.json', 'bare_os_hypermininet_topology.json', 'bare_os_indexer_catchup.json', 'bare_os_initd_dag.json', 'bare_os_initd_graph.json', 'bare_os_ipc_backpressure.json', 'bare_os_kernel_program.json', 'bare_os_libmqjs_queue_depth.json', 'bare_os_locale.json', 'bare_os_manifest_hints', 'bare_os_metrics_live.json', 'bare_os_multisig_quorum_pointer.json', 'bare_os_net_qos_class.json', 'bare_os_net_summary.json', 'bare_os_oidc_publishing_pointer.json', 'bare_os_pear_api_allowlist_sketch.json', 'bare_os_pear_appling_manifest.json', 'bare_os_pear_build_fingerprint.json', 'bare_os_pear_doctor_state.json', 'bare_os_pear_drop_events.json', 'bare_os_pear_ipc_health.json', 'bare_os_pear_radio_state.json', 'bare_os_pear_rti_pointer.json', 'bare_os_pear_runtime_matrix.json', 'bare_os_pear_sidecar_bundle_index.json', 'bare_os_pear_stage_pointer.json', 'bare_os_pear_trust.json', 'bare_os_pear_updater_state.json', 'bare_os_pear_user_dirs_map.json', 'bare_os_pear_wakeups_schedule.json', 'bare_os_pear_workshop_flags.json', 'bare_os_peer_health', 'bare_os_protomux_backpressure.json', 'bare_os_protomux_channel_alias_v2.json', 'bare_os_protomux_channels.json', 'bare_os_protomux_rpc_pool_health.json', 'bare_os_provenance', 'bare_os_quotas', 'bare_os_react_native_bare_kit.json', 'bare_os_relay_geo_hint.json', 'bare_os_replication', 'bare_os_replication_backpressure.json', 'bare_os_resources', 'bare_os_rlimits.json', 'bare_os_rocksdb_pointer.json', 'bare_os_safe_sodium_buffer_policy.json', 'bare_os_sandbox_profile.json', 'bare_os_sandbox_worker_queue.json', 'bare_os_security_context.json', 'bare_os_security_posture.json', 'bare_os_seed_handshake', 'bare_os_session_stats', 'bare_os_sidecar_resource_cap.json', 'bare_os_slo_hints.json', 'bare_os_snapshot_hints', 'bare_os_snapshot_hints.json', 'bare_os_staging_slot', 'bare_os_storage_tier_hint.json', 'bare_os_structured_clone_budget_v2.json', 'bare_os_structured_clone_profile.json', 'bare_os_swarm', 'bare_os_sync_window.json', 'bare_os_udx_extended.json', 'bare_os_union', 'bare_os_updater_download_state.json', 'bare_os_version', 'bare_os_virtual_registry', 'bare_os_wave11_operator_slo_v2.json', 'bare_os_wave11_peer_qos_sketch.json', 'bare_os_worker_budget.json', 'cpuinfo', 'diskstats', 'loadavg', 'meminfo', 'mounts', 'net', 'self', 'uptime', 'version' ]) t.alike(await vfs.readdir('/proc/self').then((a) => [...a].sort()), [ 'cgroups', 'cmdline', 'environ', 'exe', 'fd', 'limits' ]) const ver = b4a.toString(await vfs.readFile('/proc/version')) t.ok(ver.includes('Bare OS')) t.ok(ver.includes('bare_os_ctx_api_version=1.2.3-test')) const sysVer = b4a.toString(await vfs.readFile('/sys/fs/bare_os/version')) t.ok(sysVer.includes('1.2.3-test')) const cmd = b4a.toString(await vfs.readFile('/proc/self/cmdline')) t.ok(cmd.includes('unit-test')) const mem = b4a.toString(await vfs.readFile('/proc/meminfo')) t.ok(mem.includes('MemTotal:')) const up = b4a.toString(await vfs.readFile('/proc/uptime')) t.ok(/^\d+\.\d+\s+\d+\.\d+/.test(up.trim())) const cpu = b4a.toString(await vfs.readFile('/proc/cpuinfo')) t.ok(cpu.includes('Bare OS pseudo CPU')) const la = b4a.toString(await vfs.readFile('/proc/loadavg')) t.ok(/^\d+\.\d+\s+\d+\.\d+\s+\d+\.\d+\s+/.test(la)) const exe = b4a.toString(await vfs.readFile('/proc/self/exe')) t.ok(exe.includes('pseudo inode')) const cg = b4a.toString(await vfs.readFile('/proc/self/cgroups')) t.ok(cg.includes('bare-os')) t.alike(await vfs.readdir('/proc/net').then((a) => [...a].sort()), [ 'dev', 'tcp', 'udp' ]) const tcp = b4a.toString(await vfs.readFile('/proc/net/tcp')) t.ok(tcp.includes('local_address')) const udp = b4a.toString(await vfs.readFile('/proc/net/udp')) t.ok(udp.includes('sl')) let mountsTxt = b4a.toString(await vfs.readFile('/proc/mounts')) t.ok(mountsTxt.includes('bare-os-root')) t.ok(mountsTxt.includes(' / hyperdrive ')) mntMap.set('vol', { drive: sys, writable: true }) mountsTxt = b4a.toString(await vfs.readFile('/proc/mounts')) t.ok(mountsTxt.includes('/mnt/vol')) t.ok(mountsTxt.includes('bare-os-vol')) t.alike(await vfs.readdir('/dev').then((a) => [...a].sort()), [ 'null', 'urandom', 'zero' ]) const ur = await vfs.readFile('/dev/urandom') t.ok(ur && ur.byteLength === 4096) await vfs.writeFile('/dev/null', b4a.from('gone')) t.is((await vfs.readFile('/dev/null'))?.byteLength ?? 0, 0) const z = await vfs.readFile('/dev/zero') t.ok(z && z.byteLength === 65536) t.alike(await vfs.readdir('/run/bare-os').then((a) => [...a].sort()), [ 'boot.json', 'boot_profile', 'ipc', 'ready', 'session', 'unit-journal', 'units', 'virtual' ]) t.alike(await vfs.readdir('/run/bare-os/ipc'), []) bareOsIpc.create('q1') t.alike(await vfs.readdir('/run/bare-os/ipc'), ['q1']) const readP = vfs.readFile('/run/bare-os/ipc/q1') const t0 = Date.now() await vfs.writeFile('/run/bare-os/ipc/q1', b4a.from('ping')) t.is(b4a.toString(await readP), 'ping') t.ok(Date.now() - t0 < 60000, 'kernel ipc ping-pong completes') await vfs.unlink('/run/bare-os/ipc/q1') t.alike(await vfs.readdir('/run/bare-os/ipc'), []) t.is(b4a.toString(await vfs.readFile('/run/bare-os/boot_profile')), 'mini\n') t.is( b4a.toString(await vfs.readFile('/run/bare-os/session')), 'test-session-id\n' ) const units = b4a.toString(await vfs.readFile('/run/bare-os/units')) t.ok(units.includes('demo-unit')) let writeErr = null try { await vfs.writeFile('/proc/version', b4a.from('x')) } catch (e) { writeErr = e } t.ok(writeErr) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs BARE_OS_HIDE_PROC_HYPERCORE_PACK_HRPC_LIFECYCLE=0 hides wave11 proc nodes', async (t) => { const dir = testCorestoreDir('vfsprocw11') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvprocw11')) await sys.ready() await personal.ready() const env = { HOME: '/home/guest', PWD: '/home/guest', PATH: '/bin', USER: 'guest', BARE_OS_HIDE_PROC_HYPERCORE_PACK_HRPC_LIFECYCLE: '0' } const mntMap = new Map() const vfs = createVfs(sys, personal, env, { getMounts: () => mntMap }, { procBareOsSwarmText: () => '{}\n' }) const flatW11 = Object.keys(BARE_OS_PROC_FILE_TO_ID_HYPERCORE_PACK_HRPC_LIFECYCLE).map((k) => k.endsWith('.json') ? k : `${k}.json` ) const bareOsW11 = Object.keys(BARE_OS_PROC_FILE_TO_ID_HYPERCORE_PACK_HRPC_LIFECYCLE).map((k) => { const base = k.startsWith('bare_os_') ? k.slice('bare_os_'.length) : k return base.endsWith('.json') ? base : `${base}.json` }) const procRoot = await vfs.readdir('/proc').then((a) => [...a]) for (const n of flatW11) { t.ok(!procRoot.includes(n), `flat ${n} should be hidden`) } const bo = await vfs.readdir('/proc/bare_os').then((a) => [...a]) for (const n of bareOsW11) { t.ok(!bo.includes(n), `bare_os/${n} should be hidden`) } t.is( await vfs.readFile('/proc/bare_os_hypercore_replicate_budget.json'), null ) const idxRaw = b4a.toString(await vfs.readFile('/proc/bare_os/index.json')) const idx = JSON.parse(idxRaw) t.ok(Array.isArray(idx.entries)) const names = new Set(idx.entries.map((e) => e.name)) t.ok(!names.has('hypercore_replicate_budget.json')) t.ok(!names.has('wave11_peer_qos_sketch.json')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs /proc/self/environ omits secret-like env keys', async (t) => { const dir = testCorestoreDir('vfsprocenv') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvpe')) await sys.ready() await personal.ready() const env = { HOME: '/home/guest', PWD: '/home/guest', PATH: '/bin', USER: 'guest', MY_PASSWORD: 'hunter2', BARE_OS_SAFE: 'visible' } const vfs = createVfs(sys, personal, env) const raw = b4a.toString(await vfs.readFile('/proc/self/environ')) t.ok(raw.includes('HOME=')) t.ok(raw.includes('BARE_OS_SAFE=')) t.ok(!raw.includes('MY_PASSWORD')) t.ok(!raw.includes('hunter2')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs /tmp maps to personal drive per HOME basename', async (t) => { const dir = testCorestoreDir('vfstmp') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvtmp')) await sys.ready() await personal.ready() const vfsGuest = createVfs(sys, personal, { HOME: '/home/guest', PWD: '/home/guest', PATH: '/bin' }) await vfsGuest.writeFile('/tmp/session.dat', b4a.from('g')) t.is(b4a.toString(await personal.get('/.bare-os/tmp/guest/session.dat')), 'g') const vfsUser = createVfs(sys, personal, { HOME: '/home/hexuserdead', PWD: '/home/hexuserdead', PATH: '/bin' }) t.is(await vfsUser.readFile('/tmp/session.dat'), null) await vfsUser.writeFile('/tmp/session.dat', b4a.from('u')) t.is( b4a.toString(await personal.get('/.bare-os/tmp/hexuserdead/session.dat')), 'u' ) t.is(b4a.toString(await personal.get('/.bare-os/tmp/guest/session.dat')), 'g') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs isolates home and /var/log per HOME basename on personal drive', async (t) => { const dir = testCorestoreDir('vfsisol') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvis')) await sys.ready() await personal.ready() const vfsGuest = createVfs(sys, personal, { HOME: '/home/guest', PWD: '/home/guest', PATH: '/bin' }) await vfsGuest.writeFile('shared-name.txt', b4a.from('guest-data')) await vfsGuest.writeFile('/var/log/bare-os/g.log', b4a.from('glog')) const vfsUser = createVfs(sys, personal, { HOME: '/home/alice12hex', PWD: '/home/alice12hex', PATH: '/bin' }) t.is(await vfsUser.readFile('/home/alice12hex/shared-name.txt'), null) await vfsUser.writeFile('shared-name.txt', b4a.from('user-data')) t.is( b4a.toString( await personal.get(personalHomeBacking('/home/guest', 'shared-name.txt')) ), 'guest-data' ) t.is( b4a.toString( await personal.get( personalHomeBacking('/home/alice12hex', 'shared-name.txt') ) ), 'user-data' ) t.is( b4a.toString(await personal.get('/.bare-os/var/log/guest/bare-os/g.log')), 'glog' ) await vfsUser.writeFile('/var/log/bare-os/u.log', b4a.from('ulog')) t.is( b4a.toString( await personal.get('/.bare-os/var/log/alice12hex/bare-os/u.log') ), 'ulog' ) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs /mnt lists HDMS mounts and allows writable put', async (t) => { const dir = testCorestoreDir('vfsmnt') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvm')) await sys.ready() await personal.ready() const env = { HOME: '/home/u', PWD: '/home/u', PATH: '/bin' } const extra = new Hyperdrive(store.namespace('exm', { writable: true })) await extra.ready() const mntRef = { getMounts: () => new Map([['vault', { drive: extra, writable: true }]]) } const vfs = createVfs(sys, personal, env, mntRef) const root = await vfs.readdir('/') t.ok(root.includes('mnt')) t.alike(await vfs.readdir('/mnt'), ['vault']) await vfs.writeFile('/mnt/vault/x.txt', b4a.from('ok')) const buf = await extra.get('/x.txt') t.ok(buf) t.is(b4a.toString(buf), 'ok') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs /var in root readdir; /var/log empty lstat; writes map to personal', async (t) => { const dir = testCorestoreDir('vfsvar') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvvar')) await sys.ready() await personal.ready() const env = { HOME: '/home/u', PWD: '/home/u', PATH: '/bin' } const vfs = createVfs(sys, personal, env) const root = await vfs.readdir('/') t.ok(root.includes('var')) t.alike(await vfs.readdir('/var'), ['log']) const stLog = await vfs.lstat('/var/log') t.ok(stLog) t.is(stLog.type, 'directory') await vfs.mkdir('/var/log/bare-os', { recursive: true }) await vfs.writeFile('/var/log/bare-os/test-vfs.log', b4a.from('hello')) const buf = await personal.get('/.bare-os/var/log/u/bare-os/test-vfs.log') t.ok(buf) t.is(b4a.toString(buf), 'hello') const sysTry = await sys.get('/.bare-os/var/log/u/bare-os/test-vfs.log') t.is(sysTry, null) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('vfs chdir /var/log from home', async (t) => { const dir = testCorestoreDir('vfsvarcd') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvcv')) await sys.ready() await personal.ready() const vfs = createVfs(sys, personal, { HOME: '/home/u', PWD: '/home/u', PATH: '/bin' }) await vfs.chdir('/var/log') t.is(vfs.getcwd(), '/var/log') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tokenize handles quotes and ops', async (t) => { const tok = tokenize('ls -la | cat > out') t.ok(tok.some((x) => x.type === 'op' && x.value === '|')) t.ok(tok.some((x) => x.type === 'op' && x.value === '>')) const w = tokenize("echo 'a b'") const words = w.filter((x) => x.type === 'word').map((x) => x.value) t.is(words.join(','), 'echo,a b') }) test('expandWord reads env', async (t) => { t.is(expandWord('x${HOME}y', { HOME: '/h' }), 'x/hy') }) test('expandWord $? and ${?} use BARE_OS_EXIT_STATUS', async (t) => { const env = { [BARE_OS_EXIT_STATUS_ENV]: '7', HOME: '/h' } t.is(expandWord('code=$?', env), 'code=7') t.is(expandWord('c=${?}', env), 'c=7') t.is(expandWord('missing=$?', {}), 'missing=0') }) test('expandWord param expansion v2 (## %% :=)', async (t) => { const base = { BARE_OS_SHELL_PARAM_EXPANSION: '1', BARE_OS_SHELL_PARAM_EXPANSION_V2: '1', P: '/usr/bin/foo', Q: 'caba' } t.is(expandWord('${P##*/}', base), 'foo') t.is(expandWord('${P#*/}', base), 'usr/bin/foo') t.is(expandWord('${Q%%ba}', base), 'ca') t.is(expandWord('${Q%ba}', base), 'ca') const assign = { ...base, EMPTY: '' } t.is(expandWord('${EMPTY:=set}', assign), 'set') t.is(assign.EMPTY, 'set') }) test('syncBareOsExitStatusEnv and execShellLine update env', async (t) => { const dir = testCorestoreDir('exstat') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pex')) await drive.ready() await personal.ready() await drive.put( '/bin/false', b4a.from(`async function run(ctx) { ctx.exitCode = 1 }`) ) await drive.put( '/bin/true', b4a.from(`async function run(ctx) { ctx.exitCode = 0 }`) ) const ctx = testCtx(drive, personal) ctx.exitCode = 0 syncBareOsExitStatusEnv(ctx) t.is(ctx.vfs.env[BARE_OS_EXIT_STATUS_ENV], '0') await execShellLine(ctx, 'false') t.is(ctx.vfs.env[BARE_OS_EXIT_STATUS_ENV], '1') await execShellLine(ctx, 'true') t.is(ctx.vfs.env[BARE_OS_EXIT_STATUS_ENV], '0') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('BARE_OS_CTX_API_VERSION is semver-shaped', async (t) => { t.ok(/^\d+\.\d+\.\d+$/.test(BARE_OS_CTX_API_VERSION)) }) test('getBareOsPipelineLimits reads BARE_OS_PIPELINE_* from env', async (t) => { const def = getBareOsPipelineLimits({}) t.is(def.maxStages, DEFAULT_PIPELINE_MAX_STAGES) const custom = getBareOsPipelineLimits({ BARE_OS_PIPELINE_MAX_STAGES: '4', BARE_OS_PIPELINE_MAX_BYTES: '100', BARE_OS_PIPELINE_MAX_LINES: '20' }) t.is(custom.maxStages, 4) t.is(custom.maxBytes, 100) t.is(custom.maxLines, 20) }) test('buildBareOsRuntimeCaps matches ctx API version and pipeline env', async (t) => { const caps = buildBareOsRuntimeCaps({ BARE_OS_PIPELINE_MAX_STAGES: '8', BARE_OS_CTX_API_VERSION }) t.is(caps.ctxApiVersion, BARE_OS_CTX_API_VERSION) t.is(caps.pipeline.maxStages, 8) t.ok(Array.isArray(caps.pseudoFsPaths)) t.ok(caps.pseudoFsPaths.includes('/proc/version')) t.ok(caps.pseudoFsPaths.includes('/run/bare-os/boot_profile')) t.ok(caps.pseudoFsPaths.includes('/run/bare-os/ipc')) t.ok(caps.pseudoFsPaths.includes('/run/bare-os/session')) t.ok(caps.pseudoFsPaths.includes('/proc/mounts')) t.ok(caps.pseudoFsPaths.includes('/proc/bare_os_resources')) t.ok(caps.pseudoFsPaths.includes('/run/bare-os/virtual')) t.ok(caps.pseudoFsPaths.includes('/run/bare-os/unit-journal')) t.ok(caps.pseudoFsPaths.includes('/snapshots')) t.ok(caps.pseudoFsPaths.includes('/snapshots/system')) t.is(caps.features.simulatedPipelines, true) t.is(caps.features.httpDelegate, true) t.is(caps.features.gitDelegate, true) t.is(caps.features.systemctlDelegate, true) t.is(caps.features.bareCtxModules, true) t.is(caps.features.bareDriveBundles, true) t.is(caps.features.bareHostImportsForCtx, true) const capsOff = buildBareOsRuntimeCaps({ BARE_OS_BARE_MODULES: '0' }) t.is(capsOff.features.bareCtxModules, false) t.is(capsOff.features.bareDriveBundles, false) t.is(capsOff.features.bareHostImportsForCtx, false) const capsIso = buildBareOsRuntimeCaps({ BARE_OS_BARE_HOST_IMPORTS: '0' }) t.is(capsIso.features.bareHostImportsForCtx, false) t.is(capsIso.features.bareCtxModules, true) }) test('bareOsBareModulesEnabled respects BARE_OS_BARE_MODULES', async (t) => { t.ok(bareOsBareModulesEnabled({})) t.ok(!bareOsBareModulesEnabled({ BARE_OS_BARE_MODULES: '0' })) t.ok(!bareOsBareModulesEnabled({ BARE_OS_BARE_MODULES: 'false' })) }) test('loadBareModuleManifest has entries', async (t) => { const m = loadBareModuleManifest() t.ok(m.version >= 1) t.ok(Array.isArray(m.entries)) t.ok(m.entries.some((e) => e.ctxKey === 'b4a')) }) test('buildBareCtxObjectFromHost loads core keys on Node', async (t) => { const target = {} await buildBareCtxObjectFromHost({}, target) t.ok(target.b4a) t.ok(target.compactEncoding) t.ok(target.protomux) }) test('maybeMergeBareFromDrive fills missing keys from bundle (mock vfs)', async (t) => { const repoRoot = path.join( fileURLToPath(new URL('.', import.meta.url)), '..', '..' ) const bundleAbs = path.join(repoRoot, 'kernel/lib/bare/bundles/b4a.js') const bundleSrc = await readFile(bundleAbs) const manifest = { version: 1, bundles: [{ path: '/lib/bare/bundles/b4a.js', keys: ['b4a'] }] } const target = {} const vfs = { async readFile(p) { if (p === '/lib/bare/manifest.json') return b4a.from(JSON.stringify(manifest)) if (p === '/lib/bare/bundles/b4a.js') return new Uint8Array(bundleSrc) return null } } await maybeMergeBareFromDrive({}, vfs, target) t.ok(target.b4a) }) test('expandArgvAliases expands first word and keeps trailing argv', async (t) => { t.alike(expandArgvAliases(['ll', 'z'], defaultShellAliases()), [ 'ls', '-la', 'z' ]) }) test('expandArgvAliases leaves sed unchanged', async (t) => { t.alike( expandArgvAliases(['sed', 's/a/b/', 'x.txt'], defaultShellAliases()), ['sed', 's/a/b/', 'x.txt'] ) }) test('defaultShellAliases does not remap sed', async (t) => { t.is(defaultShellAliases().sed, undefined) }) test('defaultShellAliases top maps to baretop', async (t) => { t.is(defaultShellAliases().top, 'baretop') }) test('defaultShellAliases btop maps to baretop', async (t) => { t.is(defaultShellAliases().btop, 'baretop') }) test('defaultShellAliases nano maps to edit', async (t) => { t.is(defaultShellAliases().nano, 'edit') t.alike(expandArgvAliases(['nano', 'x'], defaultShellAliases()), [ 'edit', 'x' ]) }) test('expandArgvAliases throws on cyclic alias chain', async (t) => { const cyclic = { a: 'b', b: 'a' } t.exception( () => expandArgvAliases(['a'], cyclic), /alias: expansion nested too deeply/ ) }) test('loadBarerc applies export and alias from personal ~/.barerc', async (t) => { const dir = testCorestoreDir('barerc') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('brc')) await drive.ready() await personal.ready() await personal.put( personalHomeBacking('/home/user', '.barerc'), b4a.from('export MYRC=1\nalias dog=echo woof\n') ) const ctx = testCtx(drive, personal) await loadBarerc(ctx) t.is(ctx.vfs.env.MYRC, '1') t.is(ctx.shellAliases.dog, 'echo woof') t.is(ctx.shellAliases.ll, 'ls -la') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('loadBarerc createSkeletonIfMissing writes ~/.barerc when absent', async (t) => { const dir = testCorestoreDir('barercskel') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('brcsk')) await drive.ready() await personal.ready() const ctx = testCtx(drive, personal) await loadBarerc(ctx, { createSkeletonIfMissing: true }) const back = await ctx.vfs.readFile('~/.barerc') t.ok(back) t.is(ctx.b4a.toString(back), BARERC_SKELETON) t.is(ctx.shellAliases.ll, 'ls -la') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('loadBarerc theme nord sets REPL color env and LS_COLORS', async (t) => { const dir = testCorestoreDir('barerctheme') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('brcth')) await drive.ready() await personal.ready() await personal.put( personalHomeBacking('/home/user', '.barerc'), b4a.from('theme nord\n') ) const ctx = testCtx(drive, personal) await loadBarerc(ctx) t.is(ctx.vfs.env.BARE_OS_THEME, 'nord') t.ok( String(ctx.vfs.env.BARE_OS_COLOR_PROMPT || '').includes('38;2;'), 'nord preset uses truecolor prompt' ) t.ok( String(ctx.vfs.env.LS_COLORS || '').includes('di='), 'LS_COLORS set from preset' ) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('execShellLine barerc reload reapplies barerc', async (t) => { const dir = testCorestoreDir('barercrel') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('brcrel')) await drive.ready() await personal.ready() await personal.put( personalHomeBacking('/home/user', '.barerc'), b4a.from('export MARK=before\n') ) const ctx = testCtx(drive, personal) await loadBarerc(ctx) t.is(ctx.vfs.env.MARK, 'before') await personal.put( personalHomeBacking('/home/user', '.barerc'), b4a.from('export MARK=after\n') ) await execShellLine(ctx, 'barerc reload') t.is(ctx.vfs.env.MARK, 'after') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('bareParseLsColors roundtrip', async (t) => { const s = 'di=01;34:ln=36:ex=32:*.tar=01;31' const m = bareParseLsColors(s) t.is(m.di, '01;34') t.is(m.ln, '36') t.alike(bareParseLsColors(bareSerializeLsColors(m)), m) }) test('bareLsColorOpenSgrFromMap directory and glob', async (t) => { const map = bareParseLsColors('di=01;34:*.md=00;32') const d = bareLsColorOpenSgrFromMap( { type: 'directory', mode: 0o040755 }, 'foo', map ) t.ok(d.startsWith('\x1b['), 'directory colored') const md = bareLsColorOpenSgrFromMap( { type: 'file', mode: 0o100644 }, 'README.md', map ) t.ok(md.includes('32'), 'markdown glob') }) test('bareLsColorOpenSgrFromMap mh for multi-link regular file', async (t) => { const map = bareParseLsColors('mh=01;44:fi=40;31') const one = bareLsColorOpenSgrFromMap( { type: 'file', mode: 0o100644, nlink: 1 }, 'a', map ) const two = bareLsColorOpenSgrFromMap( { type: 'file', mode: 0o100644, nlink: 2 }, 'a', map ) t.ok(two.includes('44'), 'nlink>1 uses mh SGR') t.ok(one.includes('31'), 'nlink 1 uses fi') }) test('bareLsColorOpenSgrFromMap ca when stat has capabilities', async (t) => { const map = bareParseLsColors('ca=30;41:fi=00') const sgr = bareLsColorOpenSgrFromMap( { type: 'file', mode: 0o100644, nlink: 1, capabilities: true }, 'cap', map ) t.ok(sgr.includes('41'), 'capabilities use ca') }) test('applyBareOsThemeFromEnv BARE_OS_COLOR_DEPTH=256 drops truecolor', async (t) => { const ctx = { vfs: { env: { BARE_OS_THEME: 'nord', BARE_OS_COLOR_DEPTH: '256' } } } await applyBareOsThemeFromEnv(ctx) const p = String(ctx.vfs.env.BARE_OS_COLOR_PROMPT || '') t.ok(p.includes('38;5;'), '256-color palette index SGR') t.ok(!p.includes('38;2;'), 'no RGB truecolor') }) test('dircolors -p includes TERM and di', async (t) => { const db = bareDefaultDircolorsDatabase() t.ok(db.includes('TERM')) t.ok(db.includes('di ')) }) test('bareParseDircolorsDatabase TERM block', async (t) => { const text = 'TERM xterm\ndi 01;34\nTERM none\nfi 00\nTERM *\nln 01;36\n' const m = bareParseDircolorsDatabase(text, 'xterm') t.is(m.di, '01;34') t.is(m.ln, '01;36') }) test('runBinCommand theme set writes barerc and updates env', async (t) => { const themePath = path.join(__dirname, '../../kernel/bin/theme') const themeSrc = await readFile(themePath, 'utf8') const dir = testCorestoreDir('themecmd') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('thcmd')) await drive.ready() await personal.ready() await drive.put('/bin/theme', b4a.from(themeSrc)) const ctx = testCtx(drive, personal) await loadBarerc(ctx) await runBinCommand(ctx, ['theme', 'set', 'dracula']) t.is(ctx.vfs.env.BARE_OS_THEME, 'dracula') const barc = ctx.b4a.toString(await ctx.vfs.readFile('~/.barerc')) t.ok(barc.includes('theme dracula')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand dircolors -p prints database', async (t) => { const dcPath = path.join(__dirname, '../../kernel/bin/dircolors') const dcSrc = await readFile(dcPath, 'utf8') const dir = testCorestoreDir('dircolp') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('dcp')) await drive.ready() await personal.ready() await drive.put('/bin/dircolors', b4a.from(dcSrc)) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await runBinCommand(ctx, ['dircolors', '-p']) const out = lines.join('\n') t.ok(out.includes('TERM')) t.ok(out.includes('di')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand edit --help prints usage', async (t) => { const editPath = path.join(__dirname, '../../kernel/bin/edit') const editSrc = await readFile(editPath, 'utf8') const dir = testCorestoreDir('edithlp') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('edh')) await drive.ready() await personal.ready() await drive.put('/bin/edit', b4a.from(editSrc)) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await runBinCommand(ctx, ['edit', '--help']) const out = lines.join('\n') t.ok(out.includes('usage:')) t.ok(out.includes('TTY')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand edit requires TTY', async (t) => { const editPath = path.join(__dirname, '../../kernel/bin/edit') const editSrc = await readFile(editPath, 'utf8') const dir = testCorestoreDir('ednotty') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('ednt')) await drive.ready() await personal.ready() await drive.put('/bin/edit', b4a.from(editSrc)) const lines = [] const ctx = testCtx(drive, personal) ctx.replStdin = { isTTY: false } ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await runBinCommand(ctx, ['edit', 'x.txt']) t.is(ctx.exitCode, 1) t.ok(lines.some((l) => l.includes('TTY'))) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand baretop --help prints usage', async (t) => { const binPath = path.join(__dirname, '../../kernel/bin/baretop') const src = await readFile(binPath, 'utf8') const dir = testCorestoreDir('baretophlp') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('bth')) await drive.ready() await personal.ready() await drive.put('/bin/baretop', b4a.from(src)) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await runBinCommand(ctx, ['baretop', '--help']) const out = lines.join('\n') t.ok(out.includes('usage:')) t.ok(out.includes('TTY')) t.ok(out.toLowerCase().includes('dashboard')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand baretop requires TTY', async (t) => { const binPath = path.join(__dirname, '../../kernel/bin/baretop') const src = await readFile(binPath, 'utf8') const dir = testCorestoreDir('baretopntty') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('btnt')) await drive.ready() await personal.ready() await drive.put('/bin/baretop', b4a.from(src)) const lines = [] const ctx = testCtx(drive, personal) ctx.replStdin = { isTTY: false } ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await runBinCommand(ctx, ['baretop']) t.is(ctx.exitCode, 1) t.ok(lines.some((l) => l.includes('TTY'))) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand nano --help matches edit bundle', async (t) => { const nanoPath = path.join(__dirname, '../../kernel/bin/nano') const nanoSrc = await readFile(nanoPath, 'utf8') const dir = testCorestoreDir('nanohlp') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('nanh')) await drive.ready() await personal.ready() await drive.put('/bin/nano', b4a.from(nanoSrc)) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await runBinCommand(ctx, ['nano', '-h']) const out = lines.join('\n') t.ok(out.includes('usage:')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tokenize leaves echo 2 > file as stdout redirect not 2>', async (t) => { const toks = tokenize('echo 2 > /tmp/x') const words = toks.filter((x) => x.type === 'word').map((x) => x.value) t.ok(words.includes('2')) t.ok(toks.some((x) => x.type === 'op' && x.value === '>')) t.ok(!toks.some((x) => x.type === 'op' && x.value === '2>')) }) test('execShellLine stderr 2> and 2>&1 in pipeline', async (t) => { const dir = testCorestoreDir('sherr') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('serr')) await drive.ready() await personal.ready() const emit = ` async function run(ctx) { ctx.console.log('OUT') ctx.console.error('ERR') } ` const cat = ` function bareStdin(ctx) { return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : '' } async function run(ctx) { ctx.console.log(bareStdin(ctx).replace(/\\n$/, '')) } ` await drive.put('/bin/emit', b4a.from(emit)) await drive.put('/bin/cat', b4a.from(cat)) const ctx = testCtx(drive, personal) await execShellLine(ctx, 'emit 2>~/e.out') const eb = await ctx.vfs.readFile('~/e.out') t.ok(eb && ctx.b4a.toString(eb).includes('ERR')) t.ok(!ctx.b4a.toString(eb).includes('OUT')) await ctx.vfs.unlink('~/e.out') const logs = [] ctx.console = { log: (...a) => logs.push(['out', ...a]), error: (...a) => logs.push(['err', ...a]) } await execShellLine(ctx, 'emit 2>&1 | cat') const piped = logs .filter((x) => x[0] === 'out') .map((x) => x.slice(1).join(' ')) t.ok(piped.some((l) => l.includes('OUT') && l.includes('ERR'))) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('execShellLine pipeline stage and byte limits', async (t) => { const dir = testCorestoreDir('shpipe') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('spipe')) await drive.ready() await personal.ready() const echo = ` async function run(ctx, argv) { ctx.console.log(argv.slice(1).join(' ')) } ` const cat = ` function bareStdin(ctx) { return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : '' } async function run(ctx) { ctx.console.log(bareStdin(ctx).replace(/\\n$/, '')) } ` await drive.put('/bin/echo', b4a.from(echo)) await drive.put('/bin/cat', b4a.from(cat)) const spam = ` async function run(ctx) { ctx.console.log('z'.repeat(200)) } ` await drive.put('/bin/spam', b4a.from(spam)) const logs = [] const ctx = testCtx(drive, personal) ctx.console = { log: (...a) => logs.push(a.join(' ')), error: (...a) => logs.push(a.join(' ')) } ctx.env.BARE_OS_PIPELINE_MAX_STAGES = '2' await execShellLine(ctx, 'echo a | echo b | echo c') t.is(ctx.exitCode, 1) t.ok(logs.some((l) => l.includes('BARE_OS_PIPELINE_MAX_STAGES'))) logs.length = 0 ctx.env.BARE_OS_PIPELINE_MAX_STAGES = '32' ctx.env.BARE_OS_PIPELINE_MAX_BYTES = '80' await execShellLine(ctx, 'spam | cat') t.is(ctx.exitCode, 1) t.ok(logs.some((l) => l.includes('BARE_OS_PIPELINE_MAX_BYTES'))) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('ls bareOsStdoutCaptured lists one name per line', async (t) => { const lsPath = path.join(__dirname, '../../kernel/bin/ls') const lsSrc = await readFile(lsPath, 'utf8') const dir = testCorestoreDir('lscap') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('plcap')) await drive.ready() await personal.ready() await drive.put('/bin/ls', b4a.from(lsSrc)) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await ctx.vfs.writeFile('aaa', b4a.from('')) await ctx.vfs.writeFile('lib', b4a.from('')) await ctx.vfs.writeFile('zzz', b4a.from('')) await runBinCommand(Object.assign({}, ctx, { bareOsStdoutCaptured: true }), [ 'ls' ]) t.is(lines.length, 3) t.ok(lines.includes('aaa') && lines.includes('lib') && lines.includes('zzz')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('execShellLine ls pipe grep prints only matching entry line', async (t) => { const lsPath = path.join(__dirname, '../../kernel/bin/ls') const grepPath = path.join(__dirname, '../../kernel/bin/grep') const lsSrc = await readFile(lsPath, 'utf8') const grepSrc = await readFile(grepPath, 'utf8') const dir = testCorestoreDir('lspipegrep') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('plpg')) await drive.ready() await personal.ready() await drive.put('/bin/ls', b4a.from(lsSrc)) await drive.put('/bin/grep', b4a.from(grepSrc)) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await ctx.vfs.writeFile('aaa', b4a.from('')) await ctx.vfs.writeFile('lib', b4a.from('')) await ctx.vfs.writeFile('zzz', b4a.from('')) await execShellLine(ctx, 'ls | grep -F lib') t.is(ctx.exitCode, 0) t.alike(lines, ['lib']) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('execShellLine ls pipe wc -l counts lines', async (t) => { const lsPath = path.join(__dirname, '../../kernel/bin/ls') const wcPath = path.join(__dirname, '../../kernel/bin/wc') const lsSrc = await readFile(lsPath, 'utf8') const wcSrc = await readFile(wcPath, 'utf8') const dir = testCorestoreDir('lspipewc') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('plwc')) await drive.ready() await personal.ready() await drive.put('/bin/ls', b4a.from(lsSrc)) await drive.put('/bin/wc', b4a.from(wcSrc)) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await ctx.vfs.writeFile('a', b4a.from('')) await ctx.vfs.writeFile('b', b4a.from('')) await ctx.vfs.writeFile('c', b4a.from('')) await execShellLine(ctx, 'ls | wc -l') t.is(ctx.exitCode, 0) const out = lines.join('\n').trim() t.is(out, '3', 'three directory entries => three lines') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('execShellLine runs cd and external', async (t) => { const dir = testCorestoreDir('sh') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('psh')) await drive.ready() await personal.ready() await drive.put( '/bin/xy', b4a.from(` async function run(ctx, argv) { ctx.got.push(argv.join(' ')) } `) ) const got = [] const ctx = testCtx(drive, personal) ctx.got = got await execShellLine(ctx, 'cd /bin') t.is(ctx.vfs.getcwd(), '/bin') await execShellLine(ctx, 'xy one two') t.is(got[0], 'xy one two') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('execShellLine expands default ll to ls -la', async (t) => { const dir = testCorestoreDir('llalias') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('lla')) await drive.ready() await personal.ready() await drive.put( '/bin/ls', b4a.from(` async function run(ctx, argv) { ctx.got.push(argv.join(' ')) } `) ) const got = [] const ctx = testCtx(drive, personal) ctx.got = got await execShellLine(ctx, 'll one') t.is(got[0], 'ls -la one') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tokenize && || ; and split helpers', async (t) => { const toks = tokenize('a&&b||c;d') t.is(toks.map((x) => x.value).join(' '), 'a && b || c ; d') const lists = splitTokensBySemicolon(toks) t.is(lists.length, 2) const { segments, ops } = splitTokensByAndOr(lists[0]) t.is(segments.length, 3) t.is(ops.join(' '), '&& ||') }) test('execShellLine && || ; short-circuit and exitCode', async (t) => { const dir = testCorestoreDir('shandor') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('sand')) await drive.ready() await personal.ready() const stub = ` async function run(ctx, argv) { const c = argv[0] ctx.ran.push(c) ctx.exitCode = c === 'false' ? 1 : 0 } ` await drive.put('/bin/true', b4a.from(stub)) await drive.put('/bin/false', b4a.from(stub)) await drive.put( '/bin/rec', b4a.from(` async function run(ctx, argv) { ctx.ran.push('rec') ctx.exitCode = 0 } `) ) const ran = [] const ctx = testCtx(drive, personal) ctx.ran = ran ctx.exitCode = 0 await execShellLine(ctx, 'false && rec') t.is(ran.join(','), 'false') t.is(ctx.exitCode, 1) ran.length = 0 ctx.exitCode = 0 await execShellLine(ctx, 'false || rec') t.is(ran.join(','), 'false,rec') t.is(ctx.exitCode, 0) ran.length = 0 ctx.exitCode = 0 await execShellLine(ctx, 'true && rec') t.is(ran.join(','), 'true,rec') t.is(ctx.exitCode, 0) ran.length = 0 ctx.exitCode = 0 await execShellLine(ctx, 'true || rec') t.is(ran.join(','), 'true') t.is(ctx.exitCode, 0) ran.length = 0 ctx.exitCode = 0 await execShellLine(ctx, 'false || false || rec') t.is(ran.join(','), 'false,false,rec') t.is(ctx.exitCode, 0) ran.length = 0 ctx.exitCode = 0 await execShellLine(ctx, 'true && false || rec') t.is(ran.join(','), 'true,false,rec') t.is(ctx.exitCode, 0) ran.length = 0 ctx.exitCode = 0 await execShellLine(ctx, 'true; rec') t.is(ran.join(','), 'true,rec') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('execShellLine if then else fi', async (t) => { const dir = testCorestoreDir('shif') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('sif')) await drive.ready() await personal.ready() await drive.put( '/bin/echo', b4a.from(` async function run(ctx, argv) { ctx.console.log(argv.slice(1).join(' ')) } `) ) await drive.put( '/bin/true', b4a.from(` async function run(ctx) { ctx.exitCode = 0 } `) ) await drive.put( '/bin/false', b4a.from(` async function run(ctx) { ctx.exitCode = 1 } `) ) const lines = [] const ctx = testCtx(drive, personal) ctx.console = { log: (s) => lines.push(String(s)), error: (...a) => lines.push(a.join(' ')) } await execShellLine(ctx, 'if false; then echo no; else echo yes; fi') t.ok(lines.some((l) => l.includes('yes'))) lines.length = 0 await execShellLine(ctx, 'if true; then echo ok; fi') t.ok(lines.some((l) => l.includes('ok'))) lines.length = 0 await execShellLine(ctx, 'if false; then echo x; fi') t.ok(!lines.some((l) => l.includes('x'))) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('filenameFromContentDisposition parses attachment names', async (t) => { t.is( filenameFromContentDisposition('attachment; filename="a b.txt"'), 'a b.txt' ) t.is( filenameFromContentDisposition("attachment; filename*=UTF-8''x%20y.bin"), 'x y.bin' ) t.is(filenameFromContentDisposition(null), null) }) test('cron fieldMatches and dowFieldMatches', async (t) => { t.ok(fieldMatches('*', 0, 0, 59)) t.ok(fieldMatches('*/5', 10, 0, 59)) t.ok(!fieldMatches('*/5', 11, 0, 59)) t.ok(fieldMatches('1-3', 2, 0, 59)) t.ok(!fieldMatches('1-3', 4, 0, 59)) t.ok(fieldMatches('1,4', 1, 0, 59)) t.ok(fieldMatches('1,4', 4, 0, 59)) t.ok(fieldMatches('1-10/2', 3, 0, 59)) t.ok(!fieldMatches('1-10/2', 4, 0, 59)) t.ok(dowFieldMatches('7', 0)) t.ok(!dowFieldMatches('7', 1)) t.ok(dowFieldMatches('0', 0)) t.ok(dowFieldMatches('1-5', 3)) }) test('cron parseCronLine and jobMatchesDate', async (t) => { t.absent(parseCronLine('')) t.absent(parseCronLine('# comment')) t.absent(parseCronLine('0 0 * *')) const j = parseCronLine('30 14 15 6 * echo hello world') t.ok(j) t.is(j.command, 'echo hello world') const when = new Date(2020, 5, 15, 14, 30, 0) t.ok(jobMatchesDate(j, when)) t.ok(!jobMatchesDate(j, new Date(2020, 5, 15, 14, 31, 0))) const reboot = parseCronLine('@reboot echo hi') t.ok(reboot) t.is(reboot.minute, '@reboot') t.is(reboot.command, 'echo hi') t.ok(!jobMatchesDate(reboot, when)) const jit = parseCronLine('@reboot JitterSec=12 /bin/true') t.ok(jit) t.is(jit.jitterSec, 12) t.is(jit.command, '/bin/true') const jl = parseCronLine('* * * * * JitterSec=3 echo x') t.ok(jl) t.is(jl.jitterSec, 3) t.is(jl.command, 'echo x') }) test('systemctl list after startBareInitd shows kernel-logger and bare-cron', async (t) => { const dir = testCorestoreDir('initctl') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pinit')) await sys.ready() await personal.ready() const logs = [] const ctx = testCtx(sys, personal) ctx.execLine = async () => {} await startBareInitd(ctx) ctx.console = { log: (...a) => logs.push(a.join(' ')), error: (...a) => logs.push(a.join(' ')) } ctx.exitCode = 0 await runBinCommand(ctx, ['systemctl', 'list']) t.is(ctx.exitCode, 0) const text = logs.join('\n') t.ok(text.includes('kernel-logger')) t.ok(text.includes('bare-cron')) stopBareInitd() await store.close() rmSync(dir, { recursive: true, force: true }) }) test('systemctl list-units delegates to same backend', async (t) => { const dir = testCorestoreDir('initctlsys') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pics')) await sys.ready() await personal.ready() const logs = [] const ctx = testCtx(sys, personal) ctx.execLine = async () => {} await startBareInitd(ctx) ctx.console = { log: (...a) => logs.push(a.join(' ')), error: (...a) => logs.push(a.join(' ')) } ctx.exitCode = 0 await runBinCommand(ctx, ['systemctl', 'list-units']) t.is(ctx.exitCode, 0) t.ok(logs.join('\n').includes('bare-cron')) stopBareInitd() await store.close() rmSync(dir, { recursive: true, force: true }) }) test('systemctl is-active matches bare-initd runtime', async (t) => { const dir = testCorestoreDir('initctlactive') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pica')) await sys.ready() await personal.ready() const logs = [] const ctx = testCtx(sys, personal) ctx.execLine = async () => {} await startBareInitd(ctx) ctx.console = { log: (...a) => logs.push(a.join(' ')), error: (...a) => logs.push(a.join(' ')) } ctx.exitCode = 0 await runBinCommand(ctx, ['systemctl', 'is-active', 'kernel-logger']) t.is(ctx.exitCode, 0) t.ok(logs.join('\n').includes('active')) logs.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['systemctl', 'is-active', 'nonexistent-unit']) t.is(ctx.exitCode, 3) stopBareInitd() await store.close() rmSync(dir, { recursive: true, force: true }) }) test('systemctl restart bare-cron succeeds', async (t) => { const dir = testCorestoreDir('initctlrst') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('picr')) await sys.ready() await personal.ready() const logs = [] const ctx = testCtx(sys, personal) ctx.execLine = async () => {} await startBareInitd(ctx) ctx.console = { log: (...a) => logs.push(a.join(' ')), error: (...a) => logs.push(a.join(' ')) } ctx.exitCode = 0 await runBinCommand(ctx, ['systemctl', 'restart', 'bare-cron']) t.is(ctx.exitCode, 0) t.ok(logs.some((l) => /restarted bare-cron/i.test(l))) stopBareInitd() await store.close() rmSync(dir, { recursive: true, force: true }) }) test('initd disabled.txt skips unit on boot; systemctl enable undoes', async (t) => { const dir = testCorestoreDir('initdis') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pdis')) await sys.ready() await personal.ready() const ctx = testCtx(sys, personal) ctx.execLine = async () => {} await ctx.vfs.mkdir('/home/user/.config/bare-os/initd', { recursive: true }) await ctx.vfs.writeFile( '/home/user/.config/bare-os/initd/disabled.txt', b4a.from('bare-cron\n') ) await startBareInitd(ctx) t.is(getBareServiceRuntime('bare-cron'), undefined) t.is(getBareServiceRuntime('kernel-logger')?.phase, 'active') stopBareInitd() ctx.exitCode = 0 ctx.console = { log: () => {}, error: () => {} } await runBinCommand(ctx, ['systemctl', 'enable', 'bare-cron']) t.is(ctx.exitCode, 0) await startBareInitd(ctx) t.is(getBareServiceRuntime('bare-cron')?.phase, 'active') stopBareInitd() await store.close() rmSync(dir, { recursive: true, force: true }) }) test('stopBareInitd runs registered disposers', async (t) => { let n = 0 registerBareInitdDisposer(() => { n++ }) stopBareInitd() t.is(n, 1) stopBareInitd() t.is(n, 2) }) test('runKernelShutdownHooks runs LIFO once', async (t) => { const o = [] registerKernelShutdownHook(async () => { o.push('a') }) registerKernelShutdownHook(async () => { o.push('b') }) await runKernelShutdownHooks() t.is(o.join(','), 'b,a') await runKernelShutdownHooks() t.is(o.join(','), 'b,a') }) test('fish-readline stripAnsi and fuzzyMatch', async (t) => { t.is(stripAnsi('\x1b[32mhi\x1b[0m'), 'hi') t.ok(fuzzyMatch('hello', 'hlo')) t.ok(!fuzzyMatch('hello', 'hxo')) }) test('fish-readline history parse format dedupe search', async (t) => { const parsed = parseHistoryFile('#1:a\n#2:b\n') t.is(parsed.length, 2) t.is(parsed[0].command, 'a') const round = parseHistoryFile(formatHistoryFile(parsed)) t.is(round[1].command, 'b') const deduped = dedupeConsecutiveHistory([ { timestamp: 1, command: 'x' }, { timestamp: 2, command: 'x' }, { timestamp: 3, command: 'y' } ]) t.is(deduped.length, 2) t.is(deduped[1].command, 'y') const hist = [{ command: 'aa' }, { command: 'ba' }] const found = searchHistoryEntries(hist, 'a') t.ok(found.includes('ba')) t.ok(found.includes('aa')) }) test('tier-1 cat from system drive', async (t) => { const dir = testCorestoreDir('cat') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pc')) await drive.ready() await personal.ready() await drive.put('/bin/cat', b4a.from(await readBuiltBin('cat'))) await drive.put('/etc/x', b4a.from('hello')) const ctx = testCtx(drive, personal) ctx.console = { log() {}, error() {} } const catOut = [] const prevCatWrite = process.stdout.write process.stdout.write = (chunk) => { catOut.push( typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8') ) return true } try { await runBinCommand(ctx, ['cat', '/etc/x']) } finally { process.stdout.write = prevCatWrite } t.is(catOut.join(''), 'hello') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-1 tail head options and tail -f poll', async (t) => { const dir = testCorestoreDir('tail-head') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pth')) await drive.ready() await personal.ready() await drive.put('/bin/tail', b4a.from(await readBuiltBin('tail'))) await drive.put('/bin/head', b4a.from(await readBuiltBin('head'))) const lines = [] const ctx = testCtx(drive, personal, { BARE_OS_TAIL_F_POLL_MS: '25', BARE_OS_TAIL_F_MAX_ROUNDS: '8' }) ctx.exitCode = 0 ctx.bareOsRuntimeCaps = buildBareOsRuntimeCaps(ctx.env) ctx.console = { log(s) { lines.push(String(s)) }, error() {} } await ctx.vfs.writeFile('t.txt', b4a.from('one\ntwo\nthree\n')) await runBinCommand(ctx, ['tail', '-n', '2', 't.txt']) t.is(ctx.exitCode, 0) t.is(lines.join('\n'), 'two\nthree') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['tail', '-n', '+2', 't.txt']) t.is(lines.join('\n'), 'two\nthree') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['head', '-c', '4', 't.txt']) t.is(lines[0], 'one\n') lines.length = 0 ctx.exitCode = 0 await ctx.vfs.writeFile('f.log', b4a.from('a\n')) const tailP = runBinCommand(ctx, ['tail', '-f', 'f.log']) await new Promise((r) => setTimeout(r, 15)) const cur = b4a.toString(await ctx.vfs.readFile('f.log')) await ctx.vfs.writeFile('f.log', b4a.from(cur + 'b\n')) await tailP t.ok(lines.includes('a')) t.ok(lines.includes('b')) lines.length = 0 ctx.exitCode = 0 ctx.shellStdin = 'x\ny\n' await runBinCommand(ctx, ['tail', '-f']) t.is(ctx.exitCode, 1) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-1 grep and mkfifo from system drive', async (t) => { const dir = testCorestoreDir('grep') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pg')) await drive.ready() await personal.ready() await drive.put('/bin/grep', b4a.from(await readBuiltBin('grep'))) await drive.put('/bin/mkfifo', b4a.from(await readBuiltBin('mkfifo'))) const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error() {} } await ctx.vfs.writeFile( 'w.txt', b4a.from('aaa\nneedle line\nbbb\nneedle line two') ) await runBinCommand(ctx, ['grep', '-F', 'needle', 'w.txt']) t.is(ctx.exitCode, 0) t.is(lines.length, 2) t.ok(lines[0].includes('needle line')) t.ok(lines[1].includes('needle line two')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['grep', '-F', 'nomatch', 'w.txt']) t.is(ctx.exitCode, 1) t.is(lines.length, 0) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['grep', '-v', '-F', 'needle', 'w.txt']) t.is(ctx.exitCode, 0) t.is(lines.join('\n'), 'aaa\nbbb') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['grep', '-c', '-F', 'needle', 'w.txt']) t.is(ctx.exitCode, 0) t.is(lines[0], '2') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['grep', '-n', '-F', 'bbb', 'w.txt']) t.is(ctx.exitCode, 0) t.is(lines[0], '3:bbb') lines.length = 0 ctx.exitCode = 0 ctx.shellStdin = 'alpha\nbeta\n' await runBinCommand(ctx, ['grep', '-F', 'beta']) t.is(ctx.exitCode, 0) t.is(lines[0], 'beta') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['grep', '-x', '-F', 'aaa', 'w.txt']) t.is(ctx.exitCode, 0) t.is(lines[0], 'aaa') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['grep', '-m', '1', '-F', 'needle', 'w.txt']) t.is(ctx.exitCode, 0) t.is(lines.length, 1) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['grep', '-o', 'ee', 'w.txt']) t.is(ctx.exitCode, 0) t.ok(lines.includes('ee')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['mkfifo', '/run/bare-os/ipc/t1']) t.is(ctx.exitCode, 0) const readP = ctx.vfs.readFile('/run/bare-os/ipc/t1') await ctx.vfs.writeFile('/run/bare-os/ipc/t1', b4a.from('ok')) t.is(b4a.toString(await readP), 'ok') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['grep', '-F', '-C', '1', 'needle', 'w.txt']) t.is(ctx.exitCode, 0) t.ok(lines.some((l) => l === 'aaa')) t.ok(lines.some((l) => l.includes('needle line'))) t.ok(lines.some((l) => l === 'bbb')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-1 sort and wc flags', async (t) => { const dir = testCorestoreDir('sort-wc') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('psw')) await drive.ready() await personal.ready() await drive.put('/bin/sort', b4a.from(await readBuiltBin('sort'))) await drive.put('/bin/wc', b4a.from(await readBuiltBin('wc'))) const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error() {} } await ctx.vfs.writeFile('nums.txt', b4a.from('10\n2\n1\n')) await runBinCommand(ctx, ['sort', '-n', 'nums.txt']) t.is(lines.join('\n'), '1\n2\n10') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['sort', '-nru', 'nums.txt']) t.is(lines.join('\n'), '10\n2\n1') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['wc', '-l', 'nums.txt']) t.is(lines[0].trim(), '3 nums.txt') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['wc', '-c', 'nums.txt']) t.is(lines[0], ' 7 nums.txt') const errs = [] ctx.console = { log(s) { lines.push(String(s)) }, error(...a) { errs.push(a.join(' ')) } } await ctx.vfs.writeFile('ord.txt', b4a.from('a\nb\nc\n')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['sort', '-c', 'ord.txt']) t.is(ctx.exitCode, 0) t.is(errs.length, 0) await ctx.vfs.writeFile('bad.txt', b4a.from('b\na\n')) lines.length = 0 errs.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['sort', '-c', 'bad.txt']) t.is(ctx.exitCode, 1) t.ok(errs.some((e) => e.includes('disorder'))) errs.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['sort', '-C', 'bad.txt']) t.is(ctx.exitCode, 1) t.is(errs.length, 0) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['sort', '-o', 'sorted.txt', '-n', 'nums.txt']) t.is(ctx.exitCode, 0) const sortedBuf = await ctx.vfs.readFile('sorted.txt') t.is(ctx.b4a.toString(sortedBuf), '1\n2\n10\n') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['sort', '-s', 'ord.txt']) t.is(lines.join('\n'), 'a\nb\nc') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-1 find du basename options', async (t) => { const dir = testCorestoreDir('fdu-base') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pfdb')) await drive.ready() await personal.ready() await drive.put('/bin/find', b4a.from(await readBuiltBin('find'))) await drive.put('/bin/du', b4a.from(await readBuiltBin('du'))) await drive.put('/bin/basename', b4a.from(await readBuiltBin('basename'))) const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error() {} } await ctx.vfs.writeFile('Lo.txt', b4a.from('ab')) await runBinCommand(ctx, ['find', '.', '-iname', 'lo.txt']) t.is(ctx.exitCode, 0) t.ok(lines.some((p) => /Lo\.txt$/.test(String(p).replace(/\\/g, '/')))) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['du', '-h', 'Lo.txt']) t.ok(/^2\tLo\.txt$/.test(lines[0]) || /^3\tLo\.txt$/.test(lines[0])) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['basename', '-a', '/x/a', '/y/b']) t.is(lines.join('\n'), 'a\nb') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['basename', 'z.h', '.h']) t.is(lines[0], 'z') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('execShellLine find pipes to wc -l', async (t) => { const dir = testCorestoreDir('findpipewc') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('fpwc')) await drive.ready() await personal.ready() await drive.put('/bin/find', b4a.from(await readBuiltBin('find'))) await drive.put('/bin/wc', b4a.from(await readBuiltBin('wc'))) const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error() {} } await ctx.vfs.writeFile('p.txt', b4a.from('')) await execShellLine(ctx, 'find . -maxdepth 1 | wc -l') t.is(ctx.exitCode, 0) const n = Number.parseInt(String(lines[0] || '').trim(), 10) t.ok(Number.isFinite(n) && n >= 1) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-1 date format and test numeric', async (t) => { const dir = testCorestoreDir('date-test') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pdt')) await drive.ready() await personal.ready() await drive.put('/bin/date', b4a.from(await readBuiltBin('date'))) await drive.put('/bin/test', b4a.from(await readBuiltBin('test'))) const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error() {} } await runBinCommand(ctx, ['test', '2', '-lt', '5']) t.is(ctx.exitCode, 0) await runBinCommand(ctx, ['test', '5', '-lt', '2']) t.is(ctx.exitCode, 1) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['date', '+%Y']) t.is(ctx.exitCode, 0) t.ok(/^\d{4}$/.test(lines[0])) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-1 find -mindepth skips shallow paths', async (t) => { const dir = testCorestoreDir('find-mindepth') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pfindmd')) await drive.ready() await personal.ready() await drive.put('/bin/find', b4a.from(await readBuiltBin('find'))) const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error() {} } await ctx.vfs.mkdir('nest', { recursive: true }) await ctx.vfs.mkdir('nest/sub', { recursive: true }) await ctx.vfs.writeFile('nest/a.txt', b4a.from('a')) await ctx.vfs.writeFile('nest/sub/b.txt', b4a.from('b')) await runBinCommand(ctx, ['find', '.', '-mindepth', '2', '-type', 'f']) t.is(ctx.exitCode, 0) const norm = lines.map((p) => p.replace(/\\/g, '/')).sort() t.ok(norm.some((p) => p.endsWith('/nest/a.txt'))) t.ok(norm.some((p) => p.endsWith('/nest/sub/b.txt'))) lines.length = 0 await runBinCommand(ctx, ['find', 'nest', '-mindepth', '2', '-type', 'f']) t.is(ctx.exitCode, 0) t.ok( lines.some((p) => String(p).replace(/\\/g, '/').endsWith('/nest/sub/b.txt')) ) t.ok( !lines.some((p) => String(p).replace(/\\/g, '/').endsWith('/nest/a.txt')) ) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-1 jq from system drive', async (t) => { const dir = testCorestoreDir('jq') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pjq')) await drive.ready() await personal.ready() await drive.put('/bin/jq', b4a.from(await readBuiltBin('jq'))) const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error() {} } await ctx.vfs.writeFile('data.json', b4a.from('{"x":42,"name":"hi"}')) await runBinCommand(ctx, ['jq', '.x', 'data.json']) t.is(ctx.exitCode, 0) t.is(lines[0], '42') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['jq', '-c', '.', 'data.json']) t.is(ctx.exitCode, 0) t.is(lines[0], '{"x":42,"name":"hi"}') lines.length = 0 ctx.exitCode = 0 ctx.shellStdin = '{"a":1}' await runBinCommand(ctx, ['jq', '.a']) t.is(ctx.exitCode, 0) t.is(lines[0], '1') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-1 getconf and xargs from system drive', async (t) => { const dir = testCorestoreDir('gxc') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pgx')) await drive.ready() await personal.ready() await drive.put('/bin/getconf', b4a.from(await readBuiltBin('getconf'))) await drive.put( '/bin/echolog', b4a.from(` async function run(ctx, argv) { ctx.console.log(argv.slice(1).join(' ')) } `) ) await drive.put('/bin/xargs', b4a.from(await readBuiltBin('xargs'))) await drive.put('/bin/false', b4a.from(await readBuiltBin('false'))) await drive.put('/bin/printf', b4a.from(await readBuiltBin('printf'))) const lines = [] const ctx = testCtx(drive, personal) ctx.runBinCommand = (argv) => runBinCommand(ctx, argv) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error(s) { lines.push(String(s)) } } await runBinCommand(ctx, ['getconf', 'PATH_MAX']) t.is(ctx.exitCode, 0) t.is(lines.pop(), '4096') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['getconf', 'BARE_OS_YES_MAX_LINES']) t.is(ctx.exitCode, 0) t.is(lines.pop(), '100000') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['getconf', 'NOT_A_REAL_CONF_NAME']) t.is(ctx.exitCode, 1) lines.length = 0 ctx.exitCode = 0 ctx.shellStdin = 'hello\tworld\n' await runBinCommand(ctx, ['xargs', 'echolog']) t.is(ctx.exitCode, 0) t.is(lines.join('\n'), 'hello world') lines.length = 0 ctx.exitCode = 0 ctx.shellStdin = 'a\0b\0' await runBinCommand(ctx, ['xargs', '-0', '-n1', 'echolog']) t.is(ctx.exitCode, 0) t.is(lines.join('\n'), 'a\nb') lines.length = 0 ctx.exitCode = 0 ctx.shellStdin = 'one\ntwo\n' await runBinCommand(ctx, ['xargs', '-I', '{}', 'echolog', 'x', '{}', 'y']) t.is(ctx.exitCode, 0) t.is(lines.join('\n'), 'x one y\nx two y') lines.length = 0 ctx.exitCode = 0 ctx.shellStdin = '' await execShellLine(ctx, 'false || printf recovered') t.is(lines.pop(), 'recovered') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-2 cat env touch mkdir', async (t) => { const dir = testCorestoreDir('tier2tem') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pt2')) await drive.ready() await personal.ready() for (const name of ['cat', 'env', 'touch', 'mkdir', 'printf']) { await drive.put('/bin/' + name, b4a.from(await readBuiltBin(name))) } const catOut = [] const lines = [] const ctx = testCtx(drive, personal, { MARK: 'parent', HELLO: 'world' }) ctx.exitCode = 0 ctx.runBinCommand = function (argv, o) { return runBinCommand(this, argv, o) } ctx.console = { log(s) { lines.push(String(s)) }, error(s) { lines.push('e:' + String(s)) } } await ctx.vfs.chdir('/home/user') await ctx.vfs.writeFile('plain.txt', b4a.from('a\nb\n')) const captureCat = async (argv) => { catOut.length = 0 const prevWrite = process.stdout.write process.stdout.write = (chunk) => { catOut.push( typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8') ) return true } try { ctx.exitCode = 0 await runBinCommand(ctx, argv) } finally { process.stdout.write = prevWrite } } await captureCat(['cat', '-n', 'plain.txt']) t.is(ctx.exitCode, 0) t.is(catOut.join(''), ' 1\ta\n 2\tb\n') await captureCat(['cat', '-A', 'plain.txt']) t.is(ctx.exitCode, 0) t.is(catOut.join(''), 'a$\nb$\n') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, [ 'env', '-i', 'PATH=/bin', 'HELLO=there', 'printf', '%s', 'ok' ]) t.is(ctx.exitCode, 0) t.is(lines.join('\n'), 'ok') t.is(ctx.vfs.env.MARK, 'parent') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['touch', '-d', '@3600', 'ts.txt']) t.is(ctx.exitCode, 0) const stTs = await ctx.vfs.lstat('ts.txt') t.is(stTs && stTs.mtimeMs, 3600000) ctx.exitCode = 0 await runBinCommand(ctx, ['touch', 'ref.txt']) const stRef = await ctx.vfs.lstat('ref.txt') t.ok(stRef && typeof stRef.mtimeMs === 'number') ctx.exitCode = 0 await runBinCommand(ctx, ['touch', '-r', 'ref.txt', 'ts2.txt']) t.is(ctx.exitCode, 0) const st2 = await ctx.vfs.lstat('ts2.txt') t.is(st2 && st2.mtimeMs, stRef.mtimeMs) ctx.exitCode = 0 await runBinCommand(ctx, ['mkdir', '-m', '700', 'secret_dir']) t.is(ctx.exitCode, 0) const stD = await ctx.vfs.lstat('secret_dir') t.ok(stD && (stD.mode & 0o777) === 0o700) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('printenv -0 uses ctx.bareOsBinWrite when stdout is unavailable', async (t) => { const dir = testCorestoreDir('binw') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pbin')) await drive.ready() await personal.ready() await drive.put('/bin/printenv', b4a.from(await readBuiltBin('printenv'))) const raw = [] const ctx = testCtx(drive, personal, { ZZ: 'z', AA: 'a' }) ctx.exitCode = 0 ctx.runBinCommand = function (argv, o) { return runBinCommand(this, argv, o) } ctx.bareOsBinWrite = (u) => { raw.push(b4a.toString(u instanceof Uint8Array ? u : new Uint8Array(u))) } ctx.console = { log() {}, error() {} } await runBinCommand(ctx, ['printenv', '-0', 'AA', 'ZZ']) t.is(ctx.exitCode, 0) t.is(raw.join(''), 'a\0z\0') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('sed and awk golden one-liners', async (t) => { const dir = testCorestoreDir('sawk') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('psawk')) await drive.ready() await personal.ready() await drive.put('/bin/sed', b4a.from(await readBuiltBin('sed'))) await drive.put('/bin/awk', b4a.from(await readBuiltBin('awk'))) const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error() {} } await ctx.vfs.chdir('/home/user') await ctx.vfs.writeFile('f.txt', b4a.from('abc\ndef\n')) await runBinCommand(ctx, ['sed', '-e', 's/a/X/', 'f.txt']) t.is(ctx.exitCode, 0) t.is(lines.join('\n'), 'Xbc\ndef') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['awk', '{ print NF }', 'f.txt']) t.is(ctx.exitCode, 0) t.is(lines.join('\n'), '1\n1') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('curl delegated from booter with stub fetch', async (t) => { const dir = testCorestoreDir('curl') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pcurl')) await drive.ready() await personal.ready() const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error(s) { lines.push('e:' + String(s)) } } /** @type {RequestInit | undefined} */ let curlInitHello ctx.httpFetch = async (_url, init) => { curlInitHello = init return new Response('hello', { status: 200, headers: { 'Content-Type': 'text/plain' } }) } await runBinCommand(ctx, ['curl', 'https://stub.example/x']) t.is(ctx.exitCode, 0) t.is(lines[0], 'hello') t.is(headerFromInit(curlInitHello, 'User-Agent'), DEFAULT_CURL_USER_AGENT) lines.length = 0 ctx.exitCode = 0 ctx.httpFetch = async () => new Response('', { status: 404 }) await runBinCommand(ctx, ['curl', '-f', '-s', 'https://stub.example/missing']) t.is(ctx.exitCode, 22) lines.length = 0 ctx.exitCode = 0 let curlSeenUrl = '' /** @type {RequestInit | undefined} */ let curlSeenInit ctx.httpFetch = async (url, init) => { curlSeenUrl = String(url) curlSeenInit = init return new Response('', { status: 200 }) } await runBinCommand(ctx, ['curl', 'example.com', '-IL']) t.is(ctx.exitCode, 0) t.is(curlSeenUrl, 'http://example.com') t.is(curlSeenInit && curlSeenInit.method, 'HEAD') lines.length = 0 ctx.exitCode = 0 /** @type {{ url: string, method: string }[]} */ const curlHopCalls = [] ctx.httpFetch = async (url, init) => { const u = String(url) const method = String(init?.method || 'GET') curlHopCalls.push({ url: u, method }) if (method === 'HEAD' && u === 'http://hop.example/start') { return new Response('', { status: 302, headers: { Location: 'https://hop.example/done' } }) } if (method === 'GET' && u === 'https://hop.example/done') { return new Response('secret-body', { status: 200, headers: { 'Content-Type': 'text/plain' } }) } return new Response('unexpected', { status: 500 }) } await runBinCommand(ctx, ['curl', '-IL', 'http://hop.example/start']) t.is(ctx.exitCode, 0) t.is(curlHopCalls.length, 2) t.is(curlHopCalls[0].method, 'HEAD') t.is(curlHopCalls[1].method, 'GET') t.ok(lines[0].includes('200')) t.ok(!lines[0].includes('secret-body')) lines.length = 0 ctx.exitCode = 0 ctx.httpFetch = async (url) => { curlSeenUrl = String(url) return new Response('', { status: 200 }) } await runBinCommand(ctx, ['curl', '-I', '//stub.example/p']) t.is(ctx.exitCode, 0) t.is(curlSeenUrl, 'https://stub.example/p') lines.length = 0 ctx.exitCode = 0 /** @type {RequestInit | undefined} */ let curlInitUa ctx.httpFetch = async (_url, init) => { curlInitUa = init return new Response('x', { status: 200 }) } await runBinCommand(ctx, [ 'curl', '-A', 'CustomCurlUA/9', 'https://stub.example/ua' ]) t.is(ctx.exitCode, 0) t.is(headerFromInit(curlInitUa, 'User-Agent'), 'CustomCurlUA/9') lines.length = 0 ctx.exitCode = 0 ctx.httpFetch = async (_url, init) => { curlInitUa = init return new Response('x', { status: 200 }) } await runBinCommand(ctx, [ 'curl', '-H', 'User-Agent: from-header', '-A', 'from-flag', 'https://stub.example/ua2' ]) t.is(ctx.exitCode, 0) t.is(headerFromInit(curlInitUa, 'User-Agent'), 'from-flag') lines.length = 0 ctx.exitCode = 0 ctx.httpFetch = async (_url, init) => { curlInitUa = init return new Response('x', { status: 200 }) } await runBinCommand(ctx, [ 'curl', '-A', 'from-flag', '-H', 'User-Agent: from-header', 'https://stub.example/ua3' ]) t.is(ctx.exitCode, 0) t.is(headerFromInit(curlInitUa, 'User-Agent'), 'from-header') lines.length = 0 ctx.exitCode = 0 ctx.httpFetch = async () => new Response('body-o', { status: 200, headers: { 'Content-Type': 'text/plain' } }) await runBinCommand(ctx, [ 'curl', '-sO', 'https://stub.example/dir/named.txt' ]) t.is(ctx.exitCode, 0) const named = await ctx.vfs.readFile('named.txt') t.is(ctx.b4a.toString(named), 'body-o') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['curl', '-o', 'x', '-O', 'https://stub.example/y']) t.is(ctx.exitCode, 2) lines.length = 0 ctx.exitCode = 0 /** @type {{ url: string, method: string }[]} */ const curlRedirectCountCalls = [] ctx.httpFetch = async (url, init) => { const u = String(url) const method = String(init?.method || 'GET') curlRedirectCountCalls.push({ url: u, method }) if (method === 'HEAD' && u === 'http://rc.example/a') { return new Response('', { status: 302, headers: { Location: 'https://rc.example/b' } }) } if (method === 'GET' && u === 'https://rc.example/b') { return new Response('', { status: 200 }) } return new Response('bad', { status: 500 }) } await runBinCommand(ctx, [ 'curl', '-s', '-w', '%{num_redirects}', '-o', 'hdr.dump', '-IL', 'http://rc.example/a' ]) t.is(ctx.exitCode, 0) t.is(lines[lines.length - 1], '1') lines.length = 0 ctx.exitCode = 0 /** @type {RequestInit | undefined} */ let curlCookieInit ctx.httpFetch = async (_url, init) => { curlCookieInit = init return new Response('c', { status: 200 }) } await runBinCommand(ctx, [ 'curl', '-b', 'sid=abc', 'https://stub.example/cookie-inline' ]) t.is(ctx.exitCode, 0) t.is(headerFromInit(curlCookieInit, 'Cookie'), 'sid=abc') lines.length = 0 ctx.exitCode = 0 await ctx.vfs.writeFile( '/home/user/cookies.json', b4a.from(JSON.stringify({ 'stub.example': { x: 'y' } }), 'utf8') ) ctx.httpFetch = async (_url, init) => { curlCookieInit = init return new Response('c', { status: 200 }) } await runBinCommand(ctx, [ 'curl', '-b', '/home/user/cookies.json', 'https://stub.example/cookie-file' ]) t.is(ctx.exitCode, 0) t.ok(String(headerFromInit(curlCookieInit, 'Cookie')).includes('x=y')) lines.length = 0 ctx.exitCode = 0 ctx.httpFetch = async () => new Response('z', { status: 200, headers: { 'Set-Cookie': 'sess=hello; Path=/' } }) await runBinCommand(ctx, [ 'curl', '-c', '/home/user/jar.json', 'https://stub.example/jar' ]) t.is(ctx.exitCode, 0) const jraw = await ctx.vfs.readFile('/home/user/jar.json') t.ok(jraw && ctx.b4a.toString(jraw).includes('sess')) lines.length = 0 ctx.exitCode = 0 /** @type {{ insecure?: boolean, caPem?: string } | null} */ let curlTlsSeen = null ctx.httpFetch = async (_url, init) => { curlTlsSeen = init && init.bareOsCurlTls return new Response('z', { status: 200 }) } await runBinCommand(ctx, ['curl', '-k', 'https://stub.example/insecure']) t.is(ctx.exitCode, 0) t.ok(curlTlsSeen && curlTlsSeen.insecure === true) t.is(lines[0], 'z') lines.length = 0 ctx.exitCode = 0 await ctx.vfs.writeFile( '/home/user/ca-test.pem', b4a.from('-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----\n') ) let cacertInit = null ctx.httpFetch = async (_url, init) => { cacertInit = init && init.bareOsCurlTls return new Response('pem-ok', { status: 200 }) } await runBinCommand(ctx, [ 'curl', '--cacert', '/home/user/ca-test.pem', 'https://stub.example/ca' ]) t.is(ctx.exitCode, 0) t.ok( cacertInit && typeof cacertInit.caPem === 'string' && cacertInit.caPem.includes('BEGIN CERTIFICATE') ) t.is(lines[0], 'pem-ok') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('curl --connect-timeout aborts hanging stub fetch', async (t) => { const dir = testCorestoreDir('curlcto') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pccto')) await drive.ready() await personal.ready() const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log() {}, error() {} } ctx.httpFetch = async (_url, init) => new Promise((_resolve, reject) => { const sig = init && init.signal if (sig && sig.aborted) { reject(new Error('The operation was aborted')) return } if (sig) { sig.addEventListener('abort', () => reject(new Error('The operation was aborted')) ) } }) await runBinCommand(ctx, [ 'curl', '--connect-timeout', '1', 'https://stub.example/hang' ]) t.is(ctx.exitCode, 7) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('wget delegated from booter with stub fetch', async (t) => { const dir = testCorestoreDir('wget') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pwget')) await drive.ready() await personal.ready() const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error(s) { lines.push('e:' + String(s)) } } /** @type {RequestInit | undefined} */ let wgetInitPayload ctx.httpFetch = async (_url, init) => { wgetInitPayload = init return new Response('payload', { status: 200, headers: { 'Content-Type': 'text/plain' } }) } await runBinCommand(ctx, [ 'wget', '-O', 'saved.txt', '-q', 'https://stub.example/a' ]) t.is(ctx.exitCode, 0) t.is(headerFromInit(wgetInitPayload, 'User-Agent'), DEFAULT_WGET_USER_AGENT) const out = await ctx.vfs.readFile('saved.txt') t.ok(out) t.is(ctx.b4a.toString(out), 'payload') lines.length = 0 ctx.exitCode = 0 ctx.httpFetch = async () => new Response('', { status: 500 }) await runBinCommand(ctx, ['wget', '-q', 'https://stub.example/err']) t.is(ctx.exitCode, 8) lines.length = 0 ctx.exitCode = 0 ctx.httpFetch = async () => new Response('stdout-body', { status: 200 }) await runBinCommand(ctx, ['wget', '-O', '-', '-q', 'https://stub.example/b']) t.is(ctx.exitCode, 0) t.is(lines[0], 'stdout-body') lines.length = 0 ctx.exitCode = 0 let wgetSeenUrl = '' ctx.httpFetch = async (url) => { wgetSeenUrl = String(url) return new Response('p2', { status: 200, headers: { 'Content-Type': 'text/plain' } }) } await runBinCommand(ctx, ['wget', 'stub.example/z', '-qO', 'w2.txt']) t.is(ctx.exitCode, 0) t.is(wgetSeenUrl, 'http://stub.example/z') const w2 = await ctx.vfs.readFile('w2.txt') t.ok(w2) t.is(ctx.b4a.toString(w2), 'p2') lines.length = 0 ctx.exitCode = 0 /** @type {RequestInit | undefined} */ let wgetInitU ctx.httpFetch = async (_url, init) => { wgetInitU = init return new Response('u', { status: 200 }) } await runBinCommand(ctx, [ 'wget', '-q', '-U', 'WgetCustom/1', '-O', 'u.txt', 'https://stub.example/u' ]) t.is(ctx.exitCode, 0) t.is(headerFromInit(wgetInitU, 'User-Agent'), 'WgetCustom/1') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['wget', '-c', '-O', '-', 'https://stub.example/n']) t.is(ctx.exitCode, 2) lines.length = 0 ctx.exitCode = 0 await ctx.vfs.writeFile('partial.bin', b4a.from('ab')) ctx.httpFetch = async (_url, init) => { t.is(headerFromInit(init, 'Range'), 'bytes=2-') return new Response('cde', { status: 206, headers: { 'Content-Type': 'application/octet-stream' } }) } await runBinCommand(ctx, [ 'wget', '-q', '-c', '-O', 'partial.bin', 'https://stub.example/resume' ]) t.is(ctx.exitCode, 0) const merged = await ctx.vfs.readFile('partial.bin') t.is(ctx.b4a.toString(merged), 'abcde') lines.length = 0 ctx.exitCode = 0 await ctx.vfs.writeFile('part.txt', b4a.from('ab')) ctx.httpFetch = async (_url, init) => { t.is(headerFromInit(init, 'Range'), 'bytes=2-') return new Response('cd', { status: 206 }) } await runBinCommand(ctx, ['wget', '-qc', 'http://stub.example/blob/part.txt']) t.is(ctx.exitCode, 0) const partMerged = await ctx.vfs.readFile('part.txt') t.is(ctx.b4a.toString(partMerged), 'abcd') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('tier-1 rm -rf removes directory tree on personal drive', async (t) => { const dir = testCorestoreDir('rmrf') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('prm')) await drive.ready() await personal.ready() await drive.put('/bin/rm', b4a.from(await readBuiltBin('rm'))) const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log() {}, error() {} } await personal.put( personalHomeBacking('/home/user', 'nest/leaf/x.txt'), b4a.from('x') ) await personal.put( personalHomeBacking('/home/user', 'nest/other/y.txt'), b4a.from('y') ) t.ok((await ctx.vfs.readdir('nest')).includes('leaf')) await runBinCommand(ctx, ['rm', '-rf', 'nest']) t.is(ctx.exitCode, 0) const after = await ctx.vfs.readdir('.') t.ok(!after.includes('nest')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('git-fs-adapter mkdir recursive and readdir hides .bareos_empty', async (t) => { const dir = testCorestoreDir('gitfs') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pgf')) await drive.ready() await personal.ready() const ctx = testCtx(drive, personal) const fs = createGitFsFromVfs(ctx.vfs) const base = '/home/user/gittest' await fs.promises.mkdir(path.posix.join(base, 'a', 'b'), { recursive: true }) const inA = await fs.promises.readdir(path.posix.join(base, 'a')) t.is(inA.indexOf('.bareos_empty'), -1) t.ok(inA.includes('b')) const top = await fs.promises.readdir(base) t.ok(top.includes('a')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand delegates git to booter (ignores /bin/git script body)', async (t) => { const dir = testCorestoreDir('gitdel') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pgd')) await drive.ready() await personal.ready() await drive.put( '/bin/git', b4a.from( `async function run() { throw new Error('eval git should not run') }` ) ) const logs = [] const ctx = testCtx(drive, personal) ctx.console = { log: (...a) => logs.push(a.join(' ')), error: (...a) => logs.push(a.join(' ')) } await runBinCommand(ctx, ['git', 'version']) t.ok(logs.some((l) => /isomorphic-git/i.test(l))) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runBinCommand runs ./git from cwd instead of booter delegate', async (t) => { const dir = testCorestoreDir('gitlocal') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pgl')) await drive.ready() await personal.ready() await personal.put( personalHomeBacking('/home/user', 'git'), b4a.from(` async function run(ctx) { ctx.out.push('local-git-script') } `) ) const out = [] const ctx = testCtx(drive, personal) ctx.out = out await runBinCommand(ctx, ['./git']) t.is(out[0], 'local-git-script') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('runGitCli init and status on personal drive', async (t) => { const dir = testCorestoreDir('gitcmd') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pgc')) await drive.ready() await personal.ready() const logs = [] const ctx = testCtx(drive, personal) ctx.console = { log: (...a) => logs.push(a.join(' ')), error: (...a) => logs.push(a.join(' ')) } await runGitCli(ctx, ['git', 'init', '-C', '/home/user/myrepo']) t.ok(logs.some((l) => /initialized|git repository/i.test(l))) logs.length = 0 await runGitCli(ctx, ['git', '-C', '/home/user/myrepo', 'status']) t.ok(logs.length > 0) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('git clean -fd removes untracked files only', async (t) => { const dir = testCorestoreDir('gitclean') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pgcl')) await drive.ready() await personal.ready() const ctx = testCtx(drive, personal) ctx.console = { log() {}, error() {} } await runGitCli(ctx, ['git', 'init', '-C', '/home/user/clrepo']) await ctx.vfs.writeFile('/home/user/clrepo/a.txt', b4a.from('a')) await runGitCli(ctx, ['git', '-C', '/home/user/clrepo', 'add', 'a.txt']) await runGitCli(ctx, [ 'git', '-C', '/home/user/clrepo', 'commit', '-m', 'init' ]) await ctx.vfs.writeFile('/home/user/clrepo/junk.txt', b4a.from('j')) await runGitCli(ctx, ['git', '-C', '/home/user/clrepo', 'clean', '-fd']) t.is(await ctx.vfs.readFile('/home/user/clrepo/junk.txt'), null) t.ok(await ctx.vfs.readFile('/home/user/clrepo/a.txt')) await store.close() rmSync(dir, { recursive: true, force: true }) }) test('curl -O -J saves Content-Disposition filename', async (t) => { const dir = testCorestoreDir('curlj') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pcj')) await drive.ready() await personal.ready() const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.httpFetch = async () => new Response(b4a.from('payload'), { status: 200, headers: { 'Content-Disposition': 'attachment; filename="from-server.bin"' } }) await runBinCommand(ctx, [ 'curl', '-s', '-O', '-J', 'https://stub.example/blob' ]) t.is(ctx.exitCode, 0) const out = await ctx.vfs.readFile('/home/user/from-server.bin') t.ok(out) t.is(ctx.b4a.toString(out), 'payload') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('bare-os-ipc fanout publishes to subscribers', async (t) => { const ipc = createBareOsIpc({ maxFifoBytes: 65536 }) const a = ipc.fanoutSubscribe('news') const b = ipc.fanoutSubscribe('news') ipc.fanoutPublish('news', b4a.from('x', 'utf8')) t.is(b4a.toString(await a.take()), 'x') t.is(b4a.toString(await b.take()), 'x') a.dispose() b.dispose() }) test('bare-os-ipc pushJson requires token when configured', async (t) => { const ipc = createBareOsIpc({ ipcRpcToken: 'secret' }) ipc.create('q') t.exception(() => ipc.pushJson('q', { x: 1 }), /token/) ipc.pushJson('q', { x: 1, bareOsIpcToken: 'secret' }) const j = await ipc.takeJson('q') t.is(j.x, 1) }) test('bareOsHttpUrlAllowed allowlist and denylist', async (t) => { t.ok(bareOsHttpUrlAllowed('https://a.example/x', { allow: [], deny: [] }).ok) t.ok( !bareOsHttpUrlAllowed('https://evil.com/', { allow: ['a.example'], deny: [] }).ok ) t.ok( bareOsHttpUrlAllowed('https://a.example/', { allow: ['a.example'], deny: [] }).ok ) t.ok( !bareOsHttpUrlAllowed('https://a.example/', { allow: ['a.example'], deny: ['a.example'] }).ok ) }) test('raceWithAbortAndTimeout rejects on timeout', async (t) => { try { await raceWithAbortAndTimeout( new Promise(() => {}), { timeoutMs: 30 }, 'hang' ) t.ok(false, 'expected timeout') } catch (e) { t.ok(/timed out/.test(String(e && e.message))) } }) test('kernel share/man/man.json page count matches coreutils + extras + handbook + devguide', async (t) => { const manPath = path.join(__dirname, '../../kernel/share/man/man.json') const raw = JSON.parse(await readFile(manPath, 'utf8')) const { COREUTILS_COMMANDS, MAN_EXTRA_PAGES } = await import('../bare-os-coreutils/lib/commands.mjs') const handbookDir = path.join(__dirname, '../../handbook') const devguideDir = path.join(__dirname, '../../developer-guide') const handbookMd = (await readdir(handbookDir)).filter((f) => f.endsWith('.md') ).length const devguideMd = (await readdir(devguideDir)).filter((f) => f.endsWith('.md') ).length t.is( raw.pages.length, COREUTILS_COMMANDS.length + MAN_EXTRA_PAGES.length + handbookMd + devguideMd ) t.ok(Array.isArray(raw.apropos) && raw.apropos.length > 0) t.is(typeof raw.index.ls, 'number') t.is(typeof raw.index.handbook, 'number') t.is(typeof raw.index.devguide, 'number') const hb = raw.pages[raw.index.handbook] t.is(hb.section, 7) t.is(hb.name, 'bare-os-handbook') const dg = raw.pages[raw.index.devguide] t.is(dg.section, 7) t.is(dg.name, 'bare-os-developer-guide') }) test('runBinCommand man ls prints manual text', async (t) => { const dir = testCorestoreDir('mann') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pmn')) await drive.ready() await personal.ready() const manPath = path.join(__dirname, '../../kernel/share/man/man.json') await drive.put( '/share/man/man.json', b4a.from(await readFile(manPath, 'utf8')) ) await drive.put('/bin/man', b4a.from(await readBuiltBin('man'))) const logs = [] const ctx = testCtx(drive, personal) ctx.console = { log: (...a) => logs.push(a.join(' ')), error: (...a) => logs.push(a.join(' ')) } ctx.exitCode = 0 await runBinCommand(ctx, ['man', 'ls']) t.is(ctx.exitCode, 0) const text = logs.join('\n') t.ok(text.includes('SYNOPSIS')) t.ok(text.includes('EXAMPLES')) t.ok(text.includes('ls')) logs.length = 0 await runBinCommand(ctx, ['man', '-w']) t.is(ctx.exitCode, 0) t.is(logs.join('\n').trim(), '/share/man/man.json') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('coreutils sed and awk fixture corpus', async (t) => { const corpusPath = path.join( __dirname, '../bare-os-coreutils/fixtures/sed-awk-corpus.json' ) const corpus = JSON.parse(await readFile(corpusPath, 'utf8')) const dir = testCorestoreDir('sedawkcorpus') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('psac')) await drive.ready() await personal.ready() await drive.put('/bin/sed', b4a.from(await readBuiltBin('sed'))) await drive.put('/bin/awk', b4a.from(await readBuiltBin('awk'))) const lines = [] const ctx = testCtx(drive, personal) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error(...a) { lines.push(a.join(' ')) } } function corpusNormLines(logs) { return logs .flatMap((l) => String(l).split('\n')) .filter((x) => x.length > 0) } for (const c of corpus.sed) { await ctx.vfs.writeFile(c.file, b4a.from(c.content)) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, c.argv) t.is(ctx.exitCode, 0, 'sed ' + c.name) t.alike(corpusNormLines(lines), c.lines, 'sed ' + c.name) } for (const c of corpus.awk) { if (c.progFile) { await ctx.vfs.writeFile(c.progFile, b4a.from(c.progContent)) } if (c.file) await ctx.vfs.writeFile(c.file, b4a.from(c.content)) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, c.argv) t.is(ctx.exitCode, 0, 'awk ' + c.name) t.alike(corpusNormLines(lines), c.lines, 'awk ' + c.name) } await store.close() rmSync(dir, { recursive: true, force: true }) }) test('coreutils matrix: cp find sort printf uniq realpath sha256sum base64 rm -d', async (t) => { const dir = testCorestoreDir('corematrix') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pcm')) await drive.ready() await personal.ready() const bins = [ 'cp', 'find', 'sort', 'printf', 'uniq', 'realpath', 'sha256sum', 'base64', 'rm', 'mkdir', 'touch' ] for (const b of bins) { await drive.put('/bin/' + b, b4a.from(await readBuiltBin(b))) } await drive.put( '/bin/_corpus_echo', b4a.from(`async function run(ctx, argv) { ctx.console.log(argv.slice(1).join(' ')) } `) ) const lines = [] const ctx = testCtx(drive, personal) ctx.runBinCommand = (argv) => runBinCommand(ctx, argv) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error(...a) { lines.push(a.join(' ')) } } await ctx.vfs.mkdir('tree', { recursive: true }) await ctx.vfs.writeFile('tree/a.txt', b4a.from('newdata')) await ctx.vfs.writeFile('dest.txt', b4a.from('stale')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['touch', '-d', '@1', 'dest.txt']) t.is(ctx.exitCode, 0) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['touch', '-d', '@100000', 'tree/a.txt']) t.is(ctx.exitCode, 0) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['cp', '-u', 'tree/a.txt', 'dest.txt']) t.is(ctx.exitCode, 0, 'cp -u') t.is(ctx.b4a.toString(await ctx.vfs.readFile('dest.txt')), 'newdata') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['find', '.', '-type', 'f', '-regex', '.*\\.txt$']) t.is(ctx.exitCode, 0, 'find -regex') t.ok(lines.some((l) => String(l).includes('a.txt'))) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['find', 'tree', '-exec', '_corpus_echo', '{}', ';']) t.is(ctx.exitCode, 0, 'find -exec') t.ok(lines.some((l) => /a\.txt/.test(String(l)))) lines.length = 0 ctx.exitCode = 0 ctx.shellStdin = '3\n1\n2\n' await runBinCommand(ctx, ['sort', '-n']) t.is(lines.join('\n'), '1\n2\n3') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['printf', '%s-%d', 'n', '7']) t.is(lines[0], 'n-7') await ctx.vfs.writeFile('u.txt', b4a.from('a\na\nb\n')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['uniq', '-c', 'u.txt']) t.ok(lines.some((l) => /^\s*2\s+a$/.test(String(l)))) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['realpath', 'tree/a.txt']) t.ok(/a\.txt$/.test(lines[0])) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['sha256sum', 'u.txt']) t.is(lines.length, 1) t.ok(/^[a-f0-9]{64}\s+/.test(lines[0])) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['base64', '-w', '0', 'u.txt']) const dec = Buffer.from( lines.join('').replace(/\s+/g, ''), 'base64' ).toString() t.is(dec, 'a\na\nb\n') await ctx.vfs.mkdir('emptydir', { recursive: true }) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['rm', '-d', 'emptydir']) t.is(ctx.exitCode, 0, 'rm -d') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('coreutils gnu-gap batch: paste tac rev md5sum expr tsort numfmt truncate install comm join', async (t) => { const dir = testCorestoreDir('gnugap') const store = new Corestore(dir) const drive = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('ngg')) await drive.ready() await personal.ready() const bins = [ 'paste', 'tac', 'rev', 'md5sum', 'expr', 'tsort', 'numfmt', 'sync', 'truncate', 'install', 'unlink', 'comm', 'join', 'yes', 'cp', 'touch', 'mkdir', 'ls' ] for (const b of bins) { await drive.put('/bin/' + b, b4a.from(await readBuiltBin(b))) } const lines = [] const ctx = testCtx(drive, personal) ctx.runBinCommand = (argv) => runBinCommand(ctx, argv) ctx.exitCode = 0 ctx.console = { log(s) { lines.push(String(s)) }, error(...a) { lines.push(a.join(' ')) } } ctx.vfs.env.BARE_OS_YES_MAX_LINES = '2' lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['yes', 'ok']) t.is(ctx.exitCode, 0) t.is(lines.filter((l) => l === 'ok').length, 2) await ctx.vfs.writeFile('nums.txt', b4a.from('1\n2\n3\n')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['tac', 'nums.txt']) t.is(lines.join('\n'), '3\n2\n1') await ctx.vfs.writeFile('rv.txt', b4a.from('ab\ncd\n')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['rev', 'rv.txt']) t.is(lines.join('\n'), 'ba\ndc') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['md5sum', 'nums.txt']) t.ok(/^[a-f0-9]{32}\s/.test(lines[0])) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['expr', '1', '+', '2', '*', '3']) t.is(lines[0], '7') await ctx.vfs.writeFile('ts.txt', b4a.from('a b\nb c\n')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['tsort', 'ts.txt']) t.is(lines.join('\n'), 'a\nb\nc') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['numfmt', '--to=iec', '1024']) t.is(lines[0], '1K') lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['sync']) t.is(ctx.exitCode, 0) await ctx.vfs.writeFile('tr.txt', b4a.from('hello')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['truncate', '-s', '2', 'tr.txt']) t.is(ctx.exitCode, 0) t.is(ctx.b4a.toString(await ctx.vfs.readFile('tr.txt')), 'he') await ctx.vfs.writeFile('src.txt', b4a.from('data')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['install', '-m', '600', 'src.txt', 'dest.txt']) t.is(ctx.exitCode, 0) t.is(ctx.b4a.toString(await ctx.vfs.readFile('dest.txt')), 'data') await ctx.vfs.writeFile('s1.txt', b4a.from('a\nb\n')) await ctx.vfs.writeFile('s2.txt', b4a.from('a\nc\n')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['comm', 's1.txt', 's2.txt']) t.ok(lines.some((l) => l.includes('\t\ta'))) await ctx.vfs.writeFile('j1.txt', b4a.from('1 x\n2 y\n')) await ctx.vfs.writeFile('j2.txt', b4a.from('1 p\n2 q\n')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['join', 'j1.txt', 'j2.txt']) t.ok(lines.some((l) => /1\s+x\s+1\s+p/.test(String(l)))) await ctx.vfs.writeFile('u.txt', b4a.from('x')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['unlink', 'u.txt']) t.is(ctx.exitCode, 0) t.is(await ctx.vfs.readFile('u.txt'), null) await ctx.vfs.writeFile('p1.txt', b4a.from('a\nb\n')) await ctx.vfs.writeFile('p2.txt', b4a.from('1\n2\n')) lines.length = 0 ctx.exitCode = 0 await runBinCommand(ctx, ['paste', 'p1.txt', 'p2.txt']) t.is(lines[0], 'a\t1') t.is(lines[1], 'b\t2') await store.close() rmSync(dir, { recursive: true, force: true }) }) test('verifyBootManifestEd25519 rejects invalid inputs', async (t) => { const { verifyBootManifestEd25519 } = await import('#bare-os-boot-manifest-sig') const msg = b4a.from('manifest-bytes', 'utf8') t.absent(verifyBootManifestEd25519(msg, null, '')) t.absent(verifyBootManifestEd25519(msg, msg, '00ff')) const z64 = '0'.repeat(64) t.absent(verifyBootManifestEd25519(msg, new Uint8Array(64), z64)) }) test('bareOsIpc.duplexJsonRoundTrip', async (t) => { const ipc = createBareOsIpc() const { left, right } = ipc.createDuplexBridge('dupjx') const respP = ipc.duplexJsonRoundTrip(right, { id: 7, method: 'ping' }) const u8 = await left.take() const req = JSON.parse(b4a.toString(u8, 'utf8')) t.is(req.method, 'ping') left.push( b4a.from( JSON.stringify({ bareOsRpc: '2', id: 7, result: 'pong' }) + '\n', 'utf8' ) ) const out = await respP t.is(out.result, 'pong') }) test('unit journal exposed under /run/bare-os/unit-journal', async (t) => { const { appendBareInitdJournal, clearBareInitdJournalForTests, getBareInitdJournalNdjson } = await import('./lib/bare-initd-journal.js') clearBareInitdJournalForTests() appendBareInitdJournal('demo', { event: 'unit_test' }) const dir = testCorestoreDir('vj') const store = new Corestore(dir) const sys = new Hyperdrive(store) const personal = new Hyperdrive(store.namespace('pvj')) await sys.ready() await personal.ready() const env = { HOME: '/home/guest', PWD: '/home/guest', PATH: '/bin', USER: 'guest' } const vfs = createVfs(sys, personal, env, null, { getUnitJournalNdjson: (u) => getBareInitdJournalNdjson(u) }) t.ok((await vfs.readdir('/run/bare-os/unit-journal')).includes('demo.ndjson')) const j = b4a.toString( await vfs.readFile('/run/bare-os/unit-journal/demo.ndjson') ) t.ok(j.includes('unit_test')) clearBareInitdJournalForTests() await store.close() rmSync(dir, { recursive: true, force: true }) }) async function readBuiltBin(name) { const fs = await import('node:fs/promises') const p = path.join(__dirname, '../../kernel/bin', name) return fs.readFile(p, 'utf8') }