add gstack 2 parity and lifecycle gates

This commit is contained in:
Sinabina
2026-07-17 11:08:32 -07:00
parent b6572ebbb7
commit 9919c4cdd3
212 changed files with 29098 additions and 3845 deletions
+80
View File
@@ -3,10 +3,17 @@ import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import {
DEFAULT_MAX_FILES_PER_SHARD,
FREE_TEST_ROOTS,
isFreeTestFile,
collectFreeTestFiles,
containsScheduledProcessExitZero,
containsTopLevelProcessEnvMutation,
detectWindowsFragility,
curateWindowsSafe,
hasScheduledProcessExitZero,
hasTopLevelProcessEnvMutation,
planBoundedFreeTestShards,
stableHash,
assignFilesToShards,
normalizeRelativePath,
@@ -15,6 +22,16 @@ import {
const ROOT = path.resolve(import.meta.dir, '..');
describe('test-free-shards: enumeration', () => {
test('uses the canonical five free-test roots', () => {
expect(FREE_TEST_ROOTS).toEqual([
'browse/test',
'test',
'make-pdf/test',
'design/test',
'ios-qa/daemon/test',
]);
});
test('isFreeTestFile rejects non-test files', () => {
expect(isFreeTestFile('test/foo.ts')).toBe(false);
expect(isFreeTestFile('test/foo.test.ts')).toBe(true);
@@ -23,8 +40,10 @@ describe('test-free-shards: enumeration', () => {
});
test('isFreeTestFile rejects paid eval tests', () => {
expect(isFreeTestFile('browse/test/security-review-fullstack.test.ts')).toBe(false);
expect(isFreeTestFile('test/skill-e2e-foo.test.ts')).toBe(false);
expect(isFreeTestFile('test/skill-llm-eval.test.ts')).toBe(false);
expect(isFreeTestFile('test/skill-routing-e2e.test.ts')).toBe(false);
expect(isFreeTestFile('test/codex-e2e.test.ts')).toBe(false);
expect(isFreeTestFile('test/gemini-e2e.test.ts')).toBe(false);
});
@@ -125,4 +144,65 @@ describe('test-free-shards: sharding', () => {
const b = assignFilesToShards(files, 5);
expect(a).toEqual(b);
});
test('detects scheduled exit-zero cleanup without treating direct fixture exits as scheduled', () => {
const scheduledArrow = ['setTimeout(() => process', '.exit(0), 500);'].join('');
const scheduledFunction = ['setImmediate(function cleanup() { process', '.exit(0); });'].join('');
const directExit = ['process', '.exit(0);'].join('');
const fixtureExit = ["const fixture = 'process", ".exit(0)';"].join('');
expect(containsScheduledProcessExitZero(scheduledArrow)).toBe(true);
expect(containsScheduledProcessExitZero(scheduledFunction)).toBe(true);
expect(containsScheduledProcessExitZero(directExit)).toBe(false);
expect(containsScheduledProcessExitZero(fixtureExit)).toBe(false);
});
test('detects only definite column-zero process.env mutations', () => {
expect(containsTopLevelProcessEnvMutation("process.env.GSTACK_HOME = '/tmp/test';")).toBe(true);
expect(containsTopLevelProcessEnvMutation('delete process.env.GSTACK_HOME; // reset module setup')).toBe(true);
expect(containsTopLevelProcessEnvMutation(" process.env.GSTACK_HOME = '/tmp/test';")).toBe(false);
expect(containsTopLevelProcessEnvMutation('\tdelete process.env.GSTACK_HOME;')).toBe(false);
expect(containsTopLevelProcessEnvMutation("process.env.GSTACK_HOME === '/tmp/test';")).toBe(false);
expect(containsTopLevelProcessEnvMutation("// process.env.GSTACK_HOME = '/tmp/test';")).toBe(false);
});
test('bounded planner isolates scheduled exits and module-scope env mutations', () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'bounded-shards-'));
const files = [
'a.test.ts',
'b.test.ts',
'c.test.ts',
'd.test.ts',
'module-env.test.ts',
'scheduled.test.ts',
];
try {
for (const file of files) fs.writeFileSync(path.join(dir, file), 'test("ok", () => {});');
fs.writeFileSync(
path.join(dir, 'scheduled.test.ts'),
['afterAll(() => setTimeout(() => process', '.exit(0), 500));'].join(''),
);
fs.writeFileSync(path.join(dir, 'module-env.test.ts'), "process.env.GSTACK_HOME = '/tmp/test';");
const shards = planBoundedFreeTestShards(files, { rootDir: dir, maxFilesPerShard: 2 });
expect(shards.flat().sort()).toEqual([...files].sort());
expect(shards.find((shard) => shard.includes('scheduled.test.ts'))).toEqual(['scheduled.test.ts']);
expect(shards.find((shard) => shard.includes('module-env.test.ts'))).toEqual(['module-env.test.ts']);
expect(shards.every((shard) => shard.length <= 2)).toBe(true);
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
});
test('repository plan is bounded and isolates every process-global test', () => {
const files = collectFreeTestFiles(ROOT);
const shards = planBoundedFreeTestShards(files, { rootDir: ROOT });
expect(shards.flat().sort()).toEqual([...files].sort());
expect(shards.every((shard) => shard.length <= DEFAULT_MAX_FILES_PER_SHARD)).toBe(true);
for (const file of files.filter((candidate) => hasScheduledProcessExitZero(path.join(ROOT, candidate)))) {
expect(shards.find((shard) => shard.includes(file))).toEqual([file]);
}
for (const file of files.filter((candidate) => hasTopLevelProcessEnvMutation(path.join(ROOT, candidate)))) {
expect(shards.find((shard) => shard.includes(file))).toEqual([file]);
}
});
});