594 lines
27 KiB
Mathematica
594 lines
27 KiB
Mathematica
|
//
|
||
|
// ProgressReportingTests.m
|
||
|
// UnzipKit
|
||
|
//
|
||
|
// Created by Dov Frankel on 10/7/17.
|
||
|
// Copyright (c) 2015 Abbey Code. All rights reserved.
|
||
|
//
|
||
|
|
||
|
#import "UZKArchiveTestCase.h"
|
||
|
#import "UnzipKit.h"
|
||
|
#import "UnzipKitMacros.h"
|
||
|
|
||
|
@interface ProgressReportingTests : UZKArchiveTestCase
|
||
|
|
||
|
@property (retain) NSMutableArray<NSNumber*> *fractionsCompletedReported;
|
||
|
@property (retain) NSMutableArray<NSString*> *descriptionsReported;
|
||
|
@property (retain) NSMutableArray<NSString*> *additionalDescriptionsReported;
|
||
|
@property (retain) NSMutableArray<UZKFileInfo*> *fileInfosReported;
|
||
|
|
||
|
@end
|
||
|
|
||
|
static void *ExtractFilesContext = &ExtractFilesContext;
|
||
|
static void *OtherContext = &OtherContext;
|
||
|
static void *CancelContext = &CancelContext;
|
||
|
|
||
|
static NSUInteger observerCallCount;
|
||
|
|
||
|
|
||
|
@implementation ProgressReportingTests
|
||
|
|
||
|
- (void)setUp {
|
||
|
[super setUp];
|
||
|
|
||
|
self.fractionsCompletedReported = [NSMutableArray array];
|
||
|
self.descriptionsReported = [NSMutableArray array];
|
||
|
self.additionalDescriptionsReported = [NSMutableArray array];
|
||
|
self.fileInfosReported = [NSMutableArray array];
|
||
|
|
||
|
observerCallCount = 0;
|
||
|
}
|
||
|
|
||
|
- (void)testProgressReporting_ExtractFiles_FractionCompleted
|
||
|
{
|
||
|
NSString *testArchiveName = @"Test Archive.zip";
|
||
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
||
|
NSString *extractDirectory = [self randomDirectoryWithPrefix:
|
||
|
[testArchiveName stringByDeletingPathExtension]];
|
||
|
NSURL *extractURL = [self.tempDirectory URLByAppendingPathComponent:extractDirectory];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:testArchiveURL error:nil];
|
||
|
|
||
|
NSProgress *extractFilesProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
[extractFilesProgress becomeCurrentWithPendingUnitCount:1];
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[extractFilesProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:ExtractFilesContext];
|
||
|
|
||
|
NSError *extractError = nil;
|
||
|
BOOL success = [archive extractFilesTo:extractURL.path
|
||
|
overwrite:NO
|
||
|
error:&extractError];
|
||
|
|
||
|
XCTAssertNil(extractError, @"Error returned by extractFilesTo:overwrite:progress:error:");
|
||
|
XCTAssertTrue(success, @"Archive failed to extract %@ to %@", testArchiveName, extractURL);
|
||
|
|
||
|
[extractFilesProgress resignCurrent];
|
||
|
[extractFilesProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(extractFilesProgress.fractionCompleted, 1.00, .0000000001, @"Progress never reported as completed");
|
||
|
|
||
|
NSUInteger expectedProgressUpdates = 4;
|
||
|
NSArray<NSNumber *> *expectedProgresses = @[@0,
|
||
|
@0.000315,
|
||
|
@0.533568,
|
||
|
@1.0];
|
||
|
|
||
|
XCTAssertEqual(self.fractionsCompletedReported.count, expectedProgressUpdates, @"Incorrect number of progress updates");
|
||
|
for (NSUInteger i = 0; i < expectedProgressUpdates; i++) {
|
||
|
float expectedProgress = expectedProgresses[i].floatValue;
|
||
|
float actualProgress = self.fractionsCompletedReported[i].floatValue;
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(actualProgress, expectedProgress, 0.00001f, @"Incorrect progress reported at index %ld", (long)i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)testProgressReporting_ExtractFiles_Description
|
||
|
{
|
||
|
NSString *testArchiveName = @"Test Archive.zip";
|
||
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
||
|
NSString *extractDirectory = [self randomDirectoryWithPrefix:
|
||
|
[testArchiveName stringByDeletingPathExtension]];
|
||
|
NSURL *extractURL = [self.tempDirectory URLByAppendingPathComponent:extractDirectory];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:testArchiveURL error:nil];
|
||
|
|
||
|
NSProgress *extractFilesProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
archive.progress = extractFilesProgress;
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(localizedDescription));
|
||
|
|
||
|
[self.descriptionsReported removeAllObjects];
|
||
|
[extractFilesProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:ExtractFilesContext];
|
||
|
|
||
|
NSError *extractError = nil;
|
||
|
BOOL success = [archive extractFilesTo:extractURL.path
|
||
|
overwrite:NO
|
||
|
error:&extractError];
|
||
|
|
||
|
XCTAssertNil(extractError, @"Error returned by extractFilesTo:overwrite:error:");
|
||
|
XCTAssertTrue(success, @"Archive failed to extract %@ to %@", testArchiveName, extractURL);
|
||
|
|
||
|
[extractFilesProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
NSArray<NSString *>*expectedDescriptions = @[@"Processing “Test File A.txt”…",
|
||
|
@"Processing “Test File B.jpg”…",
|
||
|
@"Processing “Test File C.m4a”…"];
|
||
|
|
||
|
for (NSString *expectedDescription in expectedDescriptions) {
|
||
|
BOOL descriptionFound = [self.descriptionsReported containsObject:expectedDescription];
|
||
|
XCTAssertTrue(descriptionFound, @"Expected progress updates to contain '%@', but they didn't", expectedDescription);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)testProgressReporting_ExtractFiles_AdditionalDescription
|
||
|
{
|
||
|
NSString *testArchiveName = @"Test Archive.zip";
|
||
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
||
|
NSString *extractDirectory = [self randomDirectoryWithPrefix:
|
||
|
[testArchiveName stringByDeletingPathExtension]];
|
||
|
NSURL *extractURL = [self.tempDirectory URLByAppendingPathComponent:extractDirectory];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:testArchiveURL error:nil];
|
||
|
|
||
|
NSProgress *extractFilesProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
archive.progress = extractFilesProgress;
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(localizedAdditionalDescription));
|
||
|
|
||
|
[extractFilesProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:ExtractFilesContext];
|
||
|
|
||
|
NSError *extractError = nil;
|
||
|
BOOL success = [archive extractFilesTo:extractURL.path
|
||
|
overwrite:NO
|
||
|
error:&extractError];
|
||
|
|
||
|
XCTAssertNil(extractError, @"Error returned by extractFilesTo:overwrite:error:");
|
||
|
XCTAssertTrue(success, @"Archive failed to extract %@ to %@", testArchiveName, extractURL);
|
||
|
|
||
|
[extractFilesProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
NSArray<NSString *>*expectedAdditionalDescriptions = @[@"Zero KB of 105 KB",
|
||
|
@"33 bytes of 105 KB",
|
||
|
@"56 KB of 105 KB",
|
||
|
@"105 KB of 105 KB"];
|
||
|
|
||
|
for (NSString *expectedDescription in expectedAdditionalDescriptions) {
|
||
|
BOOL descriptionFound = [self.additionalDescriptionsReported containsObject:expectedDescription];
|
||
|
XCTAssertTrue(descriptionFound, @"Expected progress updates to contain '%@', but they didn't", expectedDescription);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)testProgressReporting_ExtractFiles_FileInfo
|
||
|
{
|
||
|
NSString *testArchiveName = @"Test Archive.zip";
|
||
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
||
|
NSString *extractDirectory = [self randomDirectoryWithPrefix:
|
||
|
[testArchiveName stringByDeletingPathExtension]];
|
||
|
NSURL *extractURL = [self.tempDirectory URLByAppendingPathComponent:extractDirectory];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:testArchiveURL error:nil];
|
||
|
|
||
|
NSProgress *extractFilesProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
archive.progress = extractFilesProgress;
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[extractFilesProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:ExtractFilesContext];
|
||
|
|
||
|
NSError *extractError = nil;
|
||
|
BOOL success = [archive extractFilesTo:extractURL.path
|
||
|
overwrite:NO
|
||
|
error:&extractError];
|
||
|
|
||
|
XCTAssertNil(extractError, @"Error returned by extractFilesTo:overwrite:error:");
|
||
|
XCTAssertTrue(success, @"Archive failed to extract %@ to %@", testArchiveName, extractURL);
|
||
|
|
||
|
[extractFilesProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
NSUInteger expectedFileInfos = 3;
|
||
|
NSArray<NSString *> *expectedFileNames = @[@"Test File A.txt",
|
||
|
@"Test File B.jpg",
|
||
|
@"Test File C.m4a"];
|
||
|
|
||
|
NSArray<NSString *> *actualFilenames = [self.fileInfosReported valueForKeyPath:NSStringFromSelector(@selector(filename))];
|
||
|
|
||
|
XCTAssertEqual(self.fileInfosReported.count, expectedFileInfos, @"Incorrect number of progress updates");
|
||
|
XCTAssertTrue([expectedFileNames isEqualToArray:actualFilenames], @"Incorrect filenames returned: %@", actualFilenames);
|
||
|
}
|
||
|
|
||
|
- (void)testProgressReporting_PerformOnFiles {
|
||
|
NSString *testArchiveName = @"Test Archive.zip";
|
||
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:testArchiveURL error:nil];
|
||
|
|
||
|
NSProgress *performProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
[performProgress becomeCurrentWithPendingUnitCount:1];
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[performProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:OtherContext];
|
||
|
|
||
|
NSError *performError = nil;
|
||
|
BOOL success = [archive performOnFilesInArchive:^(UZKFileInfo * _Nonnull fileInfo, BOOL * _Nonnull stop) {}
|
||
|
error:&performError];
|
||
|
|
||
|
XCTAssertNil(performError, @"Error returned by performOnFilesInArchive:error:");
|
||
|
XCTAssertTrue(success, @"Archive failed to perform operation on files of archive");
|
||
|
|
||
|
[performProgress resignCurrent];
|
||
|
[performProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(performProgress.fractionCompleted, 1.00, 0.000001, @"Progress never reported as completed");
|
||
|
|
||
|
NSUInteger expectedProgressUpdates = 4;
|
||
|
NSArray<NSNumber *> *expectedProgresses = @[@0,
|
||
|
@0.333333,
|
||
|
@0.666666,
|
||
|
@1.0];
|
||
|
|
||
|
XCTAssertEqual(self.fractionsCompletedReported.count, expectedProgressUpdates, @"Incorrect number of progress updates");
|
||
|
for (NSUInteger i = 0; i < expectedProgressUpdates; i++) {
|
||
|
float expectedProgress = expectedProgresses[i].floatValue;
|
||
|
float actualProgress = self.fractionsCompletedReported[i].floatValue;
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(actualProgress, expectedProgress, 0.000001f, @"Incorrect progress reported at index %ld", (long)i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)testProgressReporting_PerformOnData {
|
||
|
NSString *testArchiveName = @"Test Archive.zip";
|
||
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:testArchiveURL error:nil];
|
||
|
|
||
|
NSProgress *performProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
[performProgress becomeCurrentWithPendingUnitCount:1];
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[performProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:OtherContext];
|
||
|
|
||
|
NSError *performError = nil;
|
||
|
BOOL success = [archive performOnDataInArchive:
|
||
|
^(UZKFileInfo * _Nonnull fileInfo, NSData * _Nonnull fileData, BOOL * _Nonnull stop) {}
|
||
|
error:&performError];
|
||
|
|
||
|
XCTAssertNil(performError, @"Error returned by performOnDataInArchive:error:");
|
||
|
XCTAssertTrue(success, @"Archive failed to perform operation on data of archive");
|
||
|
|
||
|
[performProgress resignCurrent];
|
||
|
[performProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(performProgress.fractionCompleted, 1.00, 0.000001, @"Progress never reported as completed");
|
||
|
|
||
|
NSUInteger expectedProgressUpdates = 4;
|
||
|
NSArray<NSNumber *> *expectedProgresses = @[@0,
|
||
|
@0.333333,
|
||
|
@0.666666,
|
||
|
@1.0];
|
||
|
|
||
|
XCTAssertEqual(self.fractionsCompletedReported.count, expectedProgressUpdates, @"Incorrect number of progress updates");
|
||
|
for (NSUInteger i = 0; i < expectedProgressUpdates; i++) {
|
||
|
float expectedProgress = expectedProgresses[i].floatValue;
|
||
|
float actualProgress = self.fractionsCompletedReported[i].floatValue;
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(actualProgress, expectedProgress, 0.000001f, @"Incorrect progress reported at index %ld", (long)i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)testProgressCancellation_ExtractFiles {
|
||
|
NSString *testArchiveName = @"Test Archive.zip";
|
||
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
||
|
NSString *extractDirectory = [self randomDirectoryWithPrefix:
|
||
|
[testArchiveName stringByDeletingPathExtension]];
|
||
|
NSURL *extractURL = [self.tempDirectory URLByAppendingPathComponent:extractDirectory];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:testArchiveURL error:nil];
|
||
|
|
||
|
NSProgress *extractFilesProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
[extractFilesProgress becomeCurrentWithPendingUnitCount:1];
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[extractFilesProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:CancelContext];
|
||
|
|
||
|
NSError *extractError = nil;
|
||
|
BOOL success = [archive extractFilesTo:extractURL.path
|
||
|
overwrite:NO
|
||
|
error:&extractError];
|
||
|
|
||
|
XCTAssertNotNil(extractError, @"Error not returned by extractFilesTo:overwrite:error:");
|
||
|
XCTAssertEqual(extractError.code, UZKErrorCodeUserCancelled, @"Incorrect error code returned from user cancellation");
|
||
|
XCTAssertFalse(success, @"Archive didn't cancel extraction");
|
||
|
|
||
|
[extractFilesProgress resignCurrent];
|
||
|
[extractFilesProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
|
||
|
NSUInteger expectedProgressUpdates = 2;
|
||
|
XCTAssertEqual(self.fractionsCompletedReported.count, expectedProgressUpdates, @"Incorrect number of progress updates");
|
||
|
|
||
|
NSError *listContentsError = nil;
|
||
|
NSFileManager *fm = [NSFileManager defaultManager];
|
||
|
NSArray *extractedFiles = [fm contentsOfDirectoryAtPath:extractURL.path
|
||
|
error:&listContentsError];
|
||
|
|
||
|
XCTAssertNil(listContentsError, @"Error listing contents of extraction directory");
|
||
|
XCTAssertEqual(extractedFiles.count, (unsigned long)1, @"Cancellation didn't occur in as timely a fashion as expected");
|
||
|
}
|
||
|
|
||
|
- (void)testProgressReporting_WriteData {
|
||
|
NSURL *testArchiveURL = [self.tempDirectory URLByAppendingPathComponent:@"WriteData.zip"];
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:testArchiveURL error:nil];
|
||
|
|
||
|
// NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES];
|
||
|
// NSArray<NSString *> *nonZipFiles = [self.nonZipTestFilePaths sortedArrayUsingDescriptors:@[sort]];
|
||
|
// NSString *firstFile = nonZipFiles.firstObject;
|
||
|
NSData *firstFileData = [NSData dataWithContentsOfURL:self.testFileURLs[@"Aces.zip"]];
|
||
|
|
||
|
NSProgress *performProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
[performProgress becomeCurrentWithPendingUnitCount:1];
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[performProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:OtherContext];
|
||
|
|
||
|
NSError *writeError = nil;
|
||
|
BOOL success = [archive writeData:firstFileData
|
||
|
filePath:@"First File.idk"
|
||
|
error:&writeError];
|
||
|
|
||
|
XCTAssertNil(writeError, @"Error returned by writeData:filePath:error:");
|
||
|
XCTAssertTrue(success, @"Failed to write data to archive");
|
||
|
|
||
|
[performProgress resignCurrent];
|
||
|
[performProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(performProgress.fractionCompleted, 1.00, 0.000001, @"Progress never reported as completed");
|
||
|
|
||
|
NSUInteger expectedProgressUpdates = 4;
|
||
|
NSArray<NSNumber *> *expectedProgresses = @[@0,
|
||
|
@0.402872,
|
||
|
@0.805744,
|
||
|
@1.0];
|
||
|
|
||
|
XCTAssertEqual(self.fractionsCompletedReported.count, expectedProgressUpdates, @"Incorrect number of progress updates");
|
||
|
for (NSUInteger i = 0; i < expectedProgressUpdates; i++) {
|
||
|
float expectedProgress = expectedProgresses[i].floatValue;
|
||
|
float actualProgress = self.fractionsCompletedReported[i].floatValue;
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(actualProgress, expectedProgress, 0.000001f, @"Incorrect progress reported at index %ld", (long)i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#pragma mark - Mac-only tests
|
||
|
|
||
|
|
||
|
#if !TARGET_OS_IPHONE
|
||
|
- (void)testProgressReporting_ExtractData {
|
||
|
NSURL *largeArchiveURL = [self largeArchive];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
||
|
NSString *firstFile = [[archive listFilenames:nil] firstObject];
|
||
|
|
||
|
NSProgress *extractFileProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
[extractFileProgress becomeCurrentWithPendingUnitCount:1];
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[extractFileProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:OtherContext];
|
||
|
|
||
|
NSError *extractError = nil;
|
||
|
NSData *data = [archive extractDataFromFile:firstFile error:&extractError];
|
||
|
|
||
|
XCTAssertNil(extractError, @"Error returned by extractDataFromFile:error:");
|
||
|
XCTAssertNotNil(data, @"Archive failed to extract large archive");
|
||
|
|
||
|
[extractFileProgress resignCurrent];
|
||
|
[extractFileProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(extractFileProgress.fractionCompleted, 1.00, 0.000001, @"Progress never reported as completed");
|
||
|
|
||
|
NSUInteger expectedProgressUpdates = 78;
|
||
|
NSDictionary<NSNumber *, NSNumber *> *expectedProgresses = @{
|
||
|
@00: @0,
|
||
|
@20: @0.262144,
|
||
|
@35: @0.458752,
|
||
|
@60: @0.786432,
|
||
|
@76: @0.996147,
|
||
|
@77: @1,
|
||
|
};
|
||
|
|
||
|
XCTAssertEqual(self.fractionsCompletedReported.count, expectedProgressUpdates, @"Incorrect number of progress updates");
|
||
|
[expectedProgresses enumerateKeysAndObjectsUsingBlock:
|
||
|
^(NSNumber *key, NSNumber *obj, BOOL *stop) {
|
||
|
float expectedProgress = obj.floatValue;
|
||
|
float actualProgress = self.fractionsCompletedReported[key.intValue].floatValue;
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(actualProgress, expectedProgress, 0.000001f, @"Incorrect progress reported at index %d", key.intValue);
|
||
|
}];
|
||
|
}
|
||
|
|
||
|
- (void)testProgressReporting_ExtractBufferedData {
|
||
|
NSURL *largeArchiveURL = [self largeArchive];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
||
|
NSString *firstFile = [[archive listFilenames:nil] firstObject];
|
||
|
|
||
|
NSProgress *extractFileProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
[extractFileProgress becomeCurrentWithPendingUnitCount:1];
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[extractFileProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:OtherContext];
|
||
|
|
||
|
NSError *extractError = nil;
|
||
|
BOOL success = [archive extractBufferedDataFromFile:firstFile
|
||
|
error:&extractError
|
||
|
action:^(NSData * _Nonnull dataChunk, CGFloat percentDecompressed) {}];
|
||
|
|
||
|
XCTAssertNil(extractError, @"Error returned by extractDataFromFile:error:");
|
||
|
XCTAssertTrue(success, @"Archive failed to extract large archive into buffer");
|
||
|
|
||
|
[extractFileProgress resignCurrent];
|
||
|
[extractFileProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(extractFileProgress.fractionCompleted, 1.00, 0.000001, @"Progress never reported as completed");
|
||
|
|
||
|
NSUInteger expectedProgressUpdates = 78;
|
||
|
NSDictionary<NSNumber *, NSNumber *> *expectedProgresses = @{
|
||
|
@00: @0,
|
||
|
@20: @0.262144,
|
||
|
@35: @0.458752,
|
||
|
@60: @0.786432,
|
||
|
@76: @0.996147,
|
||
|
@77: @1,
|
||
|
};
|
||
|
|
||
|
XCTAssertEqual(self.fractionsCompletedReported.count, expectedProgressUpdates, @"Incorrect number of progress updates");
|
||
|
[expectedProgresses enumerateKeysAndObjectsUsingBlock:
|
||
|
^(NSNumber *key, NSNumber *obj, BOOL *stop) {
|
||
|
float expectedProgress = obj.floatValue;
|
||
|
float actualProgress = self.fractionsCompletedReported[key.intValue].floatValue;
|
||
|
|
||
|
XCTAssertEqualWithAccuracy(actualProgress, expectedProgress, 0.000001f, @"Incorrect progress reported at index %d", key.intValue);
|
||
|
}];
|
||
|
}
|
||
|
|
||
|
- (void)testProgressCancellation_ExtractData {
|
||
|
NSURL *largeArchiveURL = [self largeArchive];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
||
|
NSString *firstFile = [[archive listFilenames:nil] firstObject];
|
||
|
|
||
|
NSProgress *extractFileProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
[extractFileProgress becomeCurrentWithPendingUnitCount:1];
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[extractFileProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:CancelContext];
|
||
|
|
||
|
NSError *extractError = nil;
|
||
|
NSData *data = [archive extractDataFromFile:firstFile error:&extractError];
|
||
|
|
||
|
XCTAssertNotNil(extractError, @"No error returned by cancelled extractDataFromFile:error:");
|
||
|
XCTAssertEqual(extractError.code, UZKErrorCodeUserCancelled, @"Incorrect error code returned from user cancellation");
|
||
|
XCTAssertNil(data, @"extractData didn't return nil when cancelled");
|
||
|
|
||
|
[extractFileProgress resignCurrent];
|
||
|
[extractFileProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
NSUInteger expectedProgressUpdates = 2;
|
||
|
XCTAssertEqual(self.fractionsCompletedReported.count, expectedProgressUpdates, @"Incorrect number of progress updates");
|
||
|
}
|
||
|
|
||
|
- (void)testProgressCancellation_ExtractBufferedData {
|
||
|
NSURL *largeArchiveURL = [self largeArchive];
|
||
|
|
||
|
UZKArchive *archive = [[UZKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
||
|
NSString *firstFile = [[archive listFilenames:nil] firstObject];
|
||
|
|
||
|
NSProgress *extractFileProgress = [NSProgress progressWithTotalUnitCount:1];
|
||
|
[extractFileProgress becomeCurrentWithPendingUnitCount:1];
|
||
|
|
||
|
NSString *observedSelector = NSStringFromSelector(@selector(fractionCompleted));
|
||
|
|
||
|
[extractFileProgress addObserver:self
|
||
|
forKeyPath:observedSelector
|
||
|
options:NSKeyValueObservingOptionInitial
|
||
|
context:CancelContext];
|
||
|
|
||
|
__block NSUInteger blockCallCount = 0;
|
||
|
|
||
|
NSError *extractError = nil;
|
||
|
BOOL success = [archive extractBufferedDataFromFile:firstFile
|
||
|
error:&extractError
|
||
|
action:^(NSData * _Nonnull dataChunk, CGFloat percentDecompressed) {
|
||
|
blockCallCount++;
|
||
|
}];
|
||
|
|
||
|
XCTAssertNotNil(extractError, @"No error returned by cancelled extractDataFromFile:error:");
|
||
|
XCTAssertEqual(extractError.code, UZKErrorCodeUserCancelled, @"Incorrect error code returned from user cancellation");
|
||
|
XCTAssertFalse(success, @"extractBufferedData didn't return false when cancelled");
|
||
|
|
||
|
[extractFileProgress resignCurrent];
|
||
|
[extractFileProgress removeObserver:self forKeyPath:observedSelector];
|
||
|
|
||
|
NSUInteger expectedProgressUpdates = 2;
|
||
|
XCTAssertEqual(self.fractionsCompletedReported.count, expectedProgressUpdates, @"Incorrect number of progress updates");
|
||
|
XCTAssertEqual(blockCallCount, (NSUInteger)1, @"Action block called incorrect number of times after cancellation");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#pragma mark - Private methods
|
||
|
|
||
|
|
||
|
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||
|
ofObject:(id)object
|
||
|
change:(NSDictionary<NSKeyValueChangeKey,id> *)change
|
||
|
context:(void *)context
|
||
|
{
|
||
|
observerCallCount++;
|
||
|
|
||
|
NSProgress *progress;
|
||
|
|
||
|
if ([object isKindOfClass:[NSProgress class]]) {
|
||
|
progress = object;
|
||
|
[self.fractionsCompletedReported addObject:@(progress.fractionCompleted)];
|
||
|
} else {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (context == ExtractFilesContext) {
|
||
|
[self.descriptionsReported addObject:progress.localizedDescription];
|
||
|
[self.additionalDescriptionsReported addObject:progress.localizedAdditionalDescription];
|
||
|
|
||
|
UZKFileInfo *fileInfo = progress.userInfo[UZKProgressInfoKeyFileInfoExtracting];
|
||
|
if (fileInfo) [self.fileInfosReported addObject:fileInfo];
|
||
|
}
|
||
|
|
||
|
if (context == CancelContext && observerCallCount == 2) {
|
||
|
[progress cancel];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@end
|