// Shared contract for the ActorStoragePort methods that let commits drop the // blocks they leave unreachable. Every adapter that has them runs this suite. import { describe, expect, it } from 'vitest'; /** @typedef {Required} BlockStorage */ /** * @param {string} name * @param {() => Promise} open */ export function runBlockStorageConformance(name, open) { describe(`${name}: blocks`, () => { it('list in CID order a page at a time, and delete', async () => { const storage = await open(); for (const cid of ['c', 'a', 'b']) { await storage.putBlock(cid, new Uint8Array([cid.charCodeAt(0)])); } const first = await storage.listBlocks(null, 2); expect(first.blocks.map((b) => b.cid)).toEqual(['a', 'b']); expect(first.cursor).toBe('b'); const rest = await storage.listBlocks(first.cursor, 2); expect(rest.blocks.map((b) => [b.cid, [...b.data]])).toEqual([ ['c', [99]], ]); expect(rest.cursor).toBeNull(); await storage.deleteBlocks(['a', 'c']); const left = await storage.listBlocks(null, 10); expect(left.blocks.map((b) => b.cid)).toEqual(['b']); }); it('delete and look up more CIDs than one statement binds', async () => { const storage = await open(); const cids = Array.from({ length: 250 }, (_, i) => `cid${1000 + i}`); for (const cid of cids) { await storage.putBlock(cid, new Uint8Array([1])); await storage.putRecord( `at://did:x/c/${cid}`, cid, 'c', cid, new Uint8Array([1]), ); } expect(await storage.recordCidsAmong(cids)).toHaveLength(250); await storage.deleteBlocks(cids.slice(0, 240)); const left = await storage.listBlocks(null, 500); expect(left.blocks.map((b) => b.cid)).toEqual(cids.slice(240)); }); it('say which CIDs a record still has', async () => { const storage = await open(); const value = new Uint8Array([1]); await storage.putRecord('at://did:x/c/1', 'kept', 'c', '1', value); await storage.putRecord('at://did:x/c/2', 'kept', 'c', '2', value); expect(await storage.recordCidsAmong(['kept', 'gone'])).toEqual(['kept']); }); it('are not collected until a sweep says so', async () => { const storage = await open(); expect(await storage.getBlocksCollected()).toBe(false); await storage.setBlocksCollected(true); expect(await storage.getBlocksCollected()).toBe(true); await storage.setBlocksCollected(false); expect(await storage.getBlocksCollected()).toBe(false); }); }); }