Assessor_2.0/tests/server/gpo-inventory-worker-client...

126 lines
6.7 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { NodeGpoInventoryWorkerExecutor } from '../../server/gpo/gpo-inventory-worker-client';
import { executeGpoWorkerOperation } from '../../server/gpo/gpo-inventory-executor';
function workerUrl(source: string): URL {
return new URL(`data:text/javascript,${encodeURIComponent(source)}`);
}
describe('Node GPO inventory worker executor', () => {
it('turns synchronous parser rejections into worker-operation promise rejections', async () => {
let operation: ReturnType<typeof executeGpoWorkerOperation> | undefined;
expect(() => {
operation = executeGpoWorkerOperation({ operation: 'recognition', bytes: new Uint8Array([0, 1, 2, 3]) });
}).not.toThrow();
await expect(operation).rejects.toMatchObject({
diagnostics: [{ code: 'zip-directory-missing' }]
});
});
it('returns isolated inventory results', async () => {
const executor = new NodeGpoInventoryWorkerExecutor({
workerUrl: workerUrl(`import { parentPort } from 'node:worker_threads'; parentPort.postMessage({ ok: true, inventory: { version: 1, recognition: { status: 'unrecognized-zip', evidenceCodes: [] }, archive: { version: 1, containerSha256: '${'a'.repeat(64)}', compressedBytes: 1, uncompressedBytes: 0, entries: [] }, inventory: { version: 1, status: 'unknown', entries: [], diagnosticCodes: [] } } });`),
timeoutMs: 2_000
});
await expect(executor.execute({ bytes: new Uint8Array([1]) })).resolves.toMatchObject({ version: 1 });
await executor.close();
});
it('transfers a worker-owned byte copy without detaching the caller input', async () => {
const sourceBytes = new Uint8Array([1, 2, 3, 4]);
const executor = new NodeGpoInventoryWorkerExecutor({
workerUrl: workerUrl(`import { parentPort, workerData } from 'node:worker_threads'; const valid = workerData.bytes instanceof Uint8Array && workerData.bytes.byteLength === 4 && workerData.bytes[3] === 4; parentPort.postMessage({ ok: valid, inventory: valid ? { version: 1, recognition: { status: 'unrecognized-zip', evidenceCodes: [] }, archive: { version: 1, containerSha256: '${'b'.repeat(64)}', compressedBytes: 4, uncompressedBytes: 0, entries: [] }, inventory: { version: 1, status: 'unknown', entries: [], diagnosticCodes: [] } } : undefined });`),
timeoutMs: 2_000
});
await expect(executor.execute({ bytes: sourceBytes })).resolves.toMatchObject({ version: 1 });
expect([...sourceBytes]).toEqual([1, 2, 3, 4]);
await executor.close();
});
it('returns a compact recognition-only result for upload preflight', async () => {
const executor = new NodeGpoInventoryWorkerExecutor({
workerUrl: workerUrl(
"import { parentPort, workerData } from 'node:worker_threads'; "
+ "parentPort.postMessage({ ok: workerData.operation === 'recognition', "
+ "recognition: { version: 1, recognition: { status: 'gpo-backup-candidate', evidenceCodes: [] } } });"
),
timeoutMs: 2_000
});
await expect(executor.recognize({ bytes: new Uint8Array([1]) })).resolves.toEqual({
version: 1,
recognition: { status: 'gpo-backup-candidate', evidenceCodes: [] }
});
await executor.close();
});
it('returns metadata ingestion results through the same bounded worker boundary', async () => {
const executor = new NodeGpoInventoryWorkerExecutor({
workerUrl: workerUrl(`import { parentPort } from 'node:worker_threads'; parentPort.postMessage({ ok: true, backup: { version: 1, container: {}, metadataDocuments: [], backupInstances: [] } });`),
timeoutMs: 2_000
});
await expect(executor.executeBackup({
bytes: new Uint8Array([1]),
options: { projectId: 'synthetic-project', sourceArtifactId: 'synthetic-artifact', discoveredAt: '2026-07-20T12:00:00.000Z' }
})).resolves.toMatchObject({ version: 1, backupInstances: [] });
await executor.close();
});
it('returns Microsoft baseline analyses through the same bounded worker boundary', async () => {
const executor = new NodeGpoInventoryWorkerExecutor({
workerUrl: workerUrl(
"import { parentPort, workerData } from 'node:worker_threads'; "
+ "parentPort.postMessage({ ok: workerData.operation === 'microsoft-baseline', microsoftBaseline: { "
+ "version: 1, id: 'analysis', baselineId: 'baseline', packageSha256: '" + 'a'.repeat(64) + "', "
+ "analyzer: { id: 'microsoft-baseline-gpo-settings', version: '1.0.0' }, analyzedAt: '2026-08-04T10:00:00.000Z', "
+ "status: 'partial', admxCatalog: {}, backupCount: 0, registryPolicyFileCount: 0, settings: [], diagnosticCodes: [] } });"
),
timeoutMs: 2_000
});
await expect(executor.executeMicrosoftBaseline({
bytes: new Uint8Array([1]),
options: { baselineId: 'baseline', analyzedAt: '2026-08-04T10:00:00.000Z' }
})).resolves.toMatchObject({ baselineId: 'baseline', analyzer: { version: '1.0.0' } });
await executor.close();
});
it('enforces input, concurrency and time limits', async () => {
const executor = new NodeGpoInventoryWorkerExecutor({
workerUrl: workerUrl('setInterval(() => {}, 1000);'), timeoutMs: 50, maximumConcurrent: 1, maximumSourceBytes: 1
});
await expect(executor.execute({ bytes: new Uint8Array(2) }))
.rejects.toMatchObject({ diagnostics: [{ code: 'gpo-inventory-source-size-limit' }] });
const active = executor.execute({ bytes: new Uint8Array(1) });
await expect(executor.execute({ bytes: new Uint8Array(1) }))
.rejects.toMatchObject({ diagnostics: [{ code: 'gpo-inventory-capacity-limit' }] });
await expect(active).rejects.toMatchObject({ diagnostics: [{ code: 'gpo-inventory-time-limit' }] });
await executor.close();
});
it('classifies worker memory failures without exposing raw worker messages', async () => {
const coded = new NodeGpoInventoryWorkerExecutor({
workerUrl: workerUrl(
"const error = new Error('synthetic private worker message'); "
+ "error.code = 'ERR_WORKER_OUT_OF_MEMORY'; throw error;"
),
timeoutMs: 2_000
});
await expect(coded.execute({ bytes: new Uint8Array([1]) })).rejects.toMatchObject({
diagnostics: [{
code: 'gpo-inventory-memory-limit',
details: { workerErrorCode: 'ERR_WORKER_OUT_OF_MEMORY', workerErrorName: 'Error' }
}]
});
await coded.close();
const messageOnly = new NodeGpoInventoryWorkerExecutor({
workerUrl: workerUrl("throw new Error('Worker terminated: JS heap out of memory');"),
timeoutMs: 2_000
});
await expect(messageOnly.execute({ bytes: new Uint8Array([1]) })).rejects.toMatchObject({
diagnostics: [{
code: 'gpo-inventory-memory-limit',
details: { workerErrorCode: 'UNAVAILABLE', workerErrorName: 'Error' }
}]
});
await messageOnly.close();
});
});