⚡ Zero-dependency plcbundle library exclusively for Bun
at main 2.9 kB view raw
1import { describe, test, expect, beforeEach } from 'bun:test'; 2import { PLCBundle } from '../src/plcbundle'; 3import { TEMP_DIR, createMockIndex, createMockOperations } from './setup'; 4 5describe('Multi-threaded Processing', () => { 6 let bundle: PLCBundle; 7 let modulePath: string; 8 9 beforeEach(async () => { 10 bundle = new PLCBundle(TEMP_DIR); 11 12 const mockIndex = createMockIndex(); 13 await bundle.saveIndex(mockIndex); 14 15 // Create test bundles 16 for (let i = 1; i <= 5; i++) { 17 const operations = createMockOperations(100); 18 const jsonl = operations.map(op => JSON.stringify(op)).join('\n') + '\n'; 19 const compressed = Bun.zstdCompressSync(new TextEncoder().encode(jsonl)); 20 await Bun.write(bundle.getBundlePath(i), compressed); 21 } 22 23 // Create test module - use absolute path 24 modulePath = `${process.cwd()}/${TEMP_DIR}/test-module.ts`; 25 await Bun.write(modulePath, ` 26 export function detect({ op }) { 27 return op.did.length > 10 ? ['long-did'] : []; 28 } 29 `); 30 }); 31 32 test('module loads correctly', async () => { 33 const mod = await import(modulePath); 34 expect(mod.detect).toBeDefined(); 35 }); 36 37 test('single-threaded processing works', async () => { 38 const stats = await bundle.processBundles(1, 2, { 39 module: modulePath, 40 threads: 1, 41 }); 42 43 expect(stats.totalOps).toBe(200); // 2 bundles * 100 ops 44 expect(stats.totalBytes).toBeGreaterThan(0); 45 }); 46 47 test('multi-threaded processing with 2 threads', async () => { 48 const stats = await bundle.processBundles(1, 4, { 49 module: modulePath, 50 threads: 2, 51 }); 52 53 expect(stats.totalOps).toBe(400); // 4 bundles * 100 ops 54 expect(stats.totalBytes).toBeGreaterThan(0); 55 }); 56 57 test('multi-threaded produces same op count as single-threaded', async () => { 58 const stats1 = await bundle.processBundles(1, 3, { 59 module: modulePath, 60 threads: 1, 61 }); 62 63 const stats2 = await bundle.processBundles(1, 3, { 64 module: modulePath, 65 threads: 2, 66 }); 67 68 expect(stats1.totalOps).toBe(stats2.totalOps); 69 expect(stats1.totalBytes).toBe(stats2.totalBytes); 70 }); 71 72 test('progress callback works with multi-threading', async () => { 73 let progressCalls = 0; 74 75 await bundle.processBundles(1, 5, { 76 module: modulePath, 77 threads: 2, 78 onProgress: () => { 79 progressCalls++; 80 }, 81 }); 82 83 // May or may not be called depending on threshold 84 expect(typeof progressCalls).toBe('number'); 85 }); 86 87 test('validates threads parameter', async () => { 88 let errorThrown = false; 89 90 try { 91 await bundle.processBundles(1, 1, () => {}, { 92 threads: 4, // Without module - should throw 93 }); 94 } catch (error) { 95 errorThrown = true; 96 expect((error as Error).message).toContain('module'); 97 } 98 99 expect(errorThrown).toBe(true); 100 }); 101});