storage-admin.integration.test.ts84 lines · main
| 1 | /** |
| 2 | * Storage admin against REAL DoltGres — sprint plan Sprint 4. |
| 3 | * |
| 4 | * Phase 1: getProjectRowCount counts user tables + total rows correctly on |
| 5 | * DoltGres and excludes _briven_* platform tables. (Bytes stay unmeasurable on |
| 6 | * DoltGres, so rows + tables are what we report.) |
| 7 | * |
| 8 | * Skips when BRIVEN_DATA_PLANE_URL is unset. |
| 9 | */ |
| 10 | import { afterAll, beforeAll, describe, expect, test } from 'bun:test'; |
| 11 | import pg from 'pg'; |
| 12 | |
| 13 | import { |
| 14 | closeProjectDbPools, |
| 15 | dropProjectDatabase, |
| 16 | provisionProjectDatabase, |
| 17 | runInProjectDatabase, |
| 18 | } from '../db/data-plane.js'; |
| 19 | import { getProjectRowCount } from './storage-admin.js'; |
| 20 | |
| 21 | const URL = process.env.BRIVEN_DATA_PLANE_URL; |
| 22 | const HAS_DB = Boolean(URL); |
| 23 | const PROJECT_ID = `p_stor${Date.now().toString(36)}`; |
| 24 | |
| 25 | describe.skipIf(!HAS_DB)('storage-admin getProjectRowCount on real DoltGres (Sprint 4)', () => { |
| 26 | beforeAll(async () => { |
| 27 | await provisionProjectDatabase(PROJECT_ID); |
| 28 | await runInProjectDatabase(PROJECT_ID, async (tx) => { |
| 29 | await tx.unsafe('SET dolt_transaction_commit = 1'); |
| 30 | await tx.unsafe(`CREATE TABLE "widgets" (id integer PRIMARY KEY, label text)`); |
| 31 | await tx.unsafe(`CREATE TABLE "gadgets" (id integer PRIMARY KEY)`); |
| 32 | await tx.unsafe(`INSERT INTO "widgets" (id, label) VALUES (1,'a'),(2,'b'),(3,'c')`); |
| 33 | await tx.unsafe(`INSERT INTO "gadgets" (id) VALUES (10),(20)`); |
| 34 | }); |
| 35 | // NOTE: provisionProjectDatabase already creates the platform _briven_* |
| 36 | // tables (_briven_meta, _briven_migrations). Those exercise the exclusion |
| 37 | // filter for free — getProjectRowCount must NOT count them. |
| 38 | }); |
| 39 | |
| 40 | afterAll(async () => { |
| 41 | await dropProjectDatabase(PROJECT_ID).catch(() => {}); |
| 42 | await closeProjectDbPools().catch(() => {}); |
| 43 | }); |
| 44 | |
| 45 | test('counts user tables + total rows, excluding _briven_*', async () => { |
| 46 | const { rowCount, tableCount } = await getProjectRowCount(PROJECT_ID); |
| 47 | expect(tableCount).toBe(2); // widgets + gadgets; _briven_meta excluded |
| 48 | expect(rowCount).toBe(5); // 3 widgets + 2 gadgets; _briven_meta row excluded |
| 49 | }); |
| 50 | |
| 51 | test('returns zeros (no throw) for an unprovisioned project', async () => { |
| 52 | const res = await getProjectRowCount('p_does_not_exist_zzz'); |
| 53 | expect(res).toEqual({ rowCount: 0, tableCount: 0 }); |
| 54 | }); |
| 55 | |
| 56 | // Migration 0033 runs against the CONTROL-plane DB, which is DoltGres too. |
| 57 | // Prove its DDL is DoltGres-compatible: the tier_storage_caps table, the |
| 58 | // idempotent ON CONFLICT seed, and ADD COLUMN bigint (against a stand-in for |
| 59 | // `projects`, which doesn't exist in the bare data-plane container). |
| 60 | test('migration 0033 DDL is DoltGres-safe', async () => { |
| 61 | const c = new pg.Client({ connectionString: URL }); |
| 62 | await c.connect(); |
| 63 | try { |
| 64 | await c.query(`DROP TABLE IF EXISTS "tier_storage_caps"`); |
| 65 | await c.query( |
| 66 | `CREATE TABLE IF NOT EXISTS "tier_storage_caps" ("tier" text PRIMARY KEY NOT NULL, "max_rows" bigint NOT NULL, "max_tables" bigint NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_by" text)`, |
| 67 | ); |
| 68 | const seed = `INSERT INTO "tier_storage_caps" ("tier","max_rows","max_tables") VALUES ('free',100000,50),('pro',5000000,500),('team',50000000,5000) ON CONFLICT ("tier") DO NOTHING`; |
| 69 | await c.query(seed); |
| 70 | await c.query(seed); // idempotent — DoltGres supports ON CONFLICT DO NOTHING |
| 71 | const r = await c.query(`SELECT tier FROM "tier_storage_caps" ORDER BY tier`); |
| 72 | expect(r.rows.map((x) => x.tier)).toEqual(['free', 'pro', 'team']); |
| 73 | |
| 74 | await c.query(`DROP TABLE IF EXISTS "_proj_addcol_test"`); |
| 75 | await c.query(`CREATE TABLE "_proj_addcol_test" (id text PRIMARY KEY)`); |
| 76 | await c.query(`ALTER TABLE "_proj_addcol_test" ADD COLUMN "storage_max_rows" bigint`); |
| 77 | await c.query(`ALTER TABLE "_proj_addcol_test" ADD COLUMN "storage_max_tables" bigint`); |
| 78 | } finally { |
| 79 | await c.query(`DROP TABLE IF EXISTS "_proj_addcol_test"`).catch(() => {}); |
| 80 | await c.query(`DROP TABLE IF EXISTS "tier_storage_caps"`).catch(() => {}); |
| 81 | await c.end(); |
| 82 | } |
| 83 | }); |
| 84 | }); |