Run 48 deleted Kits' file for a fresh start, and the harness's rnhrevolver kit, added after boot with `oxide.reload Kits` through the panel's command endpoint, never reached Kits: no reload or compile job followed, and every test profile was refused for want of the kit. The drill now replaces kits_data.json with one holding only that kit. Kits reads it at boot; RunicNPC's first load adds its example kits beside it (it skips kits already there) and settles its own Kits reload (D329). The add-after-boot stays as a fallback, now through the console's websocket, and is a finding when Kits does not load again. Refs #20, #22 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
68 lines
3.4 KiB
JavaScript
68 lines
3.4 KiB
JavaScript
// The drill's pure parts: how it decides the harness has stopped (issue #20), and what it starts clean.
|
|
// node --test tools/drill/drill.test.js
|
|
|
|
const test = require('node:test')
|
|
const assert = require('node:assert')
|
|
const { harnessProgress, unfinishedFinding, FRESH_DATA, KITS_FILE, harnessKits, HARNESS_STALL_MS } = require('./drill.js')
|
|
|
|
const MIN = 60000
|
|
const T0 = 1000000
|
|
|
|
test('a harness that keeps writing is running, and its clock restarts on each new line', () => {
|
|
let v = harnessProgress(['# run all'], { count: 0, at: T0 }, T0 + 30000, HARNESS_STALL_MS)
|
|
assert.equal(v.state, 'running')
|
|
assert.deepEqual(v.seen, { count: 1, at: T0 + 30000 })
|
|
// Four silent minutes, then a line: still running, and the clock restarts.
|
|
v = harnessProgress(['# run all', 'a: PASS '], v.seen, T0 + 30000 + 4 * MIN, HARNESS_STALL_MS)
|
|
assert.equal(v.state, 'running')
|
|
assert.equal(v.seen.at, T0 + 30000 + 4 * MIN)
|
|
})
|
|
|
|
test('no new line for five minutes is a stall; four minutes and a bit is not', () => {
|
|
const seen = { count: 2, at: T0 }
|
|
const lines = ['# run all', 'a: PASS ']
|
|
assert.equal(harnessProgress(lines, seen, T0 + 5 * MIN - 1, HARNESS_STALL_MS).state, 'running')
|
|
assert.equal(harnessProgress(lines, seen, T0 + 5 * MIN, HARNESS_STALL_MS).state, 'stalled')
|
|
})
|
|
|
|
test('a harness that never wrote a line stalls from when the wait began', () => {
|
|
assert.equal(harnessProgress([], { count: 0, at: T0 }, T0 + 5 * MIN, HARNESS_STALL_MS).state, 'stalled')
|
|
})
|
|
|
|
test('done wins, even when the file has been still for a long time', () => {
|
|
const lines = ['# run all', '# done all: 10 pass, 1 fail']
|
|
assert.equal(harnessProgress(lines, { count: 2, at: T0 }, T0 + 30 * MIN, HARNESS_STALL_MS).state, 'done')
|
|
})
|
|
|
|
test('the stall finding names the last line and the counts', () => {
|
|
const lines = ['# run all', 'place.set.each: FAIL position: off the navmesh', 'place.spawned: FAIL each 0, group 3']
|
|
const f = unfinishedFinding({ pass: 40, fail: 2 }, lines, 'stalled')
|
|
assert.equal(f, 'The harness stopped after `place.spawned: FAIL each 0, group 3` (no output for 5 minutes; 40 pass, 2 fail so far).')
|
|
})
|
|
|
|
test('a backtick in the last line cannot break the issue body, and a long line is cut', () => {
|
|
const f = unfinishedFinding({ pass: 0, fail: 0 }, ['x`y' + 'z'.repeat(500)], 'stalled')
|
|
assert.equal(f.split('`').length, 3)
|
|
assert.ok(f.length < 330)
|
|
assert.match(unfinishedFinding({ pass: 0, fail: 0 }, [], 'stalled'), /stopped after `no line at all`/)
|
|
})
|
|
|
|
test('a capped wait keeps the 45-minute message', () => {
|
|
assert.equal(unfinishedFinding({ pass: 3, fail: 1 }, ['# run all'], 'capped'), 'The harness did not finish in 45 minutes (3 pass, 1 fail so far).')
|
|
})
|
|
|
|
test('the clean start deletes files only: every path ends in .json and none is a directory', () => {
|
|
assert.ok(FRESH_DATA.includes('/oxide/data/RunicNPC/state.json'))
|
|
for (const f of FRESH_DATA) assert.match(f, /^\/oxide\/data\/RunicNPC\/[a-z_]+\.json$/)
|
|
})
|
|
|
|
test("Kits' file is replaced, not deleted, by one holding only the harness's kit (#22)", () => {
|
|
assert.ok(!FRESH_DATA.includes(KITS_FILE))
|
|
assert.equal(KITS_FILE, '/oxide/data/Kits/kits_data.json')
|
|
const kits = harnessKits()._kits
|
|
assert.deepEqual(Object.keys(kits), ['rnhrevolver'])
|
|
assert.equal(kits.rnhrevolver.Name, 'rnhrevolver')
|
|
assert.equal(kits.rnhrevolver.IsHidden, true)
|
|
assert.deepEqual(kits.rnhrevolver.BeltItems.map((i) => i.Shortname), ['pistol.revolver'])
|
|
})
|