Skip to content

Commit 9264ee8

Browse files
test: Fix flaky SentryThreadInspectorTests (#5819)
Change the assertion approach of testGetCurrentThreadsWithStacktrace_WithSymbolication and testGetCurrentThreadsWithStacktrace_WithoutSymbolication to validate the percentage of threads having a stracktrace, which is more robust than the previous method which failed if more than one thread had no stacktrace frames. Especially during the test when launching multiple threads for the concurrent DispatchQueue it can occur that more than one thread have no stacktrace frames yet, because they just started.
1 parent c965528 commit 9264ee8

File tree

1 file changed

+57
-32
lines changed

1 file changed

+57
-32
lines changed

Tests/SentryTests/SentryCrash/SentryThreadInspectorTests.swift

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
@_spi(Private) @testable import Sentry
12
import SentryTestUtils
23
import XCTest
34

@@ -54,32 +55,45 @@ class SentryThreadInspectorTests: XCTestCase {
5455
expect.expectedFulfillmentCount = 10
5556

5657
let sut = self.fixture.getSut(testWithRealMachineContextWrapper: true)
58+
5759
for _ in 0..<10 {
58-
60+
5961
queue.async {
60-
let actual = sut.getCurrentThreadsWithStackTrace()
61-
62-
// Sometimes during tests its possible to have one thread without frames
63-
// We just need to make sure we retrieve frame information for at least one other thread than the main thread
64-
var threadsWithFrames = 0
65-
66-
for thr in actual {
67-
if (thr.stacktrace?.frames.count ?? 0) >= 1 {
68-
threadsWithFrames += 1
62+
let threads = sut.getCurrentThreadsWithStackTrace()
63+
64+
var threadsWithStackTraceFrames = 0
65+
66+
for thread in threads {
67+
68+
guard let frames = thread.stacktrace?.frames else {
69+
continue
70+
}
71+
72+
if frames.count == 0 {
73+
continue
6974
}
70-
71-
for frame in thr.stacktrace?.frames ?? [] {
75+
76+
for frame in frames {
7277
XCTAssertNotNil(frame.instructionAddress)
7378
XCTAssertNotNil(frame.imageAddress)
79+
7480
}
81+
82+
threadsWithStackTraceFrames += 1
7583
}
76-
77-
XCTAssertTrue(threadsWithFrames > 1, "Not enough threads with frames")
78-
84+
85+
let percantageWithStacktraceFrames = Double(threadsWithStackTraceFrames) / Double(threads.count)
86+
87+
// During testing we usually have around 90% to 100%
88+
// We choose a bit lower threshold to avoid flaky tests in CI
89+
// Especially during the test when launching multiple threads for the concurrent DispatchQueue
90+
// it can occur that more than one thread have no stacktrace frames yet, because they just started.
91+
XCTAssertGreaterThan(percantageWithStacktraceFrames, 0.6, "More than 60% of threads should have stacktrace frames, but got \(percantageWithStacktraceFrames * 100)%")
92+
7993
expect.fulfill()
8094
}
8195
}
82-
96+
8397
queue.activate()
8498
wait(for: [expect], timeout: 10)
8599
}
@@ -91,34 +105,45 @@ class SentryThreadInspectorTests: XCTestCase {
91105
expect.expectedFulfillmentCount = 10
92106

93107
let sut = self.fixture.getSut(testWithRealMachineContextWrapper: true, symbolicate: false)
94-
108+
95109
for _ in 0..<10 {
96110

97111
queue.async {
98-
let actual = sut.getCurrentThreadsWithStackTrace()
99-
100-
// Sometimes during tests its possible to have one thread without frames
101-
// We just need to make sure we retrieve frame information for at least one other thread than the main thread
102-
var threadsWithFrames = 0
103-
104-
for thr in actual {
105-
if (thr.stacktrace?.frames.count ?? 0) >= 1 {
106-
threadsWithFrames += 1
112+
let threads = sut.getCurrentThreadsWithStackTrace()
113+
114+
var threadsWithStackTraceFrames = 0
115+
116+
for thread in threads {
117+
118+
guard let frames = thread.stacktrace?.frames else {
119+
continue
120+
}
121+
122+
if frames.count == 0 {
123+
continue
107124
}
108-
109-
for frame in thr.stacktrace?.frames ?? [] {
125+
126+
for frame in frames {
110127
XCTAssertNotNil(frame.instructionAddress)
111128
XCTAssertNotNil(frame.imageAddress)
112129
XCTAssertNil(frame.symbolAddress)
113130
}
131+
132+
threadsWithStackTraceFrames += 1
114133
}
115-
116-
XCTAssertTrue(threadsWithFrames > 1, "Not enough threads with frames")
117-
134+
135+
let percantageWithStacktraceFrames = Double(threadsWithStackTraceFrames) / Double(threads.count)
136+
137+
// During testing we usually have around 90% to 100%
138+
// We choose a bit lower threshold to avoid flaky tests in CI
139+
// Especially during the test when launching multiple threads for the concurrent DispatchQueue
140+
// it can occur that more than one thread have no stacktrace frames yet, because they just started.
141+
XCTAssertGreaterThan(percantageWithStacktraceFrames, 0.6, "More than 60% of threads should have stacktrace frames, but got \(percantageWithStacktraceFrames * 100)%")
142+
118143
expect.fulfill()
119144
}
120145
}
121-
146+
122147
queue.activate()
123148
wait(for: [expect], timeout: 10)
124149
}

0 commit comments

Comments
 (0)