1202 lines
48 KiB
Objective-C
1202 lines
48 KiB
Objective-C
//
|
|
// URKArchiveTests.m
|
|
// UnrarKit Tests
|
|
//
|
|
//
|
|
|
|
#import "URKArchiveTestCase.h"
|
|
|
|
|
|
#import <sys/kdebug_signpost.h>
|
|
enum SignPostCode: uint { // Use to reference in Instruments (http://stackoverflow.com/a/39416673/105717)
|
|
SignPostCodeCreateTextFile = 0,
|
|
SignPostCodeArchiveData = 1,
|
|
SignPostCodeExtractData = 2,
|
|
};
|
|
|
|
enum SignPostColor: uint { // standard color scheme for signposts in Instruments
|
|
SignPostColorBlue = 0,
|
|
SignPostColorGreen = 1,
|
|
SignPostColorPurple = 2,
|
|
SignPostColorOrange = 3,
|
|
SignPostColorRed = 4,
|
|
};
|
|
|
|
|
|
|
|
@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];
|
|
|
|
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];
|
|
|
|
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 List File Info
|
|
|
|
|
|
- (void)testListFileInfo {
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[@"Test Archive.rar"] error:nil];
|
|
|
|
NSSet *expectedFileSet = [self.testFileURLs keysOfEntriesPassingTest:^BOOL(NSString *key, id obj, BOOL *stop) {
|
|
return ![key hasSuffix:@"rar"];
|
|
}];
|
|
|
|
NSArray *expectedFiles = [[expectedFileSet allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
static NSDateFormatter *testFileInfoDateFormatter;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
testFileInfoDateFormatter = [[NSDateFormatter alloc] init];
|
|
testFileInfoDateFormatter.dateFormat = @"M/dd/yyyy h:mm a";
|
|
testFileInfoDateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];
|
|
});
|
|
|
|
NSDictionary *expectedTimestamps = @{@"Test File A.txt": [testFileInfoDateFormatter dateFromString:@"3/13/2014 8:02 PM"],
|
|
@"Test File B.jpg": [testFileInfoDateFormatter dateFromString:@"3/13/2014 8:04 PM"],
|
|
@"Test File C.m4a": [testFileInfoDateFormatter dateFromString:@"3/13/2014 8:05 PM"],};
|
|
|
|
NSError *error = nil;
|
|
NSArray *filesInArchive = [archive listFileInfo:&error];
|
|
|
|
XCTAssertNil(error, @"Error returned by listFileInfo");
|
|
XCTAssertNotNil(filesInArchive, @"No list of files returned");
|
|
XCTAssertEqual(filesInArchive.count, expectedFileSet.count, @"Incorrect number of files listed in archive");
|
|
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
|
|
for (NSInteger i = 0; i < filesInArchive.count; i++) {
|
|
URKFileInfo *fileInfo = filesInArchive[i];
|
|
|
|
// Test Archive Name
|
|
NSString *expectedArchiveName = archive.filename;
|
|
XCTAssertEqualObjects(fileInfo.archiveName, expectedArchiveName, @"Incorrect archive name");
|
|
|
|
// Test Filename
|
|
NSString *expectedFilename = expectedFiles[i];
|
|
XCTAssertEqualObjects(fileInfo.filename, expectedFilename, @"Incorrect filename");
|
|
|
|
// Test CRC
|
|
NSUInteger expectedFileCRC = [self crcOfTestFile:expectedFilename];
|
|
XCTAssertEqual(fileInfo.CRC, expectedFileCRC, @"Incorrect CRC checksum");
|
|
|
|
// Test Last Modify Date
|
|
NSTimeInterval archiveFileTimeInterval = [fileInfo.timestamp timeIntervalSinceReferenceDate];
|
|
NSTimeInterval expectedFileTimeInterval = [expectedTimestamps[fileInfo.filename] timeIntervalSinceReferenceDate];
|
|
XCTAssertEqualWithAccuracy(archiveFileTimeInterval, expectedFileTimeInterval, 60, @"Incorrect file timestamp (more than 60 seconds off)");
|
|
|
|
// Test Uncompressed Size
|
|
NSError *attributesError = nil;
|
|
NSString *expectedFilePath = [[self urlOfTestFile:expectedFilename] path];
|
|
NSDictionary *expectedFileAttributes = [fm attributesOfItemAtPath:expectedFilePath
|
|
error:&attributesError];
|
|
XCTAssertNil(attributesError, @"Error getting file attributes of %@", expectedFilename);
|
|
|
|
long long expectedFileSize = expectedFileAttributes.fileSize;
|
|
XCTAssertEqual(fileInfo.uncompressedSize, expectedFileSize, @"Incorrect uncompressed file size");
|
|
|
|
// Test Compression method
|
|
XCTAssertEqual(fileInfo.compressionMethod, URKCompressionMethodNormal, @"Incorrect compression method");
|
|
|
|
// Test Host OS
|
|
XCTAssertEqual(fileInfo.hostOS, URKHostOSUnix, @"Incorrect host OS");
|
|
}
|
|
}
|
|
|
|
- (void)testListFileInfo_Unicode
|
|
{
|
|
NSSet *expectedFileSet = [self.unicodeFileURLs keysOfEntriesPassingTest:^BOOL(NSString *key, id obj, BOOL *stop) {
|
|
return ![key hasSuffix:@"rar"];
|
|
}];
|
|
|
|
NSArray *expectedFiles = [[expectedFileSet allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
NSURL *testArchiveURL = self.unicodeFileURLs[@"Ⓣest Ⓐrchive.rar"];
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *filesInArchive = [archive listFileInfo:&error];
|
|
|
|
XCTAssertNil(error, @"Error returned by listFileInfo");
|
|
XCTAssertNotNil(filesInArchive, @"No list of files returned");
|
|
XCTAssertEqual(filesInArchive.count, expectedFileSet.count,
|
|
@"Incorrect number of files listed in archive");
|
|
|
|
for (NSInteger i = 0; i < filesInArchive.count; i++) {
|
|
URKFileInfo *fileInfo = (URKFileInfo *)filesInArchive[i];
|
|
|
|
XCTAssertEqualObjects(fileInfo.filename, expectedFiles[i], @"Incorrect filename listed");
|
|
XCTAssertEqualObjects(fileInfo.archiveName, archive.filename, @"Incorrect archiveName listed");
|
|
}
|
|
}
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testListFileInfo_MultivolumeArchive {
|
|
NSArray<NSURL*> *generatedVolumeURLs = [self multiPartArchiveWithName:@"ListFileInfoTests_MultivolumeArchive.rar"];
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:generatedVolumeURLs.firstObject error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *files = [archive listFileInfo:&error];
|
|
|
|
XCTAssertNil(error, @"Error returned when listing file info for multivolume archive");
|
|
XCTAssertEqual(files.count, 1, @"Incorrect number of file info items returned for multivolume archive");
|
|
}
|
|
#endif
|
|
|
|
- (void)testListFileInfo_HeaderPassword
|
|
{
|
|
NSArray *testArchives = @[@"Test Archive (Header Password).rar"];
|
|
|
|
NSSet *expectedFileSet = [self.testFileURLs keysOfEntriesPassingTest:^BOOL(NSString *key, id obj, BOOL *stop) {
|
|
return ![key hasSuffix:@"rar"];
|
|
}];
|
|
|
|
NSArray *expectedFiles = [[expectedFileSet allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
for (NSString *testArchiveName in testArchives) {
|
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
|
|
|
URKArchive *archiveNoPassword = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *filesInArchive = [archiveNoPassword listFileInfo:&error];
|
|
|
|
XCTAssertNotNil(error, @"No error returned by listFileInfo (no password given)");
|
|
XCTAssertNil(filesInArchive, @"List of files returned (no password given)");
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL password:@"password" error:nil];
|
|
|
|
filesInArchive = nil;
|
|
error = nil;
|
|
filesInArchive = [archive listFileInfo:&error];
|
|
|
|
XCTAssertNil(error, @"Error returned by listFileInfo");
|
|
XCTAssertEqual(filesInArchive.count, expectedFileSet.count,
|
|
@"Incorrect number of files listed in archive");
|
|
|
|
for (NSInteger i = 0; i < filesInArchive.count; i++) {
|
|
URKFileInfo *archiveFileInfo = filesInArchive[i];
|
|
NSString *archiveFilename = archiveFileInfo.filename;
|
|
NSString *expectedFilename = expectedFiles[i];
|
|
|
|
XCTAssertEqualObjects(archiveFilename, expectedFilename, @"Incorrect filename listed");
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)testListFileInfo_NoHeaderPasswordGiven {
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[@"Test Archive (Header Password).rar"] error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *files = [archive listFileInfo:&error];
|
|
|
|
XCTAssertNotNil(error, @"List without password succeeded");
|
|
XCTAssertNil(files, @"List returned without password");
|
|
XCTAssertEqual(error.code, URKErrorCodeMissingPassword, @"Unexpected error code returned");
|
|
}
|
|
|
|
- (void)testListFileInfo_InvalidArchive
|
|
{
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[@"Test File A.txt"] error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *files = [archive listFileInfo:&error];
|
|
|
|
XCTAssertNotNil(error, @"List files of invalid archive succeeded");
|
|
XCTAssertNil(files, @"List returned for invalid archive");
|
|
XCTAssertEqual(error.code, URKErrorCodeBadArchive, @"Unexpected error code returned");
|
|
}
|
|
|
|
|
|
#pragma mark Extract Data
|
|
|
|
|
|
- (void)testExtractData
|
|
{
|
|
NSArray *testArchives = @[@"Test Archive.rar",
|
|
@"Test Archive (Password).rar",
|
|
@"Test Archive (Header Password).rar"];
|
|
|
|
NSSet *expectedFileSet = [self.testFileURLs keysOfEntriesPassingTest:^BOOL(NSString *key, id obj, BOOL *stop) {
|
|
return ![key hasSuffix:@"rar"];
|
|
}];
|
|
|
|
NSArray *expectedFiles = [[expectedFileSet allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
for (NSString *testArchiveName in testArchives) {
|
|
|
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
|
NSString *password = ([testArchiveName rangeOfString:@"Password"].location != NSNotFound
|
|
? @"password"
|
|
: nil);
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL password:password error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *fileInfos = [archive listFileInfo:&error];
|
|
XCTAssertNil(error, @"Error reading file info");
|
|
|
|
for (NSInteger i = 0; i < expectedFiles.count; i++) {
|
|
NSString *expectedFilename = expectedFiles[i];
|
|
|
|
NSError *error = nil;
|
|
NSData *extractedData = [archive extractDataFromFile:expectedFilename error:&error];
|
|
|
|
XCTAssertNil(error, @"Error in extractData:error:");
|
|
|
|
NSData *expectedFileData = [NSData dataWithContentsOfURL:self.testFileURLs[expectedFilename]];
|
|
|
|
XCTAssertNotNil(extractedData, @"No data extracted");
|
|
XCTAssertTrue([expectedFileData isEqualToData:extractedData], @"Extracted data doesn't match original file");
|
|
|
|
error = nil;
|
|
NSData *dataFromFileInfo = [archive extractData:fileInfos[i] error:&error];
|
|
XCTAssertNil(error, @"Error extracting data by file info");
|
|
XCTAssertTrue([expectedFileData isEqualToData:dataFromFileInfo], @"Extracted data from file info doesn't match original file");
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)testExtractData_Unicode
|
|
{
|
|
NSSet *expectedFileSet = [self.unicodeFileURLs keysOfEntriesPassingTest:^BOOL(NSString *key, id obj, BOOL *stop) {
|
|
return ![key hasSuffix:@"rar"];
|
|
}];
|
|
|
|
NSArray *expectedFiles = [[expectedFileSet allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
NSURL *testArchiveURL = self.unicodeFileURLs[@"Ⓣest Ⓐrchive.rar"];
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *fileInfos = [archive listFileInfo:&error];
|
|
XCTAssertNil(error, @"Error reading file info");
|
|
|
|
for (NSInteger i = 0; i < expectedFiles.count; i++) {
|
|
NSString *expectedFilename = expectedFiles[i];
|
|
|
|
NSError *error = nil;
|
|
NSData *extractedData = [archive extractDataFromFile:expectedFilename error:&error];
|
|
|
|
XCTAssertNil(error, @"Error in extractData:error:");
|
|
|
|
NSData *expectedFileData = [NSData dataWithContentsOfURL:self.unicodeFileURLs[expectedFilename]];
|
|
|
|
XCTAssertNotNil(extractedData, @"No data extracted");
|
|
XCTAssertTrue([expectedFileData isEqualToData:extractedData], @"Extracted data doesn't match original file");
|
|
|
|
error = nil;
|
|
NSData *dataFromFileInfo = [archive extractData:fileInfos[i] error:&error];
|
|
XCTAssertNil(error, @"Error extracting data by file info");
|
|
XCTAssertTrue([expectedFileData isEqualToData:dataFromFileInfo], @"Extracted data from file info doesn't match original file");
|
|
}
|
|
}
|
|
|
|
- (void)testExtractData_NoPassword
|
|
{
|
|
NSArray *testArchives = @[@"Test Archive (Password).rar",
|
|
@"Test Archive (Header Password).rar"];
|
|
|
|
for (NSString *testArchiveName in testArchives) {
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[testArchiveName] error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSData *data = [archive extractDataFromFile:@"Test File A.txt" error:&error];
|
|
|
|
XCTAssertNotNil(error, @"Extract data without password succeeded");
|
|
XCTAssertNil(data, @"Data returned without password");
|
|
XCTAssertEqual(error.code, URKErrorCodeMissingPassword, @"Unexpected error code returned");
|
|
}
|
|
}
|
|
|
|
- (void)testExtractData_InvalidArchive
|
|
{
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[@"Test File A.txt"] error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSData *data = [archive extractDataFromFile:@"Any file.txt" error:&error];
|
|
|
|
XCTAssertNotNil(error, @"Extract data for invalid archive succeeded");
|
|
XCTAssertNil(data, @"Data returned for invalid archive");
|
|
XCTAssertEqual(error.code, URKErrorCodeBadArchive, @"Unexpected error code returned");
|
|
}
|
|
|
|
|
|
#pragma mark Perform on Files
|
|
|
|
|
|
- (void)testPerformOnFiles
|
|
{
|
|
NSArray *testArchives = @[@"Test Archive.rar",
|
|
@"Test Archive (Password).rar",
|
|
@"Test Archive (Header Password).rar"];
|
|
|
|
NSSet *expectedFileSet = [self.testFileURLs keysOfEntriesPassingTest:^BOOL(NSString *key, id obj, BOOL *stop) {
|
|
return ![key hasSuffix:@"rar"];
|
|
}];
|
|
|
|
NSArray *expectedFiles = [[expectedFileSet allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
for (NSString *testArchiveName in testArchives) {
|
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
|
NSString *password = ([testArchiveName rangeOfString:@"Password"].location != NSNotFound
|
|
? @"password"
|
|
: nil);
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL password:password error:nil];
|
|
|
|
__block NSUInteger fileIndex = 0;
|
|
NSError *error = nil;
|
|
|
|
[archive performOnFilesInArchive:
|
|
^(URKFileInfo *fileInfo, BOOL *stop) {
|
|
NSString *expectedFilename = expectedFiles[fileIndex++];
|
|
XCTAssertEqualObjects(fileInfo.filename, expectedFilename, @"Unexpected filename encountered");
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error, @"Error iterating through files");
|
|
XCTAssertEqual(fileIndex, expectedFiles.count, @"Incorrect number of files encountered");
|
|
}
|
|
}
|
|
|
|
- (void)testPerformOnFiles_Unicode
|
|
{
|
|
NSSet *expectedFileSet = [self.unicodeFileURLs keysOfEntriesPassingTest:^BOOL(NSString *key, id obj, BOOL *stop) {
|
|
return ![key hasSuffix:@"rar"];
|
|
}];
|
|
|
|
NSArray *expectedFiles = [[expectedFileSet allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
NSURL *testArchiveURL = self.unicodeFileURLs[@"Ⓣest Ⓐrchive.rar"];
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
|
|
__block NSUInteger fileIndex = 0;
|
|
NSError *error = nil;
|
|
|
|
[archive performOnFilesInArchive:
|
|
^(URKFileInfo *fileInfo, BOOL *stop) {
|
|
NSString *expectedFilename = expectedFiles[fileIndex++];
|
|
XCTAssertEqualObjects(fileInfo.filename, expectedFilename, @"Unexpected filename encountered");
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error, @"Error iterating through files");
|
|
XCTAssertEqual(fileIndex, expectedFiles.count, @"Incorrect number of files encountered");
|
|
}
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testPerformOnFiles_Ordering
|
|
{
|
|
NSArray *testFilenames = @[@"AAA.txt",
|
|
@"BBB.txt",
|
|
@"CCC.txt"];
|
|
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
|
|
NSMutableArray *testFileURLs = [NSMutableArray array];
|
|
|
|
// Touch test files
|
|
[testFilenames enumerateObjectsUsingBlock:^(NSString *filename, NSUInteger idx, BOOL *stop) {
|
|
NSURL *outputURL = [self.tempDirectory URLByAppendingPathComponent:filename];
|
|
XCTAssertTrue([fm createFileAtPath:outputURL.path contents:nil attributes:nil], @"Failed to create test file: %@", filename);
|
|
[testFileURLs addObject:outputURL];
|
|
}];
|
|
|
|
// Create RAR archive with test files, reversed
|
|
NSURL *reversedArchiveURL = [self archiveWithFiles:testFileURLs.reverseObjectEnumerator.allObjects];
|
|
|
|
NSError *error = nil;
|
|
__block NSUInteger index = 0;
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:reversedArchiveURL error:nil];
|
|
[archive performOnFilesInArchive:^(URKFileInfo *fileInfo, BOOL *stop) {
|
|
NSString *expectedFilename = testFilenames[index++];
|
|
XCTAssertEqualObjects(fileInfo.filename, expectedFilename, @"Archive files not iterated through in correct order");
|
|
} error:&error];
|
|
}
|
|
#endif
|
|
|
|
|
|
#pragma mark Perform on Data
|
|
|
|
|
|
- (void)testPerformOnData
|
|
{
|
|
NSArray *testArchives = @[@"Test Archive.rar",
|
|
@"Test Archive (Password).rar",
|
|
@"Test Archive (Header Password).rar"];
|
|
|
|
NSSet *expectedFileSet = [self.testFileURLs keysOfEntriesPassingTest:^BOOL(NSString *key, id obj, BOOL *stop) {
|
|
return ![key hasSuffix:@"rar"];
|
|
}];
|
|
|
|
NSArray *expectedFiles = [[expectedFileSet allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
for (NSString *testArchiveName in testArchives) {
|
|
NSURL *testArchiveURL = self.testFileURLs[testArchiveName];
|
|
NSString *password = ([testArchiveName rangeOfString:@"Password"].location != NSNotFound
|
|
? @"password"
|
|
: nil);
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL password:password error:nil];
|
|
|
|
__block NSUInteger fileIndex = 0;
|
|
NSError *error = nil;
|
|
|
|
[archive performOnDataInArchive:
|
|
^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSString *expectedFilename = expectedFiles[fileIndex++];
|
|
XCTAssertEqualObjects(fileInfo.filename, expectedFilename, @"Unexpected filename encountered");
|
|
|
|
NSData *expectedFileData = [NSData dataWithContentsOfURL:self.testFileURLs[expectedFilename]];
|
|
|
|
XCTAssertNotNil(fileData, @"No data extracted");
|
|
XCTAssertTrue([expectedFileData isEqualToData:fileData], @"File data doesn't match original file");
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error, @"Error iterating through files");
|
|
XCTAssertEqual(fileIndex, expectedFiles.count, @"Incorrect number of files encountered");
|
|
}
|
|
}
|
|
|
|
- (void)testPerformOnData_Unicode
|
|
{
|
|
NSSet *expectedFileSet = [self.unicodeFileURLs keysOfEntriesPassingTest:^BOOL(NSString *key, id obj, BOOL *stop) {
|
|
return ![key hasSuffix:@"rar"];
|
|
}];
|
|
|
|
NSArray *expectedFiles = [[expectedFileSet allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
NSURL *testArchiveURL = self.unicodeFileURLs[@"Ⓣest Ⓐrchive.rar"];
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
|
|
__block NSUInteger fileIndex = 0;
|
|
NSError *error = nil;
|
|
|
|
[archive performOnDataInArchive:
|
|
^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSString *expectedFilename = expectedFiles[fileIndex++];
|
|
XCTAssertEqualObjects(fileInfo.filename, expectedFilename, @"Unexpected filename encountered");
|
|
|
|
NSData *expectedFileData = [NSData dataWithContentsOfURL:self.unicodeFileURLs[expectedFilename]];
|
|
|
|
XCTAssertNotNil(fileData, @"No data extracted");
|
|
XCTAssertTrue([expectedFileData isEqualToData:fileData], @"File data doesn't match original file");
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error, @"Error iterating through files");
|
|
XCTAssertEqual(fileIndex, expectedFiles.count, @"Incorrect number of files encountered");
|
|
}
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testPerformOnData_FileMoved
|
|
{
|
|
NSURL *largeArchiveURL = [self largeArchiveURL];
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *archiveFiles = [archive listFilenames:&error];
|
|
|
|
XCTAssertNotNil(archiveFiles, @"No filenames listed from test archive");
|
|
XCTAssertNil(error, @"Error listing files in test archive: %@", error);
|
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
[NSThread sleepForTimeInterval:1];
|
|
|
|
NSURL *movedURL = [largeArchiveURL URLByAppendingPathExtension:@"FileMoved"];
|
|
|
|
NSError *renameError = nil;
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
[fm moveItemAtURL:largeArchiveURL toURL:movedURL error:&renameError];
|
|
XCTAssertNil(renameError, @"Error renaming file: %@", renameError);
|
|
});
|
|
|
|
__block NSUInteger fileCount = 0;
|
|
|
|
error = nil;
|
|
BOOL success = [archive performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
XCTAssertNotNil(fileData, @"Extracted file is nil: %@", fileInfo.filename);
|
|
|
|
if (!fileInfo.isDirectory) {
|
|
fileCount++;
|
|
XCTAssertGreaterThan(fileData.length, 0, @"Extracted file is empty: %@", fileInfo.filename);
|
|
}
|
|
} error:&error];
|
|
|
|
XCTAssertEqual(fileCount, 20, @"Not all files read");
|
|
XCTAssertTrue(success, @"Failed to read files");
|
|
XCTAssertNil(error, @"Error reading files: %@", error);
|
|
}
|
|
#endif
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testPerformOnData_FileDeleted
|
|
{
|
|
NSURL *largeArchiveURL = [self largeArchiveURL];
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *archiveFiles = [archive listFilenames:&error];
|
|
|
|
XCTAssertNotNil(archiveFiles, @"No filenames listed from test archive");
|
|
XCTAssertNil(error, @"Error listing files in test archive: %@", error);
|
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
[NSThread sleepForTimeInterval:1];
|
|
|
|
NSError *removeError = nil;
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
[fm removeItemAtURL:largeArchiveURL error:&removeError];
|
|
XCTAssertNil(removeError, @"Error removing file: %@", removeError);
|
|
});
|
|
|
|
__block NSUInteger fileCount = 0;
|
|
|
|
error = nil;
|
|
BOOL success = [archive performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
XCTAssertNotNil(fileData, @"Extracted file is nil: %@", fileInfo.filename);
|
|
|
|
if (!fileInfo.isDirectory) {
|
|
fileCount++;
|
|
XCTAssertGreaterThan(fileData.length, 0, @"Extracted file is empty: %@", fileInfo.filename);
|
|
}
|
|
} error:&error];
|
|
|
|
XCTAssertEqual(fileCount, 20, @"Not all files read");
|
|
XCTAssertTrue(success, @"Failed to read files");
|
|
XCTAssertNil(error, @"Error reading files: %@", error);
|
|
}
|
|
#endif
|
|
|
|
#if !TARGET_OS_IPHONE
|
|
- (void)testPerformOnData_FileMovedBeforeBegin
|
|
{
|
|
NSURL *largeArchiveURL = [self largeArchiveURL];
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:largeArchiveURL error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSArray *archiveFiles = [archive listFilenames:&error];
|
|
|
|
XCTAssertNotNil(archiveFiles, @"No filenames listed from test archive");
|
|
XCTAssertNil(error, @"Error listing files in test archive: %@", error);
|
|
|
|
NSURL *movedURL = [largeArchiveURL URLByAppendingPathExtension:@"FileMovedBeforeBegin"];
|
|
|
|
NSError *renameError = nil;
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
[fm moveItemAtURL:largeArchiveURL toURL:movedURL error:&renameError];
|
|
XCTAssertNil(renameError, @"Error renaming file: %@", renameError);
|
|
|
|
__block NSUInteger fileCount = 0;
|
|
|
|
error = nil;
|
|
BOOL success = [archive performOnDataInArchive:^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
XCTAssertNotNil(fileData, @"Extracted file is nil: %@", fileInfo.filename);
|
|
|
|
if (!fileInfo.isDirectory) {
|
|
fileCount++;
|
|
XCTAssertGreaterThan(fileData.length, 0, @"Extracted file is empty: %@", fileInfo.filename);
|
|
}
|
|
} error:&error];
|
|
|
|
XCTAssertEqual(fileCount, 20, @"Not all files read");
|
|
XCTAssertTrue(success, @"Failed to read files");
|
|
XCTAssertNil(error, @"Error reading files: %@", error);
|
|
}
|
|
#endif
|
|
|
|
- (void)testPerformOnData_Folder
|
|
{
|
|
NSURL *testArchiveURL = self.testFileURLs[@"Folder Archive.rar"];
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
|
|
|
|
NSArray *expectedFiles = @[@"G070-Cliff", @"G070-Cliff/image.jpg"];
|
|
|
|
__block NSUInteger fileIndex = 0;
|
|
NSError *error = nil;
|
|
|
|
[archive performOnDataInArchive:
|
|
^(URKFileInfo *fileInfo, NSData *fileData, BOOL *stop) {
|
|
NSString *expectedFilename = expectedFiles[fileIndex++];
|
|
XCTAssertEqualObjects(fileInfo.filename, expectedFilename, @"Unexpected filename encountered");
|
|
} error:&error];
|
|
|
|
XCTAssertNil(error, @"Error iterating through files");
|
|
XCTAssertEqual(fileIndex, expectedFiles.count, @"Incorrect number of files encountered");
|
|
}
|
|
|
|
|
|
#pragma mark Extract Buffered Data
|
|
|
|
|
|
- (void)testExtractBufferedData
|
|
{
|
|
NSURL *archiveURL = self.testFileURLs[@"Test Archive.rar"];
|
|
NSString *extractedFile = @"Test File B.jpg";
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:archiveURL error:nil];
|
|
|
|
NSError *error = nil;
|
|
NSMutableData *reconstructedFile = [NSMutableData data];
|
|
BOOL success = [archive extractBufferedDataFromFile:extractedFile
|
|
error:&error
|
|
action:
|
|
^(NSData *dataChunk, CGFloat percentDecompressed) {
|
|
NSLog(@"Decompressed: %f%%", percentDecompressed);
|
|
[reconstructedFile appendBytes:dataChunk.bytes
|
|
length:dataChunk.length];
|
|
}];
|
|
|
|
XCTAssertTrue(success, @"Failed to read buffered data");
|
|
XCTAssertNil(error, @"Error reading buffered data");
|
|
XCTAssertGreaterThan(reconstructedFile.length, 0, @"No data returned");
|
|
|
|
NSData *originalFile = [NSData dataWithContentsOfURL:self.testFileURLs[extractedFile]];
|
|
XCTAssertTrue([originalFile isEqualToData:reconstructedFile],
|
|
@"File extracted in buffer not returned correctly");
|
|
}
|
|
|
|
#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
|
- (void)testExtractBufferedData_VeryLarge
|
|
{
|
|
kdebug_signpost_start(SignPostCodeCreateTextFile, 0, 0, 0, SignPostColorBlue);
|
|
NSURL *largeTextFile = [self randomTextFileOfLength:1000000]; // Increase for a more dramatic test
|
|
XCTAssertNotNil(largeTextFile, @"No large text file URL returned");
|
|
kdebug_signpost_end(SignPostCodeCreateTextFile, 0, 0, 0, SignPostColorBlue);
|
|
|
|
kdebug_signpost_start(SignPostCodeArchiveData, 0, 0, 0, SignPostColorGreen);
|
|
NSURL *archiveURL = [self archiveWithFiles:@[largeTextFile]];
|
|
XCTAssertNotNil(archiveURL, @"No archived large text file URL returned");
|
|
kdebug_signpost_end(SignPostCodeArchiveData, 0, 0, 0, SignPostColorGreen);
|
|
|
|
NSURL *deflatedFileURL = [self.tempDirectory URLByAppendingPathComponent:@"DeflatedTextFile.txt"];
|
|
BOOL createSuccess = [[NSFileManager defaultManager] createFileAtPath:deflatedFileURL.path
|
|
contents:nil
|
|
attributes:nil];
|
|
XCTAssertTrue(createSuccess, @"Failed to create empty deflate file");
|
|
|
|
NSError *handleError = nil;
|
|
NSFileHandle *deflated = [NSFileHandle fileHandleForWritingToURL:deflatedFileURL
|
|
error:&handleError];
|
|
XCTAssertNil(handleError, @"Error creating a file handle");
|
|
|
|
URKArchive *archive = [[URKArchive alloc] initWithURL:archiveURL error:nil];
|
|
|
|
kdebug_signpost_start(SignPostCodeExtractData, 0, 0, 0, SignPostColorPurple);
|
|
|
|
NSError *error = nil;
|
|
BOOL success = [archive extractBufferedDataFromFile:largeTextFile.lastPathComponent
|
|
error:&error
|
|
action:
|
|
^(NSData *dataChunk, CGFloat percentDecompressed) {
|
|
NSLog(@"Decompressed: %f%%", percentDecompressed);
|
|
[deflated writeData:dataChunk];
|
|
}];
|
|
|
|
kdebug_signpost_end(SignPostCodeExtractData, 0, 0, 0, SignPostColorPurple);
|
|
|
|
XCTAssertTrue(success, @"Failed to read buffered data");
|
|
XCTAssertNil(error, @"Error reading buffered data");
|
|
|
|
[deflated closeFile];
|
|
|
|
NSData *deflatedData = [NSData dataWithContentsOfURL:deflatedFileURL];
|
|
NSData *fileData = [NSData dataWithContentsOfURL:largeTextFile];
|
|
|
|
XCTAssertTrue([fileData isEqualToData:deflatedData], @"Data didn't restore correctly");
|
|
}
|
|
#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
|