mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-20 03:35:40 +02:00
80 lines
3.1 KiB
JavaScript
80 lines
3.1 KiB
JavaScript
// Run: node --test electron/crashReports.test.js
|
|
//
|
|
// ENG-265 / ENG-285. Four real renderer crashes were fired at the packaged app and NO crash report
|
|
// appeared, with no error line either. That left three indistinguishable explanations: the handler
|
|
// never ran, dedupe suppressed it, or the session cap was hit. `writeCrashReport` returned a bare
|
|
// null on two of those paths and said nothing, so the instrumentation built to diagnose a crash was
|
|
// itself undiagnosable.
|
|
//
|
|
// These assert that a decline is always ANNOUNCED. A crash handler that silently declines is worse
|
|
// than one that fails loudly, because the silence is read as "no crash happened".
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
const fs = require('fs');
|
|
|
|
const crash = require('./crashReports.js');
|
|
|
|
function withCapturedWarn(fn) {
|
|
const lines = [];
|
|
const original = console.warn;
|
|
console.warn = (...a) => lines.push(a.join(' '));
|
|
try { fn(); } finally { console.warn = original; }
|
|
return lines;
|
|
}
|
|
|
|
function initInTemp() {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'osw-crash-'));
|
|
crash.init({
|
|
getVersion: () => '0.0.0-test',
|
|
getPath: () => dir,
|
|
}, null);
|
|
return dir;
|
|
}
|
|
|
|
test('a deduped report says so instead of returning silently', () => {
|
|
initInTemp();
|
|
const first = crash.writeCrashReport('renderer-gone', { message: 'crashed' });
|
|
assert.ok(first, 'the first report should be written');
|
|
const lines = withCapturedWarn(() => {
|
|
const second = crash.writeCrashReport('renderer-gone', { message: 'crashed' });
|
|
assert.equal(second, null, 'an identical crash inside the window must still be suppressed');
|
|
});
|
|
assert.ok(
|
|
lines.some((l) => l.includes('declined') && l.includes('deduped')),
|
|
`a suppressed report announced nothing; lines were ${JSON.stringify(lines)}`,
|
|
);
|
|
});
|
|
|
|
test('the announcement carries the fingerprint and the repeat count, not just a word', () => {
|
|
initInTemp();
|
|
crash.writeCrashReport('gpu-gone', { message: 'oom' });
|
|
const lines = withCapturedWarn(() => crash.writeCrashReport('gpu-gone', { message: 'oom' }));
|
|
assert.ok(lines.some((l) => /seen \d+x/.test(l)), `no repeat count in ${JSON.stringify(lines)}`);
|
|
});
|
|
|
|
test('a DIFFERENT crash is not deduped, so the guard cannot swallow real reports', () => {
|
|
initInTemp();
|
|
assert.ok(crash.writeCrashReport('renderer-gone', { message: 'crashed' }));
|
|
assert.ok(
|
|
crash.writeCrashReport('renderer-gone', { message: 'oom' }),
|
|
'a different fingerprint was suppressed; the dedupe is too broad',
|
|
);
|
|
});
|
|
|
|
test('the session cap announces itself rather than going quiet', () => {
|
|
initInTemp();
|
|
for (let i = 0; i < crash.MAX_REPORTS_PER_SESSION; i++) {
|
|
crash.writeCrashReport('renderer-gone', { message: `distinct-${i}` });
|
|
}
|
|
const lines = withCapturedWarn(() => {
|
|
const over = crash.writeCrashReport('renderer-gone', { message: 'one-too-many' });
|
|
assert.equal(over, null, 'the cap must still hold');
|
|
});
|
|
assert.ok(
|
|
lines.some((l) => l.includes('declined') && l.includes('capped')),
|
|
`hitting the cap announced nothing; lines were ${JSON.stringify(lines)}`,
|
|
);
|
|
});
|