Files
bare-operating-system/packages/bare-os-booter/test.js
T
Raven Scott 8f2e3cceb0 Move editable kernel bulk from kernel/init-main.js to kernel/lib/init/
(staged as /lib/init/init-main.js); point bundle-kernel-init and verify
scripts at the new path.

Wire curl, wget, openssl, ssh-keygen, and tar through coreutils and
booter host delegates with booter-side CLI helpers; refresh related
bins, bare manifest, shell completion, and man DB (kernel + seeder).

Add booter support modules for ACL evaluation, audit chain, secret
handles, peer admission, replication priority, process table, swarm
lifecycle, boot-graph proc, metrics, monotonic time, protomux alias
registry, and swarm peer policy; extend extension resolver, VFS,
swarm connection managers, IPC, identity-account, and initd.

Harden bare-os-bare-libs build on esbuild failure; add verify scripts
for extension manifest schema and runtime incomplete markers; extend
ctx API typings, gen-ctx-client-stub, and verify-ctx-dts.

Update boot hook fragment, bundled init.js, handbook and reference
docs (incl. kernel security and VFS path classes).
2026-04-04 17:51:47 -04:00

4324 lines
130 KiB
JavaScript

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/<seg>/…` (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')
}