Core Utils Breakdown Tests
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"schema": 2,
|
"schema": 2,
|
||||||
"profileId": "bare-os-posix-like",
|
"profileId": "bare-os-posix-like",
|
||||||
"generatedAt": "2026-04-26T12:56:08.959Z",
|
"generatedAt": "2026-04-26T19:04:18.264Z",
|
||||||
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||||
"commandIndex": [
|
"commandIndex": [
|
||||||
{
|
{
|
||||||
@@ -20,6 +20,10 @@
|
|||||||
"name": "awk",
|
"name": "awk",
|
||||||
"tier": "tier1_bin"
|
"tier": "tier1_bin"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "bare-sshd",
|
||||||
|
"tier": "tier1_bin"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "baresay",
|
"name": "baresay",
|
||||||
"tier": "tier1_bin"
|
"tier": "tier1_bin"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schema": 1,
|
"schema": 1,
|
||||||
"atMs": 1777208168958,
|
"atMs": 1777230258263,
|
||||||
"commands": [
|
"commands": [
|
||||||
"agent",
|
"agent",
|
||||||
"appctl",
|
"appctl",
|
||||||
|
|||||||
+22109
-1
File diff suppressed because one or more lines are too long
@@ -36,6 +36,7 @@
|
|||||||
"os:booter": "node scripts/ensure-pear-node-modules.mjs packages/bare-os-booter && cd packages/bare-os-booter && pear run --dev .",
|
"os:booter": "node scripts/ensure-pear-node-modules.mjs packages/bare-os-booter && cd packages/bare-os-booter && pear run --dev .",
|
||||||
"vendor:bare-node-shims": "node scripts/vendor-bare-node-shims.mjs",
|
"vendor:bare-node-shims": "node scripts/vendor-bare-node-shims.mjs",
|
||||||
"smoke:agent-web-fetch:bare": "bare scripts/smoke-agent-web-fetch-bare.mjs",
|
"smoke:agent-web-fetch:bare": "bare scripts/smoke-agent-web-fetch-bare.mjs",
|
||||||
|
"probe:kernel-bin": "node scripts/probe-kernel-bin.mjs",
|
||||||
"sample:agent-workspace": "node scripts/print-agent-workspace-sample.mjs",
|
"sample:agent-workspace": "node scripts/print-agent-workspace-sample.mjs",
|
||||||
"md:rendered-asterisks:check": "node scripts/fix-markdown-rendered-asterisks.mjs",
|
"md:rendered-asterisks:check": "node scripts/fix-markdown-rendered-asterisks.mjs",
|
||||||
"md:rendered-asterisks:fix": "node scripts/fix-markdown-rendered-asterisks.mjs --write"
|
"md:rendered-asterisks:fix": "node scripts/fix-markdown-rendered-asterisks.mjs --write"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"schema": 2,
|
"schema": 2,
|
||||||
"profileId": "bare-os-posix-like",
|
"profileId": "bare-os-posix-like",
|
||||||
"generatedAt": "2026-04-26T12:56:08.959Z",
|
"generatedAt": "2026-04-26T19:04:18.264Z",
|
||||||
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||||
"commandIndex": [
|
"commandIndex": [
|
||||||
{
|
{
|
||||||
@@ -20,6 +20,10 @@
|
|||||||
"name": "awk",
|
"name": "awk",
|
||||||
"tier": "tier1_bin"
|
"tier": "tier1_bin"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "bare-sshd",
|
||||||
|
"tier": "tier1_bin"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "baresay",
|
"name": "baresay",
|
||||||
"tier": "tier1_bin"
|
"tier": "tier1_bin"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schema": 1,
|
"schema": 1,
|
||||||
"atMs": 1777208168958,
|
"atMs": 1777230258263,
|
||||||
"commands": [
|
"commands": [
|
||||||
"agent",
|
"agent",
|
||||||
"appctl",
|
"appctl",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,285 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import b4a from 'b4a'
|
||||||
|
import Corestore from 'corestore'
|
||||||
|
import Hyperdrive from 'hyperdrive'
|
||||||
|
import os from 'node:os'
|
||||||
|
import path from 'node:path'
|
||||||
|
import process from 'node:process'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import {
|
||||||
|
mkdtemp,
|
||||||
|
readdir,
|
||||||
|
readFile,
|
||||||
|
rm
|
||||||
|
} from 'node:fs/promises'
|
||||||
|
import { COREUTILS_COMMANDS } from '../packages/bare-os-coreutils/lib/commands.mjs'
|
||||||
|
import { createBareOsIpc } from '../packages/bare-os-booter/lib/bare-os-ipc.js'
|
||||||
|
import { runBinCommand } from '../packages/bare-os-booter/lib/kernel-runner.js'
|
||||||
|
import { createVfs } from '../packages/bare-os-booter/lib/vfs.js'
|
||||||
|
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||||
|
const root = path.resolve(__dirname, '..')
|
||||||
|
const kernelBinDir = path.join(root, 'kernel', 'bin')
|
||||||
|
const probeTimeoutMs = Number.parseInt(process.env.BARE_OS_BIN_PROBE_TIMEOUT_MS || '', 10) || 2_000
|
||||||
|
const truncLen = 160
|
||||||
|
|
||||||
|
const FAST_SAFE_ARGS = new Map([
|
||||||
|
['echo', ['ok']],
|
||||||
|
['false', []],
|
||||||
|
['nice', ['true']],
|
||||||
|
['nohup', ['true']],
|
||||||
|
['printf', ['ok']],
|
||||||
|
['pwd', []],
|
||||||
|
['test', ['1', '=', '1']],
|
||||||
|
['time', ['true']],
|
||||||
|
['timeout', ['1', 'true']],
|
||||||
|
['true', []]
|
||||||
|
])
|
||||||
|
|
||||||
|
const HELP_ONLY_ARGS = new Map([
|
||||||
|
['sshd', ['-h']]
|
||||||
|
])
|
||||||
|
|
||||||
|
const SKIPPED = new Map([])
|
||||||
|
|
||||||
|
function classifyNonZero(exitCode, combinedText) {
|
||||||
|
if (exitCode === 0) return 'OK'
|
||||||
|
if (exitCode === 126 && /delegate/i.test(combinedText)) return 'SKIPPED'
|
||||||
|
if (exitCode === 1 || exitCode === 2) {
|
||||||
|
if (
|
||||||
|
/(usage|--help|help|unknown option|unrecognized|illegal option|invalid option|requires tty|not supported)/i.test(
|
||||||
|
combinedText
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return 'USAGE'
|
||||||
|
}
|
||||||
|
return 'NOHELP'
|
||||||
|
}
|
||||||
|
return 'EXCEPTION'
|
||||||
|
}
|
||||||
|
|
||||||
|
function shortText(lines) {
|
||||||
|
const joined = lines.join('\n').replace(/\s+/g, ' ').trim()
|
||||||
|
if (joined.length <= truncLen) return joined
|
||||||
|
return joined.slice(0, truncLen) + '...'
|
||||||
|
}
|
||||||
|
|
||||||
|
function probeArgvFor(name) {
|
||||||
|
if (FAST_SAFE_ARGS.has(name)) return [name, ...FAST_SAFE_ARGS.get(name)]
|
||||||
|
if (HELP_ONLY_ARGS.has(name)) return [name, ...HELP_ONLY_ARGS.get(name)]
|
||||||
|
return [name, '--help']
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadKernelBinNames() {
|
||||||
|
const ents = await readdir(kernelBinDir, { withFileTypes: true })
|
||||||
|
return ents
|
||||||
|
.filter((ent) => ent.isFile())
|
||||||
|
.map((ent) => ent.name)
|
||||||
|
.sort((a, b) => a.localeCompare(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function seedSystemDrive(drive, names) {
|
||||||
|
for (const name of names) {
|
||||||
|
const src = await readFile(path.join(kernelBinDir, name), 'utf8')
|
||||||
|
await drive.put('/bin/' + name, b4a.from(src))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function makeProbeContext() {
|
||||||
|
const tmp = await mkdtemp(path.join(os.tmpdir(), 'bare-os-bin-probe-'))
|
||||||
|
const store = new Corestore(tmp)
|
||||||
|
const drive = new Hyperdrive(store)
|
||||||
|
const personal = new Hyperdrive(store.namespace('probe-personal'))
|
||||||
|
await drive.ready()
|
||||||
|
await personal.ready()
|
||||||
|
const env = {
|
||||||
|
HOME: '/home/user',
|
||||||
|
PATH: '/bin',
|
||||||
|
USER: 'user',
|
||||||
|
UID: '1000',
|
||||||
|
GID: '1000',
|
||||||
|
PWD: '/home/user',
|
||||||
|
BARE_OS_EXIT_STATUS: '0',
|
||||||
|
BARE_OS_RUNBIN_DEFAULT_TIMEOUT_MS: String(probeTimeoutMs),
|
||||||
|
BARE_OS_DELEGATE_ALLOW: 'none',
|
||||||
|
BARE_OS_DELEGATE_AUDIT_ONLY: '1',
|
||||||
|
BARE_OS_AUDIT: '1'
|
||||||
|
}
|
||||||
|
const bareOsIpc = createBareOsIpc()
|
||||||
|
const vfs = createVfs(drive, personal, env, null, { bareOsIpc })
|
||||||
|
const logs = []
|
||||||
|
const errs = []
|
||||||
|
const ctx = {
|
||||||
|
drive,
|
||||||
|
personalDrive: personal,
|
||||||
|
vfs,
|
||||||
|
bareOsIpc,
|
||||||
|
env,
|
||||||
|
b4a,
|
||||||
|
exitCode: 0,
|
||||||
|
console: {
|
||||||
|
log: (...a) => logs.push(a.join(' ')),
|
||||||
|
error: (...a) => errs.push(a.join(' '))
|
||||||
|
},
|
||||||
|
async bareOsRunCurlCli() {
|
||||||
|
errs.push('delegate disabled: curl')
|
||||||
|
this.exitCode = 126
|
||||||
|
},
|
||||||
|
async bareOsRunWgetCli() {
|
||||||
|
errs.push('delegate disabled: wget')
|
||||||
|
this.exitCode = 126
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.runBinCommand = function runSelf(argv, opts) {
|
||||||
|
return runBinCommand(this, argv, opts)
|
||||||
|
}
|
||||||
|
return { tmp, store, drive, personal, logs, errs, ctx }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const coreutils = [...COREUTILS_COMMANDS].sort((a, b) => a.localeCompare(b))
|
||||||
|
const staged = await loadKernelBinNames()
|
||||||
|
const stagedSet = new Set(staged)
|
||||||
|
const coreSet = new Set(coreutils)
|
||||||
|
const missing = coreutils.filter((name) => !stagedSet.has(name))
|
||||||
|
const extra = staged.filter((name) => !coreSet.has(name))
|
||||||
|
const candidates = [...new Set([...coreutils, ...staged])].sort((a, b) =>
|
||||||
|
a.localeCompare(b)
|
||||||
|
)
|
||||||
|
|
||||||
|
const { tmp, store, drive, personal, logs, errs, ctx } = await makeProbeContext()
|
||||||
|
let failed = false
|
||||||
|
|
||||||
|
/** @type {Array<{name:string,status:string,argv:string[],exitCode:number|null,durationMs:number,stdout:string,stderr:string,note?:string}>} */
|
||||||
|
const results = []
|
||||||
|
try {
|
||||||
|
await seedSystemDrive(drive, staged)
|
||||||
|
for (const name of candidates) {
|
||||||
|
if (!stagedSet.has(name)) {
|
||||||
|
results.push({
|
||||||
|
name,
|
||||||
|
status: 'MISSING',
|
||||||
|
argv: [],
|
||||||
|
exitCode: null,
|
||||||
|
durationMs: 0,
|
||||||
|
stdout: '',
|
||||||
|
stderr: '',
|
||||||
|
note: 'Listed in COREUTILS_COMMANDS but missing from kernel/bin'
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (SKIPPED.has(name)) {
|
||||||
|
results.push({
|
||||||
|
name,
|
||||||
|
status: 'SKIPPED',
|
||||||
|
argv: [name],
|
||||||
|
exitCode: null,
|
||||||
|
durationMs: 0,
|
||||||
|
stdout: '',
|
||||||
|
stderr: '',
|
||||||
|
note: SKIPPED.get(name)
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const argv = probeArgvFor(name)
|
||||||
|
logs.length = 0
|
||||||
|
errs.length = 0
|
||||||
|
ctx.exitCode = 0
|
||||||
|
const started = Date.now()
|
||||||
|
try {
|
||||||
|
await runBinCommand(ctx, argv, { timeoutMs: probeTimeoutMs })
|
||||||
|
const durationMs = Date.now() - started
|
||||||
|
const stdout = shortText(logs)
|
||||||
|
const stderr = shortText(errs)
|
||||||
|
const merged = `${stdout}\n${stderr}`.trim()
|
||||||
|
const status = classifyNonZero(ctx.exitCode || 0, merged)
|
||||||
|
results.push({
|
||||||
|
name,
|
||||||
|
status,
|
||||||
|
argv,
|
||||||
|
exitCode: ctx.exitCode ?? null,
|
||||||
|
durationMs,
|
||||||
|
stdout,
|
||||||
|
stderr
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
const durationMs = Date.now() - started
|
||||||
|
const msg = err instanceof Error ? err.message : String(err)
|
||||||
|
const timeout = /timeout|timed out|abort/i.test(msg)
|
||||||
|
results.push({
|
||||||
|
name,
|
||||||
|
status: timeout ? 'TIMEOUT' : 'EXCEPTION',
|
||||||
|
argv,
|
||||||
|
exitCode: ctx.exitCode ?? null,
|
||||||
|
durationMs,
|
||||||
|
stdout: shortText(logs),
|
||||||
|
stderr: shortText([...errs, msg])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await personal.close()
|
||||||
|
await drive.close()
|
||||||
|
await store.close()
|
||||||
|
await rm(tmp, { recursive: true, force: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const r of results) {
|
||||||
|
if (!coreSet.has(r.name) && r.status !== 'MISSING') r.note = 'EXTRA staged bin'
|
||||||
|
}
|
||||||
|
|
||||||
|
const counts = new Map()
|
||||||
|
for (const r of results) counts.set(r.status, (counts.get(r.status) || 0) + 1)
|
||||||
|
if (extra.length) counts.set('EXTRA', extra.length)
|
||||||
|
|
||||||
|
const broken = results.filter((r) =>
|
||||||
|
['TIMEOUT', 'EXCEPTION'].includes(r.status)
|
||||||
|
)
|
||||||
|
if (broken.length > 0 || missing.length > 0) failed = true
|
||||||
|
|
||||||
|
const order = [
|
||||||
|
'OK',
|
||||||
|
'USAGE',
|
||||||
|
'NOHELP',
|
||||||
|
'SKIPPED',
|
||||||
|
'MISSING',
|
||||||
|
'EXTRA',
|
||||||
|
'TIMEOUT',
|
||||||
|
'EXCEPTION'
|
||||||
|
]
|
||||||
|
|
||||||
|
console.log('BINS PROBE SUMMARY')
|
||||||
|
console.log('==================')
|
||||||
|
console.log(`COREUTILS_COMMANDS: ${coreutils.length}`)
|
||||||
|
console.log(`kernel/bin files: ${staged.length}`)
|
||||||
|
console.log(`Candidates probed: ${results.length}`)
|
||||||
|
console.log(`Timeout per bin: ${probeTimeoutMs}ms`)
|
||||||
|
for (const key of order) {
|
||||||
|
const n = counts.get(key)
|
||||||
|
if (n) console.log(`${key}: ${n}`)
|
||||||
|
}
|
||||||
|
console.log('')
|
||||||
|
|
||||||
|
for (const r of results) {
|
||||||
|
if (r.status === 'OK' || r.status === 'USAGE' || r.status === 'NOHELP') continue
|
||||||
|
const ec = r.exitCode == null ? 'n/a' : String(r.exitCode)
|
||||||
|
const probe = r.argv.length ? r.argv.join(' ') : '(none)'
|
||||||
|
const detail = r.stderr || r.stdout || r.note || ''
|
||||||
|
console.log(`${r.status} ${r.name} | exit=${ec} | argv=${probe}`)
|
||||||
|
if (detail) console.log(` ${detail}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed) {
|
||||||
|
process.exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
process.exitCode = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((err) => {
|
||||||
|
const msg = err instanceof Error ? err.stack || err.message : String(err)
|
||||||
|
console.error(msg)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user