import { getPublicKey, randomPrivateKey, } from "@suaveplan/crypto-curve/ed25519"; import { Drive, type DriveStorage } from "@suaveplan/drive"; import { MemoryStorage } from "@suaveplan/storage/memory"; import { describe, expect, it } from "@suaveplan/testing/runner"; import { CHUNKS_CODES, ChunksError } from "./error-codes.js"; import { chunksPlugin } from "./plugin.js"; function makeFailingStorage(failOn: (key: string) => boolean): DriveStorage { const inner = new MemoryStorage(); return Object.assign(inner, { id: "default", set(key: string, value: Uint8Array): Promise { if (failOn(key)) { throw new Error(`disk full for ${key}`); } return MemoryStorage.prototype.set.call(inner, key, value); }, }) as unknown as DriveStorage; } function makeFailingStorageNonError( failOn: (key: string) => boolean ): DriveStorage { const inner = new MemoryStorage(); return Object.assign(inner, { id: "default", set(key: string, value: Uint8Array): Promise { if (failOn(key)) { const literal: unknown = "literal-throwable"; throw literal; } return MemoryStorage.prototype.set.call(inner, key, value); }, }) as unknown as DriveStorage; } describe("CHUNKS-INGEST-FAILED — non-ChunksError storage failures wrap as INGEST_FAILED", () => { it("wraps a manifest-write Error into ChunksError(INGEST_FAILED)", { timeout: 5000, }, async () => { const privKey = randomPrivateKey(); const pubKey = getPublicKey(privKey); const storage = makeFailingStorage((k) => k.startsWith("manifest:")); const drive = new Drive(storage); await drive.initialize(); const chunks = await drive.usePlugin( chunksPlugin({ serverPrivKey: privKey, serverPubKey: pubKey, chunkSize: 1024, }) ); await drive.write("test.txt", new TextEncoder().encode("hello")); try { await chunks.ingest("test.txt"); throw new Error("expected ingest to throw"); } catch (e) { expect(e).toBeInstanceOf(ChunksError); expect((e as ChunksError).code).toBe(CHUNKS_CODES.INGEST_FAILED); expect((e as ChunksError).message).toContain("disk full"); } await drive.dispose(); }); it("passes through a ChunksError thrown inside the ingest path without re-wrapping", { timeout: 5000, }, async () => { const privKey = randomPrivateKey(); const pubKey = getPublicKey(privKey); const inner = new MemoryStorage(); const chunksErrorStorage = Object.assign(inner, { id: "default", set(key: string, value: Uint8Array): Promise { if (key.startsWith("manifest:")) { throw new ChunksError( CHUNKS_CODES.SIG_INVALID, "synthetic: bypass wrapping" ); } return MemoryStorage.prototype.set.call(inner, key, value); }, }) as unknown as DriveStorage; const drive = new Drive(chunksErrorStorage); await drive.initialize(); const chunks = await drive.usePlugin( chunksPlugin({ serverPrivKey: privKey, serverPubKey: pubKey, chunkSize: 1024, }) ); await drive.write("test.txt", new TextEncoder().encode("hello")); try { await chunks.ingest("test.txt"); throw new Error("expected ingest to throw"); } catch (e) { expect(e).toBeInstanceOf(ChunksError); expect((e as ChunksError).code).toBe(CHUNKS_CODES.SIG_INVALID); expect((e as ChunksError).message).toContain( "synthetic: bypass wrapping" ); } await drive.dispose(); }); it("wraps a non-Error throwable into ChunksError(INGEST_FAILED)", { timeout: 5000, }, async () => { const privKey = randomPrivateKey(); const pubKey = getPublicKey(privKey); const storage = makeFailingStorageNonError((k) => k.startsWith("manifest:") ); const drive = new Drive(storage); await drive.initialize(); const chunks = await drive.usePlugin( chunksPlugin({ serverPrivKey: privKey, serverPubKey: pubKey, chunkSize: 1024, }) ); await drive.write("test.txt", new TextEncoder().encode("hello")); try { await chunks.ingest("test.txt"); throw new Error("expected ingest to throw"); } catch (e) { expect(e).toBeInstanceOf(ChunksError); expect((e as ChunksError).code).toBe(CHUNKS_CODES.INGEST_FAILED); expect((e as ChunksError).message).toContain("literal-throwable"); } await drive.dispose(); }); });