Skip to content

Commit 16c6e1c

Browse files
claude[bot]claude
andauthored
test(driver-sql): budget the 35 inline live-DDL it() blocks (#13902) (#14098)
Thirty-five it() blocks nested in a declareDialectCell(...) callback across eight files each construct a FRESH new SqlDriver(...) against the cell's live MySQL/Postgres server inside their own body, so every one pays a full live connect cycle -- and for all but the charset probe, schema-sync DDL and an information_schema read-back -- per test rather than once in a beforeAll. None carried an explicit timeout, so all inherited vitest's own 5000ms default; the package sets no testTimeout, so that really is vitest's number and not a chosen one. Give each an explicit 60_000 budget, matching e4dc299, with one rationale comment per file naming why and disclaiming that it asserts anything about how slow these tests normally are. Deliberately NOT touched: the five in-cell it() blocks whose live work is hoisted into a beforeAll (sql-driver-backend-fault-envelope.test.ts x2, sql-driver-diagnostic-value-probe.test.ts x3) -- a different cost model, and the latter file's beforeAll is already budgeted at 60_000. No production code, no assertion, and no control changed. Claude-Session: https://claude.ai/code/session_01F3jdziLbAPGeceVNmSox5L Co-authored-by: Claude <noreply@anthropic.com>
1 parent c75962a commit 16c6e1c

8 files changed

Lines changed: 123 additions & 35 deletions

packages/drivers/driver-sql/src/sql-driver-11389-date-tz-skew.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,17 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
436436
driver = undefined;
437437
});
438438

439+
// ── Why the it() below carries an explicit 60_000 budget (#13902) ──
440+
// It constructs a FRESH `new SqlDriver(...)` against this cell's live
441+
// server inside its own body — so the live connect cycle, and the
442+
// schema-sync DDL and catalog read-back that all but the cheapest of these
443+
// drive through it, are paid PER TEST rather than once in a beforeAll.
444+
// With no third argument vitest applies its own 5000ms default — a number
445+
// nobody chose for that work, and one that reddens unrelated PRs when the
446+
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
447+
// no MySQL error in the logs, on a diff that touched no driver). Sized like
448+
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
449+
// an assertion that these tests are normally anywhere near that slow.
439450
it('hands back strings for `date` and `date[]`, and keeps `timestamptz` an instant', async () => {
440451
driver = new SqlDriver(cell.config());
441452
await underProcessZone('Asia/Shanghai', async () => {
@@ -456,6 +467,6 @@ declareDialectCell(PG_CELL, 'date wire form (#11389)', (cell) => {
456467
expect(row.ts instanceof Date).toBe(true);
457468
expect((row.ts as Date).toISOString()).toBe(`${DAY}T00:00:00.000Z`);
458469
});
459-
});
470+
}, 60_000);
460471
});
461472
});

packages/drivers/driver-sql/src/sql-driver-11565-row-byte-budget.test.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,23 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
198198
* the cell asserts the multiplier rather than assuming it, the same way the
199199
* matrix asserts its zone skew instead of hoping for it.
200200
*/
201+
// ── Why the 6 it() blocks below carry an explicit 60_000 budget (#13902) ──
202+
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
203+
// server inside their own body — so the live connect cycle, and the
204+
// schema-sync DDL and catalog read-back that all but the cheapest of these
205+
// drive through it, are paid PER TEST rather than once in a beforeAll.
206+
// With no third argument vitest applies its own 5000ms default — a number
207+
// nobody chose for that work, and one that reddens unrelated PRs when the
208+
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
209+
// no MySQL error in the logs, on a diff that touched no driver). Sized like
210+
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
211+
// an assertion that these tests are normally anywhere near that slow.
201212
it('runs on a 4-byte charset — the boundaries below are utf8mb4 numbers', async () => {
202213
driver = new SqlDriver(cell.config());
203214
const seen = await (driver as any).schemaBytesPerChar();
204215
expect(seen).not.toBeNull();
205216
expect(seen.bytesPerChar).toBe(4);
206-
});
217+
}, 60_000);
207218

208219
/**
209220
* Both sides of the boundary, in one test, because only the pair means
@@ -245,7 +256,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
245256
// ⛔ And nothing was left behind: the object is not registered half-built.
246257
const exists = await (driver as any).knex.schema.hasTable('os11565_over');
247258
expect(exists).toBe(false);
248-
});
259+
}, 60_000);
249260

250261
/** The card's second measured row, moved by the driver's own `id` column. */
251262
it('creates 63 fields at maxLength 255 and refuses 64', async () => {
@@ -259,7 +270,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
259270
await expect(driver.initObjects([wideObject('os11565_over255', 64, 255)])).rejects.toThrow(
260271
/cannot create table "os11565_over255".*Its 64 varchar column\(s\) take 65408 bytes/s,
261272
);
262-
});
273+
}, 60_000);
263274

264275
/**
265276
* The path that is more likely than CREATE in a living app: a field added
@@ -275,7 +286,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
275286
await expect(driver.initObjects([wideObject('os11565_grow', 16, 1024)])).rejects.toThrow(
276287
/cannot add column\(s\) "f16" to "os11565_grow".*Its 16 varchar column\(s\)/s,
277288
);
278-
});
289+
}, 60_000);
279290

280291
/**
281292
* The SECOND limit, which the card's threshold table does not reach and a
@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
296307
expect(message).toMatch(/InnoDB's per-PAGE limit of 8126 bytes/);
297308
expect(message).not.toMatch(/65535-byte budget for one ROW/);
298309
expect(message).toMatch(/"f1" varchar\(63\) = 253 bytes/);
299-
});
310+
}, 60_000);
300311

301312
/**
302313
* The shape a diagnostic reading only DECLARED bounds would have nothing to
@@ -315,6 +326,6 @@ declareDialectCell(MYSQL_CELL, 'row byte budget (#11565)', (cell) => {
315326
const message = String(failure.message);
316327
expect(message).toMatch(/"f1" varchar\(255\) = 1022 bytes/);
317328
expect(message).toMatch(/a field declaring NO `maxLength` still takes varchar\(255\)/i);
318-
});
329+
}, 60_000);
319330
});
320331
});

packages/drivers/driver-sql/src/sql-driver-11627-hash-shadow-key.test.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
132132
* The accept transition: schema creation MySQL REFUSED before this change
133133
* now succeeds, and the constraint is carried on a full-width digest.
134134
*/
135+
// ── Why the 9 it() blocks below carry an explicit 60_000 budget (#13902) ──
136+
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
137+
// server inside their own body — so the live connect cycle, and the
138+
// schema-sync DDL and catalog read-back that all but the cheapest of these
139+
// drive through it, are paid PER TEST rather than once in a beforeAll.
140+
// With no third argument vitest applies its own 5000ms default — a number
141+
// nobody chose for that work, and one that reddens unrelated PRs when the
142+
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
143+
// no MySQL error in the logs, on a diff that touched no driver). Sized like
144+
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
145+
// an assertion that these tests are normally anywhere near that slow.
135146
it('creates a UNIQUE index over a 1024-char column, on a varbinary(32) shadow', async () => {
136147
driver = new SqlDriver(cell.config());
137148
await driver.initObjects([uniqueOn('os11627_wide', 1024)]);
@@ -156,7 +167,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
156167
// ⛔ The control that separates this from the REJECTED route: a prefix
157168
// index reports a SUB_PART. The shadow index keys a whole column.
158169
expect(carried[0].SUB_PART).toBeNull();
159-
});
170+
}, 60_000);
160171

161172
/**
162173
* The boundary, both sides, read from the catalog: 768 characters is the
@@ -176,7 +187,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
176187
const over = await catalog('os11627_over');
177188
expect(String(over.cols.find((c: any) => c.COLUMN_NAME === 'v').DATA_TYPE)).toBe('text');
178189
expect(over.cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME)).length).toBe(1);
179-
});
190+
}, 60_000);
180191

181192
/**
182193
* ⛔ The assertion a PREFIX index fails. Two distinct values sharing their
@@ -198,7 +209,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
198209

199210
// …and the constraint is real: the same value twice is refused.
200211
await expect(knex('os11627_sem').insert({ id: 'dup', v: `${shared}AAA` })).rejects.toThrow();
201-
});
212+
}, 60_000);
202213

203214
/**
204215
* NULL must stay DISTINCT, exactly as under a direct UNIQUE index.
@@ -213,7 +224,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
213224
const knex = (driver as any).knex;
214225
await knex('os11627_null').insert([{ id: 'n1', v: null }, { id: 'n2', v: null }, { id: 'n3', v: null }]);
215226
expect((await knex('os11627_null').whereNull('v')).length).toBe(3);
216-
});
227+
}, 60_000);
217228

218229
/**
219230
* A COMPOSITE unique hashes the tuple, and a tuple containing NULL must
@@ -239,7 +250,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
239250
await knex('os11627_comp').insert([{ id: 's1', a: 'xy', b: '' }, { id: 's2', a: 'x', b: 'y2' }]);
240251
// …and the composite constraint still bites.
241252
await expect(knex('os11627_comp').insert({ id: 'dup', a: 'x', b: 'y' })).rejects.toThrow();
242-
});
253+
}, 60_000);
243254

244255
/**
245256
* The digest stored is the one this repo can independently recompute — the
@@ -257,7 +268,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
257268
const stored: Buffer = row[shadowCol];
258269
expect(stored.length).toBe(32);
259270
expect(stored.toString('hex')).toBe(createHash('sha256').update(value).digest('hex'));
260-
});
271+
}, 60_000);
261272

262273
/**
263274
* The clause-② half: once uniqueness is enforced over a DIGEST, MySQL's
@@ -277,7 +288,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
277288
await expect(driver.create('os11627_dup', { v: 'T'.repeat(900) })).rejects.toThrow(
278289
/duplicate value for the UNIQUE constraint 'uniq_os11627_dup_v'.*\(v\)/s,
279290
);
280-
});
291+
}, 60_000);
281292

282293
/**
283294
* ⛔ NON-UNIQUE indexes are deliberately NOT shadowed. An index over a
@@ -296,7 +307,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow key (#11627)', (cell) => {
296307
await expect(driver.initObjects([nonUnique])).rejects.toThrow(
297308
/hash-shadow|cannot create index|BLOB\/TEXT/i,
298309
);
299-
});
310+
}, 60_000);
300311
});
301312
});
302313

@@ -327,6 +338,6 @@ declareDialectCell(PG_CELL, 'hash-shadow key (#11627)', (cell) => {
327338
);
328339
const defs = (idx.rows ?? []).map((r: any) => String(r.indexdef)).join('\n');
329340
expect(defs).toMatch(/UNIQUE INDEX .*uniq_os11627_pg_v.*\(v\)/i);
330-
});
341+
}, 60_000);
331342
});
332343
});

packages/drivers/driver-sql/src/sql-driver-11794-richtext-text-family.test.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
236236
await driver?.disconnect().catch(() => {});
237237
});
238238

239+
// ── Why the 3 it() blocks below carry an explicit 60_000 budget (#13902) ──
240+
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
241+
// server inside their own body — so the live connect cycle, and the
242+
// schema-sync DDL and catalog read-back that all but the cheapest of these
243+
// drive through it, are paid PER TEST rather than once in a beforeAll.
244+
// With no third argument vitest applies its own 5000ms default — a number
245+
// nobody chose for that work, and one that reddens unrelated PRs when the
246+
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
247+
// no MySQL error in the logs, on a diff that touched no driver). Sized like
248+
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
249+
// an assertion that these tests are normally anywhere near that slow.
239250
it('accepts a >255-char richtext body, and the column really is TEXT (information_schema)', async () => {
240251
driver = new SqlDriver(cell.config());
241252
await driver.execute(`drop table if exists ${T}`).catch(() => {});
@@ -280,7 +291,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
280291
expect(refusal).toBeInstanceOf(Error);
281292
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
282293
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
283-
});
294+
}, 60_000);
284295

285296
it('closes the formerly-open half (#11875): an oversized data-URI signature/qrcode is accepted and round-trips', async () => {
286297
// The #11794 version of this case asserted the COST of leaving
@@ -299,7 +310,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
299310
const [row] = await driver.find(T, { where: { id: 's1' } }, OPTS);
300311
expect(row.body_sig).toBe(DATA_URI);
301312
expect(row.body_qr).toBe(DATA_URI);
302-
});
313+
}, 60_000);
303314

304315
it('keeps #11374 keyed-and-bounded semantics live for the new members (#11875)', async () => {
305316
// A KEYED bounded signature/qrcode column is varchar(maxLength) — the
@@ -348,7 +359,7 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) {
348359
const said = `${String((refusal as { code?: string })?.code ?? '')} ${String((refusal as Error).message)}`;
349360
expect(said).toMatch(/ER_DATA_TOO_LONG|22001|too long/i);
350361
await driver.execute(`drop table if exists ${KT}`).catch(() => {});
351-
});
362+
}, 60_000);
352363
});
353364
});
354365
}

packages/drivers/driver-sql/src/sql-driver-12998-shadow-null-safe-key.test.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,17 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
8686
* equivalence pin: the shadow enforces the SAME key the direct
8787
* `COALESCE(organization_id, '__global__')` index would have.
8888
*/
89+
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
90+
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
91+
// server inside their own body — so the live connect cycle, and the
92+
// schema-sync DDL and catalog read-back that all but the cheapest of these
93+
// drive through it, are paid PER TEST rather than once in a beforeAll.
94+
// With no third argument vitest applies its own 5000ms default — a number
95+
// nobody chose for that work, and one that reddens unrelated PRs when the
96+
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
97+
// no MySQL error in the logs, on a diff that touched no driver). Sized like
98+
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
99+
// an assertion that these tests are normally anywhere near that slow.
89100
it('collides two NULL-organization rows under an org-scoped shadow unique', async () => {
90101
driver = new SqlDriver(cell.config());
91102
await driver.initObjects([orgUniqueOn('os12998_org')]);
@@ -124,7 +135,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
124135
await expect(
125136
knex('os12998_org').insert({ id: 'f', v: V2, organization_id: null }),
126137
).rejects.toThrow(/duplicate/i);
127-
});
138+
}, 60_000);
128139

129140
/**
130141
* ⛔ The control, colocated: a PLAIN composite's expression must NOT gain a
@@ -151,7 +162,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
151162
{ id: 'n2', a: 'x'.repeat(900), b: null },
152163
]);
153164
expect((await knex('os12998_plain').whereNull('b')).length).toBe(2);
154-
});
165+
}, 60_000);
155166

156167
/**
157168
* Turning the constraint ON is data-dependent (ADR-0120 D4's exact shape):
@@ -196,7 +207,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
196207
const { cols, idx } = await catalog('os12998_dirty');
197208
expect(idx.some((i: any) => i.INDEX_NAME === 'uniq_os12998_dirty_org_v')).toBe(false);
198209
expect(cols.filter((c: any) => isHashShadowColumn(c.COLUMN_NAME))).toEqual([]);
199-
});
210+
}, 60_000);
200211

201212
/**
202213
* The write-path half of ruling #11627 clause-②, now for the NULL-safe
@@ -220,6 +231,6 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => {
220231
expect(msg).toMatch(/duplicate value for the UNIQUE constraint 'uniq_os12998_msg_org_v'/);
221232
expect(msg).toContain("COALESCE(organization_id, '__global__')");
222233
expect(msg).not.toContain('HASH COLLISION');
223-
});
234+
}, 60_000);
224235
});
225236
});

packages/drivers/driver-sql/src/sql-driver-13015-shadow-carried-index-drift.test.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,17 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
266266
);
267267
};
268268

269+
// ── Why the 4 it() blocks below carry an explicit 60_000 budget (#13902) ──
270+
// Each constructs a FRESH `new SqlDriver(...)` against this cell's live
271+
// server inside their own body — so the live connect cycle, and the
272+
// schema-sync DDL and catalog read-back that all but the cheapest of these
273+
// drive through it, are paid PER TEST rather than once in a beforeAll.
274+
// With no third argument vitest applies its own 5000ms default — a number
275+
// nobody chose for that work, and one that reddens unrelated PRs when the
276+
// runner is merely a bit slow (#13688 measured exactly this shape: a timeout,
277+
// no MySQL error in the logs, on a diff that touched no driver). Sized like
278+
// this package's siblings — 60_000 is 7 of its 9 explicit budgets — and NOT
279+
// an assertion that these tests are normally anywhere near that slow.
269280
it('a freshly synced shadow-carried unique reports no destructive index drift', async () => {
270281
driver = new SqlDriver(cell.config());
271282
const obj = orgUniqueOn('os13015_fresh');
@@ -281,7 +292,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
281292
// And the shadow COLUMN is still protected from the orphan-column pass —
282293
// the half of the vocabulary that was already taught.
283294
expect(drift.filter((d) => d.kind === 'unmapped_column')).toEqual([]);
284-
});
295+
}, 60_000);
285296

286297
/**
287298
* The remedy pin. Even on a second boot — the runtime ledger empty again,
@@ -312,7 +323,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
312323
await expect(
313324
knex('os13015_apply').insert({ id: 'b', v: V, organization_id: null }),
314325
).rejects.toThrow(/duplicate/i);
315-
});
326+
}, 60_000);
316327

317328
/**
318329
* The surviving generated column, isolated: drop the index by name (exactly
@@ -335,7 +346,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
335346

336347
await driver.initObjects([obj]);
337348
expect(await carriedUniquePresent('os13015_survive', indexName)).toBe(true);
338-
});
349+
}, 60_000);
339350

340351
/**
341352
* The direction a blind skip would have lost: a shadow hashing the RAW
@@ -376,6 +387,6 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) =>
376387
const after = await catalog('os13015_stale');
377388
const fixed = after.cols.find((c: any) => c.COLUMN_NAME === shadow);
378389
expect(String(fixed.GENERATION_EXPRESSION).toLowerCase()).toContain('coalesce');
379-
});
390+
}, 60_000);
380391
});
381392
});

0 commit comments

Comments
 (0)