Skip to content

Commit df3fd4c

Browse files
committed
Add comprehensive unit tests for CheckpointManager ancestor functionality
- Test markAncestorFinished method for adding stepIds to finished ancestors set - Test hasFinishedAncestor method for proper ancestor hierarchy checking - Test checkpoint skipping behavior when ancestors are finished - Test integration with complex nested hierarchies - Verify that only true ancestors (not siblings) trigger checkpoint skipping - All 13 tests passing with good coverage of the new functionality
1 parent 22fbc0d commit df3fd4c

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import { OperationAction } from "@aws-sdk/client-lambda";
2+
import { CheckpointManager } from "./checkpoint-manager";
3+
import { createTestCheckpointManager } from "../../testing/create-test-checkpoint-manager";
4+
import { createMockExecutionContext } from "../../testing/mock-context";
5+
import { EventEmitter } from "events";
6+
import { createDefaultLogger } from "../logger/default-logger";
7+
8+
describe("CheckpointManager - Ancestor Functionality", () => {
9+
let checkpointManager: CheckpointManager;
10+
let mockContext: any;
11+
12+
beforeEach(() => {
13+
mockContext = createMockExecutionContext();
14+
const emitter = new EventEmitter();
15+
const logger = createDefaultLogger();
16+
checkpointManager = createTestCheckpointManager(
17+
mockContext,
18+
"test-token",
19+
emitter,
20+
logger,
21+
);
22+
});
23+
24+
describe("markAncestorFinished", () => {
25+
it("should add stepId to finished ancestors set", () => {
26+
checkpointManager.markAncestorFinished("1-2");
27+
checkpointManager.markAncestorFinished("1-3-1");
28+
29+
// Access private field for testing
30+
const finishedAncestors = (checkpointManager as any).finishedAncestors;
31+
expect(finishedAncestors.has("1-2")).toBe(true);
32+
expect(finishedAncestors.has("1-3-1")).toBe(true);
33+
});
34+
35+
it("should handle duplicate stepIds", () => {
36+
checkpointManager.markAncestorFinished("1-2");
37+
checkpointManager.markAncestorFinished("1-2");
38+
39+
const finishedAncestors = (checkpointManager as any).finishedAncestors;
40+
expect(finishedAncestors.size).toBe(1);
41+
expect(finishedAncestors.has("1-2")).toBe(true);
42+
});
43+
});
44+
45+
describe("hasFinishedAncestor", () => {
46+
it("should return false when no ancestors are finished", () => {
47+
const hasFinished = (checkpointManager as any).hasFinishedAncestor(
48+
"1-2-3",
49+
);
50+
expect(hasFinished).toBe(false);
51+
});
52+
53+
it("should return true when direct parent is finished", () => {
54+
checkpointManager.markAncestorFinished("1-2");
55+
56+
const hasFinished = (checkpointManager as any).hasFinishedAncestor(
57+
"1-2-3",
58+
);
59+
expect(hasFinished).toBe(true);
60+
});
61+
62+
it("should return true when grandparent is finished", () => {
63+
checkpointManager.markAncestorFinished("1");
64+
65+
const hasFinished = (checkpointManager as any).hasFinishedAncestor(
66+
"1-2-3",
67+
);
68+
expect(hasFinished).toBe(true);
69+
});
70+
71+
it("should return true when any ancestor in chain is finished", () => {
72+
checkpointManager.markAncestorFinished("1-2-3");
73+
74+
const hasFinished = (checkpointManager as any).hasFinishedAncestor(
75+
"1-2-3-4-5",
76+
);
77+
expect(hasFinished).toBe(true);
78+
});
79+
80+
it("should return false when only sibling is finished", () => {
81+
checkpointManager.markAncestorFinished("1-3");
82+
83+
const hasFinished = (checkpointManager as any).hasFinishedAncestor(
84+
"1-2-1",
85+
);
86+
expect(hasFinished).toBe(false);
87+
});
88+
89+
it("should handle root level stepIds", () => {
90+
const hasFinished = (checkpointManager as any).hasFinishedAncestor("1");
91+
expect(hasFinished).toBe(false);
92+
});
93+
});
94+
95+
describe("checkpoint with finished ancestors", () => {
96+
it("should skip checkpoint when ancestor is finished", async () => {
97+
checkpointManager.markAncestorFinished("1-2");
98+
99+
const checkpointPromise = checkpointManager.checkpoint("1-2-3", {
100+
Action: OperationAction.START,
101+
});
102+
103+
// Promise should never resolve when ancestor is finished
104+
let resolved = false;
105+
checkpointPromise.then(() => {
106+
resolved = true;
107+
});
108+
109+
// Wait a bit to ensure promise doesn't resolve
110+
await new Promise((resolve) => setTimeout(resolve, 10));
111+
expect(resolved).toBe(false);
112+
});
113+
114+
it("should not skip checkpoint when no ancestors are finished", () => {
115+
// Test the hasFinishedAncestor logic directly
116+
const hasFinished = (checkpointManager as any).hasFinishedAncestor(
117+
"1-2-3",
118+
);
119+
expect(hasFinished).toBe(false);
120+
});
121+
122+
it("should not skip checkpoint when only siblings are finished", () => {
123+
checkpointManager.markAncestorFinished("1-3");
124+
125+
// Test the hasFinishedAncestor logic directly
126+
const hasFinished = (checkpointManager as any).hasFinishedAncestor(
127+
"1-2-1",
128+
);
129+
expect(hasFinished).toBe(false);
130+
});
131+
});
132+
133+
describe("integration with hierarchical stepIds", () => {
134+
it("should handle complex nested hierarchies", () => {
135+
checkpointManager.markAncestorFinished("1-2-3");
136+
137+
expect(
138+
(checkpointManager as any).hasFinishedAncestor("1-2-3-4-5-6"),
139+
).toBe(true);
140+
expect((checkpointManager as any).hasFinishedAncestor("1-2-4-1")).toBe(
141+
false,
142+
);
143+
expect((checkpointManager as any).hasFinishedAncestor("1-3-1")).toBe(
144+
false,
145+
);
146+
});
147+
148+
it("should handle multiple finished ancestors", () => {
149+
checkpointManager.markAncestorFinished("1");
150+
checkpointManager.markAncestorFinished("1-2");
151+
checkpointManager.markAncestorFinished("1-2-3");
152+
153+
// Should return true for any of the finished ancestors
154+
expect((checkpointManager as any).hasFinishedAncestor("1-2-3-4")).toBe(
155+
true,
156+
);
157+
});
158+
});
159+
});

0 commit comments

Comments
 (0)