Add tests for custom loader protocol, using a test loader to specify loader function

This commit is contained in:
DreamPiggy 2018-04-17 21:03:33 +08:00
parent 60759f812a
commit d5074429f0
6 changed files with 136 additions and 27 deletions

View File

@ -15,7 +15,7 @@
/**
All image loaders in manager. The loaders array is a priority queue, which means the later added loader will have the highest priority
*/
@property (nonatomic, strong, readwrite, nullable) NSArray<id<SDWebImageLoader>>* loaders;
@property (nonatomic, copy, readwrite, nullable) NSArray<id<SDWebImageLoader>>* loaders;
/**
Add a new image loader to the end of loaders array. Which has the highest priority.

View File

@ -14,7 +14,6 @@
@interface SDWebImageLoadersManager ()
@property (strong, nonatomic, nonnull) NSMutableArray<id<SDWebImageLoader>> *mutableLoaders;
@property (nonatomic, strong, nonnull) dispatch_semaphore_t loadersLock;
@end
@ -34,7 +33,7 @@
self = [super init];
if (self) {
// initialize with default image loaders
self.mutableLoaders = [@[[SDWebImageDownloader sharedDownloader]] mutableCopy];
self.loaders = @[[SDWebImageDownloader sharedDownloader]];
self.loadersLock = dispatch_semaphore_create(1);
}
return self;
@ -43,37 +42,37 @@
#pragma mark - Loader Property
- (void)addLoader:(id<SDWebImageLoader>)loader {
if ([loader conformsToProtocol:@protocol(SDWebImageLoader)]) {
LOCK(self.loadersLock);
[self.mutableLoaders addObject:loader];
UNLOCK(self.loadersLock);
if (![loader conformsToProtocol:@protocol(SDWebImageLoader)]) {
return;
}
LOCK(self.loadersLock);
NSMutableArray<id<SDWebImageLoader>> *mutableLoaders = [self.loaders mutableCopy];
if (!mutableLoaders) {
mutableLoaders = [NSMutableArray array];
}
[mutableLoaders addObject:loader];
self.loaders = [mutableLoaders copy];
UNLOCK(self.loadersLock);
}
- (void)removeLoader:(id<SDWebImageLoader>)loader {
if (![loader conformsToProtocol:@protocol(SDWebImageLoader)]) {
return;
}
LOCK(self.loadersLock);
[self.mutableLoaders removeObject:loader];
UNLOCK(self.loadersLock);
}
- (NSArray<id<SDWebImageLoader>> *)loaders {
NSArray<id<SDWebImageLoader>> *sortedLoaders;
LOCK(self.loadersLock);
sortedLoaders = [[[self.mutableLoaders copy] reverseObjectEnumerator] allObjects];
UNLOCK(self.loadersLock);
return sortedLoaders;
}
- (void)setLoaders:(NSArray<id<SDWebImageLoader>> *)loaders {
LOCK(self.loadersLock);
self.mutableLoaders = [loaders mutableCopy];
NSMutableArray<id<SDWebImageLoader>> *mutableLoaders = [self.loaders mutableCopy];
[mutableLoaders removeObject:loader];
self.loaders = [mutableLoaders copy];
UNLOCK(self.loadersLock);
}
#pragma mark - SDWebImageLoader
- (BOOL)canLoadWithURL:(nullable NSURL *)url {
for (id<SDWebImageLoader> loader in self.loaders) {
LOCK(self.loadersLock);
NSArray<id<SDWebImageLoader>> *loaders = self.loaders;
UNLOCK(self.loadersLock);
for (id<SDWebImageLoader> loader in loaders.reverseObjectEnumerator) {
if ([loader canLoadWithURL:url]) {
return YES;
}
@ -85,11 +84,12 @@
if (!url) {
return nil;
}
for (id<SDWebImageLoader> loader in self.loaders) {
LOCK(self.loadersLock);
NSArray<id<SDWebImageLoader>> *loaders = self.loaders;
UNLOCK(self.loadersLock);
for (id<SDWebImageLoader> loader in loaders.reverseObjectEnumerator) {
if ([loader respondsToSelector:@selector(loadImageWithURL:options:context:progress:completed:)]) {
if ([loader canLoadWithURL:url]) {
return [loader loadImageWithURL:url options:options context:context progress:progressBlock completed:completedBlock];
}
return [loader loadImageWithURL:url options:options context:context progress:progressBlock completed:completedBlock];
}
}
return nil;

View File

@ -15,6 +15,8 @@
321259EE1F39E4110096FE0E /* TestImageAnimated.webp in Resources */ = {isa = PBXBuildFile; fileRef = 321259ED1F39E4110096FE0E /* TestImageAnimated.webp */; };
3226ECBB20754F7700FAFACF /* SDWebImageTestDownloadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3226ECBA20754F7700FAFACF /* SDWebImageTestDownloadOperation.m */; };
3226ECBC20754F7700FAFACF /* SDWebImageTestDownloadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3226ECBA20754F7700FAFACF /* SDWebImageTestDownloadOperation.m */; };
323B8E1F20862322008952BE /* SDWebImageTestLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 323B8E1E20862322008952BE /* SDWebImageTestLoader.m */; };
323B8E2020862322008952BE /* SDWebImageTestLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 323B8E1E20862322008952BE /* SDWebImageTestLoader.m */; };
3254C32020641077008D1022 /* SDWebImageTransformerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3254C31F20641077008D1022 /* SDWebImageTransformerTests.m */; };
3254C32120641077008D1022 /* SDWebImageTransformerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3254C31F20641077008D1022 /* SDWebImageTransformerTests.m */; };
3264FF2F205D42CB00F6BD48 /* SDWebImageTestTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3264FF2E205D42CB00F6BD48 /* SDWebImageTestTransformer.m */; };
@ -70,6 +72,8 @@
321259ED1F39E4110096FE0E /* TestImageAnimated.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestImageAnimated.webp; sourceTree = "<group>"; };
3226ECB920754F7700FAFACF /* SDWebImageTestDownloadOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageTestDownloadOperation.h; sourceTree = "<group>"; };
3226ECBA20754F7700FAFACF /* SDWebImageTestDownloadOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTestDownloadOperation.m; sourceTree = "<group>"; };
323B8E1D20862322008952BE /* SDWebImageTestLoader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageTestLoader.h; sourceTree = "<group>"; };
323B8E1E20862322008952BE /* SDWebImageTestLoader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTestLoader.m; sourceTree = "<group>"; };
3254C31F20641077008D1022 /* SDWebImageTransformerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTransformerTests.m; sourceTree = "<group>"; };
3264FF2D205D42CB00F6BD48 /* SDWebImageTestTransformer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageTestTransformer.h; sourceTree = "<group>"; };
3264FF2E205D42CB00F6BD48 /* SDWebImageTestTransformer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTestTransformer.m; sourceTree = "<group>"; };
@ -223,6 +227,8 @@
32E6F0311F3A1B4700A945E6 /* SDWebImageTestDecoder.m */,
3264FF2D205D42CB00F6BD48 /* SDWebImageTestTransformer.h */,
3264FF2E205D42CB00F6BD48 /* SDWebImageTestTransformer.m */,
323B8E1D20862322008952BE /* SDWebImageTestLoader.h */,
323B8E1E20862322008952BE /* SDWebImageTestLoader.m */,
);
path = Tests;
sourceTree = "<group>";
@ -470,6 +476,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
323B8E2020862322008952BE /* SDWebImageTestLoader.m in Sources */,
32B99EAC203B36650017FD66 /* SDWebImageDownloaderTests.m in Sources */,
3254C32120641077008D1022 /* SDWebImageTransformerTests.m in Sources */,
328BB6DE20825E9800760D6C /* SDWebImageTestCache.m in Sources */,
@ -492,6 +499,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
323B8E1F20862322008952BE /* SDWebImageTestLoader.m in Sources */,
32E6F0321F3A1B4700A945E6 /* SDWebImageTestDecoder.m in Sources */,
3226ECBB20754F7700FAFACF /* SDWebImageTestDownloadOperation.m in Sources */,
3254C32020641077008D1022 /* SDWebImageTransformerTests.m in Sources */,

View File

@ -11,8 +11,10 @@
#import <SDWebImage/SDWebImageDownloader.h>
#import <SDWebImage/SDWebImageDownloaderOperation.h>
#import <SDWebImage/SDWebImageCodersManager.h>
#import <SDWebImage/SDWebImageLoadersManager.h>
#import "SDWebImageTestDownloadOperation.h"
#import "SDWebImageTestDecoder.h"
#import "SDWebImageTestLoader.h"
/**
* Category for SDWebImageDownloader so we can access the operationClass
@ -414,4 +416,34 @@
[self waitForExpectationsWithCommonTimeout];
}
#pragma mark - SDWebImageLoader
- (void)test30CustomImageLoaderWorks {
XCTestExpectation *expectation = [self expectationWithDescription:@"Custom image not works"];
SDWebImageTestLoader *loader = [[SDWebImageTestLoader alloc] init];
NSURL *imageURL = [NSURL URLWithString:kTestJpegURL];
[loader loadImageWithURL:imageURL options:0 context:nil progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
expect(targetURL).notTo.beNil();
} completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
expect(error).to.beNil();
expect(image).notTo.beNil();
[expectation fulfill];
}];
[self waitForExpectationsWithCommonTimeout];
}
- (void)test31ThatLoadersManagerWorks {
XCTestExpectation *expectation = [self expectationWithDescription:@"Loaders manager not works"];
NSURL *imageURL = [NSURL URLWithString:kTestJpegURL];
[[SDWebImageLoadersManager sharedManager] loadImageWithURL:imageURL options:0 context:nil progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
expect(targetURL).notTo.beNil();
} completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
expect(error).to.beNil();
expect(image).notTo.beNil();
[expectation fulfill];
}];
[self waitForExpectationsWithCommonTimeout];
}
@end

View File

@ -0,0 +1,16 @@
/*
* 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 <Foundation/Foundation.h>
#import <SDWebImage/SDWebImageLoader.h>
// A really naive implementation of custom image loader using `NSURLSession`
@interface SDWebImageTestLoader : NSObject <SDWebImageLoader>
@end

View File

@ -0,0 +1,53 @@
/*
* 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 "SDWebImageTestLoader.h"
#import <KVOController/KVOController.h>
@interface NSURLSessionTask (SDWebImageOperation) <SDWebImageOperation>
@end
@implementation SDWebImageTestLoader
- (BOOL)canLoadWithURL:(NSURL *)url {
return YES;
}
- (id<SDWebImageOperation>)loadImageWithURL:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDWebImageLoaderProgressBlock)progressBlock completed:(SDWebImageLoaderCompletedBlock)completedBlock {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (data) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *image = SDWebImageLoaderDecodeImageData(data, url, options, context);
if (completedBlock) {
completedBlock(image, data, nil, YES);
}
});
} else {
if (completedBlock) {
completedBlock(nil, nil, error, YES);
}
}
}];
[self.KVOController observe:task keyPath:NSStringFromSelector(@selector(countOfBytesReceived)) options:NSKeyValueObservingOptionNew block:^(id _Nullable observer, id _Nonnull object, NSDictionary<NSString *,id> * _Nonnull change) {
NSURLSessionTask *sessionTask = object;
NSInteger receivedSize = sessionTask.countOfBytesReceived;
NSInteger expectedSize = sessionTask.countOfBytesExpectedToReceive;
if (progressBlock) {
progressBlock(receivedSize, expectedSize, url);
}
}];
[task resume];
return task;
}
@end