62 lines
2.7 KiB
JavaScript
62 lines
2.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import ts from '../web/node_modules/typescript/lib/typescript.js';
|
|
|
|
const source = fs.readFileSync(new URL('../web/src/user-file-import.ts', import.meta.url), 'utf8');
|
|
const compiled = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ES2022 } }).outputText.replaceAll('import.meta.url', JSON.stringify(new URL('../web/src/user-file-import.ts', import.meta.url).href));
|
|
const { UserFileImportService } = await import(`data:text/javascript;base64,${Buffer.from(compiled).toString('base64')}`);
|
|
let worker;
|
|
globalThis.Worker = class {
|
|
messages = [];
|
|
constructor() { worker = this; }
|
|
postMessage(message) { if (this.sendError) throw this.sendError; this.messages.push(message); }
|
|
terminate() { this.terminated = true; }
|
|
emit(data) { this.onmessage({ data }); }
|
|
};
|
|
const file = { name: 'part.step', arrayBuffer: async () => new ArrayBuffer(4) };
|
|
const tick = () => new Promise(resolve => setImmediate(resolve));
|
|
const deadline = async promise => {
|
|
let timer;
|
|
try { return await Promise.race([promise, new Promise((_, reject) => { timer = setTimeout(() => reject(new Error('request hung')), 250); })]); }
|
|
finally { clearTimeout(timer); }
|
|
};
|
|
const reject = (promise, pattern) => assert.rejects(deadline(promise), pattern);
|
|
let service = new UserFileImportService();
|
|
let request = reject(service.import(file), /HTTP 503/);
|
|
worker.emit({ type: 'error', message: 'HTTP 503' });
|
|
await request;
|
|
assert.equal(worker.terminated, true);
|
|
|
|
service = new UserFileImportService();
|
|
worker.emit({ type: 'ready' });
|
|
await reject(service.import({ ...file, arrayBuffer: async () => { throw new Error('read failed'); } }), /read failed/);
|
|
worker.sendError = new Error('send failed');
|
|
await reject(service.import(file), /send failed/);
|
|
worker.sendError = null;
|
|
request = service.import(file);
|
|
await tick();
|
|
worker.emit({ type: 'mesh', requestId: worker.messages.at(-1).requestId, payload: { vertexCount: 3 } });
|
|
assert.equal((await deadline(request)).vertexCount, 3);
|
|
|
|
let release;
|
|
request = reject(service.import({ ...file, arrayBuffer: () => new Promise(resolve => { release = resolve; }) }), /cancelled/);
|
|
await tick();
|
|
service.reset();
|
|
await request;
|
|
const count = worker.messages.length;
|
|
release(new ArrayBuffer(4));
|
|
await tick();
|
|
assert.equal(worker.messages.length, count);
|
|
|
|
request = reject(service.import(file), /Worker failed: crash/);
|
|
await tick();
|
|
worker.onerror({ message: 'crash' });
|
|
await request;
|
|
await reject(service.import(file), /crash/);
|
|
|
|
service = new UserFileImportService();
|
|
request = reject(service.import(file), /disposed/);
|
|
service.dispose();
|
|
await request;
|
|
console.log('PASS: startup failure, read/send recovery, reset during read, Worker crash, disposal');
|