Update btop

This commit is contained in:
Raven Scott
2026-04-05 17:07:57 -04:00
parent 7c6b77ed62
commit f3c8ef1fc5
33 changed files with 9771 additions and 1090 deletions
@@ -17,6 +17,10 @@ test('baretop-tui uses alternate screen teardown pattern', async (t) => {
(src.match(/\\x1b\[2J\\x1b\[H/g) || []).length >= 1,
'expected full clear fallback in finally'
)
t.ok(
src.includes('incrementalFrameDiff'),
'expected incremental frame diff gate in tui source'
)
})
test('shipped kernel/bin/baretop includes snapshot + TUI', async (t) => {
@@ -19,6 +19,10 @@ test('fixture metrics_live-shaped JSON parses with expected keys', async (t) =>
t.ok(typeof o.delegateInflight === 'object')
t.ok(o.replicationLive && typeof o.replicationLive === 'object')
t.ok(o.kernelCounters && typeof o.kernelCounters === 'object')
t.ok(
o.netSummaryNestedExample &&
typeof o.netSummaryNestedExample.replicationQueue === 'object'
)
})
test('baretop-snapshot preamble lists batch proc entries', async (t) => {
@@ -29,6 +33,7 @@ test('baretop-snapshot preamble lists batch proc entries', async (t) => {
t.ok(src.includes('bareTopHealthScore'))
t.ok(src.includes('BARE_TOP_SNAPSHOT_LITE_ENTRIES'))
t.ok(src.includes('bootBudgetSummary'))
t.ok(src.includes('security_posture.json'))
})
test('bareTopHealthScore penalizes stall and inflight cardinality', async (t) => {
@@ -49,6 +54,44 @@ test('bareTopHealthScore penalizes stall and inflight cardinality', async (t) =>
t.is(ctx.bareTopHealthScore(good, 2), 100)
})
test('bareTopHealthScore: no_peers + idle delegates is not stuck at 73', async (t) => {
const src = await readFile(snapPath, 'utf8')
const ctx = createContext({})
runInContext(src, ctx)
const idle = {
peers: 0,
delegateInflight: {},
replicationLive: { peerCount: 0, stallHint: 'no_peers' }
}
t.is(ctx.bareTopHealthScore(idle, 0), 100)
const lightInflight = {
peers: 0,
delegateInflight: { http: 1, dns: 0 },
replicationLive: { peerCount: 0, stallHint: 'no_peers' }
}
const s2 = ctx.bareTopHealthScore(lightInflight, 0)
t.ok(s2 >= 90)
t.not(s2, 73)
})
test('bareTopHealthScoreDetail: benign stall hints and replicationStall flag', async (t) => {
const src = await readFile(snapPath, 'utf8')
const ctx = createContext({})
runInContext(src, ctx)
const lenOk = {
peers: 0,
replicationLive: { stallHint: 'length_unavailable', peerCount: 0 }
}
t.is(ctx.bareTopHealthScore(lenOk, 0), 100)
const explicit = {
peers: 1,
replicationLive: { stallHint: 'ok', peerCount: 1, replicationStall: true }
}
t.is(ctx.bareTopHealthScore(explicit, 1), 80)
const d = ctx.bareTopHealthScoreDetail(explicit, 1, null)
t.ok(String(d.breakdown).includes('replication_stall_flag'))
})
test('process_table fixture maps to sorted PID rows via helpers', async (t) => {
const raw = await readFile(processTableFixture, 'utf8')
const pt = JSON.parse(raw)
@@ -0,0 +1,39 @@
import test from 'brittle'
/**
* Mirrors baretop-tui incrementalFrameDiff patch builder (line CUP + EL + line).
* @param {string[]} prevLines
* @param {string[]} nextLines
*/
function bareTopLineDiffPatch(prevLines, nextLines) {
let patch = '\x1b[?25l'
let nch = 0
for (let i = 0; i < nextLines.length; i++) {
if (prevLines[i] !== nextLines[i]) {
nch++
const r = Math.max(1, Math.min(Math.floor(i + 1), 9999))
const c = 1
patch += '\x1b[' + r + ';' + c + 'H' + '\x1b[K' + nextLines[i] + '\r\n'
}
}
patch += '\x1b[?25h'
return { patch, nch }
}
test('incremental line-diff patch is smaller than full frame when one line changes', async (t) => {
const n = 48
const prev = Array.from({ length: n }, (_, i) => 'row-' + i + ' ' + 'x'.repeat(40))
const next = prev.slice()
next[22] = 'row-22 ' + 'CHANGED'.repeat(6)
const full = next.join('\r\n') + '\r\n'
const { patch, nch } = bareTopLineDiffPatch(prev, next)
t.is(nch, 1)
t.ok(
patch.length < full.length,
'expected patch bytes < full frame (' +
patch.length +
' vs ' +
full.length +
')'
)
})
@@ -120,6 +120,91 @@ test('bareTopOverviewLines keeps ASCII section lines within cols', async (t) =>
}
})
test('bareTopNetTabLines sorts interfaces by rx+tx', async (t) => {
const code = await readFile(helpersPath, 'utf8')
const ctx = createContext({})
runInContext(code, ctx)
const lines = ctx.bareTopNetTabLines(
{
interfaces: [
{ name: 'lo', rxBytes: 1, txBytes: 1 },
{ name: 'eth0', rxBytes: 100, txBytes: 50 }
]
},
100
)
t.ok(lines.some((l) => l.includes('interfaces')))
t.ok(lines.some((l) => l.includes('eth0')))
})
test('bareTopNetTabLines expands nested objects (no [object Object])', async (t) => {
const code = await readFile(helpersPath, 'utf8')
const ctx = createContext({})
runInContext(code, ctx)
const raw = await readFile(
join(__dirname, 'fixtures/baretop-net-summary-nested.json'),
'utf8'
)
const net = JSON.parse(raw)
const lines = ctx.bareTopNetTabLines(net, 100, { maxLines: 200 })
const blob = lines.join('\n')
t.ok(!blob.includes('[object Object]'), 'should not stringify objects blindly')
t.ok(blob.includes('replicationQueue'), 'section for queue')
t.ok(blob.includes('peerFirewallStats'), 'section for firewall')
t.ok(blob.includes('bsdSocketGuestBridge'), 'section for bridge')
t.ok(blob.includes('acceptedSessionCount') || blob.includes('10'), 'firewall scalar')
})
test('bareTopNetTabLines respects maxLines cap', async (t) => {
const code = await readFile(helpersPath, 'utf8')
const ctx = createContext({})
runInContext(code, ctx)
const big = { a: 1 }
for (let i = 0; i < 80; i++) big['k' + i] = i
const lines = ctx.bareTopNetTabLines(big, 80, { maxLines: 12 })
t.ok(lines.length <= 12)
t.ok(lines[lines.length - 1].includes('truncated'))
})
test('bareTopSortProcessRows supports nice and cpu keys', async (t) => {
const code = await readFile(helpersPath, 'utf8')
const ctx = createContext({})
runInContext(code, ctx)
const rows = [
{ pid: 1, name: 'a', nice: 0 },
{ pid: 2, name: 'b', nice: 5 }
]
const byNice = ctx.bareTopSortProcessRows(rows, 'nice', true)
t.is(bareTopProcessPidLocal(byNice[0]), 1)
const rows2 = [
{ pid: 1, name: 'a', cpuPct: 10 },
{ pid: 2, name: 'b', cpuPct: 99 }
]
const byCpu = ctx.bareTopSortProcessRows(rows2, 'cpu', false)
t.is(bareTopProcessPidLocal(byCpu[0]), 2)
})
test('bareTopLimitsMergedLines flattens quotas and rlimits', async (t) => {
const code = await readFile(helpersPath, 'utf8')
const ctx = createContext({})
runInContext(code, ctx)
const snap = {
extra: { quotas: { pipe: 8 }, rlimits: { nofile: 1024 } }
}
const lines = ctx.bareTopLimitsMergedLines(snap)
t.ok(lines.some((l) => l.includes('pipe=8')))
t.ok(lines.some((l) => l.includes('nofile=1024')))
})
test('bareTopDelegateInflightTableLines right-aligns counts', async (t) => {
const code = await readFile(helpersPath, 'utf8')
const ctx = createContext({})
runInContext(code, ctx)
const lines = ctx.bareTopDelegateInflightTableLines({ a: 3, b: 12 }, 5, 8)
t.ok(lines[0].includes('b') && lines[0].includes('12'))
t.ok(lines[1].includes('a') && lines[1].includes('3'))
})
test('bareTopParseMeminfoMetrics derives MemTotal and MemAvailable', async (t) => {
const code = await readFile(helpersPath, 'utf8')
const ctx = createContext({})
@@ -0,0 +1,27 @@
{
"schema": 1,
"schemaVersion": 2,
"topicHex": "deadbeef",
"peerCount": 3,
"seedHandshakeError": null,
"replicationQueueDepth": 2,
"replicationQueue": {
"depth": 2,
"pending": 1,
"items": [{ "id": "a" }]
},
"peerFirewallStats": {
"acceptedSessionCount": 10,
"rejectedSessionCount": 1,
"inboundSessionCount": 4,
"outboundSessionCount": 6,
"wave9": { "x": 1 }
},
"bsdSocketGuestBridge": {
"schema": 1,
"policyEnv": "BARE_OS_BSD_SOCKET_POLICY",
"note": "test bridge",
"activeBridgedFds": 0
},
"atMs": 1700000000000
}
@@ -28,5 +28,27 @@
"swarmLifecycle": { "phase": "steady" },
"initdReadiness": { "failed": 0, "starting": 1, "active": 4 },
"workerBudgetHints": { "wallMsMax": 60000 },
"processTable": { "schema": 7, "rows": [] }
"processTable": { "schema": 7, "rows": [] },
"netSummaryNestedExample": {
"schemaVersion": 2,
"topicHex": "deadbeef",
"peerCount": 2,
"seedHandshakeError": "",
"replicationQueueDepth": 4,
"peerFirewallBlockedSessions": 0,
"peerFirewallAllowedSessions": 12,
"replicationQueue": {
"depth": 4,
"lastError": null,
"batches": [{ "id": 1, "state": "pending" }]
},
"peerFirewallStats": {
"sessions": { "blocked": 0, "allowed": 12 }
},
"bsdSocketGuestBridge": {
"schema": 1,
"policyEnv": "default",
"note": "fixture"
}
}
}