TwitterImagePipelineTests/TIPTestsSharedUtils.m (227 lines of code) (raw):
//
// TIPTestsSharedUtils.m
// TwitterImagePipeline
//
// Created on 8/30/18.
// Copyright © 2020 Twitter. All rights reserved.
//
#import "TIP_Project.h"
#import "TIPImageDiskCache.h"
#import "TIPImageFetchOperation+Project.h"
#import "TIPImageMemoryCache.h"
#import "TIPImagePipeline+Project.h"
#import "TIPImageRenderedCache.h"
#import "TIPTestImageFetchDownloadInternalWithStubbing.h"
#import "TIPTests.h"
#import "TIPTestsSharedUtils.h"
@import MobileCoreServices;
@implementation TIPImagePipelineTestFetchRequest
- (instancetype)init
{
self = [super init];
if (self) {
_options = TIPImageFetchNoOptions;
_targetContentMode = UIViewContentModeCenter;
_targetDimensions = CGSizeZero;
_loadingSources = TIPImageFetchLoadingSourcesAll;
}
return self;
}
- (NSString *)cannedImageFilePath
{
return _cannedImageFilePath ?: [TIPImagePipelineBaseTests pathForImageOfType:self.imageType progressive:self.progressiveSource];
}
- (NSDictionary *)progressiveLoadingPolicies
{
NSMutableDictionary *policies = [NSMutableDictionary dictionaryWithCapacity:2];
if (self.jp2ProgressiveLoadingPolicy) {
policies[TIPImageTypeJPEG2000] = self.jp2ProgressiveLoadingPolicy;
}
if (self.jpegProgressiveLoadingPolicy) {
policies[TIPImageTypeJPEG] = self.jpegProgressiveLoadingPolicy;
}
return policies;
}
+ (void)stubRequest:(TIPImagePipelineTestFetchRequest *)request
bitrate:(uint64_t)bitrate
resumable:(BOOL)resumable
{
NSData *data = [NSData dataWithContentsOfFile:request.cannedImageFilePath options:NSDataReadingMappedIfSafe error:NULL];
NSString *MIMEType = (NSString *)CFBridgingRelease(UTTypeIsDeclared((__bridge CFStringRef)request.imageType) ? UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)request.imageType, kUTTagClassMIMEType) : nil);
id<TIPImageFetchDownloadProviderWithStubbingSupport> provider = (id<TIPImageFetchDownloadProviderWithStubbingSupport>)[TIPGlobalConfiguration sharedInstance].imageFetchDownloadProvider;
[provider addDownloadStubForRequestURL:request.imageURL
responseData:data
responseMIMEType:MIMEType
shouldSupportResuming:resumable
suggestedBitrate:bitrate];
}
@end
@implementation TIPImagePipelineTestContext
- (instancetype)init
{
if (self = [super init]) {
_cancelPoint = 2.0f;
}
return self;
}
- (NSUInteger)expectedFrameCount
{
if (_expectedFrameCount) {
return _expectedFrameCount;
}
return self.shouldSupportAnimatedLoading ? kFireworksFrameCount : 1;
}
@end
@implementation TIPImagePipeline (Undeprecated)
- (nonnull TIPImageFetchOperation *)undeprecatedFetchImageWithRequest:(nonnull id<TIPImageFetchRequest>)request context:(nullable id)context delegate:(nullable id<TIPImageFetchDelegate>)delegate
{
TIPImageFetchOperation *op = [self operationWithRequest:request context:context delegate:delegate];
[self fetchImageWithOperation:op];
return op;
}
- (nonnull TIPImageFetchOperation *)undeprecatedFetchImageWithRequest:(nonnull id<TIPImageFetchRequest>)request context:(nullable id)context completion:(nullable TIPImagePipelineFetchCompletionBlock)completion
{
TIPImageFetchOperation *op = [self operationWithRequest:request context:context completion:completion];
[self fetchImageWithOperation:op];
return op;
}
@end
static TIPImagePipeline *sPipeline = nil;
@implementation TIPImagePipelineBaseTests
+ (TIPImagePipeline *)sharedPipeline
{
return sPipeline;
}
+ (NSString *)pathForImageOfType:(NSString *)type progressive:(BOOL)progressive
{
NSString *imagePath = nil;
NSBundle *thisBundle = TIPTestsResourceBundle();
if ([type isEqualToString:TIPImageTypeGIF]) {
imagePath = [thisBundle pathForResource:@"fireworks" ofType:@"gif"];
} else {
NSString *extension = nil;
if ([type isEqualToString:TIPImageTypeJPEG]) {
extension = (progressive) ? @"pjpg" : @"jpg";
} else if ([type isEqualToString:TIPImageTypeJPEG2000]) {
extension = @"jp2";
} else if ([type isEqualToString:TIPImageTypePNG]) {
extension = @"png";
}
if (extension) {
imagePath = [thisBundle pathForResource:@"carnival" ofType:extension];
}
}
return imagePath;
}
+ (NSURL *)dummyURLWithPath:(NSString *)path
{
if (!path) {
path = @"";
}
if (![path hasPrefix:@"/"]) {
path = [@"/" stringByAppendingString:path];
}
return [NSURL URLWithString:[NSString stringWithFormat:@"http://www.dummy.com%@", path]];
}
+ (void)setUp
{
TIPGlobalConfiguration *globalConfig = [TIPGlobalConfiguration sharedInstance];
TIPSetDebugSTOPOnAssertEnabled(NO);
TIPSetShouldAssertDuringPipelineRegistation(NO);
sPipeline = [[TIPImagePipeline alloc] initWithIdentifier:NSStringFromClass(self)];
globalConfig.imageFetchDownloadProvider = [[TIPTestsImageFetchDownloadProviderOverrideClass() alloc] init];
globalConfig.maxConcurrentImagePipelineDownloadCount = 4;
globalConfig.maxBytesForAllRenderedCaches = 12 * 1024 * 1024;
globalConfig.maxBytesForAllMemoryCaches = 12 * 1024 * 1024;
globalConfig.maxBytesForAllDiskCaches = 16 * 1024 * 1024;
globalConfig.maxRatioSizeOfCacheEntry = 0;
}
+ (void)tearDown
{
TIPGlobalConfiguration *globalConfig = [TIPGlobalConfiguration sharedInstance];
TIPSetDebugSTOPOnAssertEnabled(YES);
TIPSetShouldAssertDuringPipelineRegistation(YES);
[sPipeline clearMemoryCaches];
[sPipeline clearDiskCache];
globalConfig.imageFetchDownloadProvider = nil;
globalConfig.maxBytesForAllRenderedCaches = -1;
globalConfig.maxBytesForAllMemoryCaches = -1;
globalConfig.maxBytesForAllDiskCaches = -1;
globalConfig.maxConcurrentImagePipelineDownloadCount = TIPMaxConcurrentImagePipelineDownloadCountDefault;
globalConfig.maxRatioSizeOfCacheEntry = -1;
sPipeline = nil;
}
- (void)tearDown
{
[sPipeline clearMemoryCaches];
[sPipeline clearDiskCache];
id<TIPImageFetchDownloadProviderWithStubbingSupport> provider = (id<TIPImageFetchDownloadProviderWithStubbingSupport>)[TIPGlobalConfiguration sharedInstance].imageFetchDownloadProvider;
[provider removeAllDownloadStubs];
// Flush ALL pipelines
__block BOOL didInspect = NO;
[[TIPGlobalConfiguration sharedInstance] inspect:^(NSDictionary *results) {
didInspect = YES;
}];
while (!didInspect) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
[super tearDown];
}
#pragma mark Delegate
- (void)tip_imageFetchOperationDidStart:(TIPImageFetchOperation *)op
{
TIPImagePipelineTestContext *context = op.context;
context.didStart = YES;
}
- (void)tip_imageFetchOperation:(TIPImageFetchOperation *)op willAttemptToLoadFromSource:(TIPImageLoadSource)source
{
TIPImagePipelineTestContext *context = op.context;
NSArray *existing = context.hitLoadSources ?: @[];
context.hitLoadSources = [existing arrayByAddingObject:@(source)];
}
- (void)tip_imageFetchOperation:(TIPImageFetchOperation *)op didLoadPreviewImage:(id<TIPImageFetchResult>)previewResult completion:(TIPImageFetchDidLoadPreviewCallback)completion
{
TIPImagePipelineTestContext *context = op.context;
context.didProvidePreviewCheck = YES;
completion(context.shouldCancelOnPreview ? TIPImageFetchPreviewLoadedBehaviorStopLoading : TIPImageFetchPreviewLoadedBehaviorContinueLoading);
}
- (BOOL)tip_imageFetchOperation:(TIPImageFetchOperation *)op shouldLoadProgressivelyWithIdentifier:(NSString *)identifier URL:(NSURL *)URL imageType:(NSString *)imageType originalDimensions:(CGSize)originalDimensions
{
TIPImagePipelineTestContext *context = op.context;
context.didMakeProgressiveCheck = YES;
return context.shouldSupportProgressiveLoading;
}
- (void)tip_imageFetchOperation:(TIPImageFetchOperation *)op didUpdateProgressiveImage:(id<TIPImageFetchResult>)progressiveResult progress:(float)progress
{
TIPImagePipelineTestContext *context = op.context;
context.progressiveProgressCount++;
}
- (void)tip_imageFetchOperation:(TIPImageFetchOperation *)op didLoadFirstAnimatedImageFrame:(id<TIPImageFetchResult>)progressiveResult progress:(float)progress
{
TIPImagePipelineTestContext *context = op.context;
context.firstAnimatedFrameProgress = progress;
}
- (void)tip_imageFetchOperation:(TIPImageFetchOperation *)op didUpdateProgress:(float)progress
{
TIPImagePipelineTestContext *context = op.context;
context.normalProgressCount++;
if (context.firstProgress == 0.0f) {
context.firstProgress = progress;
}
if (context.firstProgress > 0.0f && progress == 0.0f) {
context.progressWasReset = YES;
}
if (!context.associatedDownloadContext) {
context.associatedDownloadContext = [op associatedDownloadContext];
}
if (progress > context.cancelPoint) {
[op cancel];
}
if (context.shouldCancelOnOtherContextFirstProgress && context.otherContext.firstProgress > 0.0f) {
[op cancel];
}
}
- (void)tip_imageFetchOperation:(TIPImageFetchOperation *)op didLoadFinalImage:(id<TIPImageFetchResult>)finalResult
{
TIPImagePipelineTestContext *context = op.context;
context.finalImageContainer = finalResult.imageContainer;
context.finalSource = finalResult.imageSource;
}
- (void)tip_imageFetchOperation:(TIPImageFetchOperation *)op didFailToLoadFinalImage:(NSError *)error
{
TIPImagePipelineTestContext *context = op.context;
context.finalError = error;
}
@end