import { beforeEach, describe, expect, mock, test } from "bun:test"; import { Database } from "bun:sqlite"; import { readFileSync } from "node:fs"; import { memoryScopes } from "../scoped-db/testing"; type Value = string | number | null; function fakeD1(db: Database) { const prepare = (sql: string) => { let params: Value[] = []; const statement = { bind(...values: Value[]) { params = values; return statement; }, async run() { db.query(sql).run(...params); return { success: true, meta: {} }; }, async all() { return { results: db.query(sql).all(...params) as T[] }; }, exec: () => db.query(sql).run(...params), }; return statement; }; return { prepare, async batch(statements: Array<{ exec: () => unknown }>) { db.transaction(() => statements.forEach((statement) => statement.exec()))(); return []; }, }; } const advisoryDb = new Database(":memory:"); advisoryDb.exec( readFileSync(new URL("../../../migrations-advisories/0001_published_advisory_packages.sql", import.meta.url), "utf8"), ); const scopes = memoryScopes(); mock.module("cloudflare:workers", () => ({ env: { ADVISORY_DB: fakeD1(advisoryDb), }, })); mock.module("../scoped-db", () => scopes.module); const visibility = new Map([ ["r1", "public"], ["r2", "public"], ]); mock.module("../db", () => ({ first: async (_sql: string, repoId: string) => visibility.has(repoId) ? { visibility: visibility.get(repoId) } : null, all: async (_sql: string, ...ids: string[]) => ids.filter((id) => visibility.get(id) === "public").map((id) => ({ id })), placeholders: (count: number) => Array.from({ length: count }, () => "?").join(", "), chunks: (items: T[], size = 90) => { const out: T[][] = []; for (let index = 0; index < items.length; index += size) out.push(items.slice(index, index + size)); return out; }, })); const { dropRepoAdvisoryIndex, indexAdvisory, packageKey, publishedAdvisoryCounts, syncRepoAdvisoryIndex } = await import("./advisory-packages"); function seedAdvisory(repoId: string, id: string, state: string, packageName: string | null = "left-pad") { scopes .raw("repo", repoId) .query( `INSERT OR REPLACE INTO security_advisories (id, repo_id, ghsa_id, title, description, severity, ecosystem, package_name, state, source, created_at, updated_at) VALUES (?, ?, ?, 'T', 'D', 'high', 'npm', ?, ?, 'maintainer', 1, 1)`, ) .run(id, repoId, `GITFOR-${id}`, packageName, state); } const leftPad = [{ ecosystem: "npm", name: "left-pad" }]; describe("published advisory index", () => { beforeEach(() => { advisoryDb.exec("DELETE FROM published_advisory_packages"); visibility.set("r1", "public"); visibility.set("r2", "public"); }); test("only published advisories with a package match", async () => { seedAdvisory("r1", "a1", "published"); seedAdvisory("r1", "a2", "draft"); seedAdvisory("r2", "a3", "published", null); await Promise.all([indexAdvisory("r1", "a1"), indexAdvisory("r1", "a2"), indexAdvisory("r2", "a3")]); const counts = await publishedAdvisoryCounts([...leftPad, { ecosystem: "npm", name: "other" }]); expect(counts.get(packageKey("npm", "left-pad"))).toBe(1); expect(counts.has(packageKey("npm", "other"))).toBe(false); }); test("withdrawing or deleting the repo removes the match", async () => { seedAdvisory("r1", "a1", "published"); seedAdvisory("r2", "b1", "published"); await indexAdvisory("r1", "a1"); await indexAdvisory("r2", "b1"); expect((await publishedAdvisoryCounts(leftPad)).get(packageKey("npm", "left-pad"))).toBe(2); seedAdvisory("r1", "a1", "closed"); await indexAdvisory("r1", "a1"); expect((await publishedAdvisoryCounts(leftPad)).get(packageKey("npm", "left-pad"))).toBe(1); await dropRepoAdvisoryIndex("r2"); expect((await publishedAdvisoryCounts(leftPad)).size).toBe(0); }); test("private repositories never show up in another repository's counts", async () => { visibility.set("r1", "private"); seedAdvisory("r1", "a1", "published", "acme-internal-sdk"); await indexAdvisory("r1", "a1"); expect((await publishedAdvisoryCounts([{ ecosystem: "npm", name: "acme-internal-sdk" }])).size).toBe(0); }); test("going private drops the repository's rows; even stale rows are filtered at read time", async () => { seedAdvisory("r1", "a1", "published"); await indexAdvisory("r1", "a1"); visibility.set("r1", "private"); expect((await publishedAdvisoryCounts(leftPad)).size).toBe(0); await syncRepoAdvisoryIndex("r1"); expect(advisoryDb.query("SELECT COUNT(*) AS n FROM published_advisory_packages").get()).toEqual({ n: 0 }); visibility.set("r1", "public"); await syncRepoAdvisoryIndex("r1"); expect((await publishedAdvisoryCounts(leftPad)).get(packageKey("npm", "left-pad"))).toBe(1); }); });