192 lines
8.6 KiB
Objective-C
192 lines
8.6 KiB
Objective-C
/*
|
|
* This file is part of the SDWebImage package.
|
|
* (c) Olivier Poitrey <rs@dailymotion.com>
|
|
* (c) Matt Galloway
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
#import "SDTestCase.h"
|
|
|
|
@interface SDWebImagePrefetcher ()
|
|
|
|
@property (strong, atomic, nonnull) NSMutableSet<SDWebImagePrefetchToken *> *runningTokens;
|
|
|
|
@end
|
|
|
|
@interface SDWebImagePrefetcherTests : SDTestCase <SDWebImagePrefetcherDelegate>
|
|
|
|
@property (nonatomic, strong) SDWebImagePrefetcher *prefetcher;
|
|
@property (atomic, assign) NSUInteger finishedCount;
|
|
@property (atomic, assign) NSUInteger skippedCount;
|
|
@property (atomic, assign) NSUInteger totalCount;
|
|
|
|
@end
|
|
|
|
@implementation SDWebImagePrefetcherTests
|
|
|
|
- (void)test01ThatSharedPrefetcherIsNotEqualToInitPrefetcher {
|
|
SDWebImagePrefetcher *prefetcher = [[SDWebImagePrefetcher alloc] init];
|
|
expect(prefetcher).toNot.equal([SDWebImagePrefetcher sharedImagePrefetcher]);
|
|
}
|
|
|
|
- (void)test02PrefetchMultipleImages {
|
|
XCTestExpectation *expectation = [self expectationWithDescription:@"Correct prefetch of multiple images"];
|
|
|
|
NSArray *imageURLs = @[@"http://via.placeholder.com/20x20.jpg",
|
|
@"http://via.placeholder.com/30x30.jpg",
|
|
@"http://via.placeholder.com/40x40.jpg"];
|
|
|
|
__block NSUInteger numberOfPrefetched = 0;
|
|
|
|
[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
|
|
[[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:imageURLs progress:^(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls) {
|
|
numberOfPrefetched += 1;
|
|
expect(numberOfPrefetched).to.equal(noOfFinishedUrls);
|
|
expect(noOfFinishedUrls).to.beLessThanOrEqualTo(noOfTotalUrls);
|
|
expect(noOfTotalUrls).to.equal(imageURLs.count);
|
|
} completed:^(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls) {
|
|
expect(numberOfPrefetched).to.equal(noOfFinishedUrls);
|
|
expect(noOfFinishedUrls).to.equal(imageURLs.count);
|
|
expect(noOfSkippedUrls).to.equal(0);
|
|
[expectation fulfill];
|
|
}];
|
|
}];
|
|
|
|
[self waitForExpectationsWithTimeout:kAsyncTestTimeout * 3 handler:nil];
|
|
}
|
|
|
|
- (void)test03PrefetchWithEmptyArrayWillCallTheCompletionWithAllZeros {
|
|
XCTestExpectation *expectation = [self expectationWithDescription:@"Prefetch with empty array"];
|
|
|
|
[[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:@[] progress:nil completed:^(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls) {
|
|
expect(noOfFinishedUrls).to.equal(0);
|
|
expect(noOfSkippedUrls).to.equal(0);
|
|
[expectation fulfill];
|
|
}];
|
|
|
|
[self waitForExpectationsWithCommonTimeout];
|
|
}
|
|
|
|
- (void)test04PrefetchWithMultipleArrayDifferentQueueWorks {
|
|
XCTestExpectation *expectation = [self expectationWithDescription:@"Prefetch with multiple array at different queue failed"];
|
|
|
|
NSArray *imageURLs1 = @[@"http://via.placeholder.com/20x20.jpg",
|
|
@"http://via.placeholder.com/30x30.jpg"];
|
|
NSArray *imageURLs2 = @[@"http://via.placeholder.com/30x30.jpg",
|
|
@"http://via.placeholder.com/40x40.jpg"];
|
|
dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
|
|
dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
|
|
__block int numberOfPrefetched1 = 0;
|
|
__block int numberOfPrefetched2 = 0;
|
|
__block BOOL prefetchFinished1 = NO;
|
|
__block BOOL prefetchFinished2 = NO;
|
|
|
|
// Clear the disk cache to make it more realistic for multi-thread environment
|
|
[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
|
|
dispatch_async(queue1, ^{
|
|
[[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:imageURLs1 progress:^(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls) {
|
|
numberOfPrefetched1 += 1;
|
|
} completed:^(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls) {
|
|
expect(numberOfPrefetched1).to.equal(noOfFinishedUrls);
|
|
prefetchFinished1 = YES;
|
|
// both completion called
|
|
if (prefetchFinished1 && prefetchFinished2) {
|
|
[expectation fulfill];
|
|
}
|
|
}];
|
|
});
|
|
dispatch_async(queue2, ^{
|
|
[[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:imageURLs2 progress:^(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls) {
|
|
numberOfPrefetched2 += 1;
|
|
} completed:^(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls) {
|
|
expect(numberOfPrefetched2).to.equal(noOfFinishedUrls);
|
|
prefetchFinished2 = YES;
|
|
// both completion called
|
|
if (prefetchFinished1 && prefetchFinished2) {
|
|
[expectation fulfill];
|
|
}
|
|
}];
|
|
});
|
|
}];
|
|
|
|
[self waitForExpectationsWithCommonTimeout];
|
|
}
|
|
|
|
- (void)test05PrefetchLargeURLsAndDelegateWorks {
|
|
XCTestExpectation *expectation = [self expectationWithDescription:@"Prefetch large URLs and delegate failed"];
|
|
|
|
// This test also test large URLs and thread-safe problem. You can tested with 2000 urls and get the correct result locally. However, due to the limit of CI, 20 is enough.
|
|
NSMutableArray<NSURL *> *imageURLs = [NSMutableArray arrayWithCapacity:20];
|
|
for (size_t i = 1; i <= 20; i++) {
|
|
NSString *url = [NSString stringWithFormat:@"http://via.placeholder.com/%zux%zu.jpg", i, i];
|
|
[imageURLs addObject:[NSURL URLWithString:url]];
|
|
}
|
|
self.prefetcher = [SDWebImagePrefetcher new];
|
|
self.prefetcher.delegate = self;
|
|
// Current implementation, the delegate method called before the progressBlock and completionBlock
|
|
[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
|
|
[self.prefetcher prefetchURLs:[imageURLs copy] progress:^(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls) {
|
|
expect(self.finishedCount).to.equal(noOfFinishedUrls);
|
|
expect(self.totalCount).to.equal(noOfTotalUrls);
|
|
} completed:^(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls) {
|
|
expect(self.finishedCount).to.equal(noOfFinishedUrls);
|
|
expect(self.skippedCount).to.equal(noOfSkippedUrls);
|
|
[expectation fulfill];
|
|
}];
|
|
}];
|
|
|
|
[self waitForExpectationsWithTimeout:kAsyncTestTimeout * 20 handler:nil];
|
|
}
|
|
|
|
- (void)test06PrefetchCancelToken {
|
|
NSArray *imageURLs = @[@"http://via.placeholder.com/20x20.jpg",
|
|
@"http://via.placeholder.com/30x30.jpg",
|
|
@"http://via.placeholder.com/40x40.jpg"];
|
|
SDWebImagePrefetcher *prefetcher = [[SDWebImagePrefetcher alloc] init];
|
|
SDWebImagePrefetchToken *token = [prefetcher prefetchURLs:imageURLs];
|
|
expect(prefetcher.runningTokens.count).equal(1);
|
|
[token cancel];
|
|
expect(prefetcher.runningTokens.count).equal(0);
|
|
}
|
|
|
|
- (void)test07DownloaderCancelDuringPrefetching {
|
|
XCTestExpectation *expectation = [self expectationWithDescription:@"Downloader cancel during prefetch should not hung up"];
|
|
|
|
NSArray *imageURLs = @[@"http://via.placeholder.com/5000x5000.jpg",
|
|
@"http://via.placeholder.com/6000x6000.jpg",
|
|
@"http://via.placeholder.com/7000x7000.jpg"];
|
|
for (NSString *url in imageURLs) {
|
|
[SDImageCache.sharedImageCache removeImageFromDiskForKey:url];
|
|
}
|
|
SDWebImagePrefetcher *prefetcher = [[SDWebImagePrefetcher alloc] init];
|
|
prefetcher.maxConcurrentPrefetchCount = 3;
|
|
[prefetcher prefetchURLs:imageURLs progress:nil completed:^(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls) {
|
|
expect(noOfSkippedUrls).equal(3);
|
|
[expectation fulfill];
|
|
}];
|
|
|
|
// Cancel all download, should not effect the prefetcher logic or cause hung up
|
|
// Prefetch is not sync, so using wait for testing
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kMinDelayNanosecond), dispatch_get_main_queue(), ^{
|
|
[SDWebImageDownloader.sharedDownloader cancelAllDownloads];
|
|
});
|
|
|
|
[self waitForExpectationsWithCommonTimeout];
|
|
}
|
|
|
|
- (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount {
|
|
expect(imagePrefetcher).to.equal(self.prefetcher);
|
|
self.skippedCount = skippedCount;
|
|
self.totalCount = totalCount;
|
|
}
|
|
|
|
- (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount {
|
|
expect(imagePrefetcher).to.equal(self.prefetcher);
|
|
self.finishedCount = finishedCount;
|
|
self.totalCount = totalCount;
|
|
}
|
|
|
|
@end
|