@@ -46,6 +46,12 @@ - (void)testRunItem
46
46
};
47
47
[workQueue enqueueWorkItem: workItem1];
48
48
49
+ // Check for leaks.
50
+ MTRAsyncCallbackQueueWorkItem * __weak weakItem = workItem1;
51
+ [self addTeardownBlock: ^() {
52
+ XCTAssertNil (weakItem);
53
+ }];
54
+
49
55
[self waitForExpectationsWithTimeout: 5 handler: nil ];
50
56
51
57
// see that it only ran once
@@ -170,4 +176,84 @@ - (void)testRunItemsAfterDrain
170
176
[self waitForExpectationsWithTimeout: 5 handler: nil ];
171
177
}
172
178
179
+ - (void )testRunItemNoHandlers
180
+ {
181
+ XCTestExpectation * expectation = [self expectationWithDescription: @" Work item called" ];
182
+
183
+ MTRAsyncCallbackWorkQueue * workQueue = [[MTRAsyncCallbackWorkQueue alloc ] initWithContext: nil queue: dispatch_get_main_queue ()];
184
+
185
+ MTRAsyncCallbackQueueWorkItem * workItem1 =
186
+ [[MTRAsyncCallbackQueueWorkItem alloc ] initWithQueue: dispatch_get_global_queue (QOS_CLASS_DEFAULT , 0 )];
187
+ MTRAsyncCallbackQueueWorkItem * workItem2 =
188
+ [[MTRAsyncCallbackQueueWorkItem alloc ] initWithQueue: dispatch_get_global_queue (QOS_CLASS_DEFAULT , 0 )];
189
+
190
+ __block int counter = 0 ;
191
+ MTRAsyncCallbackReadyHandler readyHandler = ^(MTRDevice * _Nonnull device, NSUInteger retryCount) {
192
+ counter++;
193
+ [workItem2 endWork ];
194
+ [expectation fulfill ];
195
+ };
196
+ workItem2.readyHandler = readyHandler;
197
+ workItem2.cancelHandler = ^{
198
+ };
199
+
200
+ // Check that trying to run workItem1 does not crash.
201
+ [workQueue enqueueWorkItem: workItem1];
202
+ [workQueue enqueueWorkItem: workItem2];
203
+
204
+ [self waitForExpectationsWithTimeout: 5 handler: nil ];
205
+
206
+ // see that it only ran once
207
+ XCTAssertEqual (counter, 1 );
208
+ }
209
+
210
+ - (void )testInvalidation
211
+ {
212
+ XCTestExpectation * expectation = [self expectationWithDescription: @" Work item called" ];
213
+ XCTestExpectation * cancelExpectation = [self expectationWithDescription: @" Work item canceled" ];
214
+
215
+ MTRAsyncCallbackWorkQueue * workQueue = [[MTRAsyncCallbackWorkQueue alloc ] initWithContext: nil queue: dispatch_get_main_queue ()];
216
+
217
+ MTRAsyncCallbackQueueWorkItem * workItem1 =
218
+ [[MTRAsyncCallbackQueueWorkItem alloc ] initWithQueue: dispatch_get_global_queue (QOS_CLASS_DEFAULT , 0 )];
219
+ MTRAsyncCallbackReadyHandler readyHandler1 = ^(MTRDevice * _Nonnull device, NSUInteger retryCount) {
220
+ // Give the code enqueing the other items a chance to run, so they can
221
+ // actually get canceled.
222
+ sleep (1 );
223
+ [workQueue invalidate ];
224
+ [workItem1 endWork ];
225
+ [expectation fulfill ];
226
+ };
227
+ workItem1.readyHandler = readyHandler1;
228
+ // No cancel handler on purpose.
229
+ [workQueue enqueueWorkItem: workItem1];
230
+
231
+ MTRAsyncCallbackQueueWorkItem * workItem2 =
232
+ [[MTRAsyncCallbackQueueWorkItem alloc ] initWithQueue: dispatch_get_global_queue (QOS_CLASS_DEFAULT , 0 )];
233
+ MTRAsyncCallbackReadyHandler readyHandler2 = ^(MTRDevice * _Nonnull device, NSUInteger retryCount) {
234
+ // This should never get called.
235
+ XCTAssertFalse (YES );
236
+ [workItem2 endWork ];
237
+ };
238
+ workItem2.readyHandler = readyHandler2;
239
+ // No cancel handler on purpose.
240
+ [workQueue enqueueWorkItem: workItem2];
241
+
242
+ MTRAsyncCallbackQueueWorkItem * workItem3 =
243
+ [[MTRAsyncCallbackQueueWorkItem alloc ] initWithQueue: dispatch_get_global_queue (QOS_CLASS_DEFAULT , 0 )];
244
+ MTRAsyncCallbackReadyHandler readyHandler3 = ^(MTRDevice * _Nonnull device, NSUInteger retryCount) {
245
+ // This should never get called.
246
+ XCTAssertFalse (YES );
247
+ [workItem3 endWork ];
248
+ };
249
+ dispatch_block_t cancelHandler3 = ^() {
250
+ [cancelExpectation fulfill ];
251
+ };
252
+ workItem3.readyHandler = readyHandler3;
253
+ workItem3.cancelHandler = cancelHandler3;
254
+ [workQueue enqueueWorkItem: workItem3];
255
+
256
+ [self waitForExpectations: @[ expectation, cancelExpectation ] timeout: 5 ];
257
+ }
258
+
173
259
@end
0 commit comments