GitNexus/gitnexus/test/unit/lbug-publication.test.ts
Gergő Magyar c8629f1b6c
fix(storage): preserve published graph on rebuild failure (#3613)
* fix(storage): preserve published graph on rebuild failure (U1)

* test(storage): strengthen publication review coverage (U1)

* test(storage): align publication evidence (U1)

* fix(storage): retain completed recovery archives

* fix(storage): preserve quarantines before cache reads

* ci: run staged publication benchmark guard

* fix(ci): declare WAL replay probe determinism

Document that the bounded recovery read drains and discards its rows. Only WAL replay success is observed; row identity and query behavior are unchanged. The existing 21 query-determinism checks pass.

* test(storage): cover publication across platforms

* test(ci): exclude POSIX suite from Windows estimates

* test: allow native publication retry to finish

* test: verify Windows incremental recovery

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-17 18:45:11 +01:00

53 lines
1.8 KiB
TypeScript

import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { afterEach, beforeEach, expect, it } from 'vitest';
import { assertLbugPublicationReady } from '../../src/core/lbug/publication.js';
let root: string;
beforeEach(async () => {
root = await fs.mkdtemp(path.join(os.tmpdir(), 'gn-publication-'));
});
afterEach(async () => {
await fs.rm(root, { recursive: true, force: true });
});
it('allows a settling sidecar to disappear before the bounded publication check', async () => {
const db = path.join(root, 'lbug');
await fs.writeFile(`${db}.wal`, 'settling');
const removal = new Promise<void>((resolve, reject) =>
setTimeout(() => {
fs.unlink(`${db}.wal`).then(resolve, reject);
}, 10),
);
await assertLbugPublicationReady(db);
await removal;
});
it.each([
'.wal',
'.shadow',
'.wal.checkpoint',
'.checkpoint.intent.lock',
'.checkpoint.apply.lock',
'.wal.missing-shadow.1234-abcd',
'.shadow.orphan.1234',
'.wal.dirty-recovery.next',
'.shadow.dirty-recovery.next',
])('refuses a persistent %s and names the affected database', async (suffix) => {
const db = path.join(root, 'lbug');
await fs.writeFile(`${db}${suffix}`, 'pending recovery');
await expect(assertLbugPublicationReady(db)).rejects.toThrow(db);
expect(await fs.readFile(`${db}${suffix}`, 'utf8')).toBe('pending recovery');
});
it('retains completed dirty-recovery archives without blocking publication', async () => {
const db = path.join(root, 'lbug');
for (const suffix of ['.wal.dirty-recovery', '.shadow.dirty-recovery']) {
await fs.writeFile(`${db}${suffix}`, 'retained crash evidence');
}
await assertLbugPublicationReady(db);
for (const suffix of ['.wal.dirty-recovery', '.shadow.dirty-recovery']) {
expect(await fs.readFile(`${db}${suffix}`, 'utf8')).toBe('retained crash evidence');
}
});