@@ -83,44 +83,17 @@ - (void)testObservers_synchronousRegistrationAddsObserver {
83
83
84
84
/* * Tests rapid creation and deallocation to verify race condition fix. */
85
85
- (void )testRapidCreationAndDeallocation_noRaceCondition {
86
- // This test simulates the real crash scenario by forcing async dispatch timing
87
- XCTestExpectation *expectation =
88
- [self expectationWithDescription: @" All async operations complete" ];
89
-
90
- __block int completedOperations = 0 ;
91
- const int totalOperations = 50 ;
92
-
93
- for (int i = 0 ; i < totalOperations; i++) {
86
+ for (int i = 0 ; i < 100 ; i++) {
94
87
@autoreleasepool {
95
88
FPRTraceBackgroundActivityTracker *tracker = [[FPRTraceBackgroundActivityTracker alloc ] init ];
96
89
XCTAssertNotNil (tracker);
97
90
98
- // Force multiple runloop cycles to increase chance of race condition
99
- dispatch_async (dispatch_get_main_queue (), ^{
100
- // This would crash with old async registration if tracker is deallocated
101
- [[NSNotificationCenter defaultCenter ]
102
- postNotificationName: UIApplicationDidBecomeActiveNotification
103
- object: [UIApplication sharedApplication ]];
104
-
105
- // Increment counter and fulfill expectation when done
106
- completedOperations++;
107
- if (completedOperations == totalOperations) {
108
- [expectation fulfill ];
109
- }
110
- });
111
-
112
- // Tracker deallocates here immediately due to @autoreleasepool
91
+ [[NSNotificationCenter defaultCenter ]
92
+ postNotificationName: UIApplicationDidBecomeActiveNotification
93
+ object: [UIApplication sharedApplication ]];
113
94
}
114
95
}
115
96
116
- // Wait for all async operations to complete
117
- [self waitForExpectationsWithTimeout: 10.0
118
- handler: ^(NSError *error) {
119
- XCTAssertNil (
120
- error, @" Operations timed out - potential deadlock or crash" );
121
- }];
122
-
123
- // Additional safety check - post more notifications after everything is done
124
97
XCTAssertNoThrow ([[NSNotificationCenter defaultCenter ]
125
98
postNotificationName: UIApplicationDidBecomeActiveNotification
126
99
object: [UIApplication sharedApplication ]]);
@@ -166,108 +139,4 @@ - (void)testObservers_registrationFromBackgroundThread {
166
139
}];
167
140
}
168
141
169
- /* * Tests the exact crash scenario with async dispatch timing that would crash with old
170
- * implementation. */
171
- - (void )testAsyncDispatch_wouldCrashWithOldImplementation {
172
- // This test simulates what the OLD code would do and should crash with async registration
173
- // With the NEW synchronous code, this should pass safely
174
-
175
- XCTestExpectation *expectation = [self expectationWithDescription: @" Async crash test complete" ];
176
-
177
- __block int remainingOperations = 200 ;
178
-
179
- for (int i = 0 ; i < 200 ; i++) {
180
- @autoreleasepool {
181
- FPRTraceBackgroundActivityTracker *tracker = [[FPRTraceBackgroundActivityTracker alloc ] init ];
182
- XCTAssertNotNil (tracker);
183
-
184
- // Simulate the old problematic pattern
185
- __weak typeof (tracker) weakTracker = tracker;
186
-
187
- // This mimics what the OLD async registration would do
188
- dispatch_async (dispatch_get_main_queue (), ^{
189
- // In old code: tracker might be deallocated here → CRASH
190
- // In new code: observers already registered synchronously → SAFE
191
-
192
- if (weakTracker) {
193
- [[NSNotificationCenter defaultCenter ]
194
- postNotificationName: UIApplicationDidBecomeActiveNotification
195
- object: [UIApplication sharedApplication ]];
196
- }
197
-
198
- remainingOperations--;
199
- if (remainingOperations == 0 ) {
200
- [expectation fulfill ];
201
- }
202
- });
203
-
204
- // Immediately deallocate tracker - this creates the race condition window
205
- }
206
-
207
- // Force runloop processing to increase race condition likelihood
208
- [[NSRunLoop currentRunLoop ] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.001 ]];
209
- }
210
-
211
- [self waitForExpectationsWithTimeout: 5.0
212
- handler: ^(NSError *error) {
213
- XCTAssertNil (error, @" Async crash test failed" );
214
- }];
215
- }
216
-
217
- @end
218
-
219
- /* *
220
- * CRASH REPRODUCTION TEST - Only use this to verify the original bug exists
221
- * This simulates the original async registration pattern that would cause crashes
222
- */
223
-
224
- @interface CrashReproductionTracker : NSObject
225
- @property (nonatomic , readwrite ) int traceBackgroundState;
226
- @end
227
-
228
- @implementation CrashReproductionTracker
229
-
230
- - (instancetype )init {
231
- self = [super init ];
232
- if (self) {
233
- _traceBackgroundState = 0 ;
234
-
235
- // This is the ORIGINAL problematic code that would crash
236
- dispatch_async (dispatch_get_main_queue (), ^{
237
- [[NSNotificationCenter defaultCenter ] addObserver: self
238
- selector: @selector (handleNotification: )
239
- name: UIApplicationDidBecomeActiveNotification
240
- object: [UIApplication sharedApplication ]];
241
- });
242
- }
243
- return self;
244
- }
245
-
246
- - (void )handleNotification : (NSNotification *)notification {
247
- _traceBackgroundState = 1 ;
248
- }
249
-
250
- - (void )dealloc {
251
- [[NSNotificationCenter defaultCenter ] removeObserver: self ];
252
- }
253
-
254
- /* *
255
- * CRASH REPRODUCTION TEST - Only use this to verify the original bug exists
256
- * This simulates the original async registration pattern that would cause crashes
257
- * WARNING: This test is commented out because it WILL crash with the original async pattern
258
- */
259
-
260
- - (void )testCrashReproduction_originalAsyncBug {
261
- // This test WILL crash with the original async pattern
262
- for (int i = 0 ; i < 100 ; i++) {
263
- @autoreleasepool {
264
- CrashReproductionTracker *tracker = [[CrashReproductionTracker alloc ] init ];
265
- // tracker deallocates here, but async block is still queued → CRASH
266
- }
267
-
268
- // Process run loop to execute queued async blocks
269
- [[NSRunLoop currentRunLoop ] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01 ]];
270
- }
271
- }
272
-
273
142
@end
0 commit comments