Files
8bitworkshop/extension/scripts/survey.js
T

50 lines
2.6 KiB
JavaScript

// Starts each platform in out/emuworker.js and reports whether frames arrive.
// usage: node scripts/survey.js [platform...] (after npm run build)
const { Worker } = require('worker_threads');
const fs = require('fs'), path = require('path');
const ROOT = path.resolve(__dirname, '../..');
const OUT = ROOT + '/extension/out';
function rpcWorker(file) {
const w = new Worker(path.join(OUT, file), { workerData: { rootDir: ROOT }, stdout: true, stderr: true });
let id = 1; const pending = new Map(); const events = [];
w.on('message', m => {
if (m.t === 'result') { const p = pending.get(m.id); pending.delete(m.id); m.error ? p.rej(new Error(m.error.message)) : p.res(m.value); }
else if (m.t === 'event') events.push(m);
});
w.on('error', e => { for (const p of pending.values()) p.rej(e); });
return { w, events, call: (method, ...args) => new Promise((res, rej) => { const i = id++; pending.set(i, { res, rej }); w.postMessage({ t: 'call', id: i, method, args }); }) };
}
function romFor(id) {
for (const d of [id, id.split('-')[0], id.split('.')[0]]) {
const dir = path.join(ROOT, 'test/roms', d);
if (fs.existsSync(dir)) { const f = fs.readdirSync(dir).filter(f => /\.rom$|\.bin$/.test(f))[0]; if (f) return { rom: new Uint8Array(fs.readFileSync(path.join(dir, f))), name: d + '/' + f }; }
}
return { rom: new Uint8Array(+(process.env.ROMSIZE || 0x8000)), name: 'zeros' };
}
const withTimeout = (p, ms) => Promise.race([p, new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), ms))]);
(async () => {
const b = rpcWorker('buildworker.js');
const ids = process.argv[2] ? process.argv.slice(2) : await b.call('listPlatforms');
await b.w.terminate();
for (const id of ids) {
const { rom, name } = romFor(id);
const e = rpcWorker('emuworker.js');
let result;
try {
await withTimeout(e.call('start', id, rom), 8000);
await new Promise(r => setTimeout(r, 1500));
const frames = e.events.filter(x => x.name === 'frame');
const halted = e.events.find(x => x.name === 'status' && x.data?.state === 'halted');
if (halted) result = 'HALTED: ' + halted.data.message;
else if (!frames.length) result = 'NO FRAMES';
else {
const px = new Uint32Array(frames[frames.length-1].data.pixels);
result = `ok ${frames.length} frames ${frames[0].data.width}x${frames[0].data.height}` + (px.some(p => p !== px[0]) ? '' : ' (blank)');
}
} catch (err) { result = 'FAIL: ' + String(err.message).split('\n')[0].slice(0, 140); }
console.log(`${id}\t${name}\t${result}`);
await e.w.terminate().catch(() => {});
}
process.exit(0);
})();