2011-10-03 23:28:54 -07:00
//
// SSZipArchiveTests.m
// SSZipArchiveTests
//
// Created by Sam Soffes on 10/3/11.
2014-01-01 11:00:26 -08:00
// Copyright (c) 2011-2014 Sam Soffes. All rights reserved.
2011-10-03 23:28:54 -07:00
//
# import "SSZipArchive.h"
2013-09-07 08:33:47 -07:00
# import <XCTest / XCTest.h>
2012-05-08 22:55:30 -04:00
# import <CommonCrypto / CommonDigest.h>
2012-05-07 23:41:24 -07:00
2013-09-07 08:33:47 -07:00
@interface SSZipArchiveTests : XCTestCase < SSZipArchiveDelegate >
2011-10-03 23:28:54 -07:00
@end
@implementation SSZipArchiveTests
2013-09-07 08:33:47 -07:00
- ( void ) tearDown {
[ super tearDown ] ;
[ [ NSFileManager defaultManager ] removeItemAtPath : [ self _cachesPath : nil ] error : nil ] ;
}
2012-05-07 23:41:24 -07:00
2011-12-26 23:32:55 -05:00
- ( void ) testZipping {
2013-03-09 05:36:20 -08:00
// use extracted files from [-testUnzipping]
NSString * inputPath = [ self _cachesPath : @" Regular " ] ;
2011-12-26 23:32:55 -05:00
NSArray * inputPaths = [ NSArray arrayWithObjects :
2013-03-09 05:36:20 -08:00
[ inputPath stringByAppendingPathComponent : @" Readme.markdown " ] ,
[ inputPath stringByAppendingPathComponent : @" LICENSE " ] ,
2011-12-26 23:32:55 -05:00
nil ] ;
2014-01-01 11:00:26 -08:00
2013-03-09 05:36:20 -08:00
NSString * outputPath = [ self _cachesPath : @" Zipped " ] ;
2014-01-01 11:00:26 -08:00
2011-12-26 23:32:55 -05:00
NSString * archivePath = [ outputPath stringByAppendingPathComponent : @" CreatedArchive.zip " ] ;
[ SSZipArchive createZipFileAtPath : archivePath withFilesAtPaths : inputPaths ] ;
// TODO: Make sure the files are actually unzipped. They are, but the test should be better.
2013-09-07 08:33:47 -07:00
XCTAssertTrue ( [ [ NSFileManager defaultManager ] fileExistsAtPath : archivePath ] , @" Archive created " ) ;
2011-12-20 09:24:56 +00:00
}
2013-09-07 08:33:47 -07:00
2013-03-09 05:36:20 -08:00
- ( void ) testDirectoryZipping {
// use Unicode as folder (has a file in root and a file in subfolder)
NSString * inputPath = [ self _cachesPath : @" Unicode " ] ;
2014-01-01 11:00:26 -08:00
2013-03-09 05:36:20 -08:00
NSString * outputPath = [ self _cachesPath : @" FolderZipped " ] ;
NSString * archivePath = [ outputPath stringByAppendingPathComponent : @" ArchiveWithFolders.zip " ] ;
2014-01-01 11:00:26 -08:00
2013-03-09 05:36:20 -08:00
[ SSZipArchive createZipFileAtPath : archivePath withContentsOfDirectory : inputPath ] ;
2013-09-07 08:33:47 -07:00
XCTAssertTrue ( [ [ NSFileManager defaultManager ] fileExistsAtPath : archivePath ] , @" Folder Archive created " ) ;
2013-03-09 05:36:20 -08:00
}
2011-12-26 23:32:55 -05:00
- ( void ) testUnzipping {
2011-10-03 23:28:54 -07:00
NSString * zipPath = [ [ NSBundle bundleForClass : [ self class ] ] pathForResource : @" TestArchive " ofType : @" zip " ] ;
2012-05-07 23:41:24 -07:00
NSString * outputPath = [ self _cachesPath : @" Regular " ] ;
2014-01-01 11:00:26 -08:00
2012-05-07 22:27:45 -07:00
[ SSZipArchive unzipFileAtPath : zipPath toDestination : outputPath delegate : self ] ;
2014-01-01 11:00:26 -08:00
2012-05-07 22:27:45 -07:00
NSFileManager * fileManager = [ NSFileManager defaultManager ] ;
2011-10-03 23:28:54 -07:00
NSString * testPath = [ outputPath stringByAppendingPathComponent : @" Readme.markdown " ] ;
2013-09-07 08:33:47 -07:00
XCTAssertTrue ( [ fileManager fileExistsAtPath : testPath ] , @" Readme unzipped " ) ;
2014-01-01 11:00:26 -08:00
2011-10-03 23:28:54 -07:00
testPath = [ outputPath stringByAppendingPathComponent : @" LICENSE " ] ;
2013-09-07 08:33:47 -07:00
XCTAssertTrue ( [ fileManager fileExistsAtPath : testPath ] , @" LICENSE unzipped " ) ;
2011-10-03 23:28:54 -07:00
}
2012-05-07 23:41:24 -07:00
- ( void ) testUnzippingWithPassword {
NSString * zipPath = [ [ NSBundle bundleForClass : [ self class ] ] pathForResource : @" TestPasswordArchive " ofType : @" zip " ] ;
NSString * outputPath = [ self _cachesPath : @" Password " ] ;
2014-01-01 11:00:26 -08:00
2012-05-07 23:41:24 -07:00
NSError * error = nil ;
[ SSZipArchive unzipFileAtPath : zipPath toDestination : outputPath overwrite : YES password : @" passw0rd " error : & error delegate : self ] ;
2014-01-01 11:00:26 -08:00
2012-05-07 23:41:24 -07:00
NSFileManager * fileManager = [ NSFileManager defaultManager ] ;
NSString * testPath = [ outputPath stringByAppendingPathComponent : @" Readme.markdown " ] ;
2013-09-07 08:33:47 -07:00
XCTAssertTrue ( [ fileManager fileExistsAtPath : testPath ] , @" Readme unzipped " ) ;
2014-01-01 11:00:26 -08:00
2012-05-07 23:41:24 -07:00
testPath = [ outputPath stringByAppendingPathComponent : @" LICENSE " ] ;
2013-09-07 08:33:47 -07:00
XCTAssertTrue ( [ fileManager fileExistsAtPath : testPath ] , @" LICENSE unzipped " ) ;
2012-05-07 23:41:24 -07:00
}
2013-09-07 08:33:47 -07:00
2012-05-08 22:55:30 -04:00
- ( void ) testUnzippingTruncatedFileFix {
2012-05-09 09:54:16 -07:00
NSString * zipPath = [ [ NSBundle bundleForClass : [ self class ] ] pathForResource : @" IncorrectHeaders " ofType : @" zip " ] ;
NSString * outputPath = [ self _cachesPath : @" IncorrectHeaders " ] ;
2014-01-01 11:00:26 -08:00
2012-05-08 22:55:30 -04:00
[ SSZipArchive unzipFileAtPath : zipPath toDestination : outputPath delegate : self ] ;
2014-01-01 11:00:26 -08:00
2012-05-09 09:54:16 -07:00
NSString * intendedReadmeTxtMD5 = @" 31ac96301302eb388070c827447290b5 " ;
2014-01-01 11:00:26 -08:00
2012-05-09 09:54:16 -07:00
NSString * filePath = [ outputPath stringByAppendingPathComponent : @" IncorrectHeaders/Readme.txt " ] ;
NSData * data = [ NSData dataWithContentsOfFile : filePath ] ;
2014-01-01 11:00:26 -08:00
2012-05-09 09:54:16 -07:00
NSString * actualReadmeTxtMD5 = [ self _calculateMD5Digest : data ] ;
2013-09-07 08:33:47 -07:00
XCTAssertTrue ( [ actualReadmeTxtMD5 isEqualToString : intendedReadmeTxtMD5 ] , @" Readme.txt MD5 digest should match original. " ) ;
2012-05-08 22:55:30 -04:00
}
2013-09-07 08:33:47 -07:00
2012-05-09 08:18:19 -04:00
- ( void ) testUnzippingWithSymlinkedFileInside {
2014-01-01 11:00:26 -08:00
2012-05-09 09:54:16 -07:00
NSString * zipPath = [ [ NSBundle bundleForClass : [ self class ] ] pathForResource : @" SymbolicLink " ofType : @" zip " ] ;
NSString * outputPath = [ self _cachesPath : @" SymbolicLink " ] ;
2014-01-01 11:00:26 -08:00
2012-05-09 08:18:19 -04:00
[ SSZipArchive unzipFileAtPath : zipPath toDestination : outputPath delegate : self ] ;
2014-01-01 11:00:26 -08:00
2012-05-09 23:53:22 -04:00
NSString * testSymlinkFolder = [ outputPath stringByAppendingPathComponent : @" SymbolicLink/GitHub.app " ] ;
NSString * testSymlinkFile = [ outputPath stringByAppendingPathComponent : @" SymbolicLink/Icon.icns " ] ;
2014-01-01 11:00:26 -08:00
2012-05-09 23:53:22 -04:00
NSError * error = nil ;
NSString * symlinkFolderPath = [ [ NSFileManager defaultManager ] destinationOfSymbolicLinkAtPath : testSymlinkFolder error : & error ] ;
bool symbolicLinkToFolderPersists = ( ( symlinkFolderPath ! = nil ) & & [ symlinkFolderPath isEqualToString : @" /Applications/GitHub.app " ] ) & & ( error = = nil ) ;
2014-01-01 11:00:26 -08:00
2012-05-09 23:53:22 -04:00
error = nil ;
2014-01-01 11:00:26 -08:00
2012-05-09 23:53:22 -04:00
NSString * symlinkFilePath = [ [ NSFileManager defaultManager ] destinationOfSymbolicLinkAtPath : testSymlinkFile error : & error ] ;
bool symbolicLinkToFilePersists = ( ( symlinkFilePath ! = nil ) & & [ symlinkFilePath isEqualToString : @" /Applications/GitHub.app/Contents/Resources/AppIcon.icns " ] ) & & ( error = = nil ) ;
2014-01-01 11:00:26 -08:00
2013-09-07 08:33:47 -07:00
XCTAssertTrue ( symbolicLinkToFilePersists & & symbolicLinkToFolderPersists , @" Symbolic links should persist from the original archive to the outputted files. " ) ;
2012-05-09 08:18:19 -04:00
}
2013-11-08 20:34:17 +01:00
- ( void ) testUnzippingWithRelativeSymlink {
NSString * resourceName = @" RelativeSymbolicLink " ;
NSString * zipPath = [ [ NSBundle bundleForClass : [ self class ] ] pathForResource : resourceName ofType : @" zip " ] ;
NSString * outputPath = [ self _cachesPath : resourceName ] ;
[ SSZipArchive unzipFileAtPath : zipPath toDestination : outputPath delegate : self ] ;
// Determine where the symlinks are
NSString * subfolderName = @" symlinks " ;
NSString * testBasePath = [ NSString pathWithComponents : @[ outputPath , resourceName ] ] ;
NSString * testSymlinkFolder = [ NSString pathWithComponents : @[ testBasePath , subfolderName , @" folderSymlink " ] ] ;
NSString * testSymlinkFile = [ NSString pathWithComponents : @[ testBasePath , subfolderName , @" fileSymlink " ] ] ;
// Determine where the files they link to are
NSString * parentDir = @" ../ " ;
NSString * testSymlinkFolderTarget = [ NSString pathWithComponents : @[ parentDir , @" symlinkedFolder " ] ] ;
NSString * testSymlinkFileTarget = [ NSString pathWithComponents : @[ parentDir , @" symlinkedFile " ] ] ;
NSError * error = nil ;
NSString * symlinkFolderPath = [ [ NSFileManager defaultManager ] destinationOfSymbolicLinkAtPath : testSymlinkFolder error : & error ] ;
bool symbolicLinkToFolderPersists = ( ( symlinkFolderPath ! = nil ) & & [ symlinkFolderPath isEqualToString : testSymlinkFolderTarget ] ) & & ( error = = nil ) ;
error = nil ;
NSString * symlinkFilePath = [ [ NSFileManager defaultManager ] destinationOfSymbolicLinkAtPath : testSymlinkFile error : & error ] ;
bool symbolicLinkToFilePersists = ( ( symlinkFilePath ! = nil ) & & [ symlinkFilePath isEqualToString : testSymlinkFileTarget ] ) & & ( error = = nil ) ;
XCTAssertTrue ( symbolicLinkToFilePersists & & symbolicLinkToFolderPersists , @" Relative symbolic links should persist from the original archive to the outputted files (and also remain relative). " ) ;
}
2013-09-07 08:33:47 -07:00
2012-05-09 23:53:22 -04:00
- ( void ) testUnzippingWithUnicodeFilenameInside {
2014-01-01 11:00:26 -08:00
2012-05-09 23:53:22 -04:00
NSString * zipPath = [ [ NSBundle bundleForClass : [ self class ] ] pathForResource : @" Unicode " ofType : @" zip " ] ;
NSString * outputPath = [ self _cachesPath : @" Unicode " ] ;
2014-01-01 11:00:26 -08:00
2012-05-09 23:53:22 -04:00
[ SSZipArchive unzipFileAtPath : zipPath toDestination : outputPath delegate : self ] ;
2014-01-01 11:00:26 -08:00
2012-05-09 23:53:22 -04:00
bool unicodeFilenameWasExtracted = [ [ NSFileManager defaultManager ] fileExistsAtPath : [ outputPath stringByAppendingPathComponent : @" Accént.txt " ] ] ;
2014-01-01 11:00:26 -08:00
2012-05-09 23:53:22 -04:00
bool unicodeFolderWasExtracted = [ [ NSFileManager defaultManager ] fileExistsAtPath : [ outputPath stringByAppendingPathComponent : @" Fólder/Nothing.txt " ] ] ;
2014-01-01 11:00:26 -08:00
2013-09-07 08:33:47 -07:00
XCTAssertTrue ( unicodeFilenameWasExtracted , @" Files with filenames in unicode should be extracted properly. " ) ;
XCTAssertTrue ( unicodeFolderWasExtracted , @" Folders with names in unicode should be extracted propertly. " ) ;
2012-05-09 23:53:22 -04:00
}
2012-05-07 23:41:24 -07:00
2013-09-07 08:33:47 -07:00
2013-06-25 13:45:30 +02:00
- ( void ) testZippingAndUnzippingForDate {
NSString * inputPath = [ self _cachesPath : @" Regular " ] ;
NSArray * inputPaths = [ NSArray arrayWithObjects :
[ inputPath stringByAppendingPathComponent : @" Readme.markdown " ] ,
nil ] ;
2014-01-01 11:00:26 -08:00
2013-06-25 13:45:30 +02:00
NSDictionary * originalFileAttributes = [ [ NSFileManager defaultManager ] attributesOfItemAtPath : [ inputPath stringByAppendingPathComponent : @" Readme.markdown " ] error : nil ] ;
NSString * outputPath = [ self _cachesPath : @" ZippedDate " ] ;
NSString * archivePath = [ outputPath stringByAppendingPathComponent : @" CreatedArchive.zip " ] ;
2014-01-01 11:00:26 -08:00
2013-06-25 13:45:30 +02:00
[ SSZipArchive createZipFileAtPath : archivePath withFilesAtPaths : inputPaths ] ;
[ SSZipArchive unzipFileAtPath : archivePath toDestination : outputPath delegate : self ] ;
2014-01-01 11:00:26 -08:00
2013-06-25 13:45:30 +02:00
NSDictionary * createdFileAttributes = [ [ NSFileManager defaultManager ] attributesOfItemAtPath : [ outputPath stringByAppendingPathComponent : @" Readme.markdown " ] error : nil ] ;
2013-09-07 08:33:47 -07:00
XCTAssertEqualObjects ( originalFileAttributes [ NSFileCreationDate ] , createdFileAttributes [ @" NSFileCreationDate " ] , @" Orginal file creationDate should match created one " ) ;
2013-06-26 12:16:29 +01:00
}
2013-09-07 08:33:47 -07:00
2013-06-26 12:16:29 +01:00
- ( void ) testZippingAndUnzippingForPermissions {
// File we're going to test permissions on before and after zipping
NSString * targetFile = @" /Contents/MacOS/TestProject " ;
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
/********** Zipping ********/
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
// The .app file we're going to zip up
NSString * inputFile = [ [ NSBundle mainBundle ] pathForResource : @" PermissionsTestApp " ofType : @" app " ] ;
// The path to the target file in the app before zipping
NSString * targetFilePreZipPath = [ inputFile stringByAppendingPathComponent : targetFile ] ;
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
// Atribtues for the target file before zipping
NSDictionary * preZipAttributes = [ [ NSFileManager defaultManager ] attributesOfItemAtPath : targetFilePreZipPath error : nil ] ;
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
// Directory to output our created zip file
NSString * outputDir = [ self _cachesPath : @" PermissionsTest " ] ;
// The path to where the archive shall be created
NSString * archivePath = [ outputDir stringByAppendingPathComponent : @" TestAppArchive.zip " ] ;
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
// Create the zip file using the contents of the .app file as the input
[ SSZipArchive createZipFileAtPath : archivePath withContentsOfDirectory : inputFile ] ;
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
/********** Un-zipping *******/
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
// Using this newly created zip file, unzip it
[ SSZipArchive unzipFileAtPath : archivePath toDestination : outputDir ] ;
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
// Get the path to the target file after unzipping
NSString * targetFilePath = [ outputDir stringByAppendingPathComponent : @" /Contents/MacOS/TestProject " ] ;
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
// Get the file attributes of the target file following the unzipping
NSDictionary * fileAttributes = [ [ NSFileManager defaultManager ] attributesOfItemAtPath : targetFilePath error : nil ] ;
2014-01-01 11:00:26 -08:00
2013-06-26 12:16:29 +01:00
// Compare the value of the permissions attribute to assert equality
2013-09-07 08:33:47 -07:00
XCTAssertEqual ( fileAttributes [ NSFilePosixPermissions ] , preZipAttributes [ NSFilePosixPermissions ] , @" File permissions should be retained during compression and de-compression " ) ;
2013-06-25 13:45:30 +02:00
}
2012-05-07 23:41:24 -07:00
// Commented out to avoid checking in several gig file into the repository. Simply add a file named
// `LargeArchive.zip` to the project and uncomment out these lines to test.
//
//- (void)testUnzippingLargeFiles {
// NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"LargeArchive" ofType:@"zip"];
// NSString *outputPath = [self _cachesPath:@"Large"];
2014-01-01 11:00:26 -08:00
//
2012-05-07 23:41:24 -07:00
// [SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath];
//}
# pragma mark - SSZipArchiveDelegate
2012-05-07 22:27:45 -07:00
2012-05-07 23:05:06 -07:00
- ( void ) zipArchiveWillUnzipArchiveAtPath: ( NSString * ) path zipInfo: ( unz_global_info ) zipInfo {
2012-05-09 11:14:56 -04:00
NSLog ( @" *** zipArchiveWillUnzipArchiveAtPath: `%@` zipInfo: " , path ) ;
2012-05-07 23:05:06 -07:00
}
- ( void ) zipArchiveDidUnzipArchiveAtPath: ( NSString * ) path zipInfo: ( unz_global_info ) zipInfo unzippedPath: ( NSString * ) unzippedPath {
2012-05-09 11:14:56 -04:00
NSLog ( @" *** zipArchiveDidUnzipArchiveAtPath: `%@` zipInfo: unzippedPath: `%@` " , path , unzippedPath ) ;
2012-05-07 22:27:45 -07:00
}
- ( void ) zipArchiveWillUnzipFileAtIndex: ( NSInteger ) fileIndex totalFiles: ( NSInteger ) totalFiles archivePath: ( NSString * ) archivePath fileInfo: ( unz_file_info ) fileInfo {
2013-09-07 08:33:47 -07:00
NSLog ( @" *** zipArchiveWillUnzipFileAtIndex: `%d` totalFiles: `%d` archivePath: `%@` fileInfo: " , fileIndex , totalFiles , archivePath ) ;
2012-05-07 22:27:45 -07:00
}
- ( void ) zipArchiveDidUnzipFileAtIndex: ( NSInteger ) fileIndex totalFiles: ( NSInteger ) totalFiles archivePath: ( NSString * ) archivePath fileInfo: ( unz_file_info ) fileInfo {
2013-09-07 08:33:47 -07:00
NSLog ( @" *** zipArchiveDidUnzipFileAtIndex: `%d` totalFiles: `%d` archivePath: `%@` fileInfo: " , fileIndex , totalFiles , archivePath ) ;
2012-05-07 22:27:45 -07:00
}
2011-10-03 23:28:54 -07:00
# pragma mark - Private
2012-05-07 23:41:24 -07:00
- ( NSString * ) _cachesPath: ( NSString * ) directory {
NSString * path = [ [ NSSearchPathForDirectoriesInDomains ( NSCachesDirectory , NSUserDomainMask , YES ) lastObject ]
stringByAppendingPathComponent : @" com.samsoffes.ssziparchive.tests " ] ;
if ( directory ) {
path = [ path stringByAppendingPathComponent : directory ] ;
}
2014-01-01 11:00:26 -08:00
2012-05-07 23:41:24 -07:00
NSFileManager * fileManager = [ NSFileManager defaultManager ] ;
if ( ! [ fileManager fileExistsAtPath : path ] ) {
[ fileManager createDirectoryAtPath : path withIntermediateDirectories : YES attributes : nil error : nil ] ;
}
2014-01-01 11:00:26 -08:00
2012-05-07 23:41:24 -07:00
return path ;
2011-10-03 23:28:54 -07:00
}
2012-05-09 08:36:42 -07:00
// Taken from https://github.com/samsoffes/sstoolkit/blob/master/SSToolkit/NSData+SSToolkitAdditions.m
- ( NSString * ) _calculateMD5Digest: ( NSData * ) data {
unsigned char digest [ CC_MD5_DIGEST_LENGTH ] , i ;
CC_MD5 ( data . bytes , ( unsigned int ) data . length , digest ) ;
NSMutableString * ms = [ NSMutableString string ] ;
for ( i = 0 ; i < CC_MD5_DIGEST_LENGTH ; i + + ) {
[ ms appendFormat : @" %02x " , ( int ) ( digest [ i ] ) ] ;
}
return [ ms copy ] ;
2012-05-08 22:55:30 -04:00
}
2011-10-03 23:28:54 -07:00
@end