512 lines
19 KiB
Objective-C
512 lines
19 KiB
Objective-C
//
|
|
// URKArchiveTests.m
|
|
// UnrarKit Tests
|
|
//
|
|
//
|
|
|
|
#import "URKArchiveTestCase.h"
|
|
|
|
|
|
@interface URKArchiveTests : URKArchiveTestCase @end
|
|
|
|
|
|
@implementation URKArchiveTests
|
|
|
|
|
|
|
|
#pragma mark - Test Cases
|
|
|
|
|
|
#pragma mark Archive File
|
|
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testFileURL {
|
|
NSArray *testArchives = @[@"Large",
|
|
@"Test Archive.rar",
|
|
@"Test Archive (Password).rar",
|
|
@"Test Archive (Header Password).rar"];
|
|
|
|
for (NSString *testArchiveName in testArchives) {
|
|
NSLog(@"Testing fileURL of archive %@", testArchiveName);
|
|
NSURL *testArchiveURL = ([testArchiveName isEqualToString:@"Large"]
|
|
? [self largeArchiveURL]
|
|
: self.testFileURLs[testArchiveName]);
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
XCTAssertFalse(archive.ignoreCRCMismatches);
|
|
|
|
NSURL *resolvedURL = archive.fileURL.URLByResolvingSymlinksInPath;
|
|
XCTAssertNotNil(resolvedURL, @"Nil URL returned for valid archive");
|
|
XCTAssertTrue([testArchiveURL isEqual:resolvedURL], @"Resolved URL doesn't match original");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testFilename {
|
|
NSArray *testArchives = @[@"Large",
|
|
@"Test Archive.rar",
|
|
@"Test Archive (Password).rar",
|
|
@"Test Archive (Header Password).rar"];
|
|
|
|
for (NSString *testArchiveName in testArchives) {
|
|
NSLog(@"Testing filename of archive %@", testArchiveName);
|
|
NSURL *testArchiveURL = ([testArchiveName isEqualToString:@"Large"]
|
|
? [self largeArchiveURL]
|
|
: self.testFileURLs[testArchiveName]);
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
XCTAssertFalse(archive.ignoreCRCMismatches);
|
|
|
|
NSString *resolvedFilename = archive.filename;
|
|
XCTAssertNotNil(resolvedFilename, @"Nil filename returned for valid archive");
|
|
|
|
// Testing by suffix, since the original points to /private/var, but the resolved one
|
|
// points straight to /var. They're equivalent, but not character-for-character equal
|
|
XCTAssertTrue([resolvedFilename hasSuffix:testArchiveURL.path],
|
|
@"Resolved filename doesn't match original");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
- (void)testUncompressedSize {
|
|
NSURL *testArchiveURL = self.testFileURLs[@"Test Archive.rar"];
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
NSNumber *size = archive.uncompressedSize;
|
|
|
|
XCTAssertNotNil(size, @"Nil size returned");
|
|
XCTAssertEqual(size.integerValue, 104714, @"Wrong uncompressed size returned");
|
|
}
|
|
|
|
- (void)testUncompressedSize_InvalidArchive {
|
|
NSURL *testArchiveURL = self.testFileURLs[@"Test File A.txt"];
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
NSNumber *size = archive.uncompressedSize;
|
|
|
|
XCTAssertNil(size, @"Uncompressed size of invalid archive should be nil");
|
|
}
|
|
|
|
- (void)testCompressedSize {
|
|
NSURL *testArchiveURL = self.testFileURLs[@"Test Archive.rar"];
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
NSNumber *size = archive.compressedSize;
|
|
|
|
XCTAssertNotNil(size, @"Nil size returned");
|
|
XCTAssertEqual(size.integerValue, 89069, @"Wrong uncompressed size returned");
|
|
}
|
|
|
|
- (void)testCompressedSize_ArchiveMissing {
|
|
NSURL *testArchiveURL = self.testFileURLs[@"Test Archive.rar"];
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
|
|
[[NSFileManager defaultManager] removeItemAtURL:testArchiveURL error:nil];
|
|
|
|
NSNumber *size = archive.compressedSize;
|
|
|
|
XCTAssertNil(size, @"Compressed size of an archive with no path should be nil");
|
|
}
|
|
|
|
|
|
#pragma mark - RAR file Detection
|
|
|
|
#pragma By Path
|
|
|
|
- (void)testPathIsARAR
|
|
{
|
|
NSURL *url = self.testFileURLs[@"Test Archive.rar"];
|
|
NSString *path = url.path;
|
|
BOOL pathIsRAR = [URKArchive pathIsARAR:path];
|
|
XCTAssertTrue(pathIsRAR, @"RAR file is not reported as a RAR");
|
|
}
|
|
|
|
- (void)testPathIsARAR_NotARAR
|
|
{
|
|
NSURL *url = self.testFileURLs[@"Test File B.jpg"];
|
|
NSString *path = url.path;
|
|
BOOL pathIsRAR = [URKArchive pathIsARAR:path];
|
|
XCTAssertFalse(pathIsRAR, @"JPG file is reported as a RAR");
|
|
}
|
|
|
|
- (void)testPathIsARAR_SmallFile
|
|
{
|
|
NSURL *url = [self randomTextFileOfLength:1];
|
|
NSString *path = url.path;
|
|
BOOL pathIsRAR = [URKArchive pathIsARAR:path];
|
|
XCTAssertFalse(pathIsRAR, @"Small non-RAR file is reported as a RAR");
|
|
}
|
|
|
|
- (void)testPathIsARAR_MissingFile
|
|
{
|
|
NSURL *url = [self.testFileURLs[@"Test Archive.rar"] URLByAppendingPathExtension:@"missing"];
|
|
NSString *path = url.path;
|
|
BOOL pathIsRAR = [URKArchive pathIsARAR:path];
|
|
XCTAssertFalse(pathIsRAR, @"Missing file is reported as a RAR");
|
|
}
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testPathIsARAR_FileHandleLeaks
|
|
{
|
|
NSURL *smallFileURL = [self randomTextFileOfLength:1];
|
|
NSURL *jpgURL = self.testFileURLs[@"Test File B.jpg"];
|
|
|
|
NSInteger initialFileCount = [self numberOfOpenFileHandles];
|
|
|
|
for (NSInteger i = 0; i < 10000; i++) {
|
|
BOOL smallFileIsZip = [URKArchive pathIsARAR:smallFileURL.path];
|
|
XCTAssertFalse(smallFileIsZip, @"Small non-RAR file is reported as a RAR");
|
|
|
|
BOOL jpgIsZip = [URKArchive pathIsARAR:jpgURL.path];
|
|
XCTAssertFalse(jpgIsZip, @"JPG file is reported as a RAR");
|
|
|
|
NSURL *zipURL = self.testFileURLs[@"Test Archive.rar"];
|
|
BOOL zipFileIsZip = [URKArchive pathIsARAR:zipURL.path];
|
|
XCTAssertTrue(zipFileIsZip, @"RAR file is not reported as a RAR");
|
|
}
|
|
|
|
NSInteger finalFileCount = [self numberOfOpenFileHandles];
|
|
|
|
XCTAssertEqualWithAccuracy(initialFileCount, finalFileCount, 5, @"File descriptors were left open");
|
|
}
|
|
#endif
|
|
|
|
#pragma By URL
|
|
|
|
- (void)testurlIsARAR
|
|
{
|
|
NSURL *url = self.testFileURLs[@"Test Archive.rar"];
|
|
BOOL urlIsRAR = [URKArchive urlIsARAR:url];
|
|
XCTAssertTrue(urlIsRAR, @"RAR file is not reported as a RAR");
|
|
}
|
|
|
|
- (void)testurlIsARAR_NotARAR
|
|
{
|
|
NSURL *url = self.testFileURLs[@"Test File B.jpg"];
|
|
BOOL urlIsRAR = [URKArchive urlIsARAR:url];
|
|
XCTAssertFalse(urlIsRAR, @"JPG file is reported as a RAR");
|
|
}
|
|
|
|
- (void)testurlIsARAR_SmallFile
|
|
{
|
|
NSURL *url = [self randomTextFileOfLength:1];
|
|
BOOL urlIsRAR = [URKArchive urlIsARAR:url];
|
|
XCTAssertFalse(urlIsRAR, @"Small non-RAR file is reported as a RAR");
|
|
}
|
|
|
|
- (void)testurlIsARAR_MissingFile
|
|
{
|
|
NSURL *url = [self.testFileURLs[@"Test Archive.rar"] URLByAppendingPathExtension:@"missing"];
|
|
BOOL urlIsRAR = [URKArchive urlIsARAR:url];
|
|
XCTAssertFalse(urlIsRAR, @"Missing file is reported as a RAR");
|
|
}
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testurlIsARAR_FileHandleLeaks
|
|
{
|
|
NSURL *smallFileURL = [self randomTextFileOfLength:1];
|
|
NSURL *jpgURL = self.testFileURLs[@"Test File B.jpg"];
|
|
|
|
NSInteger initialFileCount = [self numberOfOpenFileHandles];
|
|
|
|
for (NSInteger i = 0; i < 10000; i++) {
|
|
BOOL smallFileIsZip = [URKArchive urlIsARAR:smallFileURL];
|
|
XCTAssertFalse(smallFileIsZip, @"Small non-RAR file is reported as a RAR");
|
|
|
|
BOOL jpgIsZip = [URKArchive urlIsARAR:jpgURL];
|
|
XCTAssertFalse(jpgIsZip, @"JPG file is reported as a RAR");
|
|
|
|
NSURL *zipURL = self.testFileURLs[@"Test Archive.rar"];
|
|
BOOL zipFileIsZip = [URKArchive urlIsARAR:zipURL];
|
|
XCTAssertTrue(zipFileIsZip, @"RAR file is not reported as a RAR");
|
|
}
|
|
|
|
NSInteger finalFileCount = [self numberOfOpenFileHandles];
|
|
|
|
XCTAssertEqualWithAccuracy(initialFileCount, finalFileCount, 5, @"File descriptors were left open");
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
#pragma mark Various
|
|
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testFileDescriptorUsage
|
|
{
|
|
NSInteger initialFileCount = [self numberOfOpenFileHandles];
|
|
|
|
NSString *testArchiveName = @"Test Archive.rar";
|
|
NSURL *testArchiveOriginalURL = self.testFileURLs[testArchiveName];
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
|
|
for (NSInteger i = 0; i < 1000; i++) {
|
|
NSString *tempDir = [self randomDirectoryName];
|
|
NSURL *tempDirURL = [self.tempDirectory URLByAppendingPathComponent:tempDir];
|
|
NSURL *testArchiveCopyURL = [tempDirURL URLByAppendingPathComponent:testArchiveName];
|
|
|
|
NSError *error = nil;
|
|
[fm createDirectoryAtURL:tempDirURL
|
|
withIntermediateDirectories:YES
|
|
attributes:nil
|
|
error:&error];
|
|
|
|
XCTAssertNil(error, @"Error creating temp directory: %@", tempDirURL);
|
|
|
|
[fm copyItemAtURL:testArchiveOriginalURL toURL:testArchiveCopyURL error:&error];
|
|
XCTAssertNil(error, @"Error copying test archive \n from: %@ \n\n to: %@", testArchiveOriginalURL, testArchiveCopyURL);
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveCopyURL error:nil];
|
|
|
|
NSArray *fileList = [archive listFilenames:&error];
|
|
XCTAssertNotNil(fileList);
|
|
|
|
for (NSString *fileName in fileList) {
|
|
NSData *fileData = [archive extractDataFromFile:fileName error:&error];
|
|
XCTAssertNotNil(fileData);
|
|
XCTAssertNil(error);
|
|
}
|
|
}
|
|
|
|
NSInteger finalFileCount = [self numberOfOpenFileHandles];
|
|
|
|
XCTAssertEqualWithAccuracy(initialFileCount, finalFileCount, 5, @"File descriptors were left open");
|
|
}
|
|
#endif
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testMultiThreading {
|
|
NSURL *largeArchiveURL_A = [self largeArchiveURL];
|
|
NSURL *largeArchiveURL_B = [largeArchiveURL_A.URLByDeletingLastPathComponent URLByAppendingPathComponent:@"Large Archive 2.rar"];
|
|
NSURL *largeArchiveURL_C = [largeArchiveURL_A.URLByDeletingLastPathComponent URLByAppendingPathComponent:@"Large Archive 3.rar"];
|
|
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
|
|
NSError *archiveBCopyError = nil;
|
|
XCTAssertTrue([fm copyItemAtURL:largeArchiveURL_A toURL:largeArchiveURL_B error:&archiveBCopyError], @"Failed to copy archive B");
|
|
XCTAssertNil(archiveBCopyError, @"Error copying archive B");
|
|
|
|
NSError *archiveCCopyError = nil;
|
|
XCTAssertTrue([fm copyItemAtURL:largeArchiveURL_A toURL:largeArchiveURL_C error:&archiveCCopyError], @"Failed to copy archive C");
|
|
XCTAssertNil(archiveCCopyError, @"Error copying archive C");
|
|
|
|
URKArchive *largeArchiveA = [[URKArchive alloc] initWithURL:largeArchiveURL_A error:nil];
|
|
URKArchive *largeArchiveB = [[URKArchive alloc] initWithURL:largeArchiveURL_B error:nil];
|
|
URKArchive *largeArchiveC = [[URKArchive alloc] initWithURL:largeArchiveURL_C error:nil];
|
|
|
|
XCTestExpectation *expectationA = [self expectationWithDescription:@"A finished"];
|
|
XCTestExpectation *expectationB = [self expectationWithDescription:@"B finished"];
|
|
XCTestExpectation *expectationC = [self expectationWithDescription:@"C finished"];
|
|
|
|
NSBlockOperation *enumerateA = [NSBlockOperation blockOperationWithBlock:^{
|
|
NSError *error = nil;
|
|
[largeArchiveA performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSLog(@"File name: %@", fileInfo.filename);
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error);
|
|
[expectationA fulfill];
|
|
}];
|
|
|
|
NSBlockOperation *enumerateB = [NSBlockOperation blockOperationWithBlock:^{
|
|
NSError *error = nil;
|
|
[largeArchiveB performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSLog(@"File name: %@", fileInfo.filename);
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error);
|
|
[expectationB fulfill];
|
|
}];
|
|
|
|
NSBlockOperation *enumerateC = [NSBlockOperation blockOperationWithBlock:^{
|
|
NSError *error = nil;
|
|
[largeArchiveC performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSLog(@"File name: %@", fileInfo.filename);
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error);
|
|
[expectationC fulfill];
|
|
}];
|
|
|
|
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
|
|
queue.maxConcurrentOperationCount = 3;
|
|
queue.suspended = YES;
|
|
|
|
[queue addOperation:enumerateA];
|
|
[queue addOperation:enumerateB];
|
|
[queue addOperation:enumerateC];
|
|
|
|
queue.suspended = NO;
|
|
|
|
[self waitForExpectationsWithTimeout:30 handler:^(NSError *error) {
|
|
if (error) {
|
|
NSLog(@"Error while waiting for expectations: %@", error);
|
|
}
|
|
}];
|
|
}
|
|
#endif
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testMultiThreading_SingleFile {
|
|
NSURL *largeArchiveURL = [self largeArchiveURL];
|
|
|
|
URKArchive *largeArchiveA = [[URKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
|
URKArchive *largeArchiveB = [[URKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
|
URKArchive *largeArchiveC = [[URKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
|
|
|
XCTestExpectation *expectationA = [self expectationWithDescription:@"A finished"];
|
|
XCTestExpectation *expectationB = [self expectationWithDescription:@"B finished"];
|
|
XCTestExpectation *expectationC = [self expectationWithDescription:@"C finished"];
|
|
|
|
NSBlockOperation *enumerateA = [NSBlockOperation blockOperationWithBlock:^{
|
|
NSError *error = nil;
|
|
[largeArchiveA performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSLog(@"File name: %@", fileInfo.filename);
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error);
|
|
[expectationA fulfill];
|
|
}];
|
|
|
|
NSBlockOperation *enumerateB = [NSBlockOperation blockOperationWithBlock:^{
|
|
NSError *error = nil;
|
|
[largeArchiveB performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSLog(@"File name: %@", fileInfo.filename);
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error);
|
|
[expectationB fulfill];
|
|
}];
|
|
|
|
NSBlockOperation *enumerateC = [NSBlockOperation blockOperationWithBlock:^{
|
|
NSError *error = nil;
|
|
[largeArchiveC performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSLog(@"File name: %@", fileInfo.filename);
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error);
|
|
[expectationC fulfill];
|
|
}];
|
|
|
|
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
|
|
queue.maxConcurrentOperationCount = 3;
|
|
queue.suspended = YES;
|
|
|
|
[queue addOperation:enumerateA];
|
|
[queue addOperation:enumerateB];
|
|
[queue addOperation:enumerateC];
|
|
|
|
queue.suspended = NO;
|
|
|
|
[self waitForExpectationsWithTimeout:30 handler:^(NSError *error) {
|
|
if (error) {
|
|
NSLog(@"Error while waiting for expectations: %@", error);
|
|
}
|
|
}];
|
|
}
|
|
#endif
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testMultiThreading_SingleArchiveObject {
|
|
NSURL *largeArchiveURL = [self largeArchiveURL];
|
|
|
|
URKArchive *largeArchive = [[URKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
|
|
|
XCTestExpectation *expectationA = [self expectationWithDescription:@"A finished"];
|
|
XCTestExpectation *expectationB = [self expectationWithDescription:@"B finished"];
|
|
XCTestExpectation *expectationC = [self expectationWithDescription:@"C finished"];
|
|
|
|
NSBlockOperation *enumerateA = [NSBlockOperation blockOperationWithBlock:^{
|
|
NSError *error = nil;
|
|
[largeArchive performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSLog(@"File name: %@", fileInfo.filename);
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error);
|
|
[expectationA fulfill];
|
|
}];
|
|
|
|
NSBlockOperation *enumerateB = [NSBlockOperation blockOperationWithBlock:^{
|
|
NSError *error = nil;
|
|
[largeArchive performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSLog(@"File name: %@", fileInfo.filename);
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error);
|
|
[expectationB fulfill];
|
|
}];
|
|
|
|
NSBlockOperation *enumerateC = [NSBlockOperation blockOperationWithBlock:^{
|
|
NSError *error = nil;
|
|
[largeArchive performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSLog(@"File name: %@", fileInfo.filename);
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error);
|
|
[expectationC fulfill];
|
|
}];
|
|
|
|
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
|
|
queue.maxConcurrentOperationCount = 3;
|
|
queue.suspended = YES;
|
|
|
|
[queue addOperation:enumerateA];
|
|
[queue addOperation:enumerateB];
|
|
[queue addOperation:enumerateC];
|
|
|
|
queue.suspended = NO;
|
|
|
|
[self waitForExpectationsWithTimeout:30 handler:^(NSError *error) {
|
|
if (error) {
|
|
NSLog(@"Error while waiting for expectations: %@", error);
|
|
}
|
|
}];
|
|
}
|
|
#endif
|
|
|
|
- (void)testErrorIsCorrect
|
|
{
|
|
NSError *error = nil;
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:self.corruptArchive error:nil];
|
|
XCTAssertNil([archive listFilenames:&error], "Listing filenames in corrupt archive should return nil");
|
|
XCTAssertNotNil(error, @"An error should be returned when listing filenames in a corrupt archive");
|
|
XCTAssertNotNil(error.description, @"Error's description is nil");
|
|
}
|
|
|
|
- (void)testUnicodeArchiveName
|
|
{
|
|
NSURL *originalArchiveURL = self.testFileURLs[@"Test Archive.rar"];
|
|
|
|
NSString *newArchiveName = @" ♔ ♕ ♖ ♗ ♘ ♙ ♚ ♛ ♜ ♝ ♞ ♟.rar";
|
|
|
|
NSURL *newArchiveURL = [[originalArchiveURL URLByDeletingLastPathComponent]
|
|
URLByAppendingPathComponent:newArchiveName];
|
|
|
|
NSError *error = nil;
|
|
BOOL moveSuccess = [[NSFileManager defaultManager] moveItemAtURL:originalArchiveURL
|
|
toURL:newArchiveURL
|
|
error:&error];
|
|
XCTAssertTrue(moveSuccess, @"Failed to rename Test Archive to unicode name");
|
|
XCTAssertNil(error, @"Error renaming Test Archive to unicode name: %@", error);
|
|
|
|
NSString *extractDirectory = [self randomDirectoryWithPrefix:
|
|
[@"Unicode contents" stringByDeletingPathExtension]];
|
|
NSURL *extractURL = [self.tempDirectory URLByAppendingPathComponent:extractDirectory];
|
|
|
|
NSError *extractFilesError = nil;
|
|
URKArchive *unicodeNamedArchive = [[URKArchive alloc] initWithURL:newArchiveURL error:nil];
|
|
BOOL extractSuccess = [unicodeNamedArchive extractFilesTo:extractURL.path
|
|
overwrite:NO
|
|
error:&error];
|
|
|
|
XCTAssertTrue(extractSuccess, @"Failed to extract archive");
|
|
XCTAssertNil(extractFilesError, @"Error extracting archive: %@", extractFilesError);
|
|
}
|
|
|
|
|
|
|
|
@end
|