import { beforeEach, describe, expect, mock, test } from "bun:test"; import { memoryScopes } from "../scoped-db/testing"; type Repo = { id: string; owner_id: string; fork_of_id: string | null }; let repos: Repo[] = []; let scopes = memoryScopes(); mock.module("cloudflare:workers", () => ({ env: {}, waitUntil: () => undefined })); mock.module("../db", () => ({ all: async (sql: string, ownerId: string) => sql.includes("owner_id = ?") ? repos.filter((repo) => repo.owner_id === ownerId && repo.fork_of_id) : [], first: async (_sql: string, id: string) => repos.find((repo) => repo.id === id) ?? null, run: async () => ({ meta: { changes: 0 } }), batch: async () => [], stmt: () => ({}), placeholders: (count: number) => Array(count).fill("?").join(", "), chunks: (items: T[]) => [items], MAX_IN_LIST: 90, })); mock.module("../scoped-db", () => ({ repoDb: (id: string) => scopes.repoDb(id), accountDb: (id: string) => scopes.accountDb(id), stmt: (sql: string, ...params: unknown[]) => ({ sql, params }), })); const quota = await import("./bridge-quota"); const GIB = 1024 * 1024 * 1024; function pull(baseId: string, issueId: string, number: number, headRepoId: string) { const db = scopes.raw("repo", baseId); db.query( "INSERT INTO issues (id, repo_id, number, author_id, title, state, is_pull, created_at, updated_at) VALUES (?, ?, ?, 'u', 't', 'open', 1, 0, 0)", ).run(issueId, baseId, number); db.query( "INSERT INTO pull_requests (issue_id, repo_id, head_repo_id, head_ref, head_sha, base_ref, base_sha) VALUES (?, ?, ?, 'f', 'x', 'main', 'y')", ).run(issueId, baseId, headRepoId); } beforeEach(() => { scopes = memoryScopes(); repos = [ { id: "base", owner_id: "upstream", fork_of_id: null }, { id: "fork", owner_id: "mallory", fork_of_id: "base" }, { id: "fork2", owner_id: "mallory", fork_of_id: "base" }, ]; pull("base", "i1", 1, "fork"); pull("base", "i2", 2, "fork2"); }); const charge = (number: number) => ({ headOwnerId: "mallory", baseRepoId: "base", number }); describe("bridge quota", () => { test("charges relayed bytes to the head owner across pull requests", async () => { await quota.recordBridgedBytes(charge(1), 300); await quota.recordBridgedBytes(charge(2), 200); expect(await quota.openBridgedBytes("mallory")).toBe(500); expect(await quota.openBridgedBytes("upstream")).toBe(0); }); test("refuses new bridges once the cap is reached and releases on drop", async () => { await quota.recordBridgedBytes(charge(1), GIB); expect(await quota.bridgeQuotaAvailable(charge(2))).toBe(false); await quota.releaseBridgedBytes("base", "i1"); expect(await quota.bridgeQuotaAvailable(charge(2))).toBe(true); }); test("a repo-wide cleanup releases every pull request touching it", async () => { await quota.recordBridgedBytes(charge(1), 10); await quota.recordBridgedBytes(charge(2), 10); await quota.releaseBridgedBytesForRepo("base"); expect(await quota.openBridgedBytes("mallory")).toBe(0); }); test("a fork's cleanup releases its pull requests held in the parent", async () => { await quota.recordBridgedBytes(charge(1), 10); await quota.recordBridgedBytes(charge(2), 7); await quota.releaseBridgedBytesForRepo("fork"); expect(await quota.openBridgedBytes("mallory")).toBe(7); }); });