UNPKG

worker-testbed

Version:

The AI-ready testbed which use Worker Threads to create isolated vm context

102 lines (98 loc) 3.22 kB
'use strict'; var worker_threads = require('worker_threads'); var url = require('url'); var functoolsKit = require('functools-kit'); var tape = require('tape'); const workerFileSubject = new functoolsKit.BehaviorSubject(); const finishSubject = new functoolsKit.Subject(); let testRegistry = new functoolsKit.ToolRegistry("workertest"); let testCounter = 0; const waitForFile = async () => { if (workerFileSubject.data) { return workerFileSubject.data; } return await workerFileSubject.toPromise(); }; class TestWrapper { testName; cb; constructor(testName, cb) { this.testName = testName; this.cb = cb; } } const test = async (testName, cb) => { if (!worker_threads.isMainThread) { testRegistry = testRegistry.register(testName, new TestWrapper(testName, cb)); return; } const workerFile = await waitForFile(); testCounter += 1; tape(testName, async (test) => { const [awaiter, { resolve }] = functoolsKit.createAwaiter(); let isFinished = false; const worker = new worker_threads.Worker(workerFile, { workerData: { testName }, }); worker.once("message", async ({ status, msg }) => { if (status === "pass") { test.pass(msg); } else if (status === "fail") { test.fail(msg); await functoolsKit.sleep(100); } isFinished = true; worker.terminate(); resolve(); }); worker.on("error", async (err) => { test.fail(`Worker error: ${functoolsKit.getErrorMessage(err)}`); await functoolsKit.sleep(100); resolve(); }); worker.on("exit", async (code) => { if (isFinished) { return; } if (code !== 0) { test.fail(`Worker stopped with exit code ${code}`); await functoolsKit.sleep(100); resolve(); } }); { await awaiter; testCounter -= 1; await finishSubject.next(); } }); }; const run = functoolsKit.singleshot(async (__filename, cb = () => { }) => { if (worker_threads.isMainThread) { await workerFileSubject.next(url.fileURLToPath(__filename)); await finishSubject.filter(() => testCounter === 0).toPromise(); cb(); return; } if (!worker_threads.parentPort) { throw new Error("workertest parentPort is null"); } const finishTest = functoolsKit.singleshot((status, msg) => { worker_threads.parentPort.postMessage({ status, msg }); process.exit(0); }); process.on('uncaughtException', function (err) { // fail current test in worker finishTest("fail", `Uncaught exception: ${functoolsKit.getErrorMessage(err)}`); }); process.on('unhandledRejection', (error) => { throw error; }); testRegistry.get(worker_threads.workerData.testName).cb({ pass: (msg) => finishTest("pass", msg), fail: (msg) => finishTest("fail", msg), }); }); exports.run = run; exports.test = test;