Fixed the windows explorer bug
[archive-zip.git] / t / 02_main.t
blobdf3b97bf173d94cdab8ebedbde45697f0b18c0a6
1 #!/usr/bin/perl
3 # Main testing for Archive::Zip
5 use strict;
6 BEGIN {
7 $| = 1;
8 $^W = 1;
11 use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
12 use FileHandle;
13 use File::Path;
14 use File::Spec;
16 use Test::More tests => 141;
18 BEGIN {
19 unshift @INC, "t/";
20 require( File::Spec->catfile('t', 'common.pl') )
21 or die "Can't load t/common.pl";
28 #####################################################################
29 # Testing Utility Functions
31 #--------- check CRC
32 is(TESTSTRINGCRC, 0xac373f32, 'Testing CRC matches expected');
34 # Bad times die
35 SCOPE: {
36 my @errors = ();
37 local $Archive::Zip::ErrorHandler = sub { push @errors, @_ };
38 eval { Archive::Zip::Member::_unixToDosTime( 0 ) };
39 ok( $errors[0] =~ /Tried to add member with zero or undef/,
40 'Got expected _unixToDosTime error' );
43 #--------- check time conversion
45 foreach my $unix_time (
46 315576062, 315576064, 315580000, 315600000,
47 316000000, 320000000, 400000000, 500000000,
48 600000000, 700000000, 800000000, 900000000,
49 1000000000, 1100000000, 1200000000,
50 int(time()/2)*2,
51 ) {
52 my $dos_time = Archive::Zip::Member::_unixToDosTime( $unix_time );
53 my $round_trip = Archive::Zip::Member::_dosToUnixTime( $dos_time );
54 is( $unix_time, $round_trip, 'Got expected DOS DateTime value' );
61 #####################################################################
62 # Testing Archives
64 #--------- empty file
65 # new # Archive::Zip
66 # new # Archive::Zip::Archive
67 my $zip = Archive::Zip->new();
68 isa_ok( $zip, 'Archive::Zip' );
70 # members # Archive::Zip::Archive
71 my @members = $zip->members;
72 is(scalar(@members), 0, '->members is 0' );
74 # numberOfMembers # Archive::Zip::Archive
75 my $numberOfMembers = $zip->numberOfMembers();
76 is($numberOfMembers, 0, '->numberofMembers is 0' );
78 # writeToFileNamed # Archive::Zip::Archive
79 my $status = $zip->writeToFileNamed( OUTPUTZIP );
80 is($status, AZ_OK, '->writeToFileNames ok' );
82 my $zipout;
83 SKIP: {
84 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
85 if ( $^O eq 'MSWin32' ) {
86 print STDERR "\n# You might see an expected 'zipfile is empty' warning now.\n";
88 ($status, $zipout) = testZip();
89 # STDERR->print("status= $status, out=$zipout\n");
91 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
92 ok( $status != 0 );
94 # unzip -t returns error code=1 for warning on empty
96 #--------- add a directory
97 my $memberName = TESTDIR . '/';
98 my $dirName = TESTDIR;
100 # addDirectory # Archive::Zip::Archive
101 # new # Archive::Zip::Member
102 my $member = $zip->addDirectory($memberName);
103 ok(defined($member));
104 is($member->fileName(), $memberName);
106 # On some (Windows systems) the modification time is
107 # corrupted. Save this to check late.
108 my $dir_time = $member->lastModFileDateTime();
110 # members # Archive::Zip::Archive
111 @members = $zip->members();
112 is(scalar(@members), 1);
113 is($members[0], $member);
115 # numberOfMembers # Archive::Zip::Archive
116 $numberOfMembers = $zip->numberOfMembers();
117 is($numberOfMembers, 1);
119 # writeToFileNamed # Archive::Zip::Archive
120 $status = $zip->writeToFileNamed( OUTPUTZIP );
121 is($status, AZ_OK);
123 # Does the modification time get corrupted?
124 is( ($zip->members)[0]->lastModFileDateTime(), $dir_time );
126 SKIP: {
127 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
128 ($status, $zipout) = testZip();
129 # STDERR->print("status= $status, out=$zipout\n");
130 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
131 is( $status, 0 );
134 #--------- extract the directory by name
135 rmtree([ TESTDIR ], 0, 0);
136 $status = $zip->extractMember($memberName);
137 is($status, AZ_OK);
138 ok(-d $dirName);
140 #--------- extract the directory by identity
141 ok(rmdir($dirName)); # it's still empty
142 $status = $zip->extractMember($member);
143 is($status, AZ_OK);
144 ok(-d $dirName);
146 #--------- add a string member, uncompressed
147 $memberName = TESTDIR . '/string.txt';
148 # addString # Archive::Zip::Archive
149 # newFromString # Archive::Zip::Member
150 $member = $zip->addString(TESTSTRING, $memberName);
151 ok(defined($member));
153 is($member->fileName(), $memberName);
155 # members # Archive::Zip::Archive
156 @members = $zip->members();
157 is(scalar(@members), 2);
158 is($members[1], $member);
160 # numberOfMembers # Archive::Zip::Archive
161 $numberOfMembers = $zip->numberOfMembers();
162 is($numberOfMembers, 2);
164 # writeToFileNamed # Archive::Zip::Archive
165 $status = $zip->writeToFileNamed( OUTPUTZIP );
166 is($status, AZ_OK);
168 SKIP: {
169 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
170 ($status, $zipout) = testZip();
171 # STDERR->print("status= $status, out=$zipout\n");
172 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
173 is( $status, 0 );
176 is($member->crc32(), TESTSTRINGCRC);
178 is($member->crc32String(), sprintf("%08x", TESTSTRINGCRC));
180 #--------- extract it by name
181 $status = $zip->extractMember($memberName);
182 is($status, AZ_OK);
183 ok(-f $memberName);
184 is(fileCRC($memberName), TESTSTRINGCRC);
186 #--------- now compress it and re-test
187 my $oldCompressionMethod =
188 $member->desiredCompressionMethod(COMPRESSION_DEFLATED);
189 is($oldCompressionMethod, COMPRESSION_STORED, 'old compression method OK');
191 # writeToFileNamed # Archive::Zip::Archive
192 $status = $zip->writeToFileNamed( OUTPUTZIP );
193 is($status, AZ_OK, 'writeToFileNamed returns AZ_OK');
194 is($member->crc32(), TESTSTRINGCRC);
195 is($member->uncompressedSize(), TESTSTRINGLENGTH);
197 SKIP: {
198 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
199 ($status, $zipout) = testZip();
200 # STDERR->print("status= $status, out=$zipout\n");
201 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
202 is( $status, 0 );
205 #--------- extract it by name
206 $status = $zip->extractMember($memberName);
207 is($status, AZ_OK);
208 ok(-f $memberName);
209 is(fileCRC($memberName), TESTSTRINGCRC);
211 #--------- add a file member, compressed
212 ok(rename($memberName, TESTDIR . '/file.txt'));
213 $memberName = TESTDIR . '/file.txt';
215 # addFile # Archive::Zip::Archive
216 # newFromFile # Archive::Zip::Member
217 $member = $zip->addFile($memberName);
218 ok(defined($member));
220 is($member->desiredCompressionMethod(), COMPRESSION_DEFLATED);
222 # writeToFileNamed # Archive::Zip::Archive
223 $status = $zip->writeToFileNamed( OUTPUTZIP );
224 is($status, AZ_OK);
225 is($member->crc32(), TESTSTRINGCRC);
226 is($member->uncompressedSize(), TESTSTRINGLENGTH);
228 SKIP: {
229 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
230 ($status, $zipout) = testZip();
231 # STDERR->print("status= $status, out=$zipout\n");
232 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
233 is( $status, 0 );
236 #--------- extract it by name (note we have to rename it first
237 #--------- or we will clobber the original file
238 my $newName = $memberName;
239 $newName =~ s/\.txt/2.txt/;
240 $status = $zip->extractMember($memberName, $newName);
241 is($status, AZ_OK);
242 ok(-f $newName);
243 is(fileCRC($newName), TESTSTRINGCRC);
245 #--------- now make it uncompressed and re-test
246 $oldCompressionMethod =
247 $member->desiredCompressionMethod(COMPRESSION_STORED);
249 is($oldCompressionMethod, COMPRESSION_DEFLATED);
251 # writeToFileNamed # Archive::Zip::Archive
252 $status = $zip->writeToFileNamed( OUTPUTZIP );
253 is($status, AZ_OK);
254 is($member->crc32(), TESTSTRINGCRC);
255 is($member->uncompressedSize(), TESTSTRINGLENGTH);
257 SKIP: {
258 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
259 ($status, $zipout) = testZip();
260 # STDERR->print("status= $status, out=$zipout\n");
261 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
262 is( $status, 0 );
265 #--------- extract it by name
266 $status = $zip->extractMember($memberName, $newName);
267 is($status, AZ_OK);
268 ok(-f $newName);
269 is(fileCRC($newName), TESTSTRINGCRC);
271 # Now, the contents of OUTPUTZIP are:
272 # Length Method Size Ratio Date Time CRC-32 Name
273 #-------- ------ ------- ----- ---- ---- ------ ----
274 # 0 Stored 0 0% 03-17-00 11:16 00000000 testDir/
275 # 300 Defl:N 146 51% 03-17-00 11:16 ac373f32 testDir/string.txt
276 # 300 Stored 300 0% 03-17-00 11:16 ac373f32 testDir/file.txt
277 #-------- ------- --- -------
278 # 600 446 26% 3 files
280 # members # Archive::Zip::Archive
281 @members = $zip->members();
282 is(scalar(@members), 3);
283 is($members[2], $member);
285 # memberNames # Archive::Zip::Archive
286 my @memberNames = $zip->memberNames();
287 is(scalar(@memberNames), 3);
288 is($memberNames[2], $memberName);
290 # memberNamed # Archive::Zip::Archive
291 is($zip->memberNamed($memberName), $member);
293 # membersMatching # Archive::Zip::Archive
294 @members = $zip->membersMatching('file');
295 is(scalar(@members), 1);
296 is($members[0], $member);
298 @members = $zip->membersMatching('.txt$');
299 is(scalar(@members), 2);
300 is($members[1], $member);
302 #--------- remove the string member and test the file
303 # removeMember # Archive::Zip::Archive
304 $member = $zip->removeMember($members[0]);
305 is($member, $members[0]);
307 $status = $zip->writeToFileNamed( OUTPUTZIP );
308 is($status, AZ_OK);
310 SKIP: {
311 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
312 ($status, $zipout) = testZip();
313 # STDERR->print("status= $status, out=$zipout\n");
314 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
315 is( $status, 0 );
318 #--------- add the string member at the end and test the file
319 # addMember # Archive::Zip::Archive
320 $zip->addMember($member);
321 @members = $zip->members();
323 is(scalar(@members), 3);
324 is($members[2], $member);
326 # memberNames # Archive::Zip::Archive
327 @memberNames = $zip->memberNames();
328 is(scalar(@memberNames), 3);
329 is($memberNames[1], $memberName);
331 $status = $zip->writeToFileNamed( OUTPUTZIP );
332 is($status, AZ_OK);
334 SKIP: {
335 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
336 ($status, $zipout) = testZip();
337 # STDERR->print("status= $status, out=$zipout\n");
338 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
339 is( $status, 0 );
342 #--------- remove the file member
343 $member = $zip->removeMember($members[1]);
344 is($member, $members[1]);
345 is($zip->numberOfMembers(), 2);
347 #--------- replace the string member with the file member
348 # replaceMember # Archive::Zip::Archive
349 $member = $zip->replaceMember($members[2], $member);
350 is($member, $members[2]);
351 is($zip->numberOfMembers(), 2);
353 #--------- re-add the string member
354 $zip->addMember($member);
355 is($zip->numberOfMembers(), 3);
357 @members = $zip->members();
358 $status = $zip->writeToFileNamed( OUTPUTZIP );
359 is($status, AZ_OK);
361 SKIP: {
362 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
363 ($status, $zipout) = testZip();
364 # STDERR->print("status= $status, out=$zipout\n");
365 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
366 is( $status, 0 );
369 #--------- add compressed file
370 $member = $zip->addFile(File::Spec->catfile(TESTDIR, 'file.txt'));
371 ok(defined($member));
372 $member->desiredCompressionMethod(COMPRESSION_DEFLATED);
373 $member->fileName(TESTDIR . '/fileC.txt');
375 #--------- add uncompressed string
376 $member = $zip->addString(TESTSTRING, TESTDIR . '/stringU.txt');
377 ok(defined($member));
378 $member->desiredCompressionMethod(COMPRESSION_STORED);
380 # Now, the file looks like this:
381 # Length Method Size Ratio Date Time CRC-32 Name
382 #-------- ------ ------- ----- ---- ---- ------ ----
383 # 0 Stored 0 0% 03-17-00 12:30 00000000 testDir/
384 # 300 Stored 300 0% 03-17-00 12:30 ac373f32 testDir/file.txt
385 # 300 Defl:N 146 51% 03-17-00 12:30 ac373f32 testDir/string.txt
386 # 300 Stored 300 0% 03-17-00 12:30 ac373f32 testDir/stringU.txt
387 # 300 Defl:N 146 51% 03-17-00 12:30 ac373f32 testDir/fileC.txt
388 #-------- ------- --- -------
389 # 1200 892 26% 5 files
391 @members = $zip->members();
392 $numberOfMembers = $zip->numberOfMembers();
393 is($numberOfMembers, 5);
395 #--------- make sure the contents of the stored file member are OK.
396 # contents # Archive::Zip::Archive
397 is($zip->contents($members[1]), TESTSTRING);
399 # contents # Archive::Zip::Member
400 is($members[1]->contents(), TESTSTRING);
402 #--------- make sure the contents of the compressed string member are OK.
403 is($members[2]->contents(), TESTSTRING);
405 #--------- make sure the contents of the stored string member are OK.
406 is($members[3]->contents(), TESTSTRING);
408 #--------- make sure the contents of the compressed file member are OK.
409 is($members[4]->contents(), TESTSTRING);
411 #--------- write to INPUTZIP
412 $status = $zip->writeToFileNamed( INPUTZIP );
413 is($status, AZ_OK);
415 SKIP: {
416 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
417 ($status, $zipout) = testZip(INPUTZIP);
418 # STDERR->print("status= $status, out=$zipout\n");
419 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
420 is( $status, 0 );
423 #--------- read from INPUTZIP (appending its entries)
424 # read # Archive::Zip::Archive
425 $status = $zip->read(INPUTZIP);
426 is($status, AZ_OK);
427 is($zip->numberOfMembers(), 10);
429 #--------- clean up duplicate names
430 @members = $zip->members();
431 $member = $zip->removeMember($members[5]);
432 is($member->fileName(), TESTDIR . '/');
434 SCOPE: {
435 for my $i (6..9)
437 $memberName = $members[$i]->fileName();
438 $memberName =~ s/\.txt/2.txt/;
439 $members[$i]->fileName($memberName);
442 is(scalar($zip->membersMatching('2.txt')), 4);
444 #--------- write zip out and test it.
445 $status = $zip->writeToFileNamed( OUTPUTZIP );
446 is($status, AZ_OK);
448 SKIP: {
449 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
450 ($status, $zipout) = testZip();
451 # STDERR->print("status= $status, out=$zipout\n");
452 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
453 is( $status, 0 );
456 #--------- Make sure that we haven't renamed files (this happened!)
457 is(scalar($zip->membersMatching('2\.txt$')), 4);
459 #--------- Now try extracting everyone
460 @members = $zip->members();
461 is($zip->extractMember($members[0]), AZ_OK); #DM
462 is($zip->extractMember($members[1]), AZ_OK); #NFM
463 is($zip->extractMember($members[2]), AZ_OK);
464 is($zip->extractMember($members[3]), AZ_OK); #NFM
465 is($zip->extractMember($members[4]), AZ_OK);
466 is($zip->extractMember($members[5]), AZ_OK);
467 is($zip->extractMember($members[6]), AZ_OK);
468 is($zip->extractMember($members[7]), AZ_OK);
469 is($zip->extractMember($members[8]), AZ_OK);
471 #--------- count dirs
473 my @dirs = grep { $_->isDirectory() } @members;
474 is(scalar(@dirs), 1);
475 is($dirs[0], $members[0]);
478 #--------- count binary and text files
480 my @binaryFiles = grep { $_->isBinaryFile() } @members;
481 my @textFiles = grep { $_->isTextFile() } @members;
482 is(scalar(@binaryFiles), 5);
483 is(scalar(@textFiles), 4);
486 #--------- Try writing zip file to file handle
488 my $fh;
489 if ($catWorks)
491 unlink( OUTPUTZIP );
492 $fh = FileHandle->new( CATPIPE . OUTPUTZIP );
493 binmode($fh);
495 SKIP: {
496 skip('cat does not work on this platform', 1) unless $catWorks;
497 ok( $fh );
499 # $status = $zip->writeToFileHandle($fh, 0) if ($catWorks);
500 $status = $zip->writeToFileHandle($fh) if ($catWorks);
501 SKIP: {
502 skip('cat does not work on this platform', 1) unless $catWorks;
503 is( $status, AZ_OK );
505 $fh->close() if ($catWorks);
506 SKIP: {
507 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
508 ($status, $zipout) = testZip();
509 is($status, 0);
513 #--------- Change the contents of a string member
514 is(ref($members[2]), 'Archive::Zip::StringMember');
515 $members[2]->contents( "This is my new contents\n" );
517 #--------- write zip out and test it.
518 $status = $zip->writeToFileNamed( OUTPUTZIP );
519 is($status, AZ_OK);
521 SKIP: {
522 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
523 ($status, $zipout) = testZip();
524 # STDERR->print("status= $status, out=$zipout\n");
525 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
526 is( $status, 0 );
529 #--------- Change the contents of a file member
530 is(ref($members[1]), 'Archive::Zip::NewFileMember');
531 $members[1]->contents( "This is my new contents\n" );
533 #--------- write zip out and test it.
534 $status = $zip->writeToFileNamed( OUTPUTZIP );
535 is($status, AZ_OK);
537 SKIP: {
538 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
539 ($status, $zipout) = testZip();
540 # STDERR->print("status= $status, out=$zipout\n");
541 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
542 is( $status, 0 );
545 #--------- Change the contents of a zip member
547 is(ref($members[7]), 'Archive::Zip::ZipFileMember');
548 $members[7]->contents( "This is my new contents\n" );
550 #--------- write zip out and test it.
551 $status = $zip->writeToFileNamed( OUTPUTZIP );
552 is($status, AZ_OK);
554 SKIP: {
555 skip( "No 'unzip' program to test against", 1 ) unless HAVEUNZIP;
556 ($status, $zipout) = testZip();
557 # STDERR->print("status= $status, out=$zipout\n");
558 skip( "test zip doesn't work", 1 ) if $testZipDoesntWork;
559 is( $status, 0 );
563 #--------- now clean up
564 # END { system("rm -rf " . TESTDIR . " " . OUTPUTZIP . " " . INPUTZIP) }
566 #--------------------- STILL UNTESTED IN THIS SCRIPT ---------------------
568 # sub setChunkSize # Archive::Zip
569 # sub _formatError # Archive::Zip
570 # sub _error # Archive::Zip
571 # sub _subclassResponsibility # Archive::Zip
572 # sub diskNumber # Archive::Zip::Archive
573 # sub diskNumberWithStartOfCentralDirectory # Archive::Zip::Archive
574 # sub numberOfCentralDirectoriesOnThisDisk # Archive::Zip::Archive
575 # sub numberOfCentralDirectories # Archive::Zip::Archive
576 # sub centralDirectoryOffsetWRTStartingDiskNumber # Archive::Zip::Archive
577 # sub extraField # Archive::Zip::Member
578 # sub isEncrypted # Archive::Zip::Member
579 # sub isTextFile # Archive::Zip::Member
580 # sub isBinaryFile # Archive::Zip::Member
581 # sub isDirectory # Archive::Zip::Member
582 # sub lastModTime # Archive::Zip::Member
583 # sub _writeDataDescriptor # Archive::Zip::Member
584 # sub isDirectory # Archive::Zip::DirectoryMember
585 # sub _becomeDirectory # Archive::Zip::DirectoryMember
586 # sub diskNumberStart # Archive::Zip::ZipFileMember