/** * AriaEngine LZ4 压缩 + LSM Merge Iterator 单元测试 */ import { compressLZ4, decompressLZ4 } from '../../src/engine/aria/compression/lz4'; import { MergeIterator, ArrayEntrySource } from '../../src/engine/aria/index/merge_iterator'; // =================================================================== // LZ4 压缩 // =================================================================== describe('AriaEngine — LZ4 Compression', () => { it('压缩+解压往返 — 简单文本', () => { const input = new TextEncoder().encode('hello world hello world hello world'); const compressed = compressLZ4(input); const decompressed = decompressLZ4(compressed, input.byteLength); expect(Array.from(decompressed)).toEqual(Array.from(input)); }); it('压缩+解压 — 重复数据', () => { const pattern = 'ABCD'; const repeated = pattern.repeat(100); const input = new TextEncoder().encode(repeated); const compressed = compressLZ4(input); // 重复数据应该有较好压缩率 expect(compressed.byteLength).toBeLessThan(input.byteLength); const decompressed = decompressLZ4(compressed, input.byteLength); expect(new TextDecoder().decode(decompressed)).toBe(repeated); }); it('压缩 — 太短不压缩', () => { const input = new Uint8Array([1, 2]); const compressed = compressLZ4(input); expect(compressed.byteLength).toBe(input.byteLength); }); it('压缩 — 不可压缩数据返回原始', () => { // 随机数据是不可压缩的 const input = new Uint8Array(256); for (let i = 0; i < 256; i++) input[i] = Math.floor(Math.random() * 256); const compressed = compressLZ4(input); // 不可压缩时应返回原始大小或更小 expect(compressed.byteLength).toBeGreaterThanOrEqual(0); }); it('解压 — 恢复原始数据', () => { const input = new TextEncoder().encode('The quick brown fox jumps over the lazy dog. '.repeat(10)); const compressed = compressLZ4(input); const decompressed = decompressLZ4(compressed, input.byteLength); expect(new TextDecoder().decode(decompressed)).toBe('The quick brown fox jumps over the lazy dog. '.repeat(10)); }); it('压缩后大小不超过原始', () => { for (const size of [10, 50, 100, 200, 500]) { const input = new Uint8Array(size); for (let i = 0; i < size; i++) input[i] = i % 256; const compressed = compressLZ4(input); expect(compressed.byteLength).toBeLessThanOrEqual(input.byteLength + 16); } }); }); // =================================================================== // MergeIterator // =================================================================== describe('AriaEngine — MergeIterator', () => { it('单数据源归并', () => { const mi = new MergeIterator(); mi.addSource(new ArrayEntrySource([ ['a', { v: 1 }], ['b', { v: 2 }], ['c', { v: 3 }], ])); const result = mi.drain(); expect(result).toHaveLength(3); expect(result.map(([k]) => k)).toEqual(['a', 'b', 'c']); }); it('多数据源归并去重(保留最新)', () => { const mi = new MergeIterator(); mi.addSource(new ArrayEntrySource([['a', { v: 'new' }], ['c', { v: 3 }]])); mi.addSource(new ArrayEntrySource([['a', { v: 'old' }], ['b', { v: 2 }]])); const result = mi.drain(); expect(result).toHaveLength(3); expect(result[0][0]).toBe('a'); expect(result[0][1].v).toBe('new'); expect(result[1][0]).toBe('b'); expect(result[2][0]).toBe('c'); }); it('空数据源归并', () => { const mi = new MergeIterator(); mi.addSource(new ArrayEntrySource([])); const result = mi.drain(); expect(result).toHaveLength(0); }); it('大数量归并', () => { const mi = new MergeIterator(); for (let s = 0; s < 5; s++) { const entries: [string, Record][] = []; for (let i = 0; i < 100; i++) { entries.push([`src${s}-key-${String(i).padStart(3, '0')}`, { src: s, idx: i }]); } mi.addSource(new ArrayEntrySource(entries)); } const result = mi.drain(); expect(result).toHaveLength(100); }); it('ArrayEntrySource — 迭代器用完返回 null', () => { const src = new ArrayEntrySource([['k', { v: 1 }]]); expect(src.next()).not.toBeNull(); expect(src.next()).toBeNull(); expect(src.next()).toBeNull(); }); it('ArrayEntrySource — reset 重置', () => { const src = new ArrayEntrySource([['k1', { v: 1 }], ['k2', { v: 2 }]]); src.next(); src.reset(); const val = src.next(); expect(val![0]).toBe('k1'); }); });