packages/bare-os-booter/index.js Added ctx.bareOsTelnetConnect(host, port, opts) that prefers ctx.bare.bareTcp.createConnection, then new bareTcp.Socket(), with explicit diagnostics if unavailable. packages/bare-os-coreutils/src/telnet.js already preferred ctx.bareOsTelnetConnect, so it now uses this richer path first automatically. Added missing ssh command: New file: packages/bare-os-coreutils/src/ssh.js Supports -h/--help Delegates to ctx.bareOsRunSshCli when present Emits explicit nonzero unavailable/runtime diagnostics when absent Registered command: packages/bare-os-coreutils/lib/commands.mjs Hardened HDMS create mount visibility: packages/bare-os-booter/lib/hdms-manager.js hdms create now verifies mount visibility via getMountMap().has(label) and errors non-silently if missing. Success message now includes mount path (mounted=/mnt/<label>). Fixed parser/semantics and explicit failures: packages/bare-os-coreutils/src/kill.js -1 is now treated as a target (not misparsed as signal shorthand), so kill -TERM -1 is explicit/non-silent. packages/bare-os-coreutils/src/test.js Numeric test comparisons now emit diagnostic + exit 2 for empty integer operand cases (keeps existing non-decimal behavior stable). packages/bare-os-coreutils/src/crontab.js Explicitly rejects stdin/fd-style installs (-, /dev/fd/*, /proc/self/fd/*) with nonzero error. Updated ctx typings: packages/bare-os-booter/lib/bare-os-ctx.d.ts Added bareOsRunSshCli? Added bareOsTelnetConnect?
133 lines
3.8 KiB
JavaScript
133 lines
3.8 KiB
JavaScript
import { readFile } from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import test from 'brittle'
|
|
import b4a from 'b4a'
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
|
|
|
|
async function loadBin(name) {
|
|
const runtime = await readFile(path.join(__dirname, '../lib/runtime.js'), 'utf8')
|
|
const body = await readFile(path.join(__dirname, `../src/${name}.js`), 'utf8')
|
|
return new AsyncFunction(
|
|
'ctx',
|
|
'argv',
|
|
`${runtime}\n${body}\nif (typeof run === 'function') return await run(ctx, argv)\n`
|
|
)
|
|
}
|
|
|
|
function mkCtx(vfs = {}) {
|
|
const logs = []
|
|
const errs = []
|
|
return {
|
|
b4a,
|
|
exitCode: 0,
|
|
identity: { state: 'locked' },
|
|
shellStdin: '',
|
|
console: { log: (m) => logs.push(String(m)), error: (m) => errs.push(String(m)) },
|
|
vfs: { env: {}, ...vfs },
|
|
_logs: logs,
|
|
_errs: errs
|
|
}
|
|
}
|
|
|
|
test('hdms unavailable returns nonzero', async (t) => {
|
|
const run = await loadBin('hdms')
|
|
const ctx = mkCtx()
|
|
await run(ctx, ['hdms', 'ls'])
|
|
t.is(ctx.exitCode, 1)
|
|
t.ok(ctx._errs.join('\n').includes('unavailable'))
|
|
})
|
|
|
|
test('git-pear clone requires url', async (t) => {
|
|
const run = await loadBin('git-pear')
|
|
const ctx = mkCtx()
|
|
await run(ctx, ['git-pear', 'clone'])
|
|
t.is(ctx.exitCode, 1)
|
|
t.ok(ctx._errs.join('\n').includes('missing repository URL'))
|
|
})
|
|
|
|
test('git-pear clone delegates to git clone', async (t) => {
|
|
const run = await loadBin('git-pear')
|
|
const ctx = mkCtx()
|
|
/** @type {string[][]} */
|
|
const seen = []
|
|
ctx.runBinCommand = async (argv) => {
|
|
seen.push(argv.slice())
|
|
ctx.exitCode = 0
|
|
}
|
|
await run(ctx, ['git-pear', 'clone', 'git.ssh.surf/org/repo', '/tmp/repo'])
|
|
t.is(ctx.exitCode, 0)
|
|
t.is(seen.length, 1)
|
|
t.is(seen[0][0], 'git')
|
|
t.is(seen[0][1], 'clone')
|
|
})
|
|
|
|
test('oidc-publish unknown subcommand is explicit', async (t) => {
|
|
const run = await loadBin('oidc-publish')
|
|
const ctx = mkCtx()
|
|
await run(ctx, ['oidc-publish', 'unknown'])
|
|
t.is(ctx.exitCode, 1)
|
|
t.ok(ctx._errs.join('\n').includes('unknown subcommand'))
|
|
})
|
|
|
|
test('crontab -e requires unlocked identity', async (t) => {
|
|
const run = await loadBin('crontab')
|
|
const ctx = mkCtx({
|
|
async readFile() {
|
|
return null
|
|
},
|
|
async writeFile() {},
|
|
async unlink() {}
|
|
})
|
|
await run(ctx, ['crontab', '-e'])
|
|
t.is(ctx.exitCode, 1)
|
|
t.ok(ctx._errs.join('\n').includes('log in'))
|
|
})
|
|
|
|
test('ssh command reports unavailable runtime explicitly', async (t) => {
|
|
const run = await loadBin('ssh')
|
|
const ctx = mkCtx()
|
|
await run(ctx, ['ssh', 'localhost'])
|
|
t.is(ctx.exitCode, 1)
|
|
t.ok(ctx._errs.join('\n').includes('client unavailable'))
|
|
})
|
|
|
|
test('kill -TERM -1 treats -1 as target', async (t) => {
|
|
const run = await loadBin('kill')
|
|
const ctx = mkCtx()
|
|
/** @type {Array<{ target: string | number, signal: string }>} */
|
|
const sent = []
|
|
ctx.bareOsSendSignal = (target, signal) => {
|
|
sent.push({ target, signal })
|
|
return { ok: true, delivered: false, exists: false, ignored: false }
|
|
}
|
|
await run(ctx, ['kill', '-TERM', '-1'])
|
|
t.is(ctx.exitCode, 1)
|
|
t.is(sent.length, 1)
|
|
t.is(String(sent[0].target), '-1')
|
|
})
|
|
|
|
test('crontab rejects fd/stdin style install paths explicitly', async (t) => {
|
|
const run = await loadBin('crontab')
|
|
const ctx = mkCtx({
|
|
async readFile() {
|
|
return null
|
|
},
|
|
async writeFile() {}
|
|
})
|
|
ctx.identity = { state: 'unlocked' }
|
|
await run(ctx, ['crontab', '/dev/fd/3'])
|
|
t.is(ctx.exitCode, 1)
|
|
t.ok(ctx._errs.join('\n').includes('stdin/fd-based installs'))
|
|
})
|
|
|
|
test('test empty integer operand returns status 2', async (t) => {
|
|
const run = await loadBin('test')
|
|
const ctx = mkCtx()
|
|
await run(ctx, ['test', '', '-eq', '1'])
|
|
t.is(ctx.exitCode, 2)
|
|
t.ok(ctx._errs.join('\n').includes('integer expression expected'))
|
|
})
|