feat(FN-4839): harden real-git test timeouts across engine suites
Hardens test timeouts across 12 reliability and integration test files (branch-conflict recovery, merger diff/overlap guards, self-healing, worktree hydration, workflow/file-scope interactions), covering both real-git and mock-based test lanes with consistent timeout adjustments to reduce flakiness. Fusion-Task-Id: FN-4839
This commit is contained in:
committed by
gsxdsm
parent
df998cb54f
commit
5cd0e66654
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { appendFile, mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
@@ -51,7 +53,7 @@ describe("inspectBranchConflict ghost references", () => {
|
||||
});
|
||||
|
||||
expect(result.kind).toBe("stale-resolved");
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("returns tip-already-merged when branch tip is reachable from main despite stale startPoint", async () => {
|
||||
const repoDir = await setupRepo();
|
||||
@@ -80,7 +82,7 @@ describe("inspectBranchConflict ghost references", () => {
|
||||
expect(result.integrationRef).toBe("main");
|
||||
expect(result.tipSha).toBe(await run("git rev-parse fusion/fn-9999", repoDir));
|
||||
}
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("returns tip-already-merged when startPoint is HEAD and tip is ancestor", async () => {
|
||||
const repoDir = await setupRepo();
|
||||
@@ -100,7 +102,7 @@ describe("inspectBranchConflict ghost references", () => {
|
||||
});
|
||||
|
||||
expect(result.kind).toBe("tip-already-merged");
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("keeps genuine live-foreign conflicts unchanged", async () => {
|
||||
const repoDir = await setupRepo();
|
||||
@@ -127,7 +129,7 @@ describe("inspectBranchConflict ghost references", () => {
|
||||
if (result.kind === "live-foreign") {
|
||||
expect(result.error.name).toBe("BranchConflictError");
|
||||
}
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("keeps stale conflictingWorktreePath short-circuit behavior", async () => {
|
||||
const repoDir = await setupRepo();
|
||||
@@ -143,5 +145,5 @@ describe("inspectBranchConflict ghost references", () => {
|
||||
});
|
||||
|
||||
expect(result.kind).toBe("stale");
|
||||
});
|
||||
}, 20_000);
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { appendFile, mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
@@ -69,7 +71,7 @@ describe("branch contamination recovery classification", () => {
|
||||
|
||||
expect(result.alreadyUpstream.map((entry) => entry.sha)).toEqual([commit.sha]);
|
||||
expect(result.unique).toEqual([]);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("classifies all foreign commits as unique when patches are absent on main", async () => {
|
||||
const { repoDir, baseSha } = await setupRepo();
|
||||
@@ -85,7 +87,7 @@ describe("branch contamination recovery classification", () => {
|
||||
|
||||
expect(result.alreadyUpstream).toEqual([]);
|
||||
expect(result.unique.map((entry) => entry.sha)).toEqual([commit.sha]);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("classifies mixed foreign commits into already-upstream and unique buckets", async () => {
|
||||
const { repoDir, baseSha } = await setupRepo();
|
||||
@@ -106,7 +108,7 @@ describe("branch contamination recovery classification", () => {
|
||||
|
||||
expect(result.alreadyUpstream.map((entry) => entry.sha)).toEqual([upstreamCommit.sha]);
|
||||
expect(result.unique.map((entry) => entry.sha)).toEqual([uniqueCommit.sha]);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("classifies bootstrap misbinding when range has only foreign-attributed commits", async () => {
|
||||
const { repoDir, baseSha } = await setupRepo();
|
||||
@@ -125,7 +127,7 @@ describe("branch contamination recovery classification", () => {
|
||||
ownCommitCount: 0,
|
||||
nonAttributedCount: 0,
|
||||
});
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("does not classify bootstrap misbinding when an own-task commit exists", async () => {
|
||||
const { repoDir, baseSha } = await setupRepo();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { mkdtemp, rm, writeFile, appendFile, mkdir } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
@@ -41,7 +43,7 @@ describe("inspectBranchConflict zero-unique behavior", () => {
|
||||
|
||||
const result = await inspectBranchConflict({ repoDir, branchName: "fusion/fn-9001", conflictingWorktreePath: stalePath, requestingTaskId: "FN-9001", ownerTaskId: "FN-9001", startPoint: "main" });
|
||||
expect(result.kind).toBe("tip-already-merged");
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("classifies branch patch already existing upstream as merged/subsumed", async () => {
|
||||
const repoDir = await setupRepo();
|
||||
@@ -60,7 +62,7 @@ describe("inspectBranchConflict zero-unique behavior", () => {
|
||||
|
||||
const result = await inspectBranchConflict({ repoDir, branchName: "fusion/fn-9001", conflictingWorktreePath: stalePath, requestingTaskId: "FN-9001", ownerTaskId: "FN-9001", startPoint: "main" });
|
||||
expect(["tip-already-merged", "fully-subsumed"]).toContain(result.kind);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("returns reclaimable when branch still has unique commit", async () => {
|
||||
const repoDir = await setupRepo();
|
||||
@@ -77,7 +79,7 @@ describe("inspectBranchConflict zero-unique behavior", () => {
|
||||
|
||||
const result = await inspectBranchConflict({ repoDir, branchName: "fusion/fn-9001", conflictingWorktreePath: stalePath, requestingTaskId: "FN-9001", ownerTaskId: "FN-9001", startPoint: "main" });
|
||||
expect(result.kind).toBe("reclaimable");
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("keeps zero-attributed foreign branch as live-foreign", async () => {
|
||||
const repoDir = await setupRepo();
|
||||
@@ -94,5 +96,5 @@ describe("inspectBranchConflict zero-unique behavior", () => {
|
||||
|
||||
const result = await inspectBranchConflict({ repoDir, branchName: "topic/other", conflictingWorktreePath: stalePath, requestingTaskId: "FN-9001", ownerTaskId: "FN-9001", startPoint: "main" });
|
||||
expect(result.kind).toBe("live-foreign");
|
||||
});
|
||||
}, 20_000);
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { join, resolve } from "node:path";
|
||||
@@ -299,7 +301,7 @@ describe("diff-volume gate merger integration", () => {
|
||||
expect(success).toBe(true);
|
||||
expect(git(dir, "git rev-parse HEAD")).not.toBe(preAttemptHeadSha);
|
||||
expect(git(dir, "git show --format= --name-only HEAD").split("\n")).toContain("src/data.gen.ts");
|
||||
});
|
||||
}, 15_000);
|
||||
|
||||
it("allows dropped lockfile-only content in attemptWithSideStrategy", async () => {
|
||||
const dir = mkdtempSync(join(testTempParent(), "fusion-test-diff-volume-merge-"));
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { execSync } from "node:child_process";
|
||||
@@ -365,7 +367,7 @@ describe("aiMergeTask overlap-aware fallback integration", () => {
|
||||
expect(result.resolutionMethod).toBe("mixed");
|
||||
expect(git(dir, "git show HEAD:store.ts")).toContain("branch hardening");
|
||||
expect(git(dir, "git show HEAD:store.ts")).not.toContain("main fallback");
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("keeps legacy main-wins behavior when the conflicting main edit is outside the overlap lookback window", async () => {
|
||||
commitFile(dir, "store.ts", "export const mode = 'base';\n", "feat: add store");
|
||||
@@ -387,7 +389,7 @@ describe("aiMergeTask overlap-aware fallback integration", () => {
|
||||
expect(result.resolutionMethod).toBe("ours");
|
||||
expect(git(dir, "git show HEAD:store.ts")).toContain("main fallback");
|
||||
expect(git(dir, "git show HEAD:store.ts")).not.toContain("branch hardening");
|
||||
}, 15_000);
|
||||
}, 20_000);
|
||||
|
||||
it("warn-only logs overlap but preserves main-wins behavior", async () => {
|
||||
commitFile(dir, "store.ts", "export const mode = 'base';\n", "feat: add store");
|
||||
@@ -408,7 +410,7 @@ describe("aiMergeTask overlap-aware fallback integration", () => {
|
||||
expect(
|
||||
vi.mocked(store.appendAgentLog).mock.calls.some(([, message]) => String(message).includes("Overlap guard detected 1 recent-main overlap file(s)")),
|
||||
).toBe(true);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("ignore preserves legacy behavior without overlap logging", async () => {
|
||||
commitFile(dir, "store.ts", "export const mode = 'base';\n", "feat: add store");
|
||||
@@ -429,7 +431,7 @@ describe("aiMergeTask overlap-aware fallback integration", () => {
|
||||
expect(
|
||||
vi.mocked(store.appendAgentLog).mock.calls.some(([, message]) => String(message).includes("Overlap guard detected")),
|
||||
).toBe(false);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it(
|
||||
"replays FN-3936 through the merger so branch hardening survives the final squash commit",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { makeReliabilityFixture, hasGit, git } from "./_helpers.js";
|
||||
|
||||
@@ -23,7 +25,7 @@ describeIfGit("reliability interactions: audit + recovery", () => {
|
||||
const task = await fx.store.getTask(fx.task.id);
|
||||
expect(recovered).toBeGreaterThanOrEqual(0);
|
||||
expect(["in-review", "done"]).toContain(task?.column ?? "");
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("Case 4: already-done is idempotent", async () => {
|
||||
const fx = await makeReliabilityFixture({ taskId: "FN-4361-C4" });
|
||||
@@ -31,7 +33,7 @@ describeIfGit("reliability interactions: audit + recovery", () => {
|
||||
await fx.store.updateTask(fx.task.id, { column: "done", status: null } as any);
|
||||
const recovered = await fx.selfHeal.recoverAlreadyMergedReviewTasks();
|
||||
expect(recovered).toBe(0);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("Case 13: tree-equal does not promote when worktree has staged changes", async () => {
|
||||
const fx = await makeReliabilityFixture({ taskId: "FN-4361-C13" });
|
||||
@@ -51,5 +53,5 @@ describeIfGit("reliability interactions: audit + recovery", () => {
|
||||
const task = await fx.store.getTask(fx.task.id);
|
||||
expect(["in-review", "done"]).toContain(task?.column ?? "");
|
||||
expect(git(fx.rootDir, "git rev-parse HEAD").length).toBe(40);
|
||||
});
|
||||
}, 20_000);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/**
|
||||
* Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
* without re-measuring under pnpm test:full. (FN-4839)
|
||||
*
|
||||
* FN-4811 follow-up: persisted dedup of done-task finalize-integrity warnings.
|
||||
*
|
||||
* Before this change, `SelfHealingManager.reconcileDoneTaskIntegrity()` deduped
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { checkDiffVolume } from "../../merger-diff-volume-gate.js";
|
||||
import { makeReliabilityFixture, hasGit, git } from "./_helpers.js";
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { classifyOwnedLandedEvidence } from "../../merger.js";
|
||||
import { makeReliabilityFixture, hasGit } from "./_helpers.js";
|
||||
@@ -75,5 +77,5 @@ describe("no-changes-finalized reliability interactions (real git)", () => {
|
||||
} finally {
|
||||
await fixture.cleanup();
|
||||
}
|
||||
});
|
||||
}, 20_000);
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { assertSquashOverlapsFileScope, FileScopeViolationError } from "../../merger.js";
|
||||
import { makeReliabilityFixture, hasGit, git } from "./_helpers.js";
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { execSync, spawnSync } from "node:child_process";
|
||||
import { existsSync, mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
@@ -267,7 +269,7 @@ describeIfGit("SelfHealingManager recoverAlreadyMergedReviewTasks (real git)", (
|
||||
expect((store as any).recordRunAuditEvent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ mutationType: "task:auto-recover-branch-misbound", target: "FN-TEST-MISBOUND" }),
|
||||
);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("is idempotent across two maintenance passes", async () => {
|
||||
const repo = setupRepo();
|
||||
@@ -292,7 +294,7 @@ describeIfGit("SelfHealingManager recoverAlreadyMergedReviewTasks (real git)", (
|
||||
const secondRecoveryLogs = (store.logEntry as any).mock.calls.filter((call: unknown[]) => String(call[1]).includes("Auto-finalized from in-review/paused")).length;
|
||||
expect(firstRecoveryLogs).toBe(1);
|
||||
expect(secondRecoveryLogs).toBe(1);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("short-circuits when paused", async () => {
|
||||
const repo = setupRepo();
|
||||
@@ -309,5 +311,5 @@ describeIfGit("SelfHealingManager recoverAlreadyMergedReviewTasks (real git)", (
|
||||
const enginePausedManager = new SelfHealingManager(enginePausedStore, { rootDir: repo, getExecutingTaskIds: () => new Set() });
|
||||
await enginePausedManager.recoverAlreadyMergedReviewTasks();
|
||||
expect(enginePausedStore.listTasks).not.toHaveBeenCalled();
|
||||
});
|
||||
}, 20_000);
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Real-git/SQLite wallclock under parallel CI load; do not lower per-test timeouts
|
||||
// without re-measuring under pnpm test:full. (FN-4839)
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { chmodSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
||||
import { mkdtempSync, rmSync } from "node:fs";
|
||||
@@ -95,7 +97,7 @@ describe("hydrateWorktreeDb", () => {
|
||||
const capped = await hydrateWorktreeDb({ rootDir: root, worktreePath: worktree, taskId: "FN-0", store: store as any, logger: { warn: vi.fn() } });
|
||||
expect(cyc.degraded).toBe(false);
|
||||
expect(capped.tasksCopied).toBeLessThanOrEqual(50);
|
||||
});
|
||||
}, 20_000);
|
||||
|
||||
it("handles schema drift by dropping missing destination columns", async () => {
|
||||
const root = makeProject("h-drift-");
|
||||
|
||||
Reference in New Issue
Block a user