import { describe, expect, it } from 'vitest'; import type { QueuedFrame } from '../database'; import { FrameStash } from './frameStash'; const frame = (index: number): QueuedFrame => ({ key: `k${index}`, resourceId: 'r', itemId: 'i', index, bytes: new Uint8Array(10), extraHeaders: {}, createdAt: index }); const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); function fakeDisk(writeMs = 5) { const stored = new Set(); const writes: string[] = []; const removes: string[] = []; return { stored, writes, removes, put: async (f: QueuedFrame) => { await sleep(writeMs); stored.add(f.key); writes.push(f.key); }, remove: async (key: string) => { stored.delete(key); removes.push(key); }, }; } describe('FrameStash', () => { it('宽限期内就被确认的帧:根本不写盘', async () => { const disk = fakeDisk(5); const stash = new FrameStash(disk.put, disk.remove, 8, 100, 4); const frames = [0, 1, 2, 3].map(frame); for (const f of frames) await stash.add(f); await sleep(20); for (const f of frames) stash.accepted(f); await stash.drain(); expect(disk.writes).toEqual([]); expect(disk.stored.size).toBe(0); }); it('超过宽限期还没确认的帧会写入,之后确认时再删除', async () => { const disk = fakeDisk(1); const stash = new FrameStash(disk.put, disk.remove, 8, 30, 4); const first = frame(0); await stash.add(first); await sleep(80); expect(disk.stored.has('k0')).toBe(true); stash.accepted(first); await sleep(10); expect(disk.stored.has('k0')).toBe(false); }); it('断网时(一直不确认)drain 之后全部帧都已落盘,续传才有东西可发', async () => { const disk = fakeDisk(1); const stash = new FrameStash(disk.put, disk.remove, 3, 5000, 4); for (let index = 0; index < 10; index += 1) await stash.add(frame(index)); await stash.drain(); expect(disk.stored.size).toBe(10); }); it('积压超过上限时 add 会等待写盘,不让内存里越堆越多', async () => { const disk = fakeDisk(30); const stash = new FrameStash(disk.put, disk.remove, 2, 5000, 1); let added = 0; const producer = (async () => { for (let index = 0; index < 6; index += 1) { await stash.add(frame(index)); added += 1; } })(); await sleep(40); expect(added).toBeLessThan(6); await producer; await stash.drain(); expect(disk.stored.size).toBe(6); }); it('取消后不会再写入新的帧', async () => { const disk = fakeDisk(5); const stash = new FrameStash(disk.put, disk.remove, 8, 20, 4); await stash.add(frame(0)); await stash.add(frame(1)); await stash.discard(); const before = disk.writes.length; await sleep(60); expect(disk.writes.length).toBe(before); }); it('写盘失败会让加密端停下来并抛出', async () => { const stash = new FrameStash(async () => { throw new Error('quota'); }, async () => {}, 1, 0, 0); await expect((async () => { for (let index = 0; index < 5; index += 1) await stash.add(frame(index)); await stash.drain(); })()).rejects.toThrow('quota'); }); });