@@ -304,8 +304,8 @@ - (void)testFetcherService {
304
304
// We'll verify we fetched from the server the same data that is on disk.
305
305
NSData *gettysburgAddress = [_testServer documentDataAtPath: kValidFileName ];
306
306
307
- // We'll create 10 fetchers. Only 2 should run simultaneously.
308
- // 1 should fail; the rest should succeeed.
307
+ // We'll create several fetchers. Only 2 should run simultaneously (per host) .
308
+ // 1 should fail; a few will be stopped the rest should succeeed.
309
309
const NSUInteger kMaxRunningFetchersPerHost = 2 ;
310
310
311
311
NSString *const kUserAgent = @" ServiceTest-UA" ;
@@ -322,10 +322,18 @@ - (void)testFetcherService {
322
322
NSString *invalidFile = [kValidFileName stringByAppendingString: @" ?status=400" ];
323
323
NSURL *invalidFileURL = [_testServer localURLForFile: invalidFile];
324
324
325
+ NSString *stopSilentFile = [kValidFileName stringByAppendingString: @" ?stop=silent" ];
326
+ NSURL *stopSilentFileURL = [_testServer localURLForFile: stopSilentFile];
327
+
328
+ NSString *stopCallbackFile = [kValidFileName stringByAppendingString: @" ?stop=callback" ];
329
+ NSURL *stopCallbackFileURL = [_testServer localURLForFile: stopCallbackFile];
330
+
325
331
NSURL *altValidURL = [_testServer localv6URLForFile: invalidFile];
326
332
327
333
XCTAssertEqualObjects (validFileURL.host , @" localhost" , @" unexpected host" );
328
334
XCTAssertEqualObjects (invalidFileURL.host , @" localhost" , @" unexpected host" );
335
+ XCTAssertEqualObjects (stopSilentFileURL.host , @" localhost" , @" unexpected host" );
336
+ XCTAssertEqualObjects (stopCallbackFileURL.host , @" localhost" , @" unexpected host" );
329
337
XCTAssertEqualObjects (altValidURL.host , @" ::1" , @" unexpected host" );
330
338
331
339
// Make an array with the urls from the different hosts, including one
@@ -334,13 +342,20 @@ - (void)testFetcherService {
334
342
for (int idx = 1 ; idx <= 4 ; idx++) [urlArray addObject: validFileURL];
335
343
[urlArray addObject: invalidFileURL];
336
344
for (int idx = 1 ; idx <= 5 ; idx++) [urlArray addObject: validFileURL];
345
+ for (int idx = 1 ; idx <= 3 ; idx++) [urlArray addObject: stopSilentFileURL];
337
346
for (int idx = 1 ; idx <= 5 ; idx++) [urlArray addObject: altValidURL];
347
+ // TODO(thomasvl) currently fail: The current code paths remove these from
348
+ // pending, but doesn't actually get the completions ever called as requested.
349
+ // Will be fixed in follow up PRs.
350
+ // for (int idx = 1; idx <= 3; idx++) [urlArray addObject:stopCallbackFileURL];
338
351
for (int idx = 1 ; idx <= 5 ; idx++) [urlArray addObject: validFileURL];
352
+ for (int idx = 1 ; idx <= 2 ; idx++) [urlArray addObject: stopSilentFileURL];
339
353
NSUInteger totalNumberOfFetchers = urlArray.count ;
340
354
341
355
__block NSMutableArray *pending = [NSMutableArray array ];
342
356
__block NSMutableArray *running = [NSMutableArray array ];
343
357
__block NSMutableArray *completed = [NSMutableArray array ];
358
+ NSMutableArray *stoppedNoCallback = [NSMutableArray array ];
344
359
345
360
NSInteger priorityVal = 0 ;
346
361
@@ -367,6 +382,10 @@ - (void)testFetcherService {
367
382
368
383
NSURLRequest *fetcherReq = fetcher.request ;
369
384
NSURL *fetcherReqURL = fetcherReq.URL ;
385
+
386
+ // A fetcher that gets stopped should not trigger any notifications.
387
+ XCTAssertFalse ([fetcherReqURL.query hasPrefix: @" stop=" ]);
388
+
370
389
NSString *host = fetcherReqURL.host ;
371
390
NSUInteger numberRunning = FetchersPerHost (running, host);
372
391
XCTAssertTrue (numberRunning > 0 , @" count error" );
@@ -403,19 +422,25 @@ - (void)testFetcherService {
403
422
[completed addObject: fetcher];
404
423
[running removeObject: fetcher];
405
424
406
- NSString *host = fetcher.request .URL .host ;
425
+ // A fetcher that gets stopped should not trigger any notifications.
426
+ NSURL *fetcherReqURL = fetcher.request .URL ;
427
+ XCTAssertFalse ([fetcherReqURL.query hasPrefix: @" stop=" ]);
407
428
429
+ NSString *host = fetcherReqURL.host ;
408
430
NSUInteger numberRunning = FetchersPerHost (running, host);
409
431
NSUInteger numberPending = FetchersPerHost (pending, host);
410
432
NSUInteger numberCompleted = FetchersPerHost (completed, host);
433
+ NSUInteger numberStopped = FetchersPerHost (stoppedNoCallback, host);
411
434
412
435
XCTAssertLessThanOrEqual (numberRunning, kMaxRunningFetchersPerHost ,
413
436
@" too many running" );
414
437
XCTAssertLessThanOrEqual (
415
- numberPending + numberRunning + numberCompleted, URLsPerHost (urlArray, host),
416
- @" %d issued running (pending:%u running:%u completed:%u )" ,
438
+ numberPending + numberRunning + numberCompleted + numberStopped,
439
+ URLsPerHost (urlArray, host),
440
+ @" %d issued running (pending:%u running:%u completed:%u stopped: %u )" ,
417
441
(unsigned int )totalNumberOfFetchers, (unsigned int )numberPending,
418
- (unsigned int )numberRunning, (unsigned int )numberCompleted);
442
+ (unsigned int )numberRunning, (unsigned int )numberCompleted,
443
+ (unsigned int )numberStopped);
419
444
420
445
// The stop notification may be posted on the main thread before or after the
421
446
// fetcher service has been notified the fetcher has stopped.
@@ -429,32 +454,56 @@ - (void)testFetcherService {
429
454
if (priorityVal > 1 ) priorityVal = -1 ;
430
455
fetcher.servicePriority = priorityVal;
431
456
457
+ BOOL stopFetch = [fileURL.query hasPrefix: @" stop=" ];
458
+ BOOL stopWithCallback = [fileURL.query isEqual: @" stop=callback" ];
459
+ if (stopWithCallback) {
460
+ fetcher.stopFetchingTriggersCompletionHandler = YES ;
461
+ }
462
+
432
463
// Start this fetcher.
433
464
[fetchersInFlight addObject: fetcher];
434
465
[fetcher beginFetchWithCompletionHandler: ^(NSData *fetchData, NSError *fetchError) {
435
466
// Callback.
436
467
XCTAssert ([fetchersInFlight containsObject: fetcher]);
437
468
[fetchersInFlight removeObjectIdenticalTo: fetcher];
438
469
439
- // The query should be empty except for the URL with a status code.
470
+ // The query should be empty except for the URL with a status code or the ones
471
+ // marked for stopping.
440
472
NSString *query = [fetcher.request.URL query ];
441
473
BOOL isValidRequest = (query.length == 0 );
442
474
if (isValidRequest) {
443
475
XCTAssertEqualObjects (fetchData, gettysburgAddress, @" Bad fetch data" );
444
476
XCTAssertNil (fetchError, @" unexpected %@ %@ " , fetchError, fetchError.userInfo );
445
477
} else {
446
- // This is the query with ?status=400.
447
- XCTAssertEqual (fetchError.code , (NSInteger )400 , @" expected error" );
478
+ if ([query isEqual: @" stop=callback" ]) {
479
+ XCTAssertEqualObjects (fetchError.domain , kGTMSessionFetcherErrorDomain , @" expected error" );
480
+ XCTAssertEqual (fetchError.code , GTMSessionFetcherErrorUserCancelled, @" expected error" );
481
+ } else if ([query hasPrefix: @" stop=" ]) {
482
+ XCTFail (@" Should not have gotten completion for stopped call" );
483
+ } else {
484
+ // This is the query with ?status=400.
485
+ XCTAssertEqual (fetchError.code , (NSInteger )400 , @" expected error" );
486
+ }
448
487
}
449
488
[expectation fulfill ];
450
489
}];
490
+ if (stopFetch) {
491
+ [fetcher stopFetching ];
492
+ [pending removeObject: fetcher];
493
+ if (!stopWithCallback) {
494
+ [stoppedNoCallback addObject: fetcher];
495
+ [fetchersInFlight removeObject: fetcher];
496
+ [expectation fulfill ];
497
+ }
498
+ }
451
499
}
452
500
453
501
[self waitForExpectations: expectations timeout: _timeoutInterval];
454
502
455
503
XCTAssertEqual (pending.count , (NSUInteger )0 , @" still pending: %@ " , pending);
456
504
XCTAssertEqual (running.count , (NSUInteger )0 , @" still running: %@ " , running);
457
- XCTAssertEqual (completed.count , (NSUInteger )totalNumberOfFetchers, @" incomplete" );
505
+ XCTAssertEqual (completed.count + stoppedNoCallback.count , (NSUInteger )totalNumberOfFetchers,
506
+ @" incomplete" );
458
507
XCTAssertEqual (fetchersInFlight.count , (NSUInteger )0 , @" Uncompleted: %@ " , fetchersInFlight);
459
508
460
509
XCTAssertEqual ([service numberOfFetchers ], (NSUInteger )0 , @" service non-empty" );
@@ -545,6 +594,9 @@ - (void)stopAllFetchersHelperUseStopAllAPI:(BOOL)useStopAllAPI
545
594
fetcher.stopFetchingTriggersCompletionHandler = doStopCallbacks;
546
595
[fetcher beginFetchWithCompletionHandler: ^(NSData *fetchData, NSError *fetchError) {
547
596
if (doStopCallbacks) {
597
+ // Since they are getting stopped, they should all produce errors, not data.
598
+ XCTAssertNil (fetchData);
599
+ XCTAssertNotNil (fetchError);
548
600
[fetcherCallbackExpectation fulfill ];
549
601
} else {
550
602
// We shouldn't reach any of the callbacks.
@@ -560,25 +612,23 @@ - (void)stopAllFetchersHelperUseStopAllAPI:(BOOL)useStopAllAPI
560
612
// We should see two fetchers running and one delayed for each host.
561
613
NSArray *localhosts = [service.runningFetchersByHost objectForKey: @" localhost" ];
562
614
XCTAssertEqual (localhosts.count , (NSUInteger )2 , @" hosts running" );
615
+ NSArray *localv6hosts = [service.runningFetchersByHost objectForKey: @" ::1" ];
616
+ XCTAssertEqual (localv6hosts.count , (NSUInteger )2 , @" hosts running" );
563
617
564
618
localhosts = [service.delayedFetchersByHost objectForKey: @" localhost" ];
565
619
XCTAssertEqual (localhosts.count , (NSUInteger )1 , @" hosts delayed" );
620
+ localv6hosts = [service.delayedFetchersByHost objectForKey: @" ::1" ];
621
+ XCTAssertEqual (localv6hosts.count , (NSUInteger )1 , @" hosts delayed" );
566
622
567
623
XCTAssertNil (service.stoppedAllFetchersDate );
568
624
569
- NSArray *delayedFetchersByHost;
570
- NSArray *runningFetchersByHost;
571
-
572
- @synchronized (self) {
573
- GTMSessionMonitorSynchronized (self);
574
-
575
- delayedFetchersByHost = service.delayedFetchersByHost .allValues ;
576
- runningFetchersByHost = service.runningFetchersByHost .allValues ;
577
- }
578
-
579
625
if (useStopAllAPI) {
580
626
[service stopAllFetchers ];
581
627
} else {
628
+ // Stop the delayed fetchers first so a delayed one doesn't get started when canceling
629
+ // a running one.
630
+ NSArray *delayedFetchersByHost = service.delayedFetchersByHost .allValues ;
631
+ NSArray *runningFetchersByHost = service.runningFetchersByHost .allValues ;
582
632
for (NSArray *delayedForHost in delayedFetchersByHost) {
583
633
NSArray *delayed = [delayedForHost copy ];
584
634
for (GTMSessionFetcher *fetcher in delayed) {
@@ -603,6 +653,8 @@ - (void)stopAllFetchersHelperUseStopAllAPI:(BOOL)useStopAllAPI
603
653
604
654
if (useStopAllAPI) {
605
655
XCTAssertNotNil (service.stoppedAllFetchersDate );
656
+ } else {
657
+ XCTAssertNil (service.stoppedAllFetchersDate );
606
658
}
607
659
}
608
660
0 commit comments