Bonsai-Chat-WebGPU / src /engine /blob-integrity.test.ts
Valeriy Selitskiy
Release v1.2.0 live model telemetry
c3633b1
Raw
History Blame Contribute Delete
2.86 kB
import { describe, expect, it, vi } from 'vitest';
import { verifyBlobSha256 } from './blob-integrity';
describe('verifyBlobSha256', () => {
it('accepts the known SHA-256 for a streamed blob', async () => {
const result = await verifyBlobSha256(
new Blob(['abc']),
'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad',
);
expect(result).toEqual({
actualSha256: 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad',
matches: true,
});
});
it('rejects same-size content with a different digest', async () => {
const expected = await verifyBlobSha256(new Blob(['good']), '0'.repeat(64));
const corrupted = await verifyBlobSha256(new Blob(['evil']), expected.actualSha256);
expect(new Blob(['good']).size).toBe(new Blob(['evil']).size);
expect(corrupted.matches).toBe(false);
expect(corrupted.actualSha256).not.toBe(expected.actualSha256);
});
it('reports monotonic byte progress while hashing a shard', async () => {
const data = new Uint8Array(256 * 1024);
data.fill(0x61);
const blob = new Blob([data]);
Object.defineProperty(blob, 'stream', {
value: () => {
let offset = 0;
return new ReadableStream<Uint8Array>({
pull(controller) {
if (offset >= data.byteLength) {
controller.close();
return;
}
const nextOffset = Math.min(data.byteLength, offset + (64 * 1024));
controller.enqueue(data.subarray(offset, nextOffset));
offset = nextOffset;
},
});
},
});
const progress: Array<{ loadedBytes: number; totalBytes: number }> = [];
let timestamp = 0;
const now = vi.spyOn(performance, 'now').mockImplementation(() => {
timestamp += 101;
return timestamp;
});
try {
await verifyBlobSha256(blob, '0'.repeat(64), undefined, (loadedBytes, totalBytes) => {
progress.push({ loadedBytes, totalBytes });
});
} finally {
now.mockRestore();
}
expect(progress[0]).toEqual({ loadedBytes: 0, totalBytes: blob.size });
expect(progress.at(-1)).toEqual({ loadedBytes: blob.size, totalBytes: blob.size });
expect(progress.some(({ loadedBytes }) => loadedBytes > 0 && loadedBytes < blob.size)).toBe(true);
expect(progress.every(({ totalBytes }) => totalBytes === blob.size)).toBe(true);
expect(progress.every((sample, index) => (
index === 0 || sample.loadedBytes >= (progress[index - 1]?.loadedBytes ?? 0)
))).toBe(true);
});
it('stops hashing when the caller aborts', async () => {
const controller = new AbortController();
controller.abort();
await expect(
verifyBlobSha256(new Blob(['abc']), '0'.repeat(64), controller.signal),
).rejects.toMatchObject({ name: 'AbortError' });
});
});