Skip to content

Commit 9a7e6ee

Browse files
jbachorikclaude
andcommitted
Fix FPChainProgression_ValidChain test flakiness
Use explicit buffer layout instead of local variables to control frame ordering in memory. Compiler stack allocation order was unpredictable, causing test failures. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 387f36d commit 9a7e6ee

1 file changed

Lines changed: 28 additions & 10 deletions

File tree

ddprof-lib/src/test/cpp/stackWalkValidation_ut.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,30 +90,48 @@ TEST_F(StackWalkValidationTest, sameStack_FarApart) {
9090
* - This violates the fp > prev_fp invariant
9191
*/
9292
TEST_F(StackWalkValidationTest, FPChainProgression_ValidChain) {
93-
// Simulate a valid FP chain where each frame is at a higher address
94-
MockFrame frame3 = {0, nullptr}; // Oldest frame (null FP = end)
95-
MockFrame frame2 = {(uintptr_t)&frame3, (void*)0x400000};
96-
MockFrame frame1 = {(uintptr_t)&frame2, (void*)0x400100};
93+
// Allocate frames in a buffer with controlled layout
94+
// Frame layout must simulate: frame1 (low addr) -> frame2 -> frame3 (high addr)
95+
// where each frame's saved_fp points to the next higher frame
96+
alignas(sizeof(uintptr_t)) char buffer[3 * sizeof(MockFrame)];
9797

98-
uintptr_t fp = (uintptr_t)&frame1;
98+
MockFrame* frame1 = (MockFrame*)(buffer);
99+
MockFrame* frame2 = (MockFrame*)(buffer + sizeof(MockFrame));
100+
MockFrame* frame3 = (MockFrame*)(buffer + 2 * sizeof(MockFrame));
101+
102+
// Verify ordering: frame1 < frame2 < frame3
103+
ASSERT_LT((uintptr_t)frame1, (uintptr_t)frame2);
104+
ASSERT_LT((uintptr_t)frame2, (uintptr_t)frame3);
105+
106+
// Setup chain: frame1 -> frame2 -> frame3 -> null
107+
frame3->saved_fp = 0; // Oldest frame (null FP = end)
108+
frame3->return_addr = nullptr;
109+
110+
frame2->saved_fp = (uintptr_t)frame3;
111+
frame2->return_addr = (void*)0x400000;
112+
113+
frame1->saved_fp = (uintptr_t)frame2;
114+
frame1->return_addr = (void*)0x400100;
115+
116+
uintptr_t fp = (uintptr_t)frame1;
99117

100118
// Walk the chain and verify progression
101119
uintptr_t prev_fp = fp;
102-
fp = *(uintptr_t*)fp; // Read saved FP
120+
fp = *(uintptr_t*)fp; // Read saved FP from frame1
103121

104-
// Valid: next FP should be greater than current
122+
// Valid: next FP (frame2) should be greater than current (frame1)
105123
EXPECT_GT(fp, prev_fp);
106124
EXPECT_TRUE(aligned(fp));
107125

108126
prev_fp = fp;
109-
fp = *(uintptr_t*)fp;
127+
fp = *(uintptr_t*)fp; // Read saved FP from frame2
110128

111-
// Valid: next FP should still be greater
129+
// Valid: next FP (frame3) should be greater than current (frame2)
112130
EXPECT_GT(fp, prev_fp);
113131

114132
// Final frame has null FP (chain terminator)
115133
prev_fp = fp;
116-
fp = *(uintptr_t*)fp;
134+
fp = *(uintptr_t*)fp; // Read saved FP from frame3
117135
EXPECT_EQ(fp, 0u);
118136
}
119137

0 commit comments

Comments
 (0)