mirror of
https://github.com/whyour/qinglong.git
synced 2026-11-04 00:42:01 +08:00
test: classify subprocess crashes without exposing credentials
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { test } = require('node:test');
|
||||
const { processFailure } = require('../helpers/process-failure.cjs');
|
||||
|
||||
test('process failure diagnostics classify native crashes without credentials or raw output', () => {
|
||||
const secret = 'private-client-secret';
|
||||
const summary = processFailure({
|
||||
code: null,
|
||||
signal: 'SIGTRAP',
|
||||
killed: false,
|
||||
cmd: `node worker.cjs ${secret}`,
|
||||
message: secret,
|
||||
stdout: JSON.stringify({ token: secret }),
|
||||
stderr: `${secret}\nCheck failed: (data_) != nullptr.\ncompiler/heap-refs.h\nv8::internal::compiler::JSHeapBroker\n`,
|
||||
});
|
||||
assert.equal(JSON.stringify(summary).includes(secret), false);
|
||||
assert.equal(summary.signal, 'SIGTRAP');
|
||||
assert.equal(summary.fatal.v8Check, true);
|
||||
assert.equal(summary.fatal.heapBroker, true);
|
||||
assert.equal(summary.fatal.compiler, true);
|
||||
assert.equal(summary.fatal.outOfMemory, false);
|
||||
assert.equal(summary.fatal.threadCreation, false);
|
||||
});
|
||||
|
||||
test('process failure diagnostics retain timeout and resource classes without arbitrary error fields', () => {
|
||||
const runtime = { versions: { node: '24.21.0' }, arch: 'x64' };
|
||||
const summary = processFailure(
|
||||
{
|
||||
code: 1,
|
||||
signal: 'SIGTERM private-token',
|
||||
killed: true,
|
||||
stderr: 'pthread_create: resource unavailable; heap out of memory',
|
||||
},
|
||||
runtime,
|
||||
);
|
||||
assert.deepEqual(summary, {
|
||||
code: 1,
|
||||
signal: null,
|
||||
killed: true,
|
||||
node: '24.21.0',
|
||||
arch: 'x64',
|
||||
fatal: {
|
||||
threadCreation: true,
|
||||
outOfMemory: true,
|
||||
v8Check: false,
|
||||
heapBroker: false,
|
||||
compiler: false,
|
||||
},
|
||||
});
|
||||
assert.equal(processFailure({ code: 'private-token' }).code, null);
|
||||
assert.equal(processFailure().signal, null);
|
||||
});
|
||||
@@ -7,6 +7,7 @@ const os = require('node:os');
|
||||
const path = require('node:path');
|
||||
const { execFile } = require('node:child_process');
|
||||
const { promisify } = require('node:util');
|
||||
const { processFailure } = require('../helpers/process-failure.cjs');
|
||||
const environment = fs.mkdtempSync(path.join(os.tmpdir(), 'ql-token-env-'));
|
||||
fs.writeFileSync(path.join(environment, '.env'), '');
|
||||
fs.mkdirSync(path.join(environment, 'data/db'), { recursive: true });
|
||||
@@ -622,11 +623,7 @@ test('real SQLite and authentication cache retain concurrent process updates', a
|
||||
assert.equal(
|
||||
outcome.status,
|
||||
'fulfilled',
|
||||
JSON.stringify({
|
||||
code: outcome.reason?.code,
|
||||
signal: outcome.reason?.signal,
|
||||
killed: outcome.reason?.killed,
|
||||
}),
|
||||
JSON.stringify(processFailure(outcome.reason)),
|
||||
);
|
||||
return outcome.value;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// execFile errors contain the command (including credentials), stdout and
|
||||
// stderr. Keep CI diagnostics useful without publishing any of those values.
|
||||
function processFailure(error, runtime = process) {
|
||||
const stderr = String(error?.stderr || '');
|
||||
return {
|
||||
code: Number.isInteger(error?.code) ? error.code : null,
|
||||
signal: /^SIG[A-Z0-9]+$/.test(error?.signal || '') ? error.signal : null,
|
||||
killed: error?.killed === true,
|
||||
node: runtime.versions.node,
|
||||
arch: runtime.arch,
|
||||
fatal: {
|
||||
threadCreation:
|
||||
/uv_thread_create|pthread_create|Failed to start thread|failed to create[^\n]*thread/i.test(
|
||||
stderr,
|
||||
),
|
||||
outOfMemory: /heap out of memory|Allocation failed|OutOfMemory/i.test(
|
||||
stderr,
|
||||
),
|
||||
v8Check: /Check failed:|Fatal error in/i.test(stderr),
|
||||
heapBroker: /JSHeapBroker|compiler\/heap-refs/.test(stderr),
|
||||
compiler: /v8::internal::(?:compiler|maglev)|PersistentHandles/.test(
|
||||
stderr,
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { processFailure };
|
||||
Reference in New Issue
Block a user