@@ -53,6 +53,43 @@ - (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result
53
53
54
54
@end
55
55
56
+ // A Fake operation that we have control over the returned error.
57
+ // We are not using mocks here because we have no way of forcing NSOperationQueues to release
58
+ // their operations, and this means that there is always going to be a race condition between
59
+ // when we "stop" our partial mock vs when NSOperationQueue attempts to access the mock object on a
60
+ // separate thread. We had mocks previously.
61
+ @interface FIRInstanceIDTokenDeleteOperationFake : FIRInstanceIDTokenDeleteOperation
62
+ @property (nonatomic , copy ) NSError *error;
63
+ @end
64
+
65
+ @implementation FIRInstanceIDTokenDeleteOperationFake
66
+
67
+ - (void )performTokenOperation {
68
+ if (self.error ) {
69
+ [self finishWithResult: FIRInstanceIDTokenOperationError token: nil error: self .error];
70
+ } else {
71
+ [self finishWithResult: FIRInstanceIDTokenOperationSucceeded token: kToken error: self .error];
72
+ }
73
+ }
74
+
75
+ @end
76
+
77
+ @interface FIRInstanceIDTokenFetchOperationFake : FIRInstanceIDTokenFetchOperation
78
+ @property (nonatomic , copy ) NSError *error;
79
+ @end
80
+
81
+ @implementation FIRInstanceIDTokenFetchOperationFake
82
+
83
+ - (void )performTokenOperation {
84
+ if (self.error ) {
85
+ [self finishWithResult: FIRInstanceIDTokenOperationError token: nil error: self .error];
86
+ } else {
87
+ [self finishWithResult: FIRInstanceIDTokenOperationSucceeded token: kToken error: self .error];
88
+ }
89
+ }
90
+
91
+ @end
92
+
56
93
@interface FIRInstanceIDTokenManager (ExposedForTests)
57
94
58
95
- (BOOL )checkTokenRefreshPolicyForIID : (NSString *)IID ;
@@ -165,19 +202,12 @@ - (void)testNewTokenSuccess {
165
202
NSDictionary *tokenOptions = [NSDictionary dictionary ];
166
203
167
204
// Create a fake operation that always returns success
168
- FIRInstanceIDTokenFetchOperation *operation =
169
- [[FIRInstanceIDTokenFetchOperation alloc ] initWithAuthorizedEntity: kAuthorizedEntity
170
- scope: kScope
171
- options: tokenOptions
172
- checkinPreferences: self .fakeCheckin
173
- instanceID: [OCMArg any ]];
174
- id mockOperation = OCMPartialMock (operation);
175
- [[[mockOperation stub ] andDo: ^(NSInvocation *invocation) {
176
- [invocation.target finishWithResult: FIRInstanceIDTokenOperationSucceeded
177
- token: kToken
178
- error: nil ];
179
- }] performTokenOperation ];
180
-
205
+ FIRInstanceIDTokenFetchOperationFake *operation =
206
+ [[FIRInstanceIDTokenFetchOperationFake alloc ] initWithAuthorizedEntity: kAuthorizedEntity
207
+ scope: kScope
208
+ options: tokenOptions
209
+ checkinPreferences: self .fakeCheckin
210
+ instanceID: [OCMArg any ]];
181
211
XCTestExpectation *operationFinishExpectation =
182
212
[self expectationWithDescription: @" operationFinishExpectation" ];
183
213
operation.completionBlock = ^{
@@ -203,11 +233,6 @@ - (void)testNewTokenSuccess {
203
233
}];
204
234
205
235
[self waitForExpectations: @[ tokenExpectation, operationFinishExpectation ] timeout: 1 ];
206
-
207
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
208
- [mockOperation stopMocking ];
209
- // Keep 'operation' alive, so it's not prematurely destroyed
210
- XCTAssertNotNil (operation);
211
236
}
212
237
213
238
/* *
@@ -223,18 +248,12 @@ - (void)testNewTokenSaveFailure {
223
248
self.fakeKeyChain .cannotWriteToKeychain = YES ;
224
249
225
250
// Create a fake operation that always returns success
226
- FIRInstanceIDTokenFetchOperation *operation =
227
- [[FIRInstanceIDTokenFetchOperation alloc ] initWithAuthorizedEntity: kAuthorizedEntity
228
- scope: kScope
229
- options: tokenOptions
230
- checkinPreferences: self .fakeCheckin
231
- instanceID: [OCMArg any ]];
232
- id mockOperation = OCMPartialMock (operation);
233
- [[[mockOperation stub ] andDo: ^(NSInvocation *invocation) {
234
- [invocation.target finishWithResult: FIRInstanceIDTokenOperationSucceeded
235
- token: kToken
236
- error: nil ];
237
- }] performTokenOperation ];
251
+ FIRInstanceIDTokenFetchOperationFake *operation =
252
+ [[FIRInstanceIDTokenFetchOperationFake alloc ] initWithAuthorizedEntity: kAuthorizedEntity
253
+ scope: kScope
254
+ options: tokenOptions
255
+ checkinPreferences: self .fakeCheckin
256
+ instanceID: [OCMArg any ]];
238
257
239
258
XCTestExpectation *operationFinishExpectation =
240
259
[self expectationWithDescription: @" operationFinishExpectation" ];
@@ -260,11 +279,6 @@ - (void)testNewTokenSaveFailure {
260
279
}];
261
280
262
281
[self waitForExpectations: @[ tokenExpectation, operationFinishExpectation ] timeout: 1 ];
263
-
264
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
265
- [mockOperation stopMocking ];
266
- // Keep 'operation' alive, so it's not prematurely destroyed
267
- XCTAssertNotNil (operation);
268
282
}
269
283
270
284
/* *
@@ -278,24 +292,19 @@ - (void)testNewTokenFailure {
278
292
NSDictionary *tokenOptions = [NSDictionary dictionary ];
279
293
280
294
// Create a fake operation that always returns failure
281
- FIRInstanceIDTokenFetchOperation *operation =
282
- [[FIRInstanceIDTokenFetchOperation alloc ] initWithAuthorizedEntity: kAuthorizedEntity
283
- scope: kScope
284
- options: tokenOptions
285
- checkinPreferences: self .fakeCheckin
286
- instanceID: [OCMArg any ]];
287
- id mockOperation = OCMPartialMock (operation);
288
- [[[mockOperation stub ] andDo: ^(NSInvocation *invocation) {
289
- NSError *someError = [[NSError alloc ] initWithDomain: @" InstanceIDUnitTest" code: 0 userInfo: nil ];
290
- [invocation.target finishWithResult: FIRInstanceIDTokenOperationError token: nil error: someError];
291
- }] performTokenOperation ];
295
+ FIRInstanceIDTokenFetchOperationFake *operation =
296
+ [[FIRInstanceIDTokenFetchOperationFake alloc ] initWithAuthorizedEntity: kAuthorizedEntity
297
+ scope: kScope
298
+ options: tokenOptions
299
+ checkinPreferences: self .fakeCheckin
300
+ instanceID: [OCMArg any ]];
301
+ operation.error = [[NSError alloc ] initWithDomain: @" InstanceIDUnitTest" code: 0 userInfo: nil ];
292
302
293
303
XCTestExpectation *operationFinishExpectation =
294
304
[self expectationWithDescription: @" operationFinishExpectation" ];
295
305
operation.completionBlock = ^{
296
306
[operationFinishExpectation fulfill ];
297
307
};
298
-
299
308
// Return our fake operation when asked for an operation
300
309
[[[self .mockTokenManager stub ] andReturn: operation]
301
310
createFetchOperationWithAuthorizedEntity: [OCMArg any ]
@@ -314,11 +323,6 @@ - (void)testNewTokenFailure {
314
323
}];
315
324
316
325
[self waitForExpectations: @[ tokenExpectation, operationFinishExpectation ] timeout: 1 ];
317
-
318
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
319
- [mockOperation stopMocking ];
320
- // Keep 'operation' alive, so it's not prematurely destroyed
321
- XCTAssertNotNil (operation);
322
326
}
323
327
324
328
/* *
@@ -329,16 +333,12 @@ - (void)testDeleteTokenSuccess {
329
333
[self expectationWithDescription: @" Delete handler invoked." ];
330
334
331
335
// Create a fake operation that always succeeds
332
- FIRInstanceIDTokenDeleteOperation *operation = [[FIRInstanceIDTokenDeleteOperation alloc ]
336
+ FIRInstanceIDTokenDeleteOperationFake *operation = [[FIRInstanceIDTokenDeleteOperationFake alloc ]
333
337
initWithAuthorizedEntity: kAuthorizedEntity
334
338
scope: kScope
335
339
checkinPreferences: self .fakeCheckin
336
340
instanceID: [OCMArg any ]
337
341
action: FIRInstanceIDTokenActionDeleteToken];
338
- id mockOperation = OCMPartialMock (operation);
339
- [[[mockOperation stub ] andDo: ^(NSInvocation *invocation) {
340
- [invocation.target finishWithResult: FIRInstanceIDTokenOperationSucceeded token: nil error: nil ];
341
- }] performTokenOperation ];
342
342
343
343
XCTestExpectation *operationFinishExpectation =
344
344
[self expectationWithDescription: @" operationFinishExpectation" ];
@@ -363,11 +363,6 @@ - (void)testDeleteTokenSuccess {
363
363
}];
364
364
365
365
[self waitForExpectations: @[ deleteExpectation, operationFinishExpectation ] timeout: 1 ];
366
-
367
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
368
- [mockOperation stopMocking ];
369
- // Keep 'operation' alive, so it's not prematurely destroyed
370
- XCTAssertNotNil (operation);
371
366
}
372
367
373
368
/* *
@@ -378,17 +373,13 @@ - (void)testDeleteTokenFailure {
378
373
[self expectationWithDescription: @" Delete handler invoked." ];
379
374
380
375
// Create a fake operation that always fails
381
- FIRInstanceIDTokenDeleteOperation *operation = [[FIRInstanceIDTokenDeleteOperation alloc ]
376
+ FIRInstanceIDTokenDeleteOperationFake *operation = [[FIRInstanceIDTokenDeleteOperationFake alloc ]
382
377
initWithAuthorizedEntity: kAuthorizedEntity
383
378
scope: kScope
384
379
checkinPreferences: self .fakeCheckin
385
380
instanceID: [OCMArg any ]
386
381
action: FIRInstanceIDTokenActionDeleteToken];
387
- id mockOperation = OCMPartialMock (operation);
388
- [[[mockOperation stub ] andDo: ^(NSInvocation *invocation) {
389
- NSError *someError = [[NSError alloc ] initWithDomain: @" InstanceIDUnitTest" code: 0 userInfo: nil ];
390
- [invocation.target finishWithResult: FIRInstanceIDTokenOperationError token: nil error: someError];
391
- }] performTokenOperation ];
382
+ operation.error = [[NSError alloc ] initWithDomain: @" InstanceIDUnitTest" code: 0 userInfo: nil ];
392
383
393
384
XCTestExpectation *operationFinishExpectation =
394
385
[self expectationWithDescription: @" operationFinishExpectation" ];
@@ -413,11 +404,6 @@ - (void)testDeleteTokenFailure {
413
404
}];
414
405
415
406
[self waitForExpectations: @[ deleteExpectation, operationFinishExpectation ] timeout: 1 ];
416
-
417
- // Make sure the partial mock stops mocking before `operation` is deallocated to avoid crash.
418
- [mockOperation stopMocking ];
419
- // Keep 'operation' alive, so it's not prematurely destroyed
420
- XCTAssertNotNil (operation);
421
407
}
422
408
423
409
#pragma mark - Cached Token Invalidation
0 commit comments