diff --git a/lib/zip.rb b/lib/zip.rb deleted file mode 100644 index 5a89853ce1..0000000000 --- a/lib/zip.rb +++ /dev/null @@ -1 +0,0 @@ -require 'zip/zip' diff --git a/lib/zip/ChangeLog b/lib/zip/ChangeLog deleted file mode 100644 index 63bf7858f0..0000000000 --- a/lib/zip/ChangeLog +++ /dev/null @@ -1,1146 +0,0 @@ -2010-01-01 13:43 thomas - - * NEWS, lib/zip/zip.rb, test/ziptest.rb: Changed - ZipOutputStream.put_next_entry to make it possible to specifiy - comments, extra field and compression method. - -2009-12-31 16:25 thomas - - * Rakefile: Updated publish method. - -2009-11-27 22:59 thomas - - * NEWS, lib/zip/zip.rb: Bumped micro number and updated NEWS file. - - * lib/zip/zip.rb: Provide convenience methods for retrieving name - and comments in character encoding of choice (pending ruby - character String class). - -2009-04-05 12:28 thomas - - * install.rb, lib/zip/zip.rb, samples/example_filesystem.rb, - test/zipfilesystemtest.rb, test/ziptest.rb: Applied ruby-1.9 - compatibility patch from Yuya Nishida. - -2008-08-26 20:49 thomas - - * lib/zip/zip.rb: Rewrote fix for rename bug. - -2008-08-24 14:34 thomas - - * lib/zip/zip.rb, test/ziptest.rb: Refixed rename to avoid - decompressing and recompressing entry. - -2008-08-24 11:43 drylight - - * NEWS, README, Rakefile, lib/zip/zip.rb: Update version number and - minor release note changes. - - * NEWS, README, lib/zip/zip.rb, test/ziptest.rb: Fixed: Renaming an - entry failed if the entry's new name was a different length than - its old name. - -2006-12-24 11:42 thomas - - * lib/zip/: ioextras.rb, zip.rb: Added IOExtras.copy_stream_n and - used it to avoid loading large entries into memory when copying - from one stream to another. - -2006-12-17 15:03 thomas - - * lib/zip/zip.rb: Bug 1614537 Version needed to extract set. - -2006-11-21 09:12 thomas - - * lib/zip/zipfilesystem.rb, test/zipfilesystemtest.rb: Bug 1600222 - Fixed it so ZipFsFile#open accepts and ignores b(inary) option. - -2006-09-05 22:53 thomas - - * test/zipfilesystemtest.rb: Avoid warnings while running tests. - -2006-08-04 19:56 technorama - - * lib/zip/zip.rb: bugfix: :link -> :symlink - -2006-07-01 10:04 thomas - - * Rakefile: Don't autorequire zip/zip - autorequire is deprecated. - -2006-06-30 09:28 thomas - - * Rakefile: [no log message] - - * NEWS, lib/zip/zip.rb: Bumped version number and reformatted NEWS - a bit. - -2006-06-29 22:49 technorama - - * lib/zip/zip.rb, NEWS: documentation additions - -2006-04-30 06:25 technorama - - * TODO, lib/zip/zip.rb, test/ziptest.rb: add documentation and test - for new ZipFile::extract - - * lib/zip/zip.rb: add some of the API suggestions from sf.net - #1281314 - - * lib/zip/zip.rb: apply patch for bug #1446926 - - * lib/zip/zip.rb: apply patch for bug #1459902 - -2006-04-26 17:17 technorama - - * lib/zip/zip.rb: add ZipFile @restore_*, documentation update - -2006-04-07 21:13 technorama - - * test/: gentestfiles.rb, zipfilesystemtest.rb, ziptest.rb: - additional tests - -2006-03-28 04:11 technorama - - * lib/zip/zip.rb: start of unix_uid, unix_gid, restore_* support - - * lib/zip/zip.rb: follow_symlinks is now optional - - * lib/zip/zip.rb: add eof? methods - - * test/ziptest.rb: eof? tests - -2006-02-26 09:57 technorama - - * README: add to authors - - * TODO: [no log message] - -2006-02-25 12:04 thomas - - * lib/zip/zip.rb, test/ziptest.rb: Did away with ZipStreamableFile. - -2006-02-23 08:03 technorama - - * lib/zip/zip.rb: unix file permissions. symlink support. rework - ZipEntry and delegate classes. reduce memory usage during - decompression. - -2006-02-22 23:44 technorama - - * lib/zip/zipfilesystem.rb: update permissionInt for mkdir - -2006-02-04 10:42 thomas - - * lib/zip/: ioextras.rb, zip.rb: Merged patch from oss-ruby. - -2005-11-19 16:17 thomas - - * lib/zip/zip.rb: [no log message] - -2005-11-08 08:23 thomas - - * lib/zip/ioextras.rb: Accepted patch from oss-ruby - -2005-10-07 09:54 thomas - - * TODO: [no log message] - -2005-09-06 21:19 thomas - - * lib/zip/zip.rb: [no log message] - - * NEWS: [no log message] - - * lib/zip/zip.rb, test/gentestfiles.rb, test/ziptest.rb: Fixed - problem on windows - tempfile has to be set to binmode again when - it is reopened - -2005-09-04 16:45 thomas - - * Rakefile: [no log message] - - * TODO: [no log message] - - * test/ziptest.rb: [no log message] - -2005-09-03 10:27 thomas - - * NEWS: [no log message] - - * TODO, lib/zip/zip.rb: [no log message] - - * lib/zip/ioextras.rb, lib/zip/zip.rb, test/ziptest.rb: Merged - patch from oss-ruby at technorama.net - - * test/ziptest.rb: Added failing test that shows that read and gets - don't mix currently - -2005-08-29 08:50 thomas - - * lib/zip/: ioextras.rb, zip.rb: [no log message] - - * NEWS, lib/zip/zip.rb: [no log message] - - * lib/zip/zip.rb: [no log message] - - * lib/zip/zip.rb: [no log message] - -2005-08-07 14:27 thomas - - * lib/zip/zip.rb, NEWS: [no log message] - -2005-08-06 11:12 thomas - - * lib/zip/: ioextras.rb, zip.rb: [no log message] - -2005-08-03 18:54 thomas - - * lib/zip/zip.rb: Read/write in chunks to preserve memory - -2005-07-02 15:08 thomas - - * lib/zip/zip.rb: Applied received patch concerning FreeBSD 4.5 - issue - -2005-04-03 16:52 thomas - - * samples/.cvsignore: [no log message] - - * samples/: qtzip.rb, zipdialogui.ui: Added a qt example - -2005-03-31 21:58 thomas - - * lib/zip/zip.rb, test/ziptest.rb: [no log message] - - * test/zipfilesystemtest.rb: [no log message] - -2005-03-17 18:17 thomas - - * Rakefile: [no log message] - - * NEWS, README, lib/zip/zip.rb: [no log message] - - * install.rb: Fixed install.rb - -2005-03-03 18:38 thomas - - * Rakefile: [no log message] - -2005-02-27 16:23 thomas - - * lib/zip/ziprequire.rb: Added documentation to ziprequire - - * README, TODO, lib/zip/ziprequire.rb: Added documentation to - ziprequire - - * Rakefile, test/ziptest.rb: [no log message] - -2005-02-19 21:30 thomas - - * lib/zip/ioextras.rb, lib/zip/stdrubyext.rb, - lib/zip/tempfile_bugfixed.rb, lib/zip/zip.rb, - lib/zip/ziprequire.rb, test/ioextrastest.rb, - test/stdrubyexttest.rb, test/zipfilesystemtest.rb, - test/ziprequiretest.rb, test/ziptest.rb: Added more rdoc and - changed the remaining tests to Test::Unit - - * lib/zip/: ioextras.rb, zip.rb: Added documentation to - ZipInputStream and ZipOutputStream - -2005-02-18 10:27 thomas - - * README: [no log message] - -2005-02-17 23:21 thomas - - * README, Rakefile: Added ppackage (publish package) task to - Rakefile - - * README, Rakefile, TODO: Added pdoc (publish doc) task to Rakefile - - * README, Rakefile, TODO, lib/zip/stdrubyext.rb, lib/zip/zip.rb, - lib/zip/zipfilesystem.rb: Added a bunch of documentation - - * test/ziptest.rb: [no log message] - -2005-02-16 20:04 thomas - - * NEWS, README, Rakefile: Improved documentation and added rdoc - task to Rakefile - - * NEWS, Rakefile, lib/zip/zip.rb: [no log message] - - * Rakefile, samples/example.rb, samples/example_filesystem.rb, - samples/gtkRubyzip.rb, samples/write_simple.rb, - samples/zipfind.rb, test/.cvsignore, test/gentestfiles.rb: - Improvements to Rakefile - -2005-02-15 23:35 thomas - - * NEWS, TODO: [no log message] - - * Rakefile, rubyzip.gemspec: Now uses Rake to build gem - - * Rakefile: [no log message] - - * lib/zip/zip.rb, test/.cvsignore, test/ziptest.rb, NEWS: Fixed - compatibility issue with ruby 1.8.2. Migrated test suite to - Test::Unit - - * NEWS, lib/zip/ioextras.rb, lib/zip/stdrubyext.rb, - lib/zip/tempfile_bugfixed.rb, lib/zip/zip.rb, - lib/zip/zipfilesystem.rb, lib/zip/ziprequire.rb, test/.cvsignore, - test/file1.txt, test/file1.txt.deflatedData, test/file2.txt, - test/gentestfiles.rb, test/ioextrastest.rb, - test/notzippedruby.rb, test/rubycode.zip, test/rubycode2.zip, - test/stdrubyexttest.rb, test/testDirectory.bin, - test/zipWithDirs.zip, test/zipfilesystemtest.rb, - test/ziprequiretest.rb, test/ziptest.rb, test/data/.cvsignore, - test/data/file1.txt, test/data/file1.txt.deflatedData, - test/data/file2.txt, test/data/notzippedruby.rb, - test/data/rubycode.zip, test/data/rubycode2.zip, - test/data/testDirectory.bin, test/data/zipWithDirs.zip: Changed - directory structure - -2005-02-13 22:44 thomas - - * Rakefile, TODO: [no log message] - - * rubyzip.gemspec: [no log message] - - * install.rb: Made install.rb independent of the current path - (fixes bug reported by Drew Robinson) - -2004-12-12 11:22 thomas - - * NEWS, TODO, samples/write_simple.rb: Fixed 'version needed to - extract'-field wrong in local headers - -2004-05-02 15:17 thomas - - * rubyzip.gemspec: Added gemspec contributed by Chad Fowler - -2004-04-02 07:25 thomas - - * NEWS: Fix for FreeBSD 4.9 - -2004-03-29 00:28 thomas - - * NEWS: [no log message] - -2004-03-28 17:59 thomas - - * NEWS: [no log message] - -2004-03-27 16:09 thomas - - * test/stdrubyexttest.rb: Patch for stdrubyext.rb from Nobu Nakada - - * test/: ioextrastest.rb, stdrubyexttest.rb: converted some files - to unix line-endings - -2004-03-25 16:34 thomas - - * NEWS, install.rb: Significantly reduced memory footprint when - modifying zip files - -2004-03-16 18:20 thomas - - * install.rb, test/alltests.rb, test/ioextrastest.rb, - test/stdrubyexttest.rb, test/ziptest.rb: IO utility classes moved - to new file ioextras.rb. Tests moved to new file ioextrastest.rb - -2004-02-27 13:21 thomas - - * NEWS: Optimization to avoid decompression and recompression - -2004-01-30 16:17 thomas - - * NEWS: [no log message] - - * README, test/zipfilesystemtest.rb, test/ziptest.rb: Applied - extra-field patch - -2003-12-13 16:57 thomas - - * TODO: [no log message] - -2003-12-10 00:25 thomas - - * test/ziptest.rb: (Temporary) fix to bug reported by Takashi Sano - -2003-08-23 09:42 thomas - - * test/ziptest.rb, NEWS: Fixed ZipFile.get_ouput_stream bug - data - was never written to zip - -2003-08-21 16:05 thomas - - * install.rb: [no log message] - - * alltests.rb, stdrubyexttest.rb, zipfilesystemtest.rb, - ziprequiretest.rb, ziptest.rb, test/alltests.rb, - test/stdrubyexttest.rb, test/zipfilesystemtest.rb, - test/ziprequiretest.rb, test/ziptest.rb: Moved all test ruby - files to test/ - - * NEWS, install.rb, stdrubyext.rb, stdrubyexttest.rb, zip.rb, - zipfilesystem.rb, zipfilesystemtest.rb, ziprequire.rb, - ziprequiretest.rb, ziptest.rb, samples/example.rb, - samples/example_filesystem.rb, samples/gtkRubyzip.rb, - samples/zipfind.rb: Moved all production source files to zip/ so - they are in the same dir as when they are installed - - * NEWS, TODO, alltests.rb: [no log message] - - * filearchive.rb, filearchivetest.rb, fileutils.rb: Removed - filearchive.rb, filearchivetest.rb and fileutils.rb - - * samples/.cvsignore, samples/example_filesystem.rb, zip.rb, - samples/example_filesystem.rb: Added - samples/example_filesystem.rb. Fixed Tempfile creation for - entries created with get_output_stream where entries were in a - subdirectory - - * zip.rb, ziptest.rb: Fixed mkdir bug. ZipFile.mkdir didn't work if - the zipfile doesn't exist already - - * ziptest.rb: [no log message] - - * TODO, zipfilesystemtest.rb: Globbing test placeholder commented - out - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented ZipFsDir.new - and open - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented DirFsIterator - and tests - -2003-08-20 22:50 thomas - - * NEWS, TODO: [no log message] - - * zipfilesystemtest.rb: [no log message] - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsDir.foreach, ZipFsDir.entries now reimplemented in terms of - it - - * README: [no log message] - - * zipfilesystem.rb, zipfilesystemtest.rb: [no log message] - - * zipfilesystem.rb: All access from ZipFsFile and ZipFsDir to - ZipFile is now routed through ZipFileNameMapper which has the - single responsibility of mapping entry/filenames - - * alltests.rb, stdrubyext.rb, stdrubyexttest.rb: Added - stdrubyexttest.rb and added test test_select_map - - * zipfilesystem.rb: ZipFsDir was in the wrong module. ZipFileSystem - now has a ctor that creates ZipFsDir and ZipFsFile instances, - instead of creating them lazily. It then passes the dir instance - to the file instance and vice versa - - * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: ZipFsFile.open - honours chdir - - * stdrubyext.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb, - ziptest.rb: Fixed ZipEntry::parent_as_string. Implemented - ZipFsDir.chdir, pwd and entries including test - -2003-08-19 15:44 thomas - - * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsDir.mkdir - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsDir.delete (and aliases rmdir and unlink) - - * zipfilesystem.rb, zipfilesystemtest.rb: Another dummy - implementation and commented out a test for select() which can be - added later - -2003-08-18 20:40 thomas - - * ziptest.rb: Honoured 1.8.0 Object.to_a deprecation warning - - * zip.rb, ziptest.rb, samples/example.rb, samples/zipfind.rb: - Converted a few more names to ruby underscore style that I missed - with the automated processing the first time around - - * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb, ziptest.rb: - Implemented Zip::ZipFile.get_output_stream - -2003-08-17 18:28 thomas - - * README, install.rb, stdrubyext.rb, zipfilesystem.rb, - zipfilesystemtest.rb: Updated README with Documentation section. - Updated install.rb. Fixed three tests that failed on 1.8.0. - -2003-08-14 05:40 thomas - - * zipfilesystem.rb, zipfilesystemtest.rb: Added empty - implementations of atime and ctime - -2003-08-13 17:08 thomas - - * simpledist.rb: Moved simpledist to a separate repository called - 'misc' - - * NEWS: [no log message] - - * stdrubyext.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb, - ziprequire.rb, ziprequiretest.rb, ziptest.rb, samples/example.rb, - samples/gtkRubyzip.rb, samples/zipfind.rb: Changed all method - names to the ruby convention underscore style - - * alltests.rb, zipfilesystem.rb, zipfilesystemtest.rb: Implemented - a lot more of the stat methods. Mostly with dummy implementations - that return values that indicate that these features aren't - supported - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented more methods - and tests in zipfilesystem. Mostly empty methods as permissions - and file types other than files and directories are not supported - - * install.rb, stdrubyext.rb, zip.rb, zipfilesystem.rb, - zipfilesystemtest.rb: Addd file stdrubyext.rb and moved the - modifications to std ruby classes to it. Refactored the ZipFsStat - tests and ZipFsStat. Added Module.forwardMessages and used it to - implement the forwarding of calls in ZipFsStat - - * zipfilesystem.rb, zipfilesystemtest.rb: Added - Zip::ZipFsFile::ZipFsStat and started implementing it and its - methods - - * zipfilesystem.rb, zipfilesystemtest.rb, ziptest.rb: Updated and - added missing copyright notices - - * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: zipfilesystem.rb - is becoming big and not everyone will want to use that code. - Therefore zip.rb no longer requires it. Instead you must require - zipfilesystem.rb itself if you want to use it - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented dummy - permission test methods - - * TODO, zip.rb, ziptest.rb: Merged from patch from Kristoffer - Lunden. Fixed more 1.8.0 incompatibilites - tests run on 1.8.0 - now - -2003-08-12 19:18 thomas - - * zip.rb: Get rid of 1.8.0 warning - - * ziptest.rb: ruby 1.8.0 compatibility fix - - * NEWS, zip.rb: ruby-zlib 0.6.0 compatibility fix - -2002-12-22 20:12 thomas - - * zip.rb: [no log message] - -2002-09-16 22:11 thomas - - * NEWS: [no log message] - -2002-09-15 17:16 thomas - - * samples/zipfind.rb: [no log message] - - * samples/zipfind.rb: [no log message] - -2002-09-14 22:59 thomas - - * samples/zipfind.rb: Added simple zipfind script - -2002-09-13 23:53 thomas - - * TODO: Added TODO about openmode for zip entries binary/ascii - - * NEWS: ziptest now runs without errors with ruby-1.7.2-4 (Andy's - latest build) - - * zip.rb, ziprequiretest.rb, ziptest.rb: ziptest now runs without - errors with ruby-1.7.2-4 (Andy's latest build) - -2002-09-12 00:20 thomas - - * zipfilesystemtest.rb: Improved ZipFsFile.delete/unlink test - - * test/.cvsignore: [no log message] - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.delete/unlink - -2002-09-11 22:22 thomas - - * alltests.rb: [no log message] - - * NEWS, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: Fixed - AbstractInputStream.each_line ignored its aSeparator argument. - Implemented more ZipFsFile methods - - * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: ZipFileSystem is - now a module instead of a class, and is mixed into ZipFile, - instead of being made available as a property fileSystem - -2002-09-10 23:45 thomas - - * NEWS: Updated NEWS file - - * zip.rb: [no log message] - - * NEWS, zip.rb, ziptest.rb: Fix bug: rewind should reset lineno. - Fix bug: Deflater.read uses separate buffer from produceInput - (feeding gets/readline etc) - -2002-09-09 23:48 thomas - - * .cvsignore: [no log message] - -2002-09-09 22:55 uid26649 - - * zip.rb, ziptest.rb: Implemented ZipInputStream.rewind and - AbstractInputStream.lineno. Tests for both - -2002-09-09 20:31 thomas - - * zip.rb, ziptest.rb: ZipInputStream and ZipOutstream (thru their - AbstractInputStream and AbstractOutputStream now lie about being - kind_of?(IO) - -2002-09-08 16:38 thomas - - * zipfilesystemtest.rb: [no log message] - - * filearchive.rb, filearchivetest.rb, zip.rb, ziptest.rb: Moved - String additions from filearchive.rb to zip.rb (and moved tests - along too to ziptest.rb). Added ZipEntry.parentAsString and - ZipEntrySet.parent - - * ziptest.rb: Implemented ZipEntrySetTest.testDup and testCompound - - * TODO, zip.rb, ziptest.rb: Replaced Array with EntrySet for - keeping entries in a zip file. Tagged repository before this - commit, so this change can be rolled back, if it stinks - -2002-09-07 20:21 thomas - - * zip.rb, ziptest.rb: Implemented ZipEntry.<=> - - * ziptest.rb: Removed unused code - -2002-08-11 15:14 thomas - - * zip.rb, ziptest.rb: Made some changes to accomodate ruby 1.7.2 - -2002-07-27 15:25 thomas - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented ZipFsFile.new - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.pipe - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.link - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.symlink - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.readlink, wrapped ZipFileSystem class in Zip module - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.zero? - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented test for - ZipFsFile.directory? - -2002-07-26 23:56 thomas - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.socket? - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.join - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.ftype - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.blockdev? - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.size? (slightly different from size) - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.split - - * zipfilesystem.rb, zipfilesystemtest.rb: Implemented - ZipFsFile.symlink? - - * alltests.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: - Implemented ZipFsFile.mtime - - * zipfilesystem.rb, zipfilesystemtest.rb: Implement ZipFsFile.file? - - * zip.rb, ziptest.rb: Implemented ZipEntry.file? - - * alltests.rb, filearchive.rb, filearchivetest.rb, zip.rb, - zipfilesystem.rb, zipfilesystemtest.rb, ziprequire.rb, - ziptest.rb: Implemented ZipFileSystem::ZipFsFile.size - - * zipfilesystem.rb, zipfilesystemtest.rb: [no log message] - - * test/zipWithDirs.zip: Changed zipWithDirs.zip so all the entries - in it have unix file endings - - * alltests.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: - Started implementing ZipFileSystem - - * test/zipWithDirs.zip: Added a zip file for testing with a - directory structure - -2002-07-22 21:40 thomas - - * TODO: [no log message] - - * TODO: [no log message] - -2002-07-21 18:20 thomas - - * NEWS: [no log message] - - * TODO: Updated TODO with a refactoring idea for FileArchive - - * filearchive.rb, filearchivetest.rb: Added some FileArchiveAdd - tests and cleaned up some of the FileArchive tests. extract and - add now have individual test fixtures. - - * filearchive.rb, filearchivetest.rb: Added tests for extract - called with regex src arg and Enumerable src arg - - * filearchivetest.rb: Added test for continueOnExistsProc when - extracting from a file archive - -2002-07-20 17:13 thomas - - * TODO, filearchivetest.rb, fileutils.rb, ziptest.rb, - test/.cvsignore: Added (failing) tests for FileArchive.add, added - code for creating test files for FileArchive.add tests. Added - fileutils.rb, which is borrowed from ruby 1.7.2 - - * filearchive.rb, filearchivetest.rb: [no log message] - - * filearchivetest.rb: Added tests for String extensions - - * alltests.rb, ziprequiretest.rb, ziptest.rb: [no log message] - - * install.rb: [no log message] - - * TODO: Updated TODO - - * filearchive.rb, filearchivetest.rb: All FileArchive.extract tests - run - -2002-07-19 23:11 thomas - - * filearchive.rb, filearchivetest.rb: [no log message] - - * filearchivetest.rb: [no log message] - - * filearchive.rb, filearchivetest.rb: [no log message] - - * filearchive.rb, filearchivetest.rb, zip.rb: [no log message] - -2002-07-08 13:41 thomas - - * TODO: [no log message] - -2002-06-11 19:47 thomas - - * filearchive.rb, filearchivetest.rb, zip.rb, ziptest.rb: [no log - message] - -2002-05-25 00:41 thomas - - * simpledist.rb: Added hackish script for creating dist files - -2002-04-30 21:22 thomas - - * TODO: [no log message] - - * filearchive.rb, filearchivetest.rb: [no log message] - - * filearchive.rb, filearchivetest.rb: Improved testing and wrote - some of the skeleton of extract. Still to do: Fix glob, so it - returns a hashmap instead of a list. The map will need to map the - full entry name to the last part of the name (which is only - really interesting for recursively extracted entries, otherwise - it is just the name). Glob.expandPathList should also output - directories with a trailing slash, which is doesn't right now. - - * filearchive.rb, filearchivetest.rb: Implemented the first few - tests for FileArchive - -2002-04-24 22:06 thomas - - * ziprequire.rb, ziprequiretest.rb: Appended copyright message to - ziprequire.rb and ziprequiretest.rb - - * zip.rb: Made ZipEntry tolerate invalid dates - -2002-04-21 00:57 thomas - - * NEWS, TODO, zip.rb, ziptest.rb: Read and write entry modification - date/time correctly - -2002-04-20 02:44 thomas - - * ziprequiretest.rb, test/rubycode2.zip: improved ZipRequireTest - - * ziprequire.rb: Made a warning go away - - * ziprequire.rb, ziprequiretest.rb, test/notzippedruby.rb, - test/rubycode.zip: Fixed a bug in ziprequire. Added - ziprequiretest.rb and test data files - -2002-04-19 22:43 thomas - - * zip.rb, ziptest.rb: Added recursion support to Glob module - -2002-04-18 21:37 thomas - - * NEWS, TODO, zip.rb, ziptest.rb: Added Glob module and GlobTest - unit test suite. This module provides the functionality to expand - a 'glob pattern' given a list of files - Next step is to use this - module in ZipFile - -2002-04-01 22:55 thomas - - * NEWS: [no log message] - - * TODO, zip.rb, ziprequire.rb: Added ziprequire.rb which contains a - proof-of-concept implementation of a require implementation that - can load ruby modules from a zip file. Needs unit tests and - polish. - -2002-03-31 01:13 thomas - - * README: [no log message] - -2002-03-30 16:14 thomas - - * TODO: [no log message] - - * .cvsignore, README, zip.rb: Added rdoc markup (only #:nodoc:all - modifiers) to zip.rb. Made README 'RDoc compliant' - -2002-03-29 23:29 thomas - - * TODO: [no log message] - - * example.rb, samples/.cvsignore, samples/example.rb, - samples/gtkRubyzip.rb: Moved example.rb to samples/. Added - another sample gtkRubyzip.rb - - * NEWS, TODO, TODO: [no log message] - - * .cvsignore, file1.txt, file1.txt.deflatedData, testDirectory.bin, - ziptest.rb, test/.cvsignore, test/file1.txt, - test/file1.txt.deflatedData, test/file2.txt, - test/testDirectory.bin: Added test/ directory and moved the - manually created test data files into it. Changed ziptest.rb so - it runs in test/ directory - - * TODO: [no log message] - - * NEWS, zip.rb, ziptest.rb: Don't decompress and recompress zip - entries when changing zip file - - * zip.rb: Performance optimization: Only write new ZipFile, if it - has been changed. The test suite runs in half the time now. - -2002-03-28 22:12 thomas - - * TODO: [no log message] - -2002-03-23 17:31 thomas - - * TODO: [no log message] - -2002-03-22 22:47 thomas - - * NEWS: [no log message] - - * NEWS, TODO: [no log message] - - * ziptest.rb: Found the tests that didn't use blocks to make sure - input streams are closed as soon as they arent used anymore and - got rid of the GC.start - - * ziptest.rb: All tests run on windows ruby 1.6.6 - - * zip.rb, ziptest.rb: Windows fixes: Fixed ZipFile.initialize which - needed to open zipfile file in binary mode. Added another - workaround for the return value from File.open(name) where name - is the name of a directory - ruby returns different exceptions in - linux, win/cygwin and windows. A number of tests failed because - in windows you cant delete a file that is open. Fixed by changing - ziptest.rb to use ZipInputStream.getInputStream with blocks a few - places. There is a hack in CommanZipFileFixture.setup where the - GC is explicitly invoked. Should be fixed with blocks instead. - The only currently failing test fails because the test data - creation fails to add a comment to 4entry.zip, because echo eats - the remainder of the line including the pipe character and the - following zip -z 4 entry.zip command - -2002-03-21 22:18 thomas - - * NEWS: [no log message] - - * NEWS, README, TODO, install.rb: Added install.rb - - * ziptest.rb: [no log message] - - * NEWS, TODO: [no log message] - - * .cvsignore, TODO, zip.rb, ziptest.rb: Added - test_extractDirectoryExistsAsFileOverwrite and fixed to pass - - * zip.rb, ziptest.rb: Extraction of directory entries is now - supported - -2002-03-20 21:59 thomas - - * NEWS: [no log message] - - * COPYING, README, README.txt: Removed COPYING, renamed README.txt - to README. Updated README - - * example.rb: Fixed example.rb added example that shows zip file - manipulation with Zip::ZipFile - - * .cvsignore: [no log message] - - * TODO, zip.rb, ziptest.rb: Directories can now be added (not - recursively, the directory entry itself. Directories are - recognized by a empty entries with a trailing /. The purpose of - storing them explicitly in the zip file is to be able to store - permission and ownership information - - * TODO, zip.rb, ziptest.rb: zip.rb depended on ftools but it was - only included in ziptest.rb - - * zip.rb, ziptest.rb: ZipError is now a subclass of StandardError - instead of RuntimeError. ZipError now has several subclasses. - -2002-03-19 22:26 thomas - - * TODO: [no log message] - - * TODO, ziptest.rb: Unit test ZipFile.getInputStream with block - - * TODO, zip.rb, ziptest.rb: Unit test for adding new entry with - name that already exists in archive, and fixed to pass test - - * TODO, zip.rb, ziptest.rb: Added unit tests for rename to existing - entry - - * TODO: [no log message] - - * TODO, zip.rb, ziptest.rb: Unit test calling ZipFile.extract with - block - -2002-03-18 21:06 thomas - - * TODO: [no log message] - - * zip.rb, ziptest.rb: ZipFile#commit now reinitializes ZipFile. - - * TODO, zip.rb, ziptest.rb: Refactoring: - - Collapsed ZipEntry and ZipStreamableZipEntry into ZipEntry. - - Collapsed BasicZipFile and ZipFile into ZipFile. - - * zip.rb: Removed method that was never called - -2002-03-17 22:33 thomas - - * TODO: [no log message] - - * ziptest.rb: Run tests with =true as default - - * NEWS, TODO, zip.rb, ziptest.rb: Now runs with -w switch without - warnings - - * .cvsignore: [no log message] - - * zip.rb, ziptest.rb: Down to one failing test - - * zip.rb, ziptest.rb: [no log message] - - * TODO, zip.rb, ziptest.rb: [no log message] - -2002-02-25 19:42 thomas - - * TODO: Added more todos - -2002-02-23 15:51 thomas - - * zip.rb: [no log message] - - * zip.rb, ziptest.rb: [no log message] - - * zip.rb, ziptest.rb: [no log message] - -2002-02-03 18:47 thomas - - * ziptest.rb: [no log message] - -2002-02-02 15:58 thomas - - * example.rb, zip.rb, ziptest.rb: [no log message] - - * .cvsignore: [no log message] - - * example.rb, zip.rb, ziptest.rb: Renamed SimpleZipFile to - BasicZipFile - - * TODO: [no log message] - - * ziptest.rb: More test cases - all of them failing, so now there - are 18 failing test cases. Three more test cases to implement, - then it is time for the production code - -2002-02-01 21:49 thomas - - * ziptest.rb: [no log message] - - * ziptest.rb: Also run SimpleZipFile tests for ZipFile. - - * example.rb, zip.rb, ziptest.rb: ZipFile renamed to SimpleZipFile. - The new ZipFile will have many more methods that are useful for - managing archives. - -2002-01-29 20:30 thomas - - * TODO: [no log message] - -2002-01-26 00:18 thomas - - * NEWS: [no log message] - - * ziptest.rb: In unit test: work around ruby/cygwin weirdness. You - get an Errno::EEXISTS instead of an Errno::EISDIR if you try to - open a file for writing that is a directory. - - * ziptest.rb: Fixed test that failed on windows because of CRLF - line ending - -2002-01-25 23:58 thomas - - * ziptest.rb: [no log message] - - * .cvsignore, example.rb, zip.rb: Fixed bug reading from empty - deflated entry in zip file - - * .cvsignore: [no log message] - - * ziptest.rb: [no log message] - - * NEWS, README.txt, zip.rb, ziptest.rb: Zip write support is now - fully functional in the form of ZipOutputStream. - - * zip.rb, ziptest.rb: [no log message] - - * zip.rb, ziptest.rb: [no log message] - -2002-01-20 16:00 thomas - - * zip.rb, ziptest.rb: Added Deflater and DeflaterTest. - - * .cvsignore: [no log message] - - * .cvsignore: Added .cvsignore file - - * zip.rb, ziptest.rb: Added ZipEntry.writeCDirEntry and misc minor - fixes - -2002-01-19 23:28 thomas - - * example.rb, zip.rb, ziptest.rb: NOTICE: Not all tests run!! - - ZipOutputStream in progress - - Wrapped rubyzip in namespace module Zip. - -2002-01-17 18:52 thomas - - * ziptest.rb: Fail nicely if the user doesn't have info-zip - compatible zip in the path - -2002-01-10 18:02 thomas - - * zip.rb: Adjusted chunk size to 32k after a few perf measurements - -2002-01-09 22:10 thomas - - * README.txt: License now same as rubys, not just GPL - -2002-01-06 00:19 thomas - - * README.txt: [no log message] - -2002-01-05 23:09 thomas - - * NEWS, README.txt, NEWS: Updated NEWS file - - * README.txt, zip.rb, ziptest.rb, zlib.c.diff: Added tests for - decompressors and a tests for ZipLocalEntry, - ZipCentralDirectoryEntry and ZipCentralDirectory for handling of - corrupt data - - * file1.txt.deflatedData: deflated data extracted from a zip file. - contains file1.txt - - * zip.rb: Changed references to Inflate to Zlib::inflate for - compatibility with ruby-zlib-0.5 - - * README.txt, zip.rb, ziptest.rb: [no log message] - - * example.rb, NEWS: [no log message] - - * COPYING, README.txt: [no log message] - - * ziptest.rb: Fixed problem with test file creation - - * README.txt: Updated README.txt - - * zip.rb, ziptest.rb: ZipFile now works - -2002-01-04 21:51 thomas - - * testDirectory.bin, zip.rb, ziptest.rb: - ZipCentralDirectoryEntryTest now runs - - * ziptest.rb: Changed - ZIpLocalNEtryTest::test_ReadLocalEntryHeaderOfFirstTestZipEntry - so it works on both unix too. It only worked on windows because - the test made assumptions about the compressed size and crc of an - entry, but that differs depending on the OS because of the CRLF - thing. - - * README.txt: Added note about zlib.c patch - -2002-01-02 18:48 thomas - - * README.txt, example.rb, file1.txt, zip.rb, ziptest.rb, - zlib.c.diff: initial - - * README.txt, example.rb, file1.txt, zip.rb, ziptest.rb, - zlib.c.diff: Initial revision - diff --git a/lib/zip/NEWS b/lib/zip/NEWS deleted file mode 100644 index a72956fd69..0000000000 --- a/lib/zip/NEWS +++ /dev/null @@ -1,162 +0,0 @@ -= Version 0.9.4 - -Changed ZipOutputStream.put_next_entry signature (API CHANGE!). Now -allows comment, extra field and compression method to be specified. - -= Version 0.9.3 - -Fixed: Added ZipEntry::name_encoding which retrieves the character -encoding of the name and comment of the entry. Also added convenience -methods ZipEntry::name_in(enc) and ZipEntry::comment_in(enc) for -getting zip entry names and comments in a specified character -encoding. - -= Version 0.9.2 - -Fixed: Renaming an entry failed if the entry's new name was a -different length than its old name. (Diego Barros) - -= Version 0.9.1 - -Added symlink support and support for unix file permissions. Reduced -memory usage during decompression. - -New methods ZipFile::[follow_symlinks, restore_times, restore_permissions, restore_ownership]. -New methods ZipEntry::unix_perms, ZipInputStream::eof?. -Added documentation and test for new ZipFile::extract. -Added some of the API suggestions from sf.net #1281314. -Applied patch for sf.net bug #1446926. -Applied patch for sf.net bug #1459902. -Rework ZipEntry and delegate classes. - -= Version 0.5.12 - -Fixed problem with writing binary content to a ZipFile in MS Windows. - -= Version 0.5.11 - -Fixed name clash file method copy_stream from fileutils.rb. Fixed -problem with references to constant CHUNK_SIZE. -ZipInputStream/AbstractInputStream read is now buffered like ruby IO's -read method, which means that read and gets etc can be mixed. The -unbuffered read method has been renamed to sysread. - -= Version 0.5.10 - -Fixed method name resolution problem with FileUtils::copy_stream and -IOExtras::copy_stream. - -= Version 0.5.9 - -Fixed serious memory consumption issue - -= Version 0.5.8 - -Fixed install script. - -= Version 0.5.7 - -install.rb no longer assumes it is being run from the toplevel source -dir. Directory structure changed to reflect common ruby library -project structure. Migrated from RubyUnit to Test::Unit format. Now -uses Rake to build source packages and gems and run unit tests. - -= Version 0.5.6 - -Fix for FreeBSD 4.9 which returns Errno::EFBIG instead of -Errno::EINVAL for some invalid seeks. Fixed 'version needed to -extract'-field incorrect in local headers. - -= Version 0.5.5 - -Fix for a problem with writing zip files that concerns only ruby 1.8.1. - -= Version 0.5.4 - -Significantly reduced memory footprint when modifying zip files. - -= Version 0.5.3 - -Added optimization to avoid decompressing and recompressing individual -entries when modifying a zip archive. - -= Version 0.5.2 - -Fixed ZipFile corruption bug in ZipFile class. Added basic unix -extra-field support. - -= Version 0.5.1 - -Fixed ZipFile.get_output_stream bug. - -= Version 0.5.0 - -List of changes: -* Ruby 1.8.0 and ruby-zlib 0.6.0 compatibility -* Changed method names from camelCase to rubys underscore style. -* Installs to zip/ subdir instead of directly to site_ruby -* Added ZipFile.directory and ZipFile.file - each method return an -object that can be used like Dir and File only for the contents of the -zip file. -* Added sample application zipfind which works like Find.find, only -Zip::ZipFind.find traverses into zip archives too. - -Bug fixes: -* AbstractInputStream.each_line with non-default separator - - -= Version 0.5.0a - -Source reorganized. Added ziprequire, which can be used to load ruby -modules from a zip file, in a fashion similar to jar files in -Java. Added gtkRubyzip, another sample application. Implemented -ZipInputStream.lineno and ZipInputStream.rewind - -Bug fixes: - -* Read and write date and time information correctly for zip entries. -* Fixed read() using separate buffer, causing mix of gets/readline/read to -cause problems. - -= Version 0.4.2 - -Performance optimizations. Test suite runs in half the time. - -= Version 0.4.1 - -Windows compatibility fixes. - -= Version 0.4.0 - -Zip::ZipFile is now mutable and provides a more convenient way of -modifying zip archives than Zip::ZipOutputStream. Operations for -adding, extracting, renaming, replacing and removing entries to zip -archives are now available. - -Runs without warnings with -w switch. - -Install script install.rb added. - - -= Version 0.3.1 - -Rudimentary support for writing zip archives. - - -= Version 0.2.2 - -Fixed and extended unit test suite. Updated to work with ruby/zlib -0.5. It doesn't work with earlier versions of ruby/zlib. - - -= Version 0.2.0 - -Class ZipFile added. Where ZipInputStream is used to read the -individual entries in a zip file, ZipFile reads the central directory -in the zip archive, so you can get to any entry in the zip archive -without having to skipping through all the preceeding entries. - - -= Version 0.1.0 - -First working version of ZipInputStream. diff --git a/lib/zip/README b/lib/zip/README deleted file mode 100644 index 79546e0b34..0000000000 --- a/lib/zip/README +++ /dev/null @@ -1,72 +0,0 @@ -= rubyzip - -rubyzip is a ruby library for reading and writing zip files. - -= Install - -If you have rubygems you can install rubyzip directly from the gem -repository - - gem install rubyzip - -Otherwise obtain the source (see below) and run - - ruby install.rb - -To run the unit tests you need to have test::unit installed - - rake test - - -= Documentation - -There is more than one way to access or create a zip archive with -rubyzip. The basic API is modeled after the classes in -java.util.zip from the Java SDK. This means there are classes such -as Zip::ZipInputStream, Zip::ZipOutputStream and -Zip::ZipFile. Zip::ZipInputStream provides a basic interface for -iterating through the entries in a zip archive and reading from the -entries in the same way as from a regular File or IO -object. ZipOutputStream is the corresponding basic output -facility. Zip::ZipFile provides a mean for accessing the archives -central directory and provides means for accessing any entry without -having to iterate through the archive. Unlike Java's -java.util.zip.ZipFile rubyzip's Zip::ZipFile is mutable, which means -it can be used to change zip files as well. - -Another way to access a zip archive with rubyzip is to use rubyzip's -Zip::ZipFileSystem API. Using this API files can be read from and -written to the archive in much the same manner as ruby's builtin -classes allows files to be read from and written to the file system. - -rubyzip also features the -zip/ziprequire.rb[link:files/lib/zip/ziprequire_rb.html] module which -allows ruby to load ruby modules from zip archives. - -For details about the specific behaviour of classes and methods refer -to the test suite. Finally you can generate the rdoc documentation or -visit http://rubyzip.sourceforge.net. - -= License - -rubyzip is distributed under the same license as ruby. See -http://www.ruby-lang.org/en/LICENSE.txt - - -= Website and Project Home - -http://rubyzip.sourceforge.net - -http://sourceforge.net/projects/rubyzip - -== Download (tarballs and gems) - -http://sourceforge.net/project/showfiles.php?group_id=43107&package_id=35377 - -= Authors - -Thomas Sondergaard (thomas at sondergaard.cc) - -Technorama Ltd. (oss-ruby-zip at technorama.net) - -extra-field support contributed by Tatsuki Sugiura (sugi at nemui.org) \ No newline at end of file diff --git a/lib/zip/TODO b/lib/zip/TODO deleted file mode 100644 index e24cde5779..0000000000 --- a/lib/zip/TODO +++ /dev/null @@ -1,16 +0,0 @@ - -* ZipInputStream: Support zip-files with trailing data descriptors -* Adjust rdoc stylesheet to advertise inherited methods if possible -* Suggestion: Add ZipFile/ZipInputStream example that demonstrates extracting all entries. -* Suggestion: ZipFile#extract destination should default to "." -* Suggestion: ZipEntry should have extract(), get_input_stream() methods etc -* SUggestion: ZipInputStream/ZipOutputStream should accept an IO object in addition to a filename. -* (is buffering used anywhere with write?) -* Inflater.sysread should pass the buffer to produce_input. -* Implement ZipFsDir.glob -* ZipFile.checkIntegrity method -* non-MSDOS permission attributes -** See mail from Ned Konz to ruby-talk subj. "Re: SV: [ANN] Archive 0.2" -* Packager version, required unpacker version in zip headers -** See mail from Ned Konz to ruby-talk subj. "Re: SV: [ANN] Archive 0.2" -* implement storing attributes and ownership information diff --git a/lib/zip/ioextras.rb b/lib/zip/ioextras.rb deleted file mode 100644 index c611535791..0000000000 --- a/lib/zip/ioextras.rb +++ /dev/null @@ -1,165 +0,0 @@ -module IOExtras #:nodoc: - - CHUNK_SIZE = 131072 - - RANGE_ALL = 0..-1 - - def self.copy_stream(ostream, istream) - s = '' - ostream.write(istream.read(CHUNK_SIZE, s)) until istream.eof? - end - - def self.copy_stream_n(ostream, istream, nbytes) - s = '' - toread = nbytes - while (toread > 0 && ! istream.eof?) - tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread - ostream.write(istream.read(tr, s)) - toread -= tr - end - end - - - # Implements kind_of? in order to pretend to be an IO object - module FakeIO - def kind_of?(object) - object == IO || super - end - end - - # Implements many of the convenience methods of IO - # such as gets, getc, readline and readlines - # depends on: input_finished?, produce_input and read - module AbstractInputStream - include Enumerable - include FakeIO - - def initialize - super - @lineno = 0 - @outputBuffer = "" - end - - attr_accessor :lineno - - def read(numberOfBytes = nil, buf = nil) - tbuf = nil - - if @outputBuffer.length > 0 - if numberOfBytes <= @outputBuffer.length - tbuf = @outputBuffer.slice!(0, numberOfBytes) - else - numberOfBytes -= @outputBuffer.length if (numberOfBytes) - rbuf = sysread(numberOfBytes, buf) - tbuf = @outputBuffer - tbuf << rbuf if (rbuf) - @outputBuffer = "" - end - else - tbuf = sysread(numberOfBytes, buf) - end - - return nil unless (tbuf) - - if buf - buf.replace(tbuf) - else - buf = tbuf - end - - buf - end - - def readlines(aSepString = $/) - retVal = [] - each_line(aSepString) { |line| retVal << line } - return retVal - end - - def gets(aSepString=$/) - @lineno = @lineno.next - return read if aSepString == nil - aSepString="#{$/}#{$/}" if aSepString == "" - - bufferIndex=0 - while ((matchIndex = @outputBuffer.index(aSepString, bufferIndex)) == nil) - bufferIndex=@outputBuffer.length - if input_finished? - return @outputBuffer.empty? ? nil : flush - end - @outputBuffer << produce_input - end - sepIndex=matchIndex + aSepString.length - return @outputBuffer.slice!(0...sepIndex) - end - - def flush - retVal=@outputBuffer - @outputBuffer="" - return retVal - end - - def readline(aSepString = $/) - retVal = gets(aSepString) - raise EOFError if retVal == nil - return retVal - end - - def each_line(aSepString = $/) - while true - yield readline(aSepString) - end - rescue EOFError - end - - alias_method :each, :each_line - end - - - # Implements many of the output convenience methods of IO. - # relies on << - module AbstractOutputStream - include FakeIO - - def write(data) - self << data - data.to_s.length - end - - - def print(*params) - self << params.join << $\.to_s - end - - def printf(aFormatString, *params) - self << sprintf(aFormatString, *params) - end - - def putc(anObject) - self << case anObject - when Fixnum then anObject.chr - when String then anObject - else raise TypeError, "putc: Only Fixnum and String supported" - end - anObject - end - - def puts(*params) - params << "\n" if params.empty? - params.flatten.each { - |element| - val = element.to_s - self << val - self << "\n" unless val[-1,1] == "\n" - } - end - - end - -end # IOExtras namespace module - - - -# Copyright (C) 2002-2004 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/samples/example.rb b/lib/zip/samples/example.rb deleted file mode 100755 index 741afa765e..0000000000 --- a/lib/zip/samples/example.rb +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env ruby - -$: << "../lib" -system("zip example.zip example.rb gtkRubyzip.rb") - -require 'zip/zip' - -####### Using ZipInputStream alone: ####### - -Zip::ZipInputStream.open("example.zip") { - |zis| - entry = zis.get_next_entry - print "First line of '#{entry.name} (#{entry.size} bytes): " - puts "'#{zis.gets.chomp}'" - entry = zis.get_next_entry - print "First line of '#{entry.name} (#{entry.size} bytes): " - puts "'#{zis.gets.chomp}'" -} - - -####### Using ZipFile to read the directory of a zip file: ####### - -zf = Zip::ZipFile.new("example.zip") -zf.each_with_index { - |entry, index| - - puts "entry #{index} is #{entry.name}, size = #{entry.size}, compressed size = #{entry.compressed_size}" - # use zf.get_input_stream(entry) to get a ZipInputStream for the entry - # entry can be the ZipEntry object or any object which has a to_s method that - # returns the name of the entry. -} - - -####### Using ZipOutputStream to write a zip file: ####### - -Zip::ZipOutputStream.open("exampleout.zip") { - |zos| - zos.put_next_entry("the first little entry") - zos.puts "Hello hello hello hello hello hello hello hello hello" - - zos.put_next_entry("the second little entry") - zos.puts "Hello again" - - # Use rubyzip or your zip client of choice to verify - # the contents of exampleout.zip -} - -####### Using ZipFile to change a zip file: ####### - -Zip::ZipFile.open("exampleout.zip") { - |zf| - zf.add("thisFile.rb", "example.rb") - zf.rename("thisFile.rb", "ILikeThisName.rb") - zf.add("Again", "example.rb") -} - -# Lets check -Zip::ZipFile.open("exampleout.zip") { - |zf| - puts "Changed zip file contains: #{zf.entries.join(', ')}" - zf.remove("Again") - puts "Without 'Again': #{zf.entries.join(', ')}" -} - -# For other examples, look at zip.rb and ziptest.rb - -# Copyright (C) 2002 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/samples/example_filesystem.rb b/lib/zip/samples/example_filesystem.rb deleted file mode 100755 index 0cacbd2aa2..0000000000 --- a/lib/zip/samples/example_filesystem.rb +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env ruby - -$: << "../lib" - -require 'zip/zipfilesystem' - -EXAMPLE_ZIP = "filesystem.zip" - -File.delete(EXAMPLE_ZIP) if File.exists?(EXAMPLE_ZIP) - -Zip::ZipFile.open(EXAMPLE_ZIP, Zip::ZipFile::CREATE) { - |zf| - zf.file.open("file1.txt", "w") { |os| os.write "first file1.txt" } - zf.dir.mkdir("dir1") - zf.dir.chdir("dir1") - zf.file.open("file1.txt", "w") { |os| os.write "second file1.txt" } - puts zf.file.read("file1.txt") - puts zf.file.read("../file1.txt") - zf.dir.chdir("..") - zf.file.open("file2.txt", "w") { |os| os.write "first file2.txt" } - puts "Entries: #{zf.entries.join(', ')}" -} - -Zip::ZipFile.open(EXAMPLE_ZIP) { - |zf| - puts "Entries from reloaded zip: #{zf.entries.join(', ')}" -} - -# For other examples, look at zip.rb and ziptest.rb - -# Copyright (C) 2003 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/samples/gtkRubyzip.rb b/lib/zip/samples/gtkRubyzip.rb deleted file mode 100755 index 0b63485d5b..0000000000 --- a/lib/zip/samples/gtkRubyzip.rb +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env ruby - -$: << "../lib" - -$VERBOSE = true - -require 'gtk' -require 'zip/zip' - -class MainApp < Gtk::Window - def initialize - super() - set_usize(400, 256) - set_title("rubyzip") - signal_connect(Gtk::Window::SIGNAL_DESTROY) { Gtk.main_quit } - - box = Gtk::VBox.new(false, 0) - add(box) - - @zipfile = nil - @buttonPanel = ButtonPanel.new - @buttonPanel.openButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) { - show_file_selector - } - @buttonPanel.extractButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) { - puts "Not implemented!" - } - box.pack_start(@buttonPanel, false, false, 0) - - sw = Gtk::ScrolledWindow.new - sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC) - box.pack_start(sw, true, true, 0) - - @clist = Gtk::CList.new(["Name", "Size", "Compression"]) - @clist.set_selection_mode(Gtk::SELECTION_BROWSE) - @clist.set_column_width(0, 120) - @clist.set_column_width(1, 120) - @clist.signal_connect(Gtk::CList::SIGNAL_SELECT_ROW) { - |w, row, column, event| - @selected_row = row - } - sw.add(@clist) - end - - class ButtonPanel < Gtk::HButtonBox - attr_reader :openButton, :extractButton - def initialize - super - set_layout(Gtk::BUTTONBOX_START) - set_spacing(0) - @openButton = Gtk::Button.new("Open archive") - @extractButton = Gtk::Button.new("Extract entry") - pack_start(@openButton) - pack_start(@extractButton) - end - end - - def show_file_selector - @fileSelector = Gtk::FileSelection.new("Open zip file") - @fileSelector.show - @fileSelector.ok_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) { - open_zip(@fileSelector.filename) - @fileSelector.destroy - } - @fileSelector.cancel_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) { - @fileSelector.destroy - } - end - - def open_zip(filename) - @zipfile = Zip::ZipFile.open(filename) - @clist.clear - @zipfile.each { - |entry| - @clist.append([ entry.name, - entry.size.to_s, - (100.0*entry.compressedSize/entry.size).to_s+"%" ]) - } - end -end - -mainApp = MainApp.new() - -mainApp.show_all - -Gtk.main diff --git a/lib/zip/samples/qtzip.rb b/lib/zip/samples/qtzip.rb deleted file mode 100755 index 3d76bd18e8..0000000000 --- a/lib/zip/samples/qtzip.rb +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE=true - -$: << "../lib" - -require 'Qt' -system('rbuic -o zipdialogui.rb zipdialogui.ui') -require 'zipdialogui.rb' -require 'zip/zip' - - - -a = Qt::Application.new(ARGV) - -class ZipDialog < ZipDialogUI - - - def initialize() - super() - connect(child('add_button'), SIGNAL('clicked()'), - self, SLOT('add_files()')) - connect(child('extract_button'), SIGNAL('clicked()'), - self, SLOT('extract_files()')) - end - - def zipfile(&proc) - Zip::ZipFile.open(@zip_filename, &proc) - end - - def each(&proc) - Zip::ZipFile.foreach(@zip_filename, &proc) - end - - def refresh() - lv = child("entry_list_view") - lv.clear - each { - |e| - lv.insert_item(Qt::ListViewItem.new(lv, e.name, e.size.to_s)) - } - end - - - def load(zipfile) - @zip_filename = zipfile - refresh - end - - def add_files - l = Qt::FileDialog.getOpenFileNames(nil, nil, self) - zipfile { - |zf| - l.each { - |path| - zf.add(File.basename(path), path) - } - } - refresh - end - - def extract_files - selected_items = [] - unselected_items = [] - lv_item = entry_list_view.first_child - while (lv_item) - if entry_list_view.is_selected(lv_item) - selected_items << lv_item.text(0) - else - unselected_items << lv_item.text(0) - end - lv_item = lv_item.next_sibling - end - puts "selected_items.size = #{selected_items.size}" - puts "unselected_items.size = #{unselected_items.size}" - items = selected_items.size > 0 ? selected_items : unselected_items - puts "items.size = #{items.size}" - - d = Qt::FileDialog.get_existing_directory(nil, self) - if (!d) - puts "No directory chosen" - else - zipfile { |zf| items.each { |e| zf.extract(e, File.join(d, e)) } } - end - - end - - slots 'add_files()', 'extract_files()' -end - -if !ARGV[0] - puts "usage: #{$0} zipname" - exit -end - -zd = ZipDialog.new -zd.load(ARGV[0]) - -a.mainWidget = zd -zd.show() -a.exec() diff --git a/lib/zip/samples/write_simple.rb b/lib/zip/samples/write_simple.rb deleted file mode 100755 index 648989a2ca..0000000000 --- a/lib/zip/samples/write_simple.rb +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env ruby - -$: << "../lib" - -require 'zip/zip' - -include Zip - -ZipOutputStream.open('simple.zip') { - |zos| - ze = zos.put_next_entry 'entry.txt' - zos.puts "Hello world" -} diff --git a/lib/zip/samples/zipfind.rb b/lib/zip/samples/zipfind.rb deleted file mode 100755 index 5a9d84ec1c..0000000000 --- a/lib/zip/samples/zipfind.rb +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -$: << "../lib" - -require 'zip/zip' -require 'find' - -module Zip - module ZipFind - def self.find(path, zipFilePattern = /\.zip$/i) - Find.find(path) { - |fileName| - yield(fileName) - if zipFilePattern.match(fileName) && File.file?(fileName) - begin - Zip::ZipFile.foreach(fileName) { - |zipEntry| - yield(fileName + File::SEPARATOR + zipEntry.to_s) - } - rescue Errno::EACCES => ex - puts ex - end - end - } - end - - def self.find_file(path, fileNamePattern, zipFilePattern = /\.zip$/i) - self.find(path, zipFilePattern) { - |fileName| - yield(fileName) if fileNamePattern.match(fileName) - } - end - - end -end - -if __FILE__ == $0 - module ZipFindConsoleRunner - - PATH_ARG_INDEX = 0; - FILENAME_PATTERN_ARG_INDEX = 1; - ZIPFILE_PATTERN_ARG_INDEX = 2; - - def self.run(args) - check_args(args) - Zip::ZipFind.find_file(args[PATH_ARG_INDEX], - args[FILENAME_PATTERN_ARG_INDEX], - args[ZIPFILE_PATTERN_ARG_INDEX]) { - |fileName| - report_entry_found fileName - } - end - - def self.check_args(args) - if (args.size != 3) - usage - exit - end - end - - def self.usage - puts "Usage: #{$0} PATH ZIPFILENAME_PATTERN FILNAME_PATTERN" - end - - def self.report_entry_found(fileName) - puts fileName - end - - end - - ZipFindConsoleRunner.run(ARGV) -end diff --git a/lib/zip/stdrubyext.rb b/lib/zip/stdrubyext.rb deleted file mode 100644 index 833365dbca..0000000000 --- a/lib/zip/stdrubyext.rb +++ /dev/null @@ -1,111 +0,0 @@ -unless Enumerable.method_defined?(:inject) - module Enumerable #:nodoc:all - def inject(n = 0) - each { |value| n = yield(n, value) } - n - end - end -end - -module Enumerable #:nodoc:all - # returns a new array of all the return values not equal to nil - # This implementation could be faster - def select_map(&aProc) - map(&aProc).reject { |e| e.nil? } - end -end - -unless Object.method_defined?(:object_id) - class Object #:nodoc:all - # Using object_id which is the new thing, so we need - # to make that work in versions prior to 1.8.0 - alias object_id id - end -end - -unless File.respond_to?(:read) - class File # :nodoc:all - # singleton method read does not exist in 1.6.x - def self.read(fileName) - open(fileName) { |f| f.read } - end - end -end - -class String #:nodoc:all - def starts_with(aString) - rindex(aString, 0) == 0 - end - - def ends_with(aString) - index(aString, -aString.size) - end - - def ensure_end(aString) - ends_with(aString) ? self : self + aString - end - - def lchop - slice(1, length) - end -end - -class Time #:nodoc:all - - #MS-DOS File Date and Time format as used in Interrupt 21H Function 57H: - # - # Register CX, the Time: - # Bits 0-4 2 second increments (0-29) - # Bits 5-10 minutes (0-59) - # bits 11-15 hours (0-24) - # - # Register DX, the Date: - # Bits 0-4 day (1-31) - # bits 5-8 month (1-12) - # bits 9-15 year (four digit year minus 1980) - - - def to_binary_dos_time - (sec/2) + - (min << 5) + - (hour << 11) - end - - def to_binary_dos_date - (day) + - (month << 5) + - ((year - 1980) << 9) - end - - # Dos time is only stored with two seconds accuracy - def dos_equals(other) - to_i/2 == other.to_i/2 - end - - def self.parse_binary_dos_format(binaryDosDate, binaryDosTime) - second = 2 * ( 0b11111 & binaryDosTime) - minute = ( 0b11111100000 & binaryDosTime) >> 5 - hour = (0b1111100000000000 & binaryDosTime) >> 11 - day = ( 0b11111 & binaryDosDate) - month = ( 0b111100000 & binaryDosDate) >> 5 - year = ((0b1111111000000000 & binaryDosDate) >> 9) + 1980 - begin - return Time.local(year, month, day, hour, minute, second) - end - end -end - -class Module #:nodoc:all - def forward_message(forwarder, *messagesToForward) - methodDefs = messagesToForward.map { - |msg| - "def #{msg}; #{forwarder}(:#{msg}); end" - } - module_eval(methodDefs.join("\n")) - end -end - - -# Copyright (C) 2002, 2003 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/tempfile_bugfixed.rb b/lib/zip/tempfile_bugfixed.rb deleted file mode 100644 index a04c59e2dc..0000000000 --- a/lib/zip/tempfile_bugfixed.rb +++ /dev/null @@ -1,195 +0,0 @@ -# -# tempfile - manipulates temporary files -# -# $Id$ -# - -require 'delegate' -require 'tmpdir' - -module BugFix #:nodoc:all - -# A class for managing temporary files. This library is written to be -# thread safe. -class Tempfile < DelegateClass(File) - MAX_TRY = 10 - @@cleanlist = [] - - # Creates a temporary file of mode 0600 in the temporary directory - # whose name is basename.pid.n and opens with mode "w+". A Tempfile - # object works just like a File object. - # - # If tmpdir is omitted, the temporary directory is determined by - # Dir::tmpdir provided by 'tmpdir.rb'. - # When $SAFE > 0 and the given tmpdir is tainted, it uses - # /tmp. (Note that ENV values are tainted by default) - def initialize(basename, tmpdir=Dir::tmpdir) - if $SAFE > 0 and tmpdir.tainted? - tmpdir = '/tmp' - end - - lock = nil - n = failure = 0 - - begin - Thread.critical = true - - begin - tmpname = sprintf('%s/%s%d.%d', tmpdir, basename, $$, n) - lock = tmpname + '.lock' - n += 1 - end while @@cleanlist.include?(tmpname) or - File.exist?(lock) or File.exist?(tmpname) - - Dir.mkdir(lock) - rescue - failure += 1 - retry if failure < MAX_TRY - raise "cannot generate tempfile `%s'" % tmpname - ensure - Thread.critical = false - end - - @data = [tmpname] - @clean_proc = Tempfile.callback(@data) - ObjectSpace.define_finalizer(self, @clean_proc) - - @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600) - @tmpname = tmpname - @@cleanlist << @tmpname - @data[1] = @tmpfile - @data[2] = @@cleanlist - - super(@tmpfile) - - # Now we have all the File/IO methods defined, you must not - # carelessly put bare puts(), etc. after this. - - Dir.rmdir(lock) - end - - # Opens or reopens the file with mode "r+". - def open - @tmpfile.close if @tmpfile - @tmpfile = File.open(@tmpname, 'r+') - @data[1] = @tmpfile - __setobj__(@tmpfile) - end - - def _close # :nodoc: - @tmpfile.close if @tmpfile - @data[1] = @tmpfile = nil - end - protected :_close - - # Closes the file. If the optional flag is true, unlinks the file - # after closing. - # - # If you don't explicitly unlink the temporary file, the removal - # will be delayed until the object is finalized. - def close(unlink_now=false) - if unlink_now - close! - else - _close - end - end - - # Closes and unlinks the file. - def close! - _close - @clean_proc.call - ObjectSpace.undefine_finalizer(self) - end - - # Unlinks the file. On UNIX-like systems, it is often a good idea - # to unlink a temporary file immediately after creating and opening - # it, because it leaves other programs zero chance to access the - # file. - def unlink - # keep this order for thread safeness - File.unlink(@tmpname) if File.exist?(@tmpname) - @@cleanlist.delete(@tmpname) if @@cleanlist - end - alias delete unlink - - if RUBY_VERSION > '1.8.0' - def __setobj__(obj) - @_dc_obj = obj - end - else - def __setobj__(obj) - @obj = obj - end - end - - # Returns the full path name of the temporary file. - def path - @tmpname - end - - # Returns the size of the temporary file. As a side effect, the IO - # buffer is flushed before determining the size. - def size - if @tmpfile - @tmpfile.flush - @tmpfile.stat.size - else - 0 - end - end - alias length size - - class << self - def callback(data) # :nodoc: - pid = $$ - lambda{ - if pid == $$ - path, tmpfile, cleanlist = *data - - print "removing ", path, "..." if $DEBUG - - tmpfile.close if tmpfile - - # keep this order for thread safeness - File.unlink(path) if File.exist?(path) - cleanlist.delete(path) if cleanlist - - print "done\n" if $DEBUG - end - } - end - - # If no block is given, this is a synonym for new(). - # - # If a block is given, it will be passed tempfile as an argument, - # and the tempfile will automatically be closed when the block - # terminates. In this case, open() returns nil. - def open(*args) - tempfile = new(*args) - - if block_given? - begin - yield(tempfile) - ensure - tempfile.close - end - - nil - else - tempfile - end - end - end -end - -end # module BugFix -if __FILE__ == $0 -# $DEBUG = true - f = Tempfile.new("foo") - f.print("foo\n") - f.close - f.open - p f.gets # => "foo\n" - f.close! -end diff --git a/lib/zip/test/alltests.rb b/lib/zip/test/alltests.rb deleted file mode 100755 index 691349af37..0000000000 --- a/lib/zip/test/alltests.rb +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -require 'stdrubyexttest' -require 'ioextrastest' -require 'ziptest' -require 'zipfilesystemtest' -require 'ziprequiretest' diff --git a/lib/zip/test/data/file1.txt b/lib/zip/test/data/file1.txt deleted file mode 100644 index 23ea2f731b..0000000000 --- a/lib/zip/test/data/file1.txt +++ /dev/null @@ -1,46 +0,0 @@ - -AUTOMAKE_OPTIONS = gnu - -EXTRA_DIST = test.zip - -CXXFLAGS= -g - -noinst_LIBRARIES = libzipios.a - -bin_PROGRAMS = test_zip test_izipfilt test_izipstream -# test_flist - -libzipios_a_SOURCES = backbuffer.h fcol.cpp fcol.h \ - fcol_common.h fcolexceptions.cpp fcolexceptions.h \ - fileentry.cpp fileentry.h flist.cpp \ - flist.h flistentry.cpp flistentry.h \ - flistscanner.h ifiltstreambuf.cpp ifiltstreambuf.h \ - inflatefilt.cpp inflatefilt.h izipfilt.cpp \ - izipfilt.h izipstream.cpp izipstream.h \ - zipfile.cpp zipfile.h ziphead.cpp \ - ziphead.h flistscanner.ll - -# test_flist_SOURCES = test_flist.cpp - -test_izipfilt_SOURCES = test_izipfilt.cpp - -test_izipstream_SOURCES = test_izipstream.cpp - -test_zip_SOURCES = test_zip.cpp - -# Notice that libzipios.a is not specified as -L. -lzipios -# If it was, automake would not include it as a dependency. - -# test_flist_LDADD = libzipios.a - -test_izipfilt_LDADD = libzipios.a -lz - -test_zip_LDADD = libzipios.a -lz - -test_izipstream_LDADD = libzipios.a -lz - - - -flistscanner.cc : flistscanner.ll - $(LEX) -+ -PFListScanner -o$@ $^ - diff --git a/lib/zip/test/data/file1.txt.deflatedData b/lib/zip/test/data/file1.txt.deflatedData deleted file mode 100644 index bfbb4f42c0..0000000000 Binary files a/lib/zip/test/data/file1.txt.deflatedData and /dev/null differ diff --git a/lib/zip/test/data/file2.txt b/lib/zip/test/data/file2.txt deleted file mode 100644 index 57221d1adf..0000000000 --- a/lib/zip/test/data/file2.txt +++ /dev/null @@ -1,1504 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -require 'rubyunit' -require 'zip' - -include Zip - -Dir.chdir "test" - -class AbstractInputStreamTest < RUNIT::TestCase - # AbstractInputStream subclass that provides a read method - - TEST_LINES = [ "Hello world#{$/}", - "this is the second line#{$/}", - "this is the last line"] - TEST_STRING = TEST_LINES.join - class TestAbstractInputStream - include AbstractInputStream - def initialize(aString) - @contents = aString - @readPointer = 0 - end - - def read(charsToRead) - retVal=@contents[@readPointer, charsToRead] - @readPointer+=charsToRead - return retVal - end - - def produceInput - read(100) - end - - def inputFinished? - @contents[@readPointer] == nil - end - end - - def setup - @io = TestAbstractInputStream.new(TEST_STRING) - end - - def test_gets - assert_equals(TEST_LINES[0], @io.gets) - assert_equals(TEST_LINES[1], @io.gets) - assert_equals(TEST_LINES[2], @io.gets) - assert_equals(nil, @io.gets) - end - - def test_getsMultiCharSeperator - assert_equals("Hell", @io.gets("ll")) - assert_equals("o world#{$/}this is the second l", @io.gets("d l")) - end - - def test_each_line - lineNumber=0 - @io.each_line { - |line| - assert_equals(TEST_LINES[lineNumber], line) - lineNumber+=1 - } - end - - def test_readlines - assert_equals(TEST_LINES, @io.readlines) - end - - def test_readline - test_gets - begin - @io.readline - fail "EOFError expected" - rescue EOFError - end - end -end - -class ZipEntryTest < RUNIT::TestCase - TEST_ZIPFILE = "someZipFile.zip" - TEST_COMMENT = "a comment" - TEST_COMPRESSED_SIZE = 1234 - TEST_CRC = 325324 - TEST_EXTRA = "Some data here" - TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED - TEST_NAME = "entry name" - TEST_SIZE = 8432 - TEST_ISDIRECTORY = false - - def test_constructorAndGetters - entry = ZipEntry.new(TEST_ZIPFILE, - TEST_NAME, - TEST_COMMENT, - TEST_EXTRA, - TEST_COMPRESSED_SIZE, - TEST_CRC, - TEST_COMPRESSIONMETHOD, - TEST_SIZE) - - assert_equals(TEST_COMMENT, entry.comment) - assert_equals(TEST_COMPRESSED_SIZE, entry.compressedSize) - assert_equals(TEST_CRC, entry.crc) - assert_equals(TEST_EXTRA, entry.extra) - assert_equals(TEST_COMPRESSIONMETHOD, entry.compressionMethod) - assert_equals(TEST_NAME, entry.name) - assert_equals(TEST_SIZE, entry.size) - assert_equals(TEST_ISDIRECTORY, entry.isDirectory) - end - - def test_equality - entry1 = ZipEntry.new("file.zip", "name", "isNotCompared", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 1234, - ZipEntry::DEFLATED, 10000) - entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::DEFLATED, 10000) - entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 10000) - entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 100000) - - assert_equals(entry1, entry1) - assert_equals(entry1, entry2) - - assert(entry2 != entry3) - assert(entry3 != entry4) - assert(entry4 != entry5) - assert(entry5 != entry6) - assert(entry6 != entry7) - assert(entry7 != entry8) - - assert(entry7 != "hello") - assert(entry7 != 12) - end -end - -module IOizeString - attr_reader :tell - - def read(count = nil) - @tell ||= 0 - count = size unless count - retVal = slice(@tell, count) - @tell += count - return retVal - end - - def seek(index, offset) - @tell ||= 0 - case offset - when IO::SEEK_END - newPos = size + index - when IO::SEEK_SET - newPos = index - when IO::SEEK_CUR - newPos = @tell + index - else - raise "Error in test method IOizeString::seek" - end - if (newPos < 0 || newPos >= size) - raise Errno::EINVAL - else - @tell=newPos - end - end - - def reset - @tell = 0 - end -end - -class ZipLocalEntryTest < RUNIT::TestCase - def test_readLocalEntryHeaderOfFirstTestZipEntry - File.open(TestZipFile::TEST_ZIP3.zipName) { - |file| - entry = ZipEntry.readLocalEntry(file) - - assert_equal("", entry.comment) - # Differs from windows and unix because of CR LF - # assert_equal(480, entry.compressedSize) - # assert_equal(0x2a27930f, entry.crc) - # extra field is 21 bytes long - # probably contains some unix attrutes or something - # disabled: assert_equal(nil, entry.extra) - assert_equal(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equal(TestZipFile::TEST_ZIP3.entryNames[0], entry.name) - assert_equal(File.size(TestZipFile::TEST_ZIP3.entryNames[0]), entry.size) - assert(! entry.isDirectory) - } - end - - def test_readLocalEntryFromNonZipFile - File.open("ziptest.rb") { - |file| - assert_equals(nil, ZipEntry.readLocalEntry(file)) - } - end - - def test_readLocalEntryFromTruncatedZipFile - zipFragment="" - File.open(TestZipFile::TEST_ZIP2.zipName) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes - zipFragment.extend(IOizeString).reset - entry = ZipEntry.new - entry.readLocalEntry(zipFragment) - fail "ZipError expected" - rescue ZipError - end - - def test_writeEntry - entry = ZipEntry.new("file.zip", "entryName", "my little comment", - "thisIsSomeExtraInformation", 100, 987654, - ZipEntry::DEFLATED, 400) - writeToFile("localEntryHeader.bin", "centralEntryHeader.bin", entry) - entryReadLocal, entryReadCentral = readFromFile("localEntryHeader.bin", "centralEntryHeader.bin") - compareLocalEntryHeaders(entry, entryReadLocal) - compareCDirEntryHeaders(entry, entryReadCentral) - end - - private - def compareLocalEntryHeaders(entry1, entry2) - assert_equals(entry1.compressedSize , entry2.compressedSize) - assert_equals(entry1.crc , entry2.crc) - assert_equals(entry1.extra , entry2.extra) - assert_equals(entry1.compressionMethod, entry2.compressionMethod) - assert_equals(entry1.name , entry2.name) - assert_equals(entry1.size , entry2.size) - assert_equals(entry1.localHeaderOffset, entry2.localHeaderOffset) - end - - def compareCDirEntryHeaders(entry1, entry2) - compareLocalEntryHeaders(entry1, entry2) - assert_equals(entry1.comment, entry2.comment) - end - - def writeToFile(localFileName, centralFileName, entry) - File.open(localFileName, "wb") { |f| entry.writeLocalEntry(f) } - File.open(centralFileName, "wb") { |f| entry.writeCDirEntry(f) } - end - - def readFromFile(localFileName, centralFileName) - localEntry = nil - cdirEntry = nil - File.open(localFileName, "rb") { |f| localEntry = ZipEntry.readLocalEntry(f) } - File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.readCDirEntry(f) } - return [localEntry, cdirEntry] - end -end - - -module DecompressorTests - # expects @refText and @decompressor - - def test_readEverything - assert_equals(@refText, @decompressor.read) - end - - def test_readInChunks - chunkSize = 5 - while (decompressedChunk = @decompressor.read(chunkSize)) - assert_equals(@refText.slice!(0, chunkSize), decompressedChunk) - end - assert_equals(0, @refText.size) - end -end - -class InflaterTest < RUNIT::TestCase - include DecompressorTests - - def setup - @file = File.new("file1.txt.deflatedData", "rb") - @refText="" - File.open("file1.txt") { |f| @refText = f.read } - @decompressor = Inflater.new(@file) - end - - def teardown - @file.close - end -end - - -class PassThruDecompressorTest < RUNIT::TestCase - include DecompressorTests - TEST_FILE="file1.txt" - def setup - @file = File.new(TEST_FILE) - @refText="" - File.open(TEST_FILE) { |f| @refText = f.read } - @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE)) - end - - def teardown - @file.close - end -end - - -module AssertEntry - def assertNextEntry(filename, zis) - assertEntry(filename, zis, zis.getNextEntry.name) - end - - def assertEntry(filename, zis, entryName) - assert_equals(filename, entryName) - assertEntryContentsForStream(filename, zis, entryName) - end - - def assertEntryContentsForStream(filename, zis, entryName) - File.open(filename, "rb") { - |file| - expected = file.read - actual = zis.read - if (expected != actual) - if (expected.length > 400 || actual.length > 400) - zipEntryFilename=entryName+".zipEntry" - File.open(zipEntryFilename, "wb") { |file| file << actual } - fail("File '#{filename}' is different from '#{zipEntryFilename}'") - else - assert_equals(expected, actual) - end - end - } - end - - def AssertEntry.assertContents(filename, aString) - fileContents = "" - File.open(filename, "rb") { |f| fileContents = f.read } - if (fileContents != aString) - if (expected.length > 400 || actual.length > 400) - stringFile = filename + ".other" - File.open(stringFile, "wb") { |f| f << aString } - fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'") - else - assert_equals(expected, actual) - end - end - end - - def assertStreamContents(zis, testZipFile) - assert(zis != nil) - testZipFile.entryNames.each { - |entryName| - assertNextEntry(entryName, zis) - } - assert_equals(nil, zis.getNextEntry) - end - - def assertTestZipContents(testZipFile) - ZipInputStream.open(testZipFile.zipName) { - |zis| - assertStreamContents(zis, testZipFile) - } - end - - def assertEntryContents(zipFile, entryName, filename = entryName.to_s) - zis = zipFile.getInputStream(entryName) - assertEntryContentsForStream(filename, zis, entryName) - ensure - zis.close if zis - end -end - - - -class ZipInputStreamTest < RUNIT::TestCase - include AssertEntry - - def test_new - zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zipName) - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - zis.close - end - - def test_openWithBlock - ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { - |zis| - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - } - end - - def test_openWithoutBlock - zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - end - - def test_incompleteReads - ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { - |zis| - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[0], entry.name) - assert zis.gets.length > 0 - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[1], entry.name) - assert_equals(0, entry.size) - assert_equals(nil, zis.gets) - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[2], entry.name) - assert zis.gets.length > 0 - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[3], entry.name) - assert zis.gets.length > 0 - } - end - -end - -class TestFiles - RANDOM_ASCII_FILE1 = "randomAscii1.txt" - RANDOM_ASCII_FILE2 = "randomAscii2.txt" - RANDOM_ASCII_FILE3 = "randomAscii3.txt" - RANDOM_BINARY_FILE1 = "randomBinary1.bin" - RANDOM_BINARY_FILE2 = "randomBinary2.bin" - - EMPTY_TEST_DIR = "emptytestdir" - - ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ] - BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ] - TEST_DIRECTORIES = [ EMPTY_TEST_DIR ] - TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten! - - def TestFiles.createTestFiles(recreate) - if (recreate || - ! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) })) - - ASCII_TEST_FILES.each_with_index { - |filename, index| - createRandomAscii(filename, 1E4 * (index+1)) - } - - BINARY_TEST_FILES.each_with_index { - |filename, index| - createRandomBinary(filename, 1E4 * (index+1)) - } - - ensureDir(EMPTY_TEST_DIR) - end - end - - private - def TestFiles.createRandomAscii(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << rand - end - } - end - - def TestFiles.createRandomBinary(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << rand.to_a.pack("V") - end - } - end - - def TestFiles.ensureDir(name) - if File.exists?(name) - return if File.stat(name).directory? - File.delete(name) - end - Dir.mkdir(name) - end - -end - -# For representation and creation of -# test data -class TestZipFile - attr_accessor :zipName, :entryNames, :comment - - def initialize(zipName, entryNames, comment = "") - @zipName=zipName - @entryNames=entryNames - @comment = comment - end - - def TestZipFile.createTestZips(recreate) - files = Dir.entries(".") - if (recreate || - ! (files.index(TEST_ZIP1.zipName) && - files.index(TEST_ZIP2.zipName) && - files.index(TEST_ZIP3.zipName) && - files.index(TEST_ZIP4.zipName) && - files.index("empty.txt") && - files.index("short.txt") && - files.index("longAscii.txt") && - files.index("longBinary.bin") )) - raise "failed to create test zip '#{TEST_ZIP1.zipName}'" unless - system("zip #{TEST_ZIP1.zipName} ziptest.rb") - raise "failed to remove entry from '#{TEST_ZIP1.zipName}'" unless - system("zip #{TEST_ZIP1.zipName} -d ziptest.rb") - - File.open("empty.txt", "w") {} - - File.open("short.txt", "w") { |file| file << "ABCDEF" } - ziptestTxt="" - File.open("ziptest.rb") { |file| ziptestTxt=file.read } - File.open("longAscii.txt", "w") { - |file| - while (file.tell < 1E5) - file << ziptestTxt - end - } - - testBinaryPattern="" - File.open("empty.zip") { |file| testBinaryPattern=file.read } - testBinaryPattern *= 4 - - File.open("longBinary.bin", "wb") { - |file| - while (file.tell < 3E5) - file << testBinaryPattern << rand - end - } - raise "failed to create test zip '#{TEST_ZIP2.zipName}'" unless - system("zip #{TEST_ZIP2.zipName} #{TEST_ZIP2.entryNames.join(' ')}") - - # without bash system interprets everything after echo as parameters to - # echo including | zip -z ... - raise "failed to add comment to test zip '#{TEST_ZIP2.zipName}'" unless - system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zipName}\"") - - raise "failed to create test zip '#{TEST_ZIP3.zipName}'" unless - system("zip #{TEST_ZIP3.zipName} #{TEST_ZIP3.entryNames.join(' ')}") - - raise "failed to create test zip '#{TEST_ZIP4.zipName}'" unless - system("zip #{TEST_ZIP4.zipName} #{TEST_ZIP4.entryNames.join(' ')}") - end - rescue - raise $!.to_s + - "\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" + - "to create test data. If you don't have it you can download\n" + - "the necessary test files at http://sf.net/projects/rubyzip." - end - - TEST_ZIP1 = TestZipFile.new("empty.zip", []) - TEST_ZIP2 = TestZipFile.new("4entry.zip", %w{ longAscii.txt empty.txt short.txt longBinary.bin}, - "my zip comment") - TEST_ZIP3 = TestZipFile.new("test1.zip", %w{ file1.txt }) - TEST_ZIP4 = TestZipFile.new("zipWithDir.zip", [ "file1.txt", - TestFiles::EMPTY_TEST_DIR]) -end - - -class AbstractOutputStreamTest < RUNIT::TestCase - class TestOutputStream - include AbstractOutputStream - - attr_accessor :buffer - - def initialize - @buffer = "" - end - - def << (data) - @buffer << data - self - end - end - - def setup - @outputStream = TestOutputStream.new - - @origCommaSep = $, - @origOutputSep = $\ - end - - def teardown - $, = @origCommaSep - $\ = @origOutputSep - end - - def test_write - count = @outputStream.write("a little string") - assert_equals("a little string", @outputStream.buffer) - assert_equals("a little string".length, count) - - count = @outputStream.write(". a little more") - assert_equals("a little string. a little more", @outputStream.buffer) - assert_equals(". a little more".length, count) - end - - def test_print - $\ = nil # record separator set to nil - @outputStream.print("hello") - assert_equals("hello", @outputStream.buffer) - - @outputStream.print(" world.") - assert_equals("hello world.", @outputStream.buffer) - - @outputStream.print(" You ok ", "out ", "there?") - assert_equals("hello world. You ok out there?", @outputStream.buffer) - - $\ = "\n" - @outputStream.print - assert_equals("hello world. You ok out there?\n", @outputStream.buffer) - - @outputStream.print("I sure hope so!") - assert_equals("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer) - - $, = "X" - @outputStream.buffer = "" - @outputStream.print("monkey", "duck", "zebra") - assert_equals("monkeyXduckXzebra\n", @outputStream.buffer) - - $\ = nil - @outputStream.buffer = "" - @outputStream.print(20) - assert_equals("20", @outputStream.buffer) - end - - def test_printf - @outputStream.printf("%d %04x", 123, 123) - assert_equals("123 007b", @outputStream.buffer) - end - - def test_putc - @outputStream.putc("A") - assert_equals("A", @outputStream.buffer) - @outputStream.putc(65) - assert_equals("AA", @outputStream.buffer) - end - - def test_puts - @outputStream.puts - assert_equals("\n", @outputStream.buffer) - - @outputStream.puts("hello", "world") - assert_equals("\nhello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts("hello\n", "world\n") - assert_equals("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"]) - assert_equals("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"], "bingo") - assert_equals("hello\nworld\nbingo\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(16, 20, 50, "hello") - assert_equals("16\n20\n50\nhello\n", @outputStream.buffer) - end -end - - -module CrcTest - def runCrcTest(compressorClass) - str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed." - fakeOut = AbstractOutputStreamTest::TestOutputStream.new - - deflater = compressorClass.new(fakeOut) - deflater << str - assert_equals(0x919920fc, deflater.crc) - end -end - - - -class PassThruCompressorTest < RUNIT::TestCase - include CrcTest - - def test_size - File.open("dummy.txt", "wb") { - |file| - compressor = PassThruCompressor.new(file) - - assert_equals(0, compressor.size) - - t1 = "hello world" - t2 = "" - t3 = "bingo" - - compressor << t1 - assert_equals(compressor.size, t1.size) - - compressor << t2 - assert_equals(compressor.size, t1.size + t2.size) - - compressor << t3 - assert_equals(compressor.size, t1.size + t2.size + t3.size) - } - end - - def test_crc - runCrcTest(PassThruCompressor) - end -end - -class DeflaterTest < RUNIT::TestCase - include CrcTest - - def test_outputOperator - txt = loadFile("ziptest.rb") - deflate(txt, "deflatertest.bin") - inflatedTxt = inflate("deflatertest.bin") - assert_equals(txt, inflatedTxt) - end - - private - def loadFile(fileName) - txt = nil - File.open(fileName, "rb") { |f| txt = f.read } - end - - def deflate(data, fileName) - File.open(fileName, "wb") { - |file| - deflater = Deflater.new(file) - deflater << data - deflater.finish - assert_equals(deflater.size, data.size) - file << "trailing data for zlib with -MAX_WBITS" - } - end - - def inflate(fileName) - txt = nil - File.open(fileName, "rb") { - |file| - inflater = Inflater.new(file) - txt = inflater.read - } - end - - def test_crc - runCrcTest(Deflater) - end -end - -class ZipOutputStreamTest < RUNIT::TestCase - include AssertEntry - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zipName = "output.zip" - - def test_new - zos = ZipOutputStream.new(TEST_ZIP.zipName) - zos.comment = TEST_ZIP.comment - writeTestZip(zos) - zos.close - assertTestZipContents(TEST_ZIP) - end - - def test_open - ZipOutputStream.open(TEST_ZIP.zipName) { - |zos| - zos.comment = TEST_ZIP.comment - writeTestZip(zos) - } - assertTestZipContents(TEST_ZIP) - end - - def test_writingToClosedStream - assertIOErrorInClosedStream { |zos| zos << "hello world" } - assertIOErrorInClosedStream { |zos| zos.puts "hello world" } - assertIOErrorInClosedStream { |zos| zos.write "hello world" } - end - - def test_cannotOpenFile - name = TestFiles::EMPTY_TEST_DIR - begin - zos = ZipOutputStream.open(name) - rescue Exception - assert($!.kind_of?(Errno::EISDIR) || # Linux - $!.kind_of?(Errno::EEXIST) || # Windows/cygwin - $!.kind_of?(Errno::EACCES), # Windows - "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.type}") - end - end - - def assertIOErrorInClosedStream - assert_exception(IOError) { - zos = ZipOutputStream.new("test_putOnClosedStream.zip") - zos.close - yield zos - } - end - - def writeTestZip(zos) - TEST_ZIP.entryNames.each { - |entryName| - zos.putNextEntry(entryName) - File.open(entryName, "rb") { |f| zos.write(f.read) } - } - end -end - - - -module Enumerable - def compareEnumerables(otherEnumerable) - otherAsArray = otherEnumerable.to_a - index=0 - each_with_index { - |element, index| - return false unless yield(element, otherAsArray[index]) - } - return index+1 == otherAsArray.size - end -end - - -class ZipCentralDirectoryEntryTest < RUNIT::TestCase - - def test_readFromStream - File.open("testDirectory.bin", "rb") { - |file| - entry = ZipEntry.readCDirEntry(file) - - assert_equals("longAscii.txt", entry.name) - assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equals(106490, entry.size) - assert_equals(3784, entry.compressedSize) - assert_equals(0xfcd1799c, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("empty.txt", entry.name) - assert_equals(ZipEntry::STORED, entry.compressionMethod) - assert_equals(0, entry.size) - assert_equals(0, entry.compressedSize) - assert_equals(0x0, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("short.txt", entry.name) - assert_equals(ZipEntry::STORED, entry.compressionMethod) - assert_equals(6, entry.size) - assert_equals(6, entry.compressedSize) - assert_equals(0xbb76fe69, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("longBinary.bin", entry.name) - assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equals(1000024, entry.size) - assert_equals(70847, entry.compressedSize) - assert_equals(0x10da7d59, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals(nil, entry) -# Fields that are not check by this test: -# version made by 2 bytes -# version needed to extract 2 bytes -# general purpose bit flag 2 bytes -# last mod file time 2 bytes -# last mod file date 2 bytes -# compressed size 4 bytes -# uncompressed size 4 bytes -# disk number start 2 bytes -# internal file attributes 2 bytes -# external file attributes 4 bytes -# relative offset of local header 4 bytes - -# file name (variable size) -# extra field (variable size) -# file comment (variable size) - - } - end - - def test_ReadEntryFromTruncatedZipFile - fragment="" - File.open("testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes - fragment.extend(IOizeString) - entry = ZipEntry.new - entry.readCDirEntry(fragment) - fail "ZipError expected" - rescue ZipError - end - -end - -class ZipCentralDirectoryTest < RUNIT::TestCase - - def test_readFromStream - File.open(TestZipFile::TEST_ZIP2.zipName, "rb") { - |zipFile| - cdir = ZipCentralDirectory.readFromStream(zipFile) - - assert_equals(TestZipFile::TEST_ZIP2.entryNames.size, cdir.size) - assert(cdir.compareEnumerables(TestZipFile::TEST_ZIP2.entryNames) { - |cdirEntry, testEntryName| - cdirEntry.name == testEntryName - }) - assert_equals(TestZipFile::TEST_ZIP2.comment, cdir.comment) - } - end - - def test_readFromInvalidStream - File.open("ziptest.rb", "rb") { - |zipFile| - cdir = ZipCentralDirectory.new - cdir.readFromStream(zipFile) - } - fail "ZipError expected!" - rescue ZipError - end - - def test_ReadFromTruncatedZipFile - fragment="" - File.open("testDirectory.bin") { |f| fragment = f.read } - fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete - fragment.extend(IOizeString) - entry = ZipCentralDirectory.new - entry.readFromStream(fragment) - fail "ZipError expected" - rescue ZipError - end - - def test_writeToStream - entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ] - cdir = ZipCentralDirectory.new(entries, "my zip comment") - File.open("cdirtest.bin", "wb") { |f| cdir.writeToStream(f) } - cdirReadback = ZipCentralDirectory.new - File.open("cdirtest.bin", "rb") { |f| cdirReadback.readFromStream(f) } - - assert_equals(cdir.entries, cdirReadback.entries) - end - - def test_equality - cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - assert_equals(cdir1, cdir1) - assert_equals(cdir1, cdir2) - - assert(cdir1 != cdir3) - assert(cdir2 != cdir3) - assert(cdir2 != cdir3) - assert(cdir3 != cdir4) - - assert(cdir3 != "hello") - end -end - - -class BasicZipFileTest < RUNIT::TestCase - include AssertEntry - - def setup - @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zipName) - @testEntryNameIndex=0 - end - - def nextTestEntryName - retVal=TestZipFile::TEST_ZIP2.entryNames[@testEntryNameIndex] - @testEntryNameIndex+=1 - return retVal - end - - def test_entries - assert_equals(TestZipFile::TEST_ZIP2.entryNames, @zipFile.entries.map {|e| e.name} ) - end - - def test_each - @zipFile.each { - |entry| - assert_equals(nextTestEntryName, entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_foreach - ZipFile.foreach(TestZipFile::TEST_ZIP2.zipName) { - |entry| - assert_equals(nextTestEntryName, entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_getInputStream - @zipFile.each { - |entry| - assertEntry(nextTestEntryName, @zipFile.getInputStream(entry), - entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_getInputStreamBlock - fileAndEntryName = @zipFile.entries.first.name - @zipFile.getInputStream(fileAndEntryName) { - |zis| - assertEntryContentsForStream(fileAndEntryName, - zis, - fileAndEntryName) - } - end -end - -class CommonZipFileFixture < RUNIT::TestCase - include AssertEntry - - EMPTY_FILENAME = "emptyZipFile.zip" - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zipName = "4entry_copy.zip" - - def setup - File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME) - File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) - end -end - -class ZipFileTest < CommonZipFileFixture - - def test_createFromScratch - comment = "a short comment" - - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.comment = comment - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equals(comment, zfRead.comment) - assert_equals(0, zfRead.entries.length) - end - - def test_add - srcFile = "ziptest.rb" - entryName = "newEntryName.rb" - assert(File.exists? srcFile) - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.add(entryName, srcFile) - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equals("", zfRead.comment) - assert_equals(1, zfRead.entries.length) - assert_equals(entryName, zfRead.entries.first.name) - AssertEntry.assertContents(srcFile, - zfRead.getInputStream(entryName) { |zis| zis.read }) - end - - def test_addExistingEntryName - assert_exception(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.add(zf.entries.first.name, "ziptest.rb") - } - } - end - - def test_addExistingEntryNameReplace - gotCalled = false - replacedEntry = nil - ZipFile.open(TEST_ZIP.zipName) { - |zf| - replacedEntry = zf.entries.first.name - zf.add(replacedEntry, "ziptest.rb") { gotCalled = true; true } - } - assert(gotCalled) - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assertContains(zf, replacedEntry, "ziptest.rb") - } - end - - def test_addDirectory - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR) - } - ZipFile.open(TEST_ZIP.zipName) { - |zf| - dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" } - assert(dirEntry.isDirectory) - } - end - - def test_remove - entryToRemove, *remainingEntries = TEST_ZIP.entryNames - - File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) - - zf = ZipFile.new(TEST_ZIP.zipName) - assert(zf.entries.map { |e| e.name }.include?(entryToRemove)) - zf.remove(entryToRemove) - assert(! zf.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equals(zf.entries.map {|x| x.name }.sort, remainingEntries.sort) - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equals(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort) - zfRead.close - end - - - def test_rename - entryToRename, *remainingEntries = TEST_ZIP.entryNames - - zf = ZipFile.new(TEST_ZIP.zipName) - assert(zf.entries.map { |e| e.name }.include? entryToRename) - - newName = "changed name" - assert(! zf.entries.map { |e| e.name }.include?(newName)) - - zf.rename(entryToRename, newName) - assert(zf.entries.map { |e| e.name }.include? newName) - - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(zfRead.entries.map { |e| e.name }.include? newName) - zfRead.close - end - - def test_renameToExistingEntry - oldEntries = nil - ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } - - assert_exception(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.rename(zf.entries[0], zf.entries[1].name) - } - } - - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_equals(oldEntries.map{ |e| e.name }, zf.entries.map{ |e| e.name }) - } - end - - def test_renameToExistingEntryOverwrite - oldEntries = nil - ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } - - gotCalled = false - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true } - } - - assert(gotCalled) - oldEntries.delete_at(0) - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_equals(oldEntries.map{ |e| e.name }, - zf.entries.map{ |e| e.name }) - } - end - - def test_renameNonEntry - nonEntry = "bogusEntry" - targetEntry = "targetEntryName" - zf = ZipFile.new(TEST_ZIP.zipName) - assert(! zf.entries.include?(nonEntry)) - assert_exception(ZipNoSuchEntryError) { - zf.rename(nonEntry, targetEntry) - } - zf.commit - assert(! zf.entries.include?(targetEntry)) - ensure - zf.close - end - - def test_renameEntryToExistingEntry - entry1, entry2, *remaining = TEST_ZIP.entryNames - zf = ZipFile.new(TEST_ZIP.zipName) - assert_exception(ZipEntryExistsError) { - zf.rename(entry1, entry2) - } - ensure - zf.close - end - - def test_replace - unchangedEntries = TEST_ZIP.entryNames.dup - entryToReplace = unchangedEntries.delete_at(2) - newEntrySrcFilename = "ziptest.rb" - - zf = ZipFile.new(TEST_ZIP.zipName) - zf.replace(entryToReplace, newEntrySrcFilename) - - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - AssertEntry::assertContents(newEntrySrcFilename, - zfRead.getInputStream(entryToReplace) { |is| is.read }) - zfRead.close - end - - def test_replaceNonEntry - entryToReplace = "nonExistingEntryname" - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_exception(ZipNoSuchEntryError) { - zf.replace(entryToReplace, "ziptest.rb") - } - } - end - - def test_commit - newName = "renamedFirst" - zf = ZipFile.new(TEST_ZIP.zipName) - oldName = zf.entries.first - zf.rename(oldName, newName) - zf.commit - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(zfRead.entries.detect { |e| e.name == newName } != nil) - assert(zfRead.entries.detect { |e| e.name == oldName } == nil) - zfRead.close - - zf.close - end - - # This test tests that after commit, you - # can delete the file you used to add the entry to the zip file - # with - def test_commitUseZipEntry - File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt") - zf = ZipFile.open(TEST_ZIP.zipName) - zf.add("okToDelete.txt", "okToDelete.txt") - assertContains(zf, "okToDelete.txt") - zf.commit - File.move("okToDelete.txt", "okToDeleteMoved.txt") - assertContains(zf, "okToDelete.txt", "okToDeleteMoved.txt") - end - -# def test_close -# zf = ZipFile.new(TEST_ZIP.zipName) -# zf.close -# assert_exception(IOError) { -# zf.extract(TEST_ZIP.entryNames.first, "hullubullu") -# } -# end - - def test_compound1 - renamedName = "renamedName" - originalEntries = [] - begin - zf = ZipFile.new(TEST_ZIP.zipName) - originalEntries = zf.entries.dup - - assertNotContains(zf, TestFiles::RANDOM_ASCII_FILE1) - zf.add(TestFiles::RANDOM_ASCII_FILE1, - TestFiles::RANDOM_ASCII_FILE1) - assertContains(zf, TestFiles::RANDOM_ASCII_FILE1) - - zf.rename(zf.entries[0], renamedName) - assertContains(zf, renamedName) - - TestFiles::BINARY_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assertContains(zf, filename) - } - - assertContains(zf, originalEntries.last.to_s) - zf.remove(originalEntries.last.to_s) - assertNotContains(zf, originalEntries.last.to_s) - - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zipName) - assertContains(zfRead, TestFiles::RANDOM_ASCII_FILE1) - assertContains(zfRead, renamedName) - TestFiles::BINARY_TEST_FILES.each { - |filename| - assertContains(zfRead, filename) - } - assertNotContains(zfRead, originalEntries.last.to_s) - ensure - zfRead.close - end - end - - def test_compound2 - begin - zf = ZipFile.new(TEST_ZIP.zipName) - originalEntries = zf.entries.dup - - originalEntries.each { - |entry| - zf.remove(entry) - assertNotContains(zf, entry) - } - assert(zf.entries.empty?) - - TestFiles::ASCII_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assertContains(zf, filename) - } - assert_equals(zf.entries.map { |e| e.name }, TestFiles::ASCII_TEST_FILES) - - zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName") - assertNotContains(zf, TestFiles::ASCII_TEST_FILES[0]) - assertContains(zf, "newName") - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zipName) - asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup - asciiTestFiles.shift - asciiTestFiles.each { - |filename| - assertContains(zf, filename) - } - - assertContains(zf, "newName") - ensure - zfRead.close - end - end - - private - def assertContains(zf, entryName, filename = entryName) - assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}") - assertEntryContents(zf, entryName, filename) if File.exists?(filename) - end - - def assertNotContains(zf, entryName) - assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}") - end -end - -class ZipFileExtractTest < CommonZipFileFixture - EXTRACTED_FILENAME = "extEntry" - ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entryNames.reverse - - def setup - super - File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME) - end - - def test_extract - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME) - - assert(File.exists? EXTRACTED_FILENAME) - AssertEntry::assertContents(EXTRACTED_FILENAME, - zf.getInputStream(ENTRY_TO_EXTRACT) { |is| is.read }) - } - end - - def test_extractExists - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - assert_exception(ZipDestinationFileExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) - } - } - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert_equals(writtenText, f.read) - } - end - - def test_extractExistsOverwrite - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - gotCalled = false - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) { gotCalled = true; true } - } - - assert(gotCalled) - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert(writtenText != f.read) - } - end - - def test_extractNonEntry - zf = ZipFile.new(TEST_ZIP.zipName) - assert_exception(ZipNoSuchEntryError) { zf.extract("nonExistingEntry", "nonExistingEntry") } - ensure - zf.close if zf - end - - def test_extractNonEntry2 - outFile = "outfile" - assert_exception(ZipNoSuchEntryError) { - zf = ZipFile.new(TEST_ZIP.zipName) - nonEntry = "hotdog-diddelidoo" - assert(! zf.entries.include?(nonEntry)) - zf.extract(nonEntry, outFile) - zf.close - } - assert(! File.exists?(outFile)) - end - -end - -class ZipFileExtractDirectoryTest < CommonZipFileFixture - TEST_OUT_NAME = "emptyOutDir" - - def openZip(&aProc) - assert(aProc != nil) - ZipFile.open(TestZipFile::TEST_ZIP4.zipName, &aProc) - end - - def extractTestDir(&aProc) - openZip { - |zf| - zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc) - } - end - - def setup - super - - Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME - File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME - end - - def test_extractDirectory - extractTestDir - assert(File.directory? TEST_OUT_NAME) - end - - def test_extractDirectoryExistsAsDir - Dir.mkdir TEST_OUT_NAME - extractTestDir - assert(File.directory? TEST_OUT_NAME) - end - - def test_extractDirectoryExistsAsFile - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - assert_exception(ZipDestinationFileExistsError) { extractTestDir } - end - - def test_extractDirectoryExistsAsFileOverwrite - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - gotCalled = false - extractTestDir { - |entry, destPath| - gotCalled = true - assert_equals(TEST_OUT_NAME, destPath) - assert(entry.isDirectory) - true - } - assert(gotCalled) - assert(File.directory? TEST_OUT_NAME) - end -end - - -TestFiles::createTestFiles(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) -TestZipFile::createTestZips(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) -exit if ARGV.index("recreateonly") != nil - -#require 'runit/cui/testrunner' -#RUNIT::CUI::TestRunner.run(ZipFileTest.suite) - -# Copyright (C) 2002 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/test/data/generated/5entry.zip b/lib/zip/test/data/generated/5entry.zip deleted file mode 100644 index ef580052ed..0000000000 Binary files a/lib/zip/test/data/generated/5entry.zip and /dev/null differ diff --git a/lib/zip/test/data/generated/empty.txt b/lib/zip/test/data/generated/empty.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/zip/test/data/generated/empty.zip b/lib/zip/test/data/generated/empty.zip deleted file mode 100644 index 15cb0ecb3e..0000000000 Binary files a/lib/zip/test/data/generated/empty.zip and /dev/null differ diff --git a/lib/zip/test/data/generated/empty_chmod640.txt b/lib/zip/test/data/generated/empty_chmod640.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/zip/test/data/generated/emptytestdir/.keep b/lib/zip/test/data/generated/emptytestdir/.keep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/zip/test/data/generated/longAscii.txt b/lib/zip/test/data/generated/longAscii.txt deleted file mode 100644 index 91e1cc1ce0..0000000000 --- a/lib/zip/test/data/generated/longAscii.txt +++ /dev/null @@ -1,4512 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -require 'rubyunit' -require 'zip' - -include Zip - -Dir.chdir "test" - -class AbstractInputStreamTest < RUNIT::TestCase - # AbstractInputStream subclass that provides a read method - - TEST_LINES = [ "Hello world#{$/}", - "this is the second line#{$/}", - "this is the last line"] - TEST_STRING = TEST_LINES.join - class TestAbstractInputStream - include AbstractInputStream - def initialize(aString) - @contents = aString - @readPointer = 0 - end - - def read(charsToRead) - retVal=@contents[@readPointer, charsToRead] - @readPointer+=charsToRead - return retVal - end - - def produceInput - read(100) - end - - def inputFinished? - @contents[@readPointer] == nil - end - end - - def setup - @io = TestAbstractInputStream.new(TEST_STRING) - end - - def test_gets - assert_equals(TEST_LINES[0], @io.gets) - assert_equals(TEST_LINES[1], @io.gets) - assert_equals(TEST_LINES[2], @io.gets) - assert_equals(nil, @io.gets) - end - - def test_getsMultiCharSeperator - assert_equals("Hell", @io.gets("ll")) - assert_equals("o world#{$/}this is the second l", @io.gets("d l")) - end - - def test_each_line - lineNumber=0 - @io.each_line { - |line| - assert_equals(TEST_LINES[lineNumber], line) - lineNumber+=1 - } - end - - def test_readlines - assert_equals(TEST_LINES, @io.readlines) - end - - def test_readline - test_gets - begin - @io.readline - fail "EOFError expected" - rescue EOFError - end - end -end - -class ZipEntryTest < RUNIT::TestCase - TEST_ZIPFILE = "someZipFile.zip" - TEST_COMMENT = "a comment" - TEST_COMPRESSED_SIZE = 1234 - TEST_CRC = 325324 - TEST_EXTRA = "Some data here" - TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED - TEST_NAME = "entry name" - TEST_SIZE = 8432 - TEST_ISDIRECTORY = false - - def test_constructorAndGetters - entry = ZipEntry.new(TEST_ZIPFILE, - TEST_NAME, - TEST_COMMENT, - TEST_EXTRA, - TEST_COMPRESSED_SIZE, - TEST_CRC, - TEST_COMPRESSIONMETHOD, - TEST_SIZE) - - assert_equals(TEST_COMMENT, entry.comment) - assert_equals(TEST_COMPRESSED_SIZE, entry.compressedSize) - assert_equals(TEST_CRC, entry.crc) - assert_equals(TEST_EXTRA, entry.extra) - assert_equals(TEST_COMPRESSIONMETHOD, entry.compressionMethod) - assert_equals(TEST_NAME, entry.name) - assert_equals(TEST_SIZE, entry.size) - assert_equals(TEST_ISDIRECTORY, entry.isDirectory) - end - - def test_equality - entry1 = ZipEntry.new("file.zip", "name", "isNotCompared", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 1234, - ZipEntry::DEFLATED, 10000) - entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::DEFLATED, 10000) - entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 10000) - entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 100000) - - assert_equals(entry1, entry1) - assert_equals(entry1, entry2) - - assert(entry2 != entry3) - assert(entry3 != entry4) - assert(entry4 != entry5) - assert(entry5 != entry6) - assert(entry6 != entry7) - assert(entry7 != entry8) - - assert(entry7 != "hello") - assert(entry7 != 12) - end -end - -module IOizeString - attr_reader :tell - - def read(count = nil) - @tell ||= 0 - count = size unless count - retVal = slice(@tell, count) - @tell += count - return retVal - end - - def seek(index, offset) - @tell ||= 0 - case offset - when IO::SEEK_END - newPos = size + index - when IO::SEEK_SET - newPos = index - when IO::SEEK_CUR - newPos = @tell + index - else - raise "Error in test method IOizeString::seek" - end - if (newPos < 0 || newPos >= size) - raise Errno::EINVAL - else - @tell=newPos - end - end - - def reset - @tell = 0 - end -end - -class ZipLocalEntryTest < RUNIT::TestCase - def test_readLocalEntryHeaderOfFirstTestZipEntry - File.open(TestZipFile::TEST_ZIP3.zipName) { - |file| - entry = ZipEntry.readLocalEntry(file) - - assert_equal("", entry.comment) - # Differs from windows and unix because of CR LF - # assert_equal(480, entry.compressedSize) - # assert_equal(0x2a27930f, entry.crc) - # extra field is 21 bytes long - # probably contains some unix attrutes or something - # disabled: assert_equal(nil, entry.extra) - assert_equal(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equal(TestZipFile::TEST_ZIP3.entryNames[0], entry.name) - assert_equal(File.size(TestZipFile::TEST_ZIP3.entryNames[0]), entry.size) - assert(! entry.isDirectory) - } - end - - def test_readLocalEntryFromNonZipFile - File.open("ziptest.rb") { - |file| - assert_equals(nil, ZipEntry.readLocalEntry(file)) - } - end - - def test_readLocalEntryFromTruncatedZipFile - zipFragment="" - File.open(TestZipFile::TEST_ZIP2.zipName) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes - zipFragment.extend(IOizeString).reset - entry = ZipEntry.new - entry.readLocalEntry(zipFragment) - fail "ZipError expected" - rescue ZipError - end - - def test_writeEntry - entry = ZipEntry.new("file.zip", "entryName", "my little comment", - "thisIsSomeExtraInformation", 100, 987654, - ZipEntry::DEFLATED, 400) - writeToFile("localEntryHeader.bin", "centralEntryHeader.bin", entry) - entryReadLocal, entryReadCentral = readFromFile("localEntryHeader.bin", "centralEntryHeader.bin") - compareLocalEntryHeaders(entry, entryReadLocal) - compareCDirEntryHeaders(entry, entryReadCentral) - end - - private - def compareLocalEntryHeaders(entry1, entry2) - assert_equals(entry1.compressedSize , entry2.compressedSize) - assert_equals(entry1.crc , entry2.crc) - assert_equals(entry1.extra , entry2.extra) - assert_equals(entry1.compressionMethod, entry2.compressionMethod) - assert_equals(entry1.name , entry2.name) - assert_equals(entry1.size , entry2.size) - assert_equals(entry1.localHeaderOffset, entry2.localHeaderOffset) - end - - def compareCDirEntryHeaders(entry1, entry2) - compareLocalEntryHeaders(entry1, entry2) - assert_equals(entry1.comment, entry2.comment) - end - - def writeToFile(localFileName, centralFileName, entry) - File.open(localFileName, "wb") { |f| entry.writeLocalEntry(f) } - File.open(centralFileName, "wb") { |f| entry.writeCDirEntry(f) } - end - - def readFromFile(localFileName, centralFileName) - localEntry = nil - cdirEntry = nil - File.open(localFileName, "rb") { |f| localEntry = ZipEntry.readLocalEntry(f) } - File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.readCDirEntry(f) } - return [localEntry, cdirEntry] - end -end - - -module DecompressorTests - # expects @refText and @decompressor - - def test_readEverything - assert_equals(@refText, @decompressor.read) - end - - def test_readInChunks - chunkSize = 5 - while (decompressedChunk = @decompressor.read(chunkSize)) - assert_equals(@refText.slice!(0, chunkSize), decompressedChunk) - end - assert_equals(0, @refText.size) - end -end - -class InflaterTest < RUNIT::TestCase - include DecompressorTests - - def setup - @file = File.new("file1.txt.deflatedData", "rb") - @refText="" - File.open("file1.txt") { |f| @refText = f.read } - @decompressor = Inflater.new(@file) - end - - def teardown - @file.close - end -end - - -class PassThruDecompressorTest < RUNIT::TestCase - include DecompressorTests - TEST_FILE="file1.txt" - def setup - @file = File.new(TEST_FILE) - @refText="" - File.open(TEST_FILE) { |f| @refText = f.read } - @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE)) - end - - def teardown - @file.close - end -end - - -module AssertEntry - def assertNextEntry(filename, zis) - assertEntry(filename, zis, zis.getNextEntry.name) - end - - def assertEntry(filename, zis, entryName) - assert_equals(filename, entryName) - assertEntryContentsForStream(filename, zis, entryName) - end - - def assertEntryContentsForStream(filename, zis, entryName) - File.open(filename, "rb") { - |file| - expected = file.read - actual = zis.read - if (expected != actual) - if (expected.length > 400 || actual.length > 400) - zipEntryFilename=entryName+".zipEntry" - File.open(zipEntryFilename, "wb") { |file| file << actual } - fail("File '#{filename}' is different from '#{zipEntryFilename}'") - else - assert_equals(expected, actual) - end - end - } - end - - def AssertEntry.assertContents(filename, aString) - fileContents = "" - File.open(filename, "rb") { |f| fileContents = f.read } - if (fileContents != aString) - if (expected.length > 400 || actual.length > 400) - stringFile = filename + ".other" - File.open(stringFile, "wb") { |f| f << aString } - fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'") - else - assert_equals(expected, actual) - end - end - end - - def assertStreamContents(zis, testZipFile) - assert(zis != nil) - testZipFile.entryNames.each { - |entryName| - assertNextEntry(entryName, zis) - } - assert_equals(nil, zis.getNextEntry) - end - - def assertTestZipContents(testZipFile) - ZipInputStream.open(testZipFile.zipName) { - |zis| - assertStreamContents(zis, testZipFile) - } - end - - def assertEntryContents(zipFile, entryName, filename = entryName.to_s) - zis = zipFile.getInputStream(entryName) - assertEntryContentsForStream(filename, zis, entryName) - ensure - zis.close if zis - end -end - - - -class ZipInputStreamTest < RUNIT::TestCase - include AssertEntry - - def test_new - zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zipName) - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - zis.close - end - - def test_openWithBlock - ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { - |zis| - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - } - end - - def test_openWithoutBlock - zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - end - - def test_incompleteReads - ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { - |zis| - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[0], entry.name) - assert zis.gets.length > 0 - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[1], entry.name) - assert_equals(0, entry.size) - assert_equals(nil, zis.gets) - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[2], entry.name) - assert zis.gets.length > 0 - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[3], entry.name) - assert zis.gets.length > 0 - } - end - -end - -class TestFiles - RANDOM_ASCII_FILE1 = "randomAscii1.txt" - RANDOM_ASCII_FILE2 = "randomAscii2.txt" - RANDOM_ASCII_FILE3 = "randomAscii3.txt" - RANDOM_BINARY_FILE1 = "randomBinary1.bin" - RANDOM_BINARY_FILE2 = "randomBinary2.bin" - - EMPTY_TEST_DIR = "emptytestdir" - - ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ] - BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ] - TEST_DIRECTORIES = [ EMPTY_TEST_DIR ] - TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten! - - def TestFiles.createTestFiles(recreate) - if (recreate || - ! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) })) - - ASCII_TEST_FILES.each_with_index { - |filename, index| - createRandomAscii(filename, 1E4 * (index+1)) - } - - BINARY_TEST_FILES.each_with_index { - |filename, index| - createRandomBinary(filename, 1E4 * (index+1)) - } - - ensureDir(EMPTY_TEST_DIR) - end - end - - private - def TestFiles.createRandomAscii(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << rand - end - } - end - - def TestFiles.createRandomBinary(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << rand.to_a.pack("V") - end - } - end - - def TestFiles.ensureDir(name) - if File.exists?(name) - return if File.stat(name).directory? - File.delete(name) - end - Dir.mkdir(name) - end - -end - -# For representation and creation of -# test data -class TestZipFile - attr_accessor :zipName, :entryNames, :comment - - def initialize(zipName, entryNames, comment = "") - @zipName=zipName - @entryNames=entryNames - @comment = comment - end - - def TestZipFile.createTestZips(recreate) - files = Dir.entries(".") - if (recreate || - ! (files.index(TEST_ZIP1.zipName) && - files.index(TEST_ZIP2.zipName) && - files.index(TEST_ZIP3.zipName) && - files.index(TEST_ZIP4.zipName) && - files.index("empty.txt") && - files.index("short.txt") && - files.index("longAscii.txt") && - files.index("longBinary.bin") )) - raise "failed to create test zip '#{TEST_ZIP1.zipName}'" unless - system("zip #{TEST_ZIP1.zipName} ziptest.rb") - raise "failed to remove entry from '#{TEST_ZIP1.zipName}'" unless - system("zip #{TEST_ZIP1.zipName} -d ziptest.rb") - - File.open("empty.txt", "w") {} - - File.open("short.txt", "w") { |file| file << "ABCDEF" } - ziptestTxt="" - File.open("ziptest.rb") { |file| ziptestTxt=file.read } - File.open("longAscii.txt", "w") { - |file| - while (file.tell < 1E5) - file << ziptestTxt - end - } - - testBinaryPattern="" - File.open("empty.zip") { |file| testBinaryPattern=file.read } - testBinaryPattern *= 4 - - File.open("longBinary.bin", "wb") { - |file| - while (file.tell < 3E5) - file << testBinaryPattern << rand - end - } - raise "failed to create test zip '#{TEST_ZIP2.zipName}'" unless - system("zip #{TEST_ZIP2.zipName} #{TEST_ZIP2.entryNames.join(' ')}") - - # without bash system interprets everything after echo as parameters to - # echo including | zip -z ... - raise "failed to add comment to test zip '#{TEST_ZIP2.zipName}'" unless - system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zipName}\"") - - raise "failed to create test zip '#{TEST_ZIP3.zipName}'" unless - system("zip #{TEST_ZIP3.zipName} #{TEST_ZIP3.entryNames.join(' ')}") - - raise "failed to create test zip '#{TEST_ZIP4.zipName}'" unless - system("zip #{TEST_ZIP4.zipName} #{TEST_ZIP4.entryNames.join(' ')}") - end - rescue - raise $!.to_s + - "\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" + - "to create test data. If you don't have it you can download\n" + - "the necessary test files at http://sf.net/projects/rubyzip." - end - - TEST_ZIP1 = TestZipFile.new("empty.zip", []) - TEST_ZIP2 = TestZipFile.new("4entry.zip", %w{ longAscii.txt empty.txt short.txt longBinary.bin}, - "my zip comment") - TEST_ZIP3 = TestZipFile.new("test1.zip", %w{ file1.txt }) - TEST_ZIP4 = TestZipFile.new("zipWithDir.zip", [ "file1.txt", - TestFiles::EMPTY_TEST_DIR]) -end - - -class AbstractOutputStreamTest < RUNIT::TestCase - class TestOutputStream - include AbstractOutputStream - - attr_accessor :buffer - - def initialize - @buffer = "" - end - - def << (data) - @buffer << data - self - end - end - - def setup - @outputStream = TestOutputStream.new - - @origCommaSep = $, - @origOutputSep = $\ - end - - def teardown - $, = @origCommaSep - $\ = @origOutputSep - end - - def test_write - count = @outputStream.write("a little string") - assert_equals("a little string", @outputStream.buffer) - assert_equals("a little string".length, count) - - count = @outputStream.write(". a little more") - assert_equals("a little string. a little more", @outputStream.buffer) - assert_equals(". a little more".length, count) - end - - def test_print - $\ = nil # record separator set to nil - @outputStream.print("hello") - assert_equals("hello", @outputStream.buffer) - - @outputStream.print(" world.") - assert_equals("hello world.", @outputStream.buffer) - - @outputStream.print(" You ok ", "out ", "there?") - assert_equals("hello world. You ok out there?", @outputStream.buffer) - - $\ = "\n" - @outputStream.print - assert_equals("hello world. You ok out there?\n", @outputStream.buffer) - - @outputStream.print("I sure hope so!") - assert_equals("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer) - - $, = "X" - @outputStream.buffer = "" - @outputStream.print("monkey", "duck", "zebra") - assert_equals("monkeyXduckXzebra\n", @outputStream.buffer) - - $\ = nil - @outputStream.buffer = "" - @outputStream.print(20) - assert_equals("20", @outputStream.buffer) - end - - def test_printf - @outputStream.printf("%d %04x", 123, 123) - assert_equals("123 007b", @outputStream.buffer) - end - - def test_putc - @outputStream.putc("A") - assert_equals("A", @outputStream.buffer) - @outputStream.putc(65) - assert_equals("AA", @outputStream.buffer) - end - - def test_puts - @outputStream.puts - assert_equals("\n", @outputStream.buffer) - - @outputStream.puts("hello", "world") - assert_equals("\nhello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts("hello\n", "world\n") - assert_equals("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"]) - assert_equals("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"], "bingo") - assert_equals("hello\nworld\nbingo\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(16, 20, 50, "hello") - assert_equals("16\n20\n50\nhello\n", @outputStream.buffer) - end -end - - -module CrcTest - def runCrcTest(compressorClass) - str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed." - fakeOut = AbstractOutputStreamTest::TestOutputStream.new - - deflater = compressorClass.new(fakeOut) - deflater << str - assert_equals(0x919920fc, deflater.crc) - end -end - - - -class PassThruCompressorTest < RUNIT::TestCase - include CrcTest - - def test_size - File.open("dummy.txt", "wb") { - |file| - compressor = PassThruCompressor.new(file) - - assert_equals(0, compressor.size) - - t1 = "hello world" - t2 = "" - t3 = "bingo" - - compressor << t1 - assert_equals(compressor.size, t1.size) - - compressor << t2 - assert_equals(compressor.size, t1.size + t2.size) - - compressor << t3 - assert_equals(compressor.size, t1.size + t2.size + t3.size) - } - end - - def test_crc - runCrcTest(PassThruCompressor) - end -end - -class DeflaterTest < RUNIT::TestCase - include CrcTest - - def test_outputOperator - txt = loadFile("ziptest.rb") - deflate(txt, "deflatertest.bin") - inflatedTxt = inflate("deflatertest.bin") - assert_equals(txt, inflatedTxt) - end - - private - def loadFile(fileName) - txt = nil - File.open(fileName, "rb") { |f| txt = f.read } - end - - def deflate(data, fileName) - File.open(fileName, "wb") { - |file| - deflater = Deflater.new(file) - deflater << data - deflater.finish - assert_equals(deflater.size, data.size) - file << "trailing data for zlib with -MAX_WBITS" - } - end - - def inflate(fileName) - txt = nil - File.open(fileName, "rb") { - |file| - inflater = Inflater.new(file) - txt = inflater.read - } - end - - def test_crc - runCrcTest(Deflater) - end -end - -class ZipOutputStreamTest < RUNIT::TestCase - include AssertEntry - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zipName = "output.zip" - - def test_new - zos = ZipOutputStream.new(TEST_ZIP.zipName) - zos.comment = TEST_ZIP.comment - writeTestZip(zos) - zos.close - assertTestZipContents(TEST_ZIP) - end - - def test_open - ZipOutputStream.open(TEST_ZIP.zipName) { - |zos| - zos.comment = TEST_ZIP.comment - writeTestZip(zos) - } - assertTestZipContents(TEST_ZIP) - end - - def test_writingToClosedStream - assertIOErrorInClosedStream { |zos| zos << "hello world" } - assertIOErrorInClosedStream { |zos| zos.puts "hello world" } - assertIOErrorInClosedStream { |zos| zos.write "hello world" } - end - - def test_cannotOpenFile - name = TestFiles::EMPTY_TEST_DIR - begin - zos = ZipOutputStream.open(name) - rescue Exception - assert($!.kind_of?(Errno::EISDIR) || # Linux - $!.kind_of?(Errno::EEXIST) || # Windows/cygwin - $!.kind_of?(Errno::EACCES), # Windows - "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.type}") - end - end - - def assertIOErrorInClosedStream - assert_exception(IOError) { - zos = ZipOutputStream.new("test_putOnClosedStream.zip") - zos.close - yield zos - } - end - - def writeTestZip(zos) - TEST_ZIP.entryNames.each { - |entryName| - zos.putNextEntry(entryName) - File.open(entryName, "rb") { |f| zos.write(f.read) } - } - end -end - - - -module Enumerable - def compareEnumerables(otherEnumerable) - otherAsArray = otherEnumerable.to_a - index=0 - each_with_index { - |element, index| - return false unless yield(element, otherAsArray[index]) - } - return index+1 == otherAsArray.size - end -end - - -class ZipCentralDirectoryEntryTest < RUNIT::TestCase - - def test_readFromStream - File.open("testDirectory.bin", "rb") { - |file| - entry = ZipEntry.readCDirEntry(file) - - assert_equals("longAscii.txt", entry.name) - assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equals(106490, entry.size) - assert_equals(3784, entry.compressedSize) - assert_equals(0xfcd1799c, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("empty.txt", entry.name) - assert_equals(ZipEntry::STORED, entry.compressionMethod) - assert_equals(0, entry.size) - assert_equals(0, entry.compressedSize) - assert_equals(0x0, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("short.txt", entry.name) - assert_equals(ZipEntry::STORED, entry.compressionMethod) - assert_equals(6, entry.size) - assert_equals(6, entry.compressedSize) - assert_equals(0xbb76fe69, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("longBinary.bin", entry.name) - assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equals(1000024, entry.size) - assert_equals(70847, entry.compressedSize) - assert_equals(0x10da7d59, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals(nil, entry) -# Fields that are not check by this test: -# version made by 2 bytes -# version needed to extract 2 bytes -# general purpose bit flag 2 bytes -# last mod file time 2 bytes -# last mod file date 2 bytes -# compressed size 4 bytes -# uncompressed size 4 bytes -# disk number start 2 bytes -# internal file attributes 2 bytes -# external file attributes 4 bytes -# relative offset of local header 4 bytes - -# file name (variable size) -# extra field (variable size) -# file comment (variable size) - - } - end - - def test_ReadEntryFromTruncatedZipFile - fragment="" - File.open("testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes - fragment.extend(IOizeString) - entry = ZipEntry.new - entry.readCDirEntry(fragment) - fail "ZipError expected" - rescue ZipError - end - -end - -class ZipCentralDirectoryTest < RUNIT::TestCase - - def test_readFromStream - File.open(TestZipFile::TEST_ZIP2.zipName, "rb") { - |zipFile| - cdir = ZipCentralDirectory.readFromStream(zipFile) - - assert_equals(TestZipFile::TEST_ZIP2.entryNames.size, cdir.size) - assert(cdir.compareEnumerables(TestZipFile::TEST_ZIP2.entryNames) { - |cdirEntry, testEntryName| - cdirEntry.name == testEntryName - }) - assert_equals(TestZipFile::TEST_ZIP2.comment, cdir.comment) - } - end - - def test_readFromInvalidStream - File.open("ziptest.rb", "rb") { - |zipFile| - cdir = ZipCentralDirectory.new - cdir.readFromStream(zipFile) - } - fail "ZipError expected!" - rescue ZipError - end - - def test_ReadFromTruncatedZipFile - fragment="" - File.open("testDirectory.bin") { |f| fragment = f.read } - fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete - fragment.extend(IOizeString) - entry = ZipCentralDirectory.new - entry.readFromStream(fragment) - fail "ZipError expected" - rescue ZipError - end - - def test_writeToStream - entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ] - cdir = ZipCentralDirectory.new(entries, "my zip comment") - File.open("cdirtest.bin", "wb") { |f| cdir.writeToStream(f) } - cdirReadback = ZipCentralDirectory.new - File.open("cdirtest.bin", "rb") { |f| cdirReadback.readFromStream(f) } - - assert_equals(cdir.entries, cdirReadback.entries) - end - - def test_equality - cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - assert_equals(cdir1, cdir1) - assert_equals(cdir1, cdir2) - - assert(cdir1 != cdir3) - assert(cdir2 != cdir3) - assert(cdir2 != cdir3) - assert(cdir3 != cdir4) - - assert(cdir3 != "hello") - end -end - - -class BasicZipFileTest < RUNIT::TestCase - include AssertEntry - - def setup - @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zipName) - @testEntryNameIndex=0 - end - - def nextTestEntryName - retVal=TestZipFile::TEST_ZIP2.entryNames[@testEntryNameIndex] - @testEntryNameIndex+=1 - return retVal - end - - def test_entries - assert_equals(TestZipFile::TEST_ZIP2.entryNames, @zipFile.entries.map {|e| e.name} ) - end - - def test_each - @zipFile.each { - |entry| - assert_equals(nextTestEntryName, entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_foreach - ZipFile.foreach(TestZipFile::TEST_ZIP2.zipName) { - |entry| - assert_equals(nextTestEntryName, entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_getInputStream - @zipFile.each { - |entry| - assertEntry(nextTestEntryName, @zipFile.getInputStream(entry), - entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_getInputStreamBlock - fileAndEntryName = @zipFile.entries.first.name - @zipFile.getInputStream(fileAndEntryName) { - |zis| - assertEntryContentsForStream(fileAndEntryName, - zis, - fileAndEntryName) - } - end -end - -class CommonZipFileFixture < RUNIT::TestCase - include AssertEntry - - EMPTY_FILENAME = "emptyZipFile.zip" - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zipName = "4entry_copy.zip" - - def setup - File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME) - File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) - end -end - -class ZipFileTest < CommonZipFileFixture - - def test_createFromScratch - comment = "a short comment" - - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.comment = comment - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equals(comment, zfRead.comment) - assert_equals(0, zfRead.entries.length) - end - - def test_add - srcFile = "ziptest.rb" - entryName = "newEntryName.rb" - assert(File.exists? srcFile) - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.add(entryName, srcFile) - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equals("", zfRead.comment) - assert_equals(1, zfRead.entries.length) - assert_equals(entryName, zfRead.entries.first.name) - AssertEntry.assertContents(srcFile, - zfRead.getInputStream(entryName) { |zis| zis.read }) - end - - def test_addExistingEntryName - assert_exception(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.add(zf.entries.first.name, "ziptest.rb") - } - } - end - - def test_addExistingEntryNameReplace - gotCalled = false - replacedEntry = nil - ZipFile.open(TEST_ZIP.zipName) { - |zf| - replacedEntry = zf.entries.first.name - zf.add(replacedEntry, "ziptest.rb") { gotCalled = true; true } - } - assert(gotCalled) - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assertContains(zf, replacedEntry, "ziptest.rb") - } - end - - def test_addDirectory - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR) - } - ZipFile.open(TEST_ZIP.zipName) { - |zf| - dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" } - assert(dirEntry.isDirectory) - } - end - - def test_remove - entryToRemove, *remainingEntries = TEST_ZIP.entryNames - - File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) - - zf = ZipFile.new(TEST_ZIP.zipName) - assert(zf.entries.map { |e| e.name }.include?(entryToRemove)) - zf.remove(entryToRemove) - assert(! zf.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equals(zf.entries.map {|x| x.name }.sort, remainingEntries.sort) - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equals(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort) - zfRead.close - end - - - def test_rename - entryToRename, *remainingEntries = TEST_ZIP.entryNames - - zf = ZipFile.new(TEST_ZIP.zipName) - assert(zf.entries.map { |e| e.name }.include? entryToRename) - - newName = "changed name" - assert(! zf.entries.map { |e| e.name }.include?(newName)) - - zf.rename(entryToRename, newName) - assert(zf.entries.map { |e| e.name }.include? newName) - - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(zfRead.entries.map { |e| e.name }.include? newName) - zfRead.close - end - - def test_renameToExistingEntry - oldEntries = nil - ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } - - assert_exception(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.rename(zf.entries[0], zf.entries[1].name) - } - } - - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_equals(oldEntries.map{ |e| e.name }, zf.entries.map{ |e| e.name }) - } - end - - def test_renameToExistingEntryOverwrite - oldEntries = nil - ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } - - gotCalled = false - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true } - } - - assert(gotCalled) - oldEntries.delete_at(0) - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_equals(oldEntries.map{ |e| e.name }, - zf.entries.map{ |e| e.name }) - } - end - - def test_renameNonEntry - nonEntry = "bogusEntry" - targetEntry = "targetEntryName" - zf = ZipFile.new(TEST_ZIP.zipName) - assert(! zf.entries.include?(nonEntry)) - assert_exception(ZipNoSuchEntryError) { - zf.rename(nonEntry, targetEntry) - } - zf.commit - assert(! zf.entries.include?(targetEntry)) - ensure - zf.close - end - - def test_renameEntryToExistingEntry - entry1, entry2, *remaining = TEST_ZIP.entryNames - zf = ZipFile.new(TEST_ZIP.zipName) - assert_exception(ZipEntryExistsError) { - zf.rename(entry1, entry2) - } - ensure - zf.close - end - - def test_replace - unchangedEntries = TEST_ZIP.entryNames.dup - entryToReplace = unchangedEntries.delete_at(2) - newEntrySrcFilename = "ziptest.rb" - - zf = ZipFile.new(TEST_ZIP.zipName) - zf.replace(entryToReplace, newEntrySrcFilename) - - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - AssertEntry::assertContents(newEntrySrcFilename, - zfRead.getInputStream(entryToReplace) { |is| is.read }) - zfRead.close - end - - def test_replaceNonEntry - entryToReplace = "nonExistingEntryname" - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_exception(ZipNoSuchEntryError) { - zf.replace(entryToReplace, "ziptest.rb") - } - } - end - - def test_commit - newName = "renamedFirst" - zf = ZipFile.new(TEST_ZIP.zipName) - oldName = zf.entries.first - zf.rename(oldName, newName) - zf.commit - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(zfRead.entries.detect { |e| e.name == newName } != nil) - assert(zfRead.entries.detect { |e| e.name == oldName } == nil) - zfRead.close - - zf.close - end - - # This test tests that after commit, you - # can delete the file you used to add the entry to the zip file - # with - def test_commitUseZipEntry - File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt") - zf = ZipFile.open(TEST_ZIP.zipName) - zf.add("okToDelete.txt", "okToDelete.txt") - assertContains(zf, "okToDelete.txt") - zf.commit - File.move("okToDelete.txt", "okToDeleteMoved.txt") - assertContains(zf, "okToDelete.txt", "okToDeleteMoved.txt") - end - -# def test_close -# zf = ZipFile.new(TEST_ZIP.zipName) -# zf.close -# assert_exception(IOError) { -# zf.extract(TEST_ZIP.entryNames.first, "hullubullu") -# } -# end - - def test_compound1 - renamedName = "renamedName" - originalEntries = [] - begin - zf = ZipFile.new(TEST_ZIP.zipName) - originalEntries = zf.entries.dup - - assertNotContains(zf, TestFiles::RANDOM_ASCII_FILE1) - zf.add(TestFiles::RANDOM_ASCII_FILE1, - TestFiles::RANDOM_ASCII_FILE1) - assertContains(zf, TestFiles::RANDOM_ASCII_FILE1) - - zf.rename(zf.entries[0], renamedName) - assertContains(zf, renamedName) - - TestFiles::BINARY_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assertContains(zf, filename) - } - - assertContains(zf, originalEntries.last.to_s) - zf.remove(originalEntries.last.to_s) - assertNotContains(zf, originalEntries.last.to_s) - - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zipName) - assertContains(zfRead, TestFiles::RANDOM_ASCII_FILE1) - assertContains(zfRead, renamedName) - TestFiles::BINARY_TEST_FILES.each { - |filename| - assertContains(zfRead, filename) - } - assertNotContains(zfRead, originalEntries.last.to_s) - ensure - zfRead.close - end - end - - def test_compound2 - begin - zf = ZipFile.new(TEST_ZIP.zipName) - originalEntries = zf.entries.dup - - originalEntries.each { - |entry| - zf.remove(entry) - assertNotContains(zf, entry) - } - assert(zf.entries.empty?) - - TestFiles::ASCII_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assertContains(zf, filename) - } - assert_equals(zf.entries.map { |e| e.name }, TestFiles::ASCII_TEST_FILES) - - zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName") - assertNotContains(zf, TestFiles::ASCII_TEST_FILES[0]) - assertContains(zf, "newName") - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zipName) - asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup - asciiTestFiles.shift - asciiTestFiles.each { - |filename| - assertContains(zf, filename) - } - - assertContains(zf, "newName") - ensure - zfRead.close - end - end - - private - def assertContains(zf, entryName, filename = entryName) - assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}") - assertEntryContents(zf, entryName, filename) if File.exists?(filename) - end - - def assertNotContains(zf, entryName) - assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}") - end -end - -class ZipFileExtractTest < CommonZipFileFixture - EXTRACTED_FILENAME = "extEntry" - ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entryNames.reverse - - def setup - super - File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME) - end - - def test_extract - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME) - - assert(File.exists? EXTRACTED_FILENAME) - AssertEntry::assertContents(EXTRACTED_FILENAME, - zf.getInputStream(ENTRY_TO_EXTRACT) { |is| is.read }) - } - end - - def test_extractExists - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - assert_exception(ZipDestinationFileExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) - } - } - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert_equals(writtenText, f.read) - } - end - - def test_extractExistsOverwrite - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - gotCalled = false - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) { gotCalled = true; true } - } - - assert(gotCalled) - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert(writtenText != f.read) - } - end - - def test_extractNonEntry - zf = ZipFile.new(TEST_ZIP.zipName) - assert_exception(ZipNoSuchEntryError) { zf.extract("nonExistingEntry", "nonExistingEntry") } - ensure - zf.close if zf - end - - def test_extractNonEntry2 - outFile = "outfile" - assert_exception(ZipNoSuchEntryError) { - zf = ZipFile.new(TEST_ZIP.zipName) - nonEntry = "hotdog-diddelidoo" - assert(! zf.entries.include?(nonEntry)) - zf.extract(nonEntry, outFile) - zf.close - } - assert(! File.exists?(outFile)) - end - -end - -class ZipFileExtractDirectoryTest < CommonZipFileFixture - TEST_OUT_NAME = "emptyOutDir" - - def openZip(&aProc) - assert(aProc != nil) - ZipFile.open(TestZipFile::TEST_ZIP4.zipName, &aProc) - end - - def extractTestDir(&aProc) - openZip { - |zf| - zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc) - } - end - - def setup - super - - Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME - File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME - end - - def test_extractDirectory - extractTestDir - assert(File.directory? TEST_OUT_NAME) - end - - def test_extractDirectoryExistsAsDir - Dir.mkdir TEST_OUT_NAME - extractTestDir - assert(File.directory? TEST_OUT_NAME) - end - - def test_extractDirectoryExistsAsFile - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - assert_exception(ZipDestinationFileExistsError) { extractTestDir } - end - - def test_extractDirectoryExistsAsFileOverwrite - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - gotCalled = false - extractTestDir { - |entry, destPath| - gotCalled = true - assert_equals(TEST_OUT_NAME, destPath) - assert(entry.isDirectory) - true - } - assert(gotCalled) - assert(File.directory? TEST_OUT_NAME) - end -end - - -TestFiles::createTestFiles(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) -TestZipFile::createTestZips(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) -exit if ARGV.index("recreateonly") != nil - -#require 'runit/cui/testrunner' -#RUNIT::CUI::TestRunner.run(ZipFileTest.suite) - -# Copyright (C) 2002 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. -#!/usr/bin/env ruby - -$VERBOSE = true - -require 'rubyunit' -require 'zip' - -include Zip - -Dir.chdir "test" - -class AbstractInputStreamTest < RUNIT::TestCase - # AbstractInputStream subclass that provides a read method - - TEST_LINES = [ "Hello world#{$/}", - "this is the second line#{$/}", - "this is the last line"] - TEST_STRING = TEST_LINES.join - class TestAbstractInputStream - include AbstractInputStream - def initialize(aString) - @contents = aString - @readPointer = 0 - end - - def read(charsToRead) - retVal=@contents[@readPointer, charsToRead] - @readPointer+=charsToRead - return retVal - end - - def produceInput - read(100) - end - - def inputFinished? - @contents[@readPointer] == nil - end - end - - def setup - @io = TestAbstractInputStream.new(TEST_STRING) - end - - def test_gets - assert_equals(TEST_LINES[0], @io.gets) - assert_equals(TEST_LINES[1], @io.gets) - assert_equals(TEST_LINES[2], @io.gets) - assert_equals(nil, @io.gets) - end - - def test_getsMultiCharSeperator - assert_equals("Hell", @io.gets("ll")) - assert_equals("o world#{$/}this is the second l", @io.gets("d l")) - end - - def test_each_line - lineNumber=0 - @io.each_line { - |line| - assert_equals(TEST_LINES[lineNumber], line) - lineNumber+=1 - } - end - - def test_readlines - assert_equals(TEST_LINES, @io.readlines) - end - - def test_readline - test_gets - begin - @io.readline - fail "EOFError expected" - rescue EOFError - end - end -end - -class ZipEntryTest < RUNIT::TestCase - TEST_ZIPFILE = "someZipFile.zip" - TEST_COMMENT = "a comment" - TEST_COMPRESSED_SIZE = 1234 - TEST_CRC = 325324 - TEST_EXTRA = "Some data here" - TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED - TEST_NAME = "entry name" - TEST_SIZE = 8432 - TEST_ISDIRECTORY = false - - def test_constructorAndGetters - entry = ZipEntry.new(TEST_ZIPFILE, - TEST_NAME, - TEST_COMMENT, - TEST_EXTRA, - TEST_COMPRESSED_SIZE, - TEST_CRC, - TEST_COMPRESSIONMETHOD, - TEST_SIZE) - - assert_equals(TEST_COMMENT, entry.comment) - assert_equals(TEST_COMPRESSED_SIZE, entry.compressedSize) - assert_equals(TEST_CRC, entry.crc) - assert_equals(TEST_EXTRA, entry.extra) - assert_equals(TEST_COMPRESSIONMETHOD, entry.compressionMethod) - assert_equals(TEST_NAME, entry.name) - assert_equals(TEST_SIZE, entry.size) - assert_equals(TEST_ISDIRECTORY, entry.isDirectory) - end - - def test_equality - entry1 = ZipEntry.new("file.zip", "name", "isNotCompared", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 1234, - ZipEntry::DEFLATED, 10000) - entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::DEFLATED, 10000) - entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 10000) - entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 100000) - - assert_equals(entry1, entry1) - assert_equals(entry1, entry2) - - assert(entry2 != entry3) - assert(entry3 != entry4) - assert(entry4 != entry5) - assert(entry5 != entry6) - assert(entry6 != entry7) - assert(entry7 != entry8) - - assert(entry7 != "hello") - assert(entry7 != 12) - end -end - -module IOizeString - attr_reader :tell - - def read(count = nil) - @tell ||= 0 - count = size unless count - retVal = slice(@tell, count) - @tell += count - return retVal - end - - def seek(index, offset) - @tell ||= 0 - case offset - when IO::SEEK_END - newPos = size + index - when IO::SEEK_SET - newPos = index - when IO::SEEK_CUR - newPos = @tell + index - else - raise "Error in test method IOizeString::seek" - end - if (newPos < 0 || newPos >= size) - raise Errno::EINVAL - else - @tell=newPos - end - end - - def reset - @tell = 0 - end -end - -class ZipLocalEntryTest < RUNIT::TestCase - def test_readLocalEntryHeaderOfFirstTestZipEntry - File.open(TestZipFile::TEST_ZIP3.zipName) { - |file| - entry = ZipEntry.readLocalEntry(file) - - assert_equal("", entry.comment) - # Differs from windows and unix because of CR LF - # assert_equal(480, entry.compressedSize) - # assert_equal(0x2a27930f, entry.crc) - # extra field is 21 bytes long - # probably contains some unix attrutes or something - # disabled: assert_equal(nil, entry.extra) - assert_equal(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equal(TestZipFile::TEST_ZIP3.entryNames[0], entry.name) - assert_equal(File.size(TestZipFile::TEST_ZIP3.entryNames[0]), entry.size) - assert(! entry.isDirectory) - } - end - - def test_readLocalEntryFromNonZipFile - File.open("ziptest.rb") { - |file| - assert_equals(nil, ZipEntry.readLocalEntry(file)) - } - end - - def test_readLocalEntryFromTruncatedZipFile - zipFragment="" - File.open(TestZipFile::TEST_ZIP2.zipName) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes - zipFragment.extend(IOizeString).reset - entry = ZipEntry.new - entry.readLocalEntry(zipFragment) - fail "ZipError expected" - rescue ZipError - end - - def test_writeEntry - entry = ZipEntry.new("file.zip", "entryName", "my little comment", - "thisIsSomeExtraInformation", 100, 987654, - ZipEntry::DEFLATED, 400) - writeToFile("localEntryHeader.bin", "centralEntryHeader.bin", entry) - entryReadLocal, entryReadCentral = readFromFile("localEntryHeader.bin", "centralEntryHeader.bin") - compareLocalEntryHeaders(entry, entryReadLocal) - compareCDirEntryHeaders(entry, entryReadCentral) - end - - private - def compareLocalEntryHeaders(entry1, entry2) - assert_equals(entry1.compressedSize , entry2.compressedSize) - assert_equals(entry1.crc , entry2.crc) - assert_equals(entry1.extra , entry2.extra) - assert_equals(entry1.compressionMethod, entry2.compressionMethod) - assert_equals(entry1.name , entry2.name) - assert_equals(entry1.size , entry2.size) - assert_equals(entry1.localHeaderOffset, entry2.localHeaderOffset) - end - - def compareCDirEntryHeaders(entry1, entry2) - compareLocalEntryHeaders(entry1, entry2) - assert_equals(entry1.comment, entry2.comment) - end - - def writeToFile(localFileName, centralFileName, entry) - File.open(localFileName, "wb") { |f| entry.writeLocalEntry(f) } - File.open(centralFileName, "wb") { |f| entry.writeCDirEntry(f) } - end - - def readFromFile(localFileName, centralFileName) - localEntry = nil - cdirEntry = nil - File.open(localFileName, "rb") { |f| localEntry = ZipEntry.readLocalEntry(f) } - File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.readCDirEntry(f) } - return [localEntry, cdirEntry] - end -end - - -module DecompressorTests - # expects @refText and @decompressor - - def test_readEverything - assert_equals(@refText, @decompressor.read) - end - - def test_readInChunks - chunkSize = 5 - while (decompressedChunk = @decompressor.read(chunkSize)) - assert_equals(@refText.slice!(0, chunkSize), decompressedChunk) - end - assert_equals(0, @refText.size) - end -end - -class InflaterTest < RUNIT::TestCase - include DecompressorTests - - def setup - @file = File.new("file1.txt.deflatedData", "rb") - @refText="" - File.open("file1.txt") { |f| @refText = f.read } - @decompressor = Inflater.new(@file) - end - - def teardown - @file.close - end -end - - -class PassThruDecompressorTest < RUNIT::TestCase - include DecompressorTests - TEST_FILE="file1.txt" - def setup - @file = File.new(TEST_FILE) - @refText="" - File.open(TEST_FILE) { |f| @refText = f.read } - @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE)) - end - - def teardown - @file.close - end -end - - -module AssertEntry - def assertNextEntry(filename, zis) - assertEntry(filename, zis, zis.getNextEntry.name) - end - - def assertEntry(filename, zis, entryName) - assert_equals(filename, entryName) - assertEntryContentsForStream(filename, zis, entryName) - end - - def assertEntryContentsForStream(filename, zis, entryName) - File.open(filename, "rb") { - |file| - expected = file.read - actual = zis.read - if (expected != actual) - if (expected.length > 400 || actual.length > 400) - zipEntryFilename=entryName+".zipEntry" - File.open(zipEntryFilename, "wb") { |file| file << actual } - fail("File '#{filename}' is different from '#{zipEntryFilename}'") - else - assert_equals(expected, actual) - end - end - } - end - - def AssertEntry.assertContents(filename, aString) - fileContents = "" - File.open(filename, "rb") { |f| fileContents = f.read } - if (fileContents != aString) - if (expected.length > 400 || actual.length > 400) - stringFile = filename + ".other" - File.open(stringFile, "wb") { |f| f << aString } - fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'") - else - assert_equals(expected, actual) - end - end - end - - def assertStreamContents(zis, testZipFile) - assert(zis != nil) - testZipFile.entryNames.each { - |entryName| - assertNextEntry(entryName, zis) - } - assert_equals(nil, zis.getNextEntry) - end - - def assertTestZipContents(testZipFile) - ZipInputStream.open(testZipFile.zipName) { - |zis| - assertStreamContents(zis, testZipFile) - } - end - - def assertEntryContents(zipFile, entryName, filename = entryName.to_s) - zis = zipFile.getInputStream(entryName) - assertEntryContentsForStream(filename, zis, entryName) - ensure - zis.close if zis - end -end - - - -class ZipInputStreamTest < RUNIT::TestCase - include AssertEntry - - def test_new - zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zipName) - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - zis.close - end - - def test_openWithBlock - ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { - |zis| - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - } - end - - def test_openWithoutBlock - zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - end - - def test_incompleteReads - ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { - |zis| - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[0], entry.name) - assert zis.gets.length > 0 - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[1], entry.name) - assert_equals(0, entry.size) - assert_equals(nil, zis.gets) - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[2], entry.name) - assert zis.gets.length > 0 - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[3], entry.name) - assert zis.gets.length > 0 - } - end - -end - -class TestFiles - RANDOM_ASCII_FILE1 = "randomAscii1.txt" - RANDOM_ASCII_FILE2 = "randomAscii2.txt" - RANDOM_ASCII_FILE3 = "randomAscii3.txt" - RANDOM_BINARY_FILE1 = "randomBinary1.bin" - RANDOM_BINARY_FILE2 = "randomBinary2.bin" - - EMPTY_TEST_DIR = "emptytestdir" - - ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ] - BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ] - TEST_DIRECTORIES = [ EMPTY_TEST_DIR ] - TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten! - - def TestFiles.createTestFiles(recreate) - if (recreate || - ! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) })) - - ASCII_TEST_FILES.each_with_index { - |filename, index| - createRandomAscii(filename, 1E4 * (index+1)) - } - - BINARY_TEST_FILES.each_with_index { - |filename, index| - createRandomBinary(filename, 1E4 * (index+1)) - } - - ensureDir(EMPTY_TEST_DIR) - end - end - - private - def TestFiles.createRandomAscii(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << rand - end - } - end - - def TestFiles.createRandomBinary(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << rand.to_a.pack("V") - end - } - end - - def TestFiles.ensureDir(name) - if File.exists?(name) - return if File.stat(name).directory? - File.delete(name) - end - Dir.mkdir(name) - end - -end - -# For representation and creation of -# test data -class TestZipFile - attr_accessor :zipName, :entryNames, :comment - - def initialize(zipName, entryNames, comment = "") - @zipName=zipName - @entryNames=entryNames - @comment = comment - end - - def TestZipFile.createTestZips(recreate) - files = Dir.entries(".") - if (recreate || - ! (files.index(TEST_ZIP1.zipName) && - files.index(TEST_ZIP2.zipName) && - files.index(TEST_ZIP3.zipName) && - files.index(TEST_ZIP4.zipName) && - files.index("empty.txt") && - files.index("short.txt") && - files.index("longAscii.txt") && - files.index("longBinary.bin") )) - raise "failed to create test zip '#{TEST_ZIP1.zipName}'" unless - system("zip #{TEST_ZIP1.zipName} ziptest.rb") - raise "failed to remove entry from '#{TEST_ZIP1.zipName}'" unless - system("zip #{TEST_ZIP1.zipName} -d ziptest.rb") - - File.open("empty.txt", "w") {} - - File.open("short.txt", "w") { |file| file << "ABCDEF" } - ziptestTxt="" - File.open("ziptest.rb") { |file| ziptestTxt=file.read } - File.open("longAscii.txt", "w") { - |file| - while (file.tell < 1E5) - file << ziptestTxt - end - } - - testBinaryPattern="" - File.open("empty.zip") { |file| testBinaryPattern=file.read } - testBinaryPattern *= 4 - - File.open("longBinary.bin", "wb") { - |file| - while (file.tell < 3E5) - file << testBinaryPattern << rand - end - } - raise "failed to create test zip '#{TEST_ZIP2.zipName}'" unless - system("zip #{TEST_ZIP2.zipName} #{TEST_ZIP2.entryNames.join(' ')}") - - # without bash system interprets everything after echo as parameters to - # echo including | zip -z ... - raise "failed to add comment to test zip '#{TEST_ZIP2.zipName}'" unless - system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zipName}\"") - - raise "failed to create test zip '#{TEST_ZIP3.zipName}'" unless - system("zip #{TEST_ZIP3.zipName} #{TEST_ZIP3.entryNames.join(' ')}") - - raise "failed to create test zip '#{TEST_ZIP4.zipName}'" unless - system("zip #{TEST_ZIP4.zipName} #{TEST_ZIP4.entryNames.join(' ')}") - end - rescue - raise $!.to_s + - "\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" + - "to create test data. If you don't have it you can download\n" + - "the necessary test files at http://sf.net/projects/rubyzip." - end - - TEST_ZIP1 = TestZipFile.new("empty.zip", []) - TEST_ZIP2 = TestZipFile.new("4entry.zip", %w{ longAscii.txt empty.txt short.txt longBinary.bin}, - "my zip comment") - TEST_ZIP3 = TestZipFile.new("test1.zip", %w{ file1.txt }) - TEST_ZIP4 = TestZipFile.new("zipWithDir.zip", [ "file1.txt", - TestFiles::EMPTY_TEST_DIR]) -end - - -class AbstractOutputStreamTest < RUNIT::TestCase - class TestOutputStream - include AbstractOutputStream - - attr_accessor :buffer - - def initialize - @buffer = "" - end - - def << (data) - @buffer << data - self - end - end - - def setup - @outputStream = TestOutputStream.new - - @origCommaSep = $, - @origOutputSep = $\ - end - - def teardown - $, = @origCommaSep - $\ = @origOutputSep - end - - def test_write - count = @outputStream.write("a little string") - assert_equals("a little string", @outputStream.buffer) - assert_equals("a little string".length, count) - - count = @outputStream.write(". a little more") - assert_equals("a little string. a little more", @outputStream.buffer) - assert_equals(". a little more".length, count) - end - - def test_print - $\ = nil # record separator set to nil - @outputStream.print("hello") - assert_equals("hello", @outputStream.buffer) - - @outputStream.print(" world.") - assert_equals("hello world.", @outputStream.buffer) - - @outputStream.print(" You ok ", "out ", "there?") - assert_equals("hello world. You ok out there?", @outputStream.buffer) - - $\ = "\n" - @outputStream.print - assert_equals("hello world. You ok out there?\n", @outputStream.buffer) - - @outputStream.print("I sure hope so!") - assert_equals("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer) - - $, = "X" - @outputStream.buffer = "" - @outputStream.print("monkey", "duck", "zebra") - assert_equals("monkeyXduckXzebra\n", @outputStream.buffer) - - $\ = nil - @outputStream.buffer = "" - @outputStream.print(20) - assert_equals("20", @outputStream.buffer) - end - - def test_printf - @outputStream.printf("%d %04x", 123, 123) - assert_equals("123 007b", @outputStream.buffer) - end - - def test_putc - @outputStream.putc("A") - assert_equals("A", @outputStream.buffer) - @outputStream.putc(65) - assert_equals("AA", @outputStream.buffer) - end - - def test_puts - @outputStream.puts - assert_equals("\n", @outputStream.buffer) - - @outputStream.puts("hello", "world") - assert_equals("\nhello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts("hello\n", "world\n") - assert_equals("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"]) - assert_equals("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"], "bingo") - assert_equals("hello\nworld\nbingo\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(16, 20, 50, "hello") - assert_equals("16\n20\n50\nhello\n", @outputStream.buffer) - end -end - - -module CrcTest - def runCrcTest(compressorClass) - str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed." - fakeOut = AbstractOutputStreamTest::TestOutputStream.new - - deflater = compressorClass.new(fakeOut) - deflater << str - assert_equals(0x919920fc, deflater.crc) - end -end - - - -class PassThruCompressorTest < RUNIT::TestCase - include CrcTest - - def test_size - File.open("dummy.txt", "wb") { - |file| - compressor = PassThruCompressor.new(file) - - assert_equals(0, compressor.size) - - t1 = "hello world" - t2 = "" - t3 = "bingo" - - compressor << t1 - assert_equals(compressor.size, t1.size) - - compressor << t2 - assert_equals(compressor.size, t1.size + t2.size) - - compressor << t3 - assert_equals(compressor.size, t1.size + t2.size + t3.size) - } - end - - def test_crc - runCrcTest(PassThruCompressor) - end -end - -class DeflaterTest < RUNIT::TestCase - include CrcTest - - def test_outputOperator - txt = loadFile("ziptest.rb") - deflate(txt, "deflatertest.bin") - inflatedTxt = inflate("deflatertest.bin") - assert_equals(txt, inflatedTxt) - end - - private - def loadFile(fileName) - txt = nil - File.open(fileName, "rb") { |f| txt = f.read } - end - - def deflate(data, fileName) - File.open(fileName, "wb") { - |file| - deflater = Deflater.new(file) - deflater << data - deflater.finish - assert_equals(deflater.size, data.size) - file << "trailing data for zlib with -MAX_WBITS" - } - end - - def inflate(fileName) - txt = nil - File.open(fileName, "rb") { - |file| - inflater = Inflater.new(file) - txt = inflater.read - } - end - - def test_crc - runCrcTest(Deflater) - end -end - -class ZipOutputStreamTest < RUNIT::TestCase - include AssertEntry - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zipName = "output.zip" - - def test_new - zos = ZipOutputStream.new(TEST_ZIP.zipName) - zos.comment = TEST_ZIP.comment - writeTestZip(zos) - zos.close - assertTestZipContents(TEST_ZIP) - end - - def test_open - ZipOutputStream.open(TEST_ZIP.zipName) { - |zos| - zos.comment = TEST_ZIP.comment - writeTestZip(zos) - } - assertTestZipContents(TEST_ZIP) - end - - def test_writingToClosedStream - assertIOErrorInClosedStream { |zos| zos << "hello world" } - assertIOErrorInClosedStream { |zos| zos.puts "hello world" } - assertIOErrorInClosedStream { |zos| zos.write "hello world" } - end - - def test_cannotOpenFile - name = TestFiles::EMPTY_TEST_DIR - begin - zos = ZipOutputStream.open(name) - rescue Exception - assert($!.kind_of?(Errno::EISDIR) || # Linux - $!.kind_of?(Errno::EEXIST) || # Windows/cygwin - $!.kind_of?(Errno::EACCES), # Windows - "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.type}") - end - end - - def assertIOErrorInClosedStream - assert_exception(IOError) { - zos = ZipOutputStream.new("test_putOnClosedStream.zip") - zos.close - yield zos - } - end - - def writeTestZip(zos) - TEST_ZIP.entryNames.each { - |entryName| - zos.putNextEntry(entryName) - File.open(entryName, "rb") { |f| zos.write(f.read) } - } - end -end - - - -module Enumerable - def compareEnumerables(otherEnumerable) - otherAsArray = otherEnumerable.to_a - index=0 - each_with_index { - |element, index| - return false unless yield(element, otherAsArray[index]) - } - return index+1 == otherAsArray.size - end -end - - -class ZipCentralDirectoryEntryTest < RUNIT::TestCase - - def test_readFromStream - File.open("testDirectory.bin", "rb") { - |file| - entry = ZipEntry.readCDirEntry(file) - - assert_equals("longAscii.txt", entry.name) - assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equals(106490, entry.size) - assert_equals(3784, entry.compressedSize) - assert_equals(0xfcd1799c, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("empty.txt", entry.name) - assert_equals(ZipEntry::STORED, entry.compressionMethod) - assert_equals(0, entry.size) - assert_equals(0, entry.compressedSize) - assert_equals(0x0, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("short.txt", entry.name) - assert_equals(ZipEntry::STORED, entry.compressionMethod) - assert_equals(6, entry.size) - assert_equals(6, entry.compressedSize) - assert_equals(0xbb76fe69, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("longBinary.bin", entry.name) - assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equals(1000024, entry.size) - assert_equals(70847, entry.compressedSize) - assert_equals(0x10da7d59, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals(nil, entry) -# Fields that are not check by this test: -# version made by 2 bytes -# version needed to extract 2 bytes -# general purpose bit flag 2 bytes -# last mod file time 2 bytes -# last mod file date 2 bytes -# compressed size 4 bytes -# uncompressed size 4 bytes -# disk number start 2 bytes -# internal file attributes 2 bytes -# external file attributes 4 bytes -# relative offset of local header 4 bytes - -# file name (variable size) -# extra field (variable size) -# file comment (variable size) - - } - end - - def test_ReadEntryFromTruncatedZipFile - fragment="" - File.open("testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes - fragment.extend(IOizeString) - entry = ZipEntry.new - entry.readCDirEntry(fragment) - fail "ZipError expected" - rescue ZipError - end - -end - -class ZipCentralDirectoryTest < RUNIT::TestCase - - def test_readFromStream - File.open(TestZipFile::TEST_ZIP2.zipName, "rb") { - |zipFile| - cdir = ZipCentralDirectory.readFromStream(zipFile) - - assert_equals(TestZipFile::TEST_ZIP2.entryNames.size, cdir.size) - assert(cdir.compareEnumerables(TestZipFile::TEST_ZIP2.entryNames) { - |cdirEntry, testEntryName| - cdirEntry.name == testEntryName - }) - assert_equals(TestZipFile::TEST_ZIP2.comment, cdir.comment) - } - end - - def test_readFromInvalidStream - File.open("ziptest.rb", "rb") { - |zipFile| - cdir = ZipCentralDirectory.new - cdir.readFromStream(zipFile) - } - fail "ZipError expected!" - rescue ZipError - end - - def test_ReadFromTruncatedZipFile - fragment="" - File.open("testDirectory.bin") { |f| fragment = f.read } - fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete - fragment.extend(IOizeString) - entry = ZipCentralDirectory.new - entry.readFromStream(fragment) - fail "ZipError expected" - rescue ZipError - end - - def test_writeToStream - entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ] - cdir = ZipCentralDirectory.new(entries, "my zip comment") - File.open("cdirtest.bin", "wb") { |f| cdir.writeToStream(f) } - cdirReadback = ZipCentralDirectory.new - File.open("cdirtest.bin", "rb") { |f| cdirReadback.readFromStream(f) } - - assert_equals(cdir.entries, cdirReadback.entries) - end - - def test_equality - cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - assert_equals(cdir1, cdir1) - assert_equals(cdir1, cdir2) - - assert(cdir1 != cdir3) - assert(cdir2 != cdir3) - assert(cdir2 != cdir3) - assert(cdir3 != cdir4) - - assert(cdir3 != "hello") - end -end - - -class BasicZipFileTest < RUNIT::TestCase - include AssertEntry - - def setup - @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zipName) - @testEntryNameIndex=0 - end - - def nextTestEntryName - retVal=TestZipFile::TEST_ZIP2.entryNames[@testEntryNameIndex] - @testEntryNameIndex+=1 - return retVal - end - - def test_entries - assert_equals(TestZipFile::TEST_ZIP2.entryNames, @zipFile.entries.map {|e| e.name} ) - end - - def test_each - @zipFile.each { - |entry| - assert_equals(nextTestEntryName, entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_foreach - ZipFile.foreach(TestZipFile::TEST_ZIP2.zipName) { - |entry| - assert_equals(nextTestEntryName, entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_getInputStream - @zipFile.each { - |entry| - assertEntry(nextTestEntryName, @zipFile.getInputStream(entry), - entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_getInputStreamBlock - fileAndEntryName = @zipFile.entries.first.name - @zipFile.getInputStream(fileAndEntryName) { - |zis| - assertEntryContentsForStream(fileAndEntryName, - zis, - fileAndEntryName) - } - end -end - -class CommonZipFileFixture < RUNIT::TestCase - include AssertEntry - - EMPTY_FILENAME = "emptyZipFile.zip" - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zipName = "4entry_copy.zip" - - def setup - File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME) - File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) - end -end - -class ZipFileTest < CommonZipFileFixture - - def test_createFromScratch - comment = "a short comment" - - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.comment = comment - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equals(comment, zfRead.comment) - assert_equals(0, zfRead.entries.length) - end - - def test_add - srcFile = "ziptest.rb" - entryName = "newEntryName.rb" - assert(File.exists? srcFile) - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.add(entryName, srcFile) - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equals("", zfRead.comment) - assert_equals(1, zfRead.entries.length) - assert_equals(entryName, zfRead.entries.first.name) - AssertEntry.assertContents(srcFile, - zfRead.getInputStream(entryName) { |zis| zis.read }) - end - - def test_addExistingEntryName - assert_exception(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.add(zf.entries.first.name, "ziptest.rb") - } - } - end - - def test_addExistingEntryNameReplace - gotCalled = false - replacedEntry = nil - ZipFile.open(TEST_ZIP.zipName) { - |zf| - replacedEntry = zf.entries.first.name - zf.add(replacedEntry, "ziptest.rb") { gotCalled = true; true } - } - assert(gotCalled) - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assertContains(zf, replacedEntry, "ziptest.rb") - } - end - - def test_addDirectory - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR) - } - ZipFile.open(TEST_ZIP.zipName) { - |zf| - dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" } - assert(dirEntry.isDirectory) - } - end - - def test_remove - entryToRemove, *remainingEntries = TEST_ZIP.entryNames - - File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) - - zf = ZipFile.new(TEST_ZIP.zipName) - assert(zf.entries.map { |e| e.name }.include?(entryToRemove)) - zf.remove(entryToRemove) - assert(! zf.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equals(zf.entries.map {|x| x.name }.sort, remainingEntries.sort) - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equals(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort) - zfRead.close - end - - - def test_rename - entryToRename, *remainingEntries = TEST_ZIP.entryNames - - zf = ZipFile.new(TEST_ZIP.zipName) - assert(zf.entries.map { |e| e.name }.include? entryToRename) - - newName = "changed name" - assert(! zf.entries.map { |e| e.name }.include?(newName)) - - zf.rename(entryToRename, newName) - assert(zf.entries.map { |e| e.name }.include? newName) - - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(zfRead.entries.map { |e| e.name }.include? newName) - zfRead.close - end - - def test_renameToExistingEntry - oldEntries = nil - ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } - - assert_exception(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.rename(zf.entries[0], zf.entries[1].name) - } - } - - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_equals(oldEntries.map{ |e| e.name }, zf.entries.map{ |e| e.name }) - } - end - - def test_renameToExistingEntryOverwrite - oldEntries = nil - ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } - - gotCalled = false - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true } - } - - assert(gotCalled) - oldEntries.delete_at(0) - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_equals(oldEntries.map{ |e| e.name }, - zf.entries.map{ |e| e.name }) - } - end - - def test_renameNonEntry - nonEntry = "bogusEntry" - targetEntry = "targetEntryName" - zf = ZipFile.new(TEST_ZIP.zipName) - assert(! zf.entries.include?(nonEntry)) - assert_exception(ZipNoSuchEntryError) { - zf.rename(nonEntry, targetEntry) - } - zf.commit - assert(! zf.entries.include?(targetEntry)) - ensure - zf.close - end - - def test_renameEntryToExistingEntry - entry1, entry2, *remaining = TEST_ZIP.entryNames - zf = ZipFile.new(TEST_ZIP.zipName) - assert_exception(ZipEntryExistsError) { - zf.rename(entry1, entry2) - } - ensure - zf.close - end - - def test_replace - unchangedEntries = TEST_ZIP.entryNames.dup - entryToReplace = unchangedEntries.delete_at(2) - newEntrySrcFilename = "ziptest.rb" - - zf = ZipFile.new(TEST_ZIP.zipName) - zf.replace(entryToReplace, newEntrySrcFilename) - - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - AssertEntry::assertContents(newEntrySrcFilename, - zfRead.getInputStream(entryToReplace) { |is| is.read }) - zfRead.close - end - - def test_replaceNonEntry - entryToReplace = "nonExistingEntryname" - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_exception(ZipNoSuchEntryError) { - zf.replace(entryToReplace, "ziptest.rb") - } - } - end - - def test_commit - newName = "renamedFirst" - zf = ZipFile.new(TEST_ZIP.zipName) - oldName = zf.entries.first - zf.rename(oldName, newName) - zf.commit - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(zfRead.entries.detect { |e| e.name == newName } != nil) - assert(zfRead.entries.detect { |e| e.name == oldName } == nil) - zfRead.close - - zf.close - end - - # This test tests that after commit, you - # can delete the file you used to add the entry to the zip file - # with - def test_commitUseZipEntry - File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt") - zf = ZipFile.open(TEST_ZIP.zipName) - zf.add("okToDelete.txt", "okToDelete.txt") - assertContains(zf, "okToDelete.txt") - zf.commit - File.move("okToDelete.txt", "okToDeleteMoved.txt") - assertContains(zf, "okToDelete.txt", "okToDeleteMoved.txt") - end - -# def test_close -# zf = ZipFile.new(TEST_ZIP.zipName) -# zf.close -# assert_exception(IOError) { -# zf.extract(TEST_ZIP.entryNames.first, "hullubullu") -# } -# end - - def test_compound1 - renamedName = "renamedName" - originalEntries = [] - begin - zf = ZipFile.new(TEST_ZIP.zipName) - originalEntries = zf.entries.dup - - assertNotContains(zf, TestFiles::RANDOM_ASCII_FILE1) - zf.add(TestFiles::RANDOM_ASCII_FILE1, - TestFiles::RANDOM_ASCII_FILE1) - assertContains(zf, TestFiles::RANDOM_ASCII_FILE1) - - zf.rename(zf.entries[0], renamedName) - assertContains(zf, renamedName) - - TestFiles::BINARY_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assertContains(zf, filename) - } - - assertContains(zf, originalEntries.last.to_s) - zf.remove(originalEntries.last.to_s) - assertNotContains(zf, originalEntries.last.to_s) - - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zipName) - assertContains(zfRead, TestFiles::RANDOM_ASCII_FILE1) - assertContains(zfRead, renamedName) - TestFiles::BINARY_TEST_FILES.each { - |filename| - assertContains(zfRead, filename) - } - assertNotContains(zfRead, originalEntries.last.to_s) - ensure - zfRead.close - end - end - - def test_compound2 - begin - zf = ZipFile.new(TEST_ZIP.zipName) - originalEntries = zf.entries.dup - - originalEntries.each { - |entry| - zf.remove(entry) - assertNotContains(zf, entry) - } - assert(zf.entries.empty?) - - TestFiles::ASCII_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assertContains(zf, filename) - } - assert_equals(zf.entries.map { |e| e.name }, TestFiles::ASCII_TEST_FILES) - - zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName") - assertNotContains(zf, TestFiles::ASCII_TEST_FILES[0]) - assertContains(zf, "newName") - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zipName) - asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup - asciiTestFiles.shift - asciiTestFiles.each { - |filename| - assertContains(zf, filename) - } - - assertContains(zf, "newName") - ensure - zfRead.close - end - end - - private - def assertContains(zf, entryName, filename = entryName) - assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}") - assertEntryContents(zf, entryName, filename) if File.exists?(filename) - end - - def assertNotContains(zf, entryName) - assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}") - end -end - -class ZipFileExtractTest < CommonZipFileFixture - EXTRACTED_FILENAME = "extEntry" - ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entryNames.reverse - - def setup - super - File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME) - end - - def test_extract - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME) - - assert(File.exists? EXTRACTED_FILENAME) - AssertEntry::assertContents(EXTRACTED_FILENAME, - zf.getInputStream(ENTRY_TO_EXTRACT) { |is| is.read }) - } - end - - def test_extractExists - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - assert_exception(ZipDestinationFileExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) - } - } - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert_equals(writtenText, f.read) - } - end - - def test_extractExistsOverwrite - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - gotCalled = false - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) { gotCalled = true; true } - } - - assert(gotCalled) - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert(writtenText != f.read) - } - end - - def test_extractNonEntry - zf = ZipFile.new(TEST_ZIP.zipName) - assert_exception(ZipNoSuchEntryError) { zf.extract("nonExistingEntry", "nonExistingEntry") } - ensure - zf.close if zf - end - - def test_extractNonEntry2 - outFile = "outfile" - assert_exception(ZipNoSuchEntryError) { - zf = ZipFile.new(TEST_ZIP.zipName) - nonEntry = "hotdog-diddelidoo" - assert(! zf.entries.include?(nonEntry)) - zf.extract(nonEntry, outFile) - zf.close - } - assert(! File.exists?(outFile)) - end - -end - -class ZipFileExtractDirectoryTest < CommonZipFileFixture - TEST_OUT_NAME = "emptyOutDir" - - def openZip(&aProc) - assert(aProc != nil) - ZipFile.open(TestZipFile::TEST_ZIP4.zipName, &aProc) - end - - def extractTestDir(&aProc) - openZip { - |zf| - zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc) - } - end - - def setup - super - - Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME - File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME - end - - def test_extractDirectory - extractTestDir - assert(File.directory? TEST_OUT_NAME) - end - - def test_extractDirectoryExistsAsDir - Dir.mkdir TEST_OUT_NAME - extractTestDir - assert(File.directory? TEST_OUT_NAME) - end - - def test_extractDirectoryExistsAsFile - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - assert_exception(ZipDestinationFileExistsError) { extractTestDir } - end - - def test_extractDirectoryExistsAsFileOverwrite - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - gotCalled = false - extractTestDir { - |entry, destPath| - gotCalled = true - assert_equals(TEST_OUT_NAME, destPath) - assert(entry.isDirectory) - true - } - assert(gotCalled) - assert(File.directory? TEST_OUT_NAME) - end -end - - -TestFiles::createTestFiles(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) -TestZipFile::createTestZips(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) -exit if ARGV.index("recreateonly") != nil - -#require 'runit/cui/testrunner' -#RUNIT::CUI::TestRunner.run(ZipFileTest.suite) - -# Copyright (C) 2002 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. -#!/usr/bin/env ruby - -$VERBOSE = true - -require 'rubyunit' -require 'zip' - -include Zip - -Dir.chdir "test" - -class AbstractInputStreamTest < RUNIT::TestCase - # AbstractInputStream subclass that provides a read method - - TEST_LINES = [ "Hello world#{$/}", - "this is the second line#{$/}", - "this is the last line"] - TEST_STRING = TEST_LINES.join - class TestAbstractInputStream - include AbstractInputStream - def initialize(aString) - @contents = aString - @readPointer = 0 - end - - def read(charsToRead) - retVal=@contents[@readPointer, charsToRead] - @readPointer+=charsToRead - return retVal - end - - def produceInput - read(100) - end - - def inputFinished? - @contents[@readPointer] == nil - end - end - - def setup - @io = TestAbstractInputStream.new(TEST_STRING) - end - - def test_gets - assert_equals(TEST_LINES[0], @io.gets) - assert_equals(TEST_LINES[1], @io.gets) - assert_equals(TEST_LINES[2], @io.gets) - assert_equals(nil, @io.gets) - end - - def test_getsMultiCharSeperator - assert_equals("Hell", @io.gets("ll")) - assert_equals("o world#{$/}this is the second l", @io.gets("d l")) - end - - def test_each_line - lineNumber=0 - @io.each_line { - |line| - assert_equals(TEST_LINES[lineNumber], line) - lineNumber+=1 - } - end - - def test_readlines - assert_equals(TEST_LINES, @io.readlines) - end - - def test_readline - test_gets - begin - @io.readline - fail "EOFError expected" - rescue EOFError - end - end -end - -class ZipEntryTest < RUNIT::TestCase - TEST_ZIPFILE = "someZipFile.zip" - TEST_COMMENT = "a comment" - TEST_COMPRESSED_SIZE = 1234 - TEST_CRC = 325324 - TEST_EXTRA = "Some data here" - TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED - TEST_NAME = "entry name" - TEST_SIZE = 8432 - TEST_ISDIRECTORY = false - - def test_constructorAndGetters - entry = ZipEntry.new(TEST_ZIPFILE, - TEST_NAME, - TEST_COMMENT, - TEST_EXTRA, - TEST_COMPRESSED_SIZE, - TEST_CRC, - TEST_COMPRESSIONMETHOD, - TEST_SIZE) - - assert_equals(TEST_COMMENT, entry.comment) - assert_equals(TEST_COMPRESSED_SIZE, entry.compressedSize) - assert_equals(TEST_CRC, entry.crc) - assert_equals(TEST_EXTRA, entry.extra) - assert_equals(TEST_COMPRESSIONMETHOD, entry.compressionMethod) - assert_equals(TEST_NAME, entry.name) - assert_equals(TEST_SIZE, entry.size) - assert_equals(TEST_ISDIRECTORY, entry.isDirectory) - end - - def test_equality - entry1 = ZipEntry.new("file.zip", "name", "isNotCompared", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 1234, - ZipEntry::DEFLATED, 10000) - entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::DEFLATED, 10000) - entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 10000) - entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 100000) - - assert_equals(entry1, entry1) - assert_equals(entry1, entry2) - - assert(entry2 != entry3) - assert(entry3 != entry4) - assert(entry4 != entry5) - assert(entry5 != entry6) - assert(entry6 != entry7) - assert(entry7 != entry8) - - assert(entry7 != "hello") - assert(entry7 != 12) - end -end - -module IOizeString - attr_reader :tell - - def read(count = nil) - @tell ||= 0 - count = size unless count - retVal = slice(@tell, count) - @tell += count - return retVal - end - - def seek(index, offset) - @tell ||= 0 - case offset - when IO::SEEK_END - newPos = size + index - when IO::SEEK_SET - newPos = index - when IO::SEEK_CUR - newPos = @tell + index - else - raise "Error in test method IOizeString::seek" - end - if (newPos < 0 || newPos >= size) - raise Errno::EINVAL - else - @tell=newPos - end - end - - def reset - @tell = 0 - end -end - -class ZipLocalEntryTest < RUNIT::TestCase - def test_readLocalEntryHeaderOfFirstTestZipEntry - File.open(TestZipFile::TEST_ZIP3.zipName) { - |file| - entry = ZipEntry.readLocalEntry(file) - - assert_equal("", entry.comment) - # Differs from windows and unix because of CR LF - # assert_equal(480, entry.compressedSize) - # assert_equal(0x2a27930f, entry.crc) - # extra field is 21 bytes long - # probably contains some unix attrutes or something - # disabled: assert_equal(nil, entry.extra) - assert_equal(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equal(TestZipFile::TEST_ZIP3.entryNames[0], entry.name) - assert_equal(File.size(TestZipFile::TEST_ZIP3.entryNames[0]), entry.size) - assert(! entry.isDirectory) - } - end - - def test_readLocalEntryFromNonZipFile - File.open("ziptest.rb") { - |file| - assert_equals(nil, ZipEntry.readLocalEntry(file)) - } - end - - def test_readLocalEntryFromTruncatedZipFile - zipFragment="" - File.open(TestZipFile::TEST_ZIP2.zipName) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes - zipFragment.extend(IOizeString).reset - entry = ZipEntry.new - entry.readLocalEntry(zipFragment) - fail "ZipError expected" - rescue ZipError - end - - def test_writeEntry - entry = ZipEntry.new("file.zip", "entryName", "my little comment", - "thisIsSomeExtraInformation", 100, 987654, - ZipEntry::DEFLATED, 400) - writeToFile("localEntryHeader.bin", "centralEntryHeader.bin", entry) - entryReadLocal, entryReadCentral = readFromFile("localEntryHeader.bin", "centralEntryHeader.bin") - compareLocalEntryHeaders(entry, entryReadLocal) - compareCDirEntryHeaders(entry, entryReadCentral) - end - - private - def compareLocalEntryHeaders(entry1, entry2) - assert_equals(entry1.compressedSize , entry2.compressedSize) - assert_equals(entry1.crc , entry2.crc) - assert_equals(entry1.extra , entry2.extra) - assert_equals(entry1.compressionMethod, entry2.compressionMethod) - assert_equals(entry1.name , entry2.name) - assert_equals(entry1.size , entry2.size) - assert_equals(entry1.localHeaderOffset, entry2.localHeaderOffset) - end - - def compareCDirEntryHeaders(entry1, entry2) - compareLocalEntryHeaders(entry1, entry2) - assert_equals(entry1.comment, entry2.comment) - end - - def writeToFile(localFileName, centralFileName, entry) - File.open(localFileName, "wb") { |f| entry.writeLocalEntry(f) } - File.open(centralFileName, "wb") { |f| entry.writeCDirEntry(f) } - end - - def readFromFile(localFileName, centralFileName) - localEntry = nil - cdirEntry = nil - File.open(localFileName, "rb") { |f| localEntry = ZipEntry.readLocalEntry(f) } - File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.readCDirEntry(f) } - return [localEntry, cdirEntry] - end -end - - -module DecompressorTests - # expects @refText and @decompressor - - def test_readEverything - assert_equals(@refText, @decompressor.read) - end - - def test_readInChunks - chunkSize = 5 - while (decompressedChunk = @decompressor.read(chunkSize)) - assert_equals(@refText.slice!(0, chunkSize), decompressedChunk) - end - assert_equals(0, @refText.size) - end -end - -class InflaterTest < RUNIT::TestCase - include DecompressorTests - - def setup - @file = File.new("file1.txt.deflatedData", "rb") - @refText="" - File.open("file1.txt") { |f| @refText = f.read } - @decompressor = Inflater.new(@file) - end - - def teardown - @file.close - end -end - - -class PassThruDecompressorTest < RUNIT::TestCase - include DecompressorTests - TEST_FILE="file1.txt" - def setup - @file = File.new(TEST_FILE) - @refText="" - File.open(TEST_FILE) { |f| @refText = f.read } - @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE)) - end - - def teardown - @file.close - end -end - - -module AssertEntry - def assertNextEntry(filename, zis) - assertEntry(filename, zis, zis.getNextEntry.name) - end - - def assertEntry(filename, zis, entryName) - assert_equals(filename, entryName) - assertEntryContentsForStream(filename, zis, entryName) - end - - def assertEntryContentsForStream(filename, zis, entryName) - File.open(filename, "rb") { - |file| - expected = file.read - actual = zis.read - if (expected != actual) - if (expected.length > 400 || actual.length > 400) - zipEntryFilename=entryName+".zipEntry" - File.open(zipEntryFilename, "wb") { |file| file << actual } - fail("File '#{filename}' is different from '#{zipEntryFilename}'") - else - assert_equals(expected, actual) - end - end - } - end - - def AssertEntry.assertContents(filename, aString) - fileContents = "" - File.open(filename, "rb") { |f| fileContents = f.read } - if (fileContents != aString) - if (expected.length > 400 || actual.length > 400) - stringFile = filename + ".other" - File.open(stringFile, "wb") { |f| f << aString } - fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'") - else - assert_equals(expected, actual) - end - end - end - - def assertStreamContents(zis, testZipFile) - assert(zis != nil) - testZipFile.entryNames.each { - |entryName| - assertNextEntry(entryName, zis) - } - assert_equals(nil, zis.getNextEntry) - end - - def assertTestZipContents(testZipFile) - ZipInputStream.open(testZipFile.zipName) { - |zis| - assertStreamContents(zis, testZipFile) - } - end - - def assertEntryContents(zipFile, entryName, filename = entryName.to_s) - zis = zipFile.getInputStream(entryName) - assertEntryContentsForStream(filename, zis, entryName) - ensure - zis.close if zis - end -end - - - -class ZipInputStreamTest < RUNIT::TestCase - include AssertEntry - - def test_new - zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zipName) - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - zis.close - end - - def test_openWithBlock - ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { - |zis| - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - } - end - - def test_openWithoutBlock - zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) - assertStreamContents(zis, TestZipFile::TEST_ZIP2) - end - - def test_incompleteReads - ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { - |zis| - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[0], entry.name) - assert zis.gets.length > 0 - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[1], entry.name) - assert_equals(0, entry.size) - assert_equals(nil, zis.gets) - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[2], entry.name) - assert zis.gets.length > 0 - entry = zis.getNextEntry - assert_equals(TestZipFile::TEST_ZIP2.entryNames[3], entry.name) - assert zis.gets.length > 0 - } - end - -end - -class TestFiles - RANDOM_ASCII_FILE1 = "randomAscii1.txt" - RANDOM_ASCII_FILE2 = "randomAscii2.txt" - RANDOM_ASCII_FILE3 = "randomAscii3.txt" - RANDOM_BINARY_FILE1 = "randomBinary1.bin" - RANDOM_BINARY_FILE2 = "randomBinary2.bin" - - EMPTY_TEST_DIR = "emptytestdir" - - ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ] - BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ] - TEST_DIRECTORIES = [ EMPTY_TEST_DIR ] - TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten! - - def TestFiles.createTestFiles(recreate) - if (recreate || - ! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) })) - - ASCII_TEST_FILES.each_with_index { - |filename, index| - createRandomAscii(filename, 1E4 * (index+1)) - } - - BINARY_TEST_FILES.each_with_index { - |filename, index| - createRandomBinary(filename, 1E4 * (index+1)) - } - - ensureDir(EMPTY_TEST_DIR) - end - end - - private - def TestFiles.createRandomAscii(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << rand - end - } - end - - def TestFiles.createRandomBinary(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << rand.to_a.pack("V") - end - } - end - - def TestFiles.ensureDir(name) - if File.exists?(name) - return if File.stat(name).directory? - File.delete(name) - end - Dir.mkdir(name) - end - -end - -# For representation and creation of -# test data -class TestZipFile - attr_accessor :zipName, :entryNames, :comment - - def initialize(zipName, entryNames, comment = "") - @zipName=zipName - @entryNames=entryNames - @comment = comment - end - - def TestZipFile.createTestZips(recreate) - files = Dir.entries(".") - if (recreate || - ! (files.index(TEST_ZIP1.zipName) && - files.index(TEST_ZIP2.zipName) && - files.index(TEST_ZIP3.zipName) && - files.index(TEST_ZIP4.zipName) && - files.index("empty.txt") && - files.index("short.txt") && - files.index("longAscii.txt") && - files.index("longBinary.bin") )) - raise "failed to create test zip '#{TEST_ZIP1.zipName}'" unless - system("zip #{TEST_ZIP1.zipName} ziptest.rb") - raise "failed to remove entry from '#{TEST_ZIP1.zipName}'" unless - system("zip #{TEST_ZIP1.zipName} -d ziptest.rb") - - File.open("empty.txt", "w") {} - - File.open("short.txt", "w") { |file| file << "ABCDEF" } - ziptestTxt="" - File.open("ziptest.rb") { |file| ziptestTxt=file.read } - File.open("longAscii.txt", "w") { - |file| - while (file.tell < 1E5) - file << ziptestTxt - end - } - - testBinaryPattern="" - File.open("empty.zip") { |file| testBinaryPattern=file.read } - testBinaryPattern *= 4 - - File.open("longBinary.bin", "wb") { - |file| - while (file.tell < 3E5) - file << testBinaryPattern << rand - end - } - raise "failed to create test zip '#{TEST_ZIP2.zipName}'" unless - system("zip #{TEST_ZIP2.zipName} #{TEST_ZIP2.entryNames.join(' ')}") - - # without bash system interprets everything after echo as parameters to - # echo including | zip -z ... - raise "failed to add comment to test zip '#{TEST_ZIP2.zipName}'" unless - system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zipName}\"") - - raise "failed to create test zip '#{TEST_ZIP3.zipName}'" unless - system("zip #{TEST_ZIP3.zipName} #{TEST_ZIP3.entryNames.join(' ')}") - - raise "failed to create test zip '#{TEST_ZIP4.zipName}'" unless - system("zip #{TEST_ZIP4.zipName} #{TEST_ZIP4.entryNames.join(' ')}") - end - rescue - raise $!.to_s + - "\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" + - "to create test data. If you don't have it you can download\n" + - "the necessary test files at http://sf.net/projects/rubyzip." - end - - TEST_ZIP1 = TestZipFile.new("empty.zip", []) - TEST_ZIP2 = TestZipFile.new("4entry.zip", %w{ longAscii.txt empty.txt short.txt longBinary.bin}, - "my zip comment") - TEST_ZIP3 = TestZipFile.new("test1.zip", %w{ file1.txt }) - TEST_ZIP4 = TestZipFile.new("zipWithDir.zip", [ "file1.txt", - TestFiles::EMPTY_TEST_DIR]) -end - - -class AbstractOutputStreamTest < RUNIT::TestCase - class TestOutputStream - include AbstractOutputStream - - attr_accessor :buffer - - def initialize - @buffer = "" - end - - def << (data) - @buffer << data - self - end - end - - def setup - @outputStream = TestOutputStream.new - - @origCommaSep = $, - @origOutputSep = $\ - end - - def teardown - $, = @origCommaSep - $\ = @origOutputSep - end - - def test_write - count = @outputStream.write("a little string") - assert_equals("a little string", @outputStream.buffer) - assert_equals("a little string".length, count) - - count = @outputStream.write(". a little more") - assert_equals("a little string. a little more", @outputStream.buffer) - assert_equals(". a little more".length, count) - end - - def test_print - $\ = nil # record separator set to nil - @outputStream.print("hello") - assert_equals("hello", @outputStream.buffer) - - @outputStream.print(" world.") - assert_equals("hello world.", @outputStream.buffer) - - @outputStream.print(" You ok ", "out ", "there?") - assert_equals("hello world. You ok out there?", @outputStream.buffer) - - $\ = "\n" - @outputStream.print - assert_equals("hello world. You ok out there?\n", @outputStream.buffer) - - @outputStream.print("I sure hope so!") - assert_equals("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer) - - $, = "X" - @outputStream.buffer = "" - @outputStream.print("monkey", "duck", "zebra") - assert_equals("monkeyXduckXzebra\n", @outputStream.buffer) - - $\ = nil - @outputStream.buffer = "" - @outputStream.print(20) - assert_equals("20", @outputStream.buffer) - end - - def test_printf - @outputStream.printf("%d %04x", 123, 123) - assert_equals("123 007b", @outputStream.buffer) - end - - def test_putc - @outputStream.putc("A") - assert_equals("A", @outputStream.buffer) - @outputStream.putc(65) - assert_equals("AA", @outputStream.buffer) - end - - def test_puts - @outputStream.puts - assert_equals("\n", @outputStream.buffer) - - @outputStream.puts("hello", "world") - assert_equals("\nhello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts("hello\n", "world\n") - assert_equals("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"]) - assert_equals("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"], "bingo") - assert_equals("hello\nworld\nbingo\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(16, 20, 50, "hello") - assert_equals("16\n20\n50\nhello\n", @outputStream.buffer) - end -end - - -module CrcTest - def runCrcTest(compressorClass) - str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed." - fakeOut = AbstractOutputStreamTest::TestOutputStream.new - - deflater = compressorClass.new(fakeOut) - deflater << str - assert_equals(0x919920fc, deflater.crc) - end -end - - - -class PassThruCompressorTest < RUNIT::TestCase - include CrcTest - - def test_size - File.open("dummy.txt", "wb") { - |file| - compressor = PassThruCompressor.new(file) - - assert_equals(0, compressor.size) - - t1 = "hello world" - t2 = "" - t3 = "bingo" - - compressor << t1 - assert_equals(compressor.size, t1.size) - - compressor << t2 - assert_equals(compressor.size, t1.size + t2.size) - - compressor << t3 - assert_equals(compressor.size, t1.size + t2.size + t3.size) - } - end - - def test_crc - runCrcTest(PassThruCompressor) - end -end - -class DeflaterTest < RUNIT::TestCase - include CrcTest - - def test_outputOperator - txt = loadFile("ziptest.rb") - deflate(txt, "deflatertest.bin") - inflatedTxt = inflate("deflatertest.bin") - assert_equals(txt, inflatedTxt) - end - - private - def loadFile(fileName) - txt = nil - File.open(fileName, "rb") { |f| txt = f.read } - end - - def deflate(data, fileName) - File.open(fileName, "wb") { - |file| - deflater = Deflater.new(file) - deflater << data - deflater.finish - assert_equals(deflater.size, data.size) - file << "trailing data for zlib with -MAX_WBITS" - } - end - - def inflate(fileName) - txt = nil - File.open(fileName, "rb") { - |file| - inflater = Inflater.new(file) - txt = inflater.read - } - end - - def test_crc - runCrcTest(Deflater) - end -end - -class ZipOutputStreamTest < RUNIT::TestCase - include AssertEntry - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zipName = "output.zip" - - def test_new - zos = ZipOutputStream.new(TEST_ZIP.zipName) - zos.comment = TEST_ZIP.comment - writeTestZip(zos) - zos.close - assertTestZipContents(TEST_ZIP) - end - - def test_open - ZipOutputStream.open(TEST_ZIP.zipName) { - |zos| - zos.comment = TEST_ZIP.comment - writeTestZip(zos) - } - assertTestZipContents(TEST_ZIP) - end - - def test_writingToClosedStream - assertIOErrorInClosedStream { |zos| zos << "hello world" } - assertIOErrorInClosedStream { |zos| zos.puts "hello world" } - assertIOErrorInClosedStream { |zos| zos.write "hello world" } - end - - def test_cannotOpenFile - name = TestFiles::EMPTY_TEST_DIR - begin - zos = ZipOutputStream.open(name) - rescue Exception - assert($!.kind_of?(Errno::EISDIR) || # Linux - $!.kind_of?(Errno::EEXIST) || # Windows/cygwin - $!.kind_of?(Errno::EACCES), # Windows - "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.type}") - end - end - - def assertIOErrorInClosedStream - assert_exception(IOError) { - zos = ZipOutputStream.new("test_putOnClosedStream.zip") - zos.close - yield zos - } - end - - def writeTestZip(zos) - TEST_ZIP.entryNames.each { - |entryName| - zos.putNextEntry(entryName) - File.open(entryName, "rb") { |f| zos.write(f.read) } - } - end -end - - - -module Enumerable - def compareEnumerables(otherEnumerable) - otherAsArray = otherEnumerable.to_a - index=0 - each_with_index { - |element, index| - return false unless yield(element, otherAsArray[index]) - } - return index+1 == otherAsArray.size - end -end - - -class ZipCentralDirectoryEntryTest < RUNIT::TestCase - - def test_readFromStream - File.open("testDirectory.bin", "rb") { - |file| - entry = ZipEntry.readCDirEntry(file) - - assert_equals("longAscii.txt", entry.name) - assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equals(106490, entry.size) - assert_equals(3784, entry.compressedSize) - assert_equals(0xfcd1799c, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("empty.txt", entry.name) - assert_equals(ZipEntry::STORED, entry.compressionMethod) - assert_equals(0, entry.size) - assert_equals(0, entry.compressedSize) - assert_equals(0x0, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("short.txt", entry.name) - assert_equals(ZipEntry::STORED, entry.compressionMethod) - assert_equals(6, entry.size) - assert_equals(6, entry.compressedSize) - assert_equals(0xbb76fe69, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals("longBinary.bin", entry.name) - assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) - assert_equals(1000024, entry.size) - assert_equals(70847, entry.compressedSize) - assert_equals(0x10da7d59, entry.crc) - assert_equals("", entry.comment) - - entry = ZipEntry.readCDirEntry(file) - assert_equals(nil, entry) -# Fields that are not check by this test: -# version made by 2 bytes -# version needed to extract 2 bytes -# general purpose bit flag 2 bytes -# last mod file time 2 bytes -# last mod file date 2 bytes -# compressed size 4 bytes -# uncompressed size 4 bytes -# disk number start 2 bytes -# internal file attributes 2 bytes -# external file attributes 4 bytes -# relative offset of local header 4 bytes - -# file name (variable size) -# extra field (variable size) -# file comment (variable size) - - } - end - - def test_ReadEntryFromTruncatedZipFile - fragment="" - File.open("testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes - fragment.extend(IOizeString) - entry = ZipEntry.new - entry.readCDirEntry(fragment) - fail "ZipError expected" - rescue ZipError - end - -end - -class ZipCentralDirectoryTest < RUNIT::TestCase - - def test_readFromStream - File.open(TestZipFile::TEST_ZIP2.zipName, "rb") { - |zipFile| - cdir = ZipCentralDirectory.readFromStream(zipFile) - - assert_equals(TestZipFile::TEST_ZIP2.entryNames.size, cdir.size) - assert(cdir.compareEnumerables(TestZipFile::TEST_ZIP2.entryNames) { - |cdirEntry, testEntryName| - cdirEntry.name == testEntryName - }) - assert_equals(TestZipFile::TEST_ZIP2.comment, cdir.comment) - } - end - - def test_readFromInvalidStream - File.open("ziptest.rb", "rb") { - |zipFile| - cdir = ZipCentralDirectory.new - cdir.readFromStream(zipFile) - } - fail "ZipError expected!" - rescue ZipError - end - - def test_ReadFromTruncatedZipFile - fragment="" - File.open("testDirectory.bin") { |f| fragment = f.read } - fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete - fragment.extend(IOizeString) - entry = ZipCentralDirectory.new - entry.readFromStream(fragment) - fail "ZipError expected" - rescue ZipError - end - - def test_writeToStream - entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ] - cdir = ZipCentralDirectory.new(entries, "my zip comment") - File.open("cdirtest.bin", "wb") { |f| cdir.writeToStream(f) } - cdirReadback = ZipCentralDirectory.new - File.open("cdirtest.bin", "rb") { |f| cdirReadback.readFromStream(f) } - - assert_equals(cdir.entries, cdirReadback.entries) - end - - def test_equality - cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - assert_equals(cdir1, cdir1) - assert_equals(cdir1, cdir2) - - assert(cdir1 != cdir3) - assert(cdir2 != cdir3) - assert(cdir2 != cdir3) - assert(cdir3 != cdir4) - - assert(cdir3 != "hello") - end -end - - -class BasicZipFileTest < RUNIT::TestCase - include AssertEntry - - def setup - @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zipName) - @testEntryNameIndex=0 - end - - def nextTestEntryName - retVal=TestZipFile::TEST_ZIP2.entryNames[@testEntryNameIndex] - @testEntryNameIndex+=1 - return retVal - end - - def test_entries - assert_equals(TestZipFile::TEST_ZIP2.entryNames, @zipFile.entries.map {|e| e.name} ) - end - - def test_each - @zipFile.each { - |entry| - assert_equals(nextTestEntryName, entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_foreach - ZipFile.foreach(TestZipFile::TEST_ZIP2.zipName) { - |entry| - assert_equals(nextTestEntryName, entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_getInputStream - @zipFile.each { - |entry| - assertEntry(nextTestEntryName, @zipFile.getInputStream(entry), - entry.name) - } - assert_equals(4, @testEntryNameIndex) - end - - def test_getInputStreamBlock - fileAndEntryName = @zipFile.entries.first.name - @zipFile.getInputStream(fileAndEntryName) { - |zis| - assertEntryContentsForStream(fileAndEntryName, - zis, - fileAndEntryName) - } - end -end - -class CommonZipFileFixture < RUNIT::TestCase - include AssertEntry - - EMPTY_FILENAME = "emptyZipFile.zip" - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zipName = "4entry_copy.zip" - - def setup - File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME) - File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) - end -end - -class ZipFileTest < CommonZipFileFixture - - def test_createFromScratch - comment = "a short comment" - - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.comment = comment - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equals(comment, zfRead.comment) - assert_equals(0, zfRead.entries.length) - end - - def test_add - srcFile = "ziptest.rb" - entryName = "newEntryName.rb" - assert(File.exists? srcFile) - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.add(entryName, srcFile) - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equals("", zfRead.comment) - assert_equals(1, zfRead.entries.length) - assert_equals(entryName, zfRead.entries.first.name) - AssertEntry.assertContents(srcFile, - zfRead.getInputStream(entryName) { |zis| zis.read }) - end - - def test_addExistingEntryName - assert_exception(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.add(zf.entries.first.name, "ziptest.rb") - } - } - end - - def test_addExistingEntryNameReplace - gotCalled = false - replacedEntry = nil - ZipFile.open(TEST_ZIP.zipName) { - |zf| - replacedEntry = zf.entries.first.name - zf.add(replacedEntry, "ziptest.rb") { gotCalled = true; true } - } - assert(gotCalled) - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assertContains(zf, replacedEntry, "ziptest.rb") - } - end - - def test_addDirectory - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR) - } - ZipFile.open(TEST_ZIP.zipName) { - |zf| - dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" } - assert(dirEntry.isDirectory) - } - end - - def test_remove - entryToRemove, *remainingEntries = TEST_ZIP.entryNames - - File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) - - zf = ZipFile.new(TEST_ZIP.zipName) - assert(zf.entries.map { |e| e.name }.include?(entryToRemove)) - zf.remove(entryToRemove) - assert(! zf.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equals(zf.entries.map {|x| x.name }.sort, remainingEntries.sort) - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equals(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort) - zfRead.close - end - - - def test_rename - entryToRename, *remainingEntries = TEST_ZIP.entryNames - - zf = ZipFile.new(TEST_ZIP.zipName) - assert(zf.entries.map { |e| e.name }.include? entryToRename) - - newName = "changed name" - assert(! zf.entries.map { |e| e.name }.include?(newName)) - - zf.rename(entryToRename, newName) - assert(zf.entries.map { |e| e.name }.include? newName) - - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(zfRead.entries.map { |e| e.name }.include? newName) - zfRead.close - end - - def test_renameToExistingEntry - oldEntries = nil - ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } - - assert_exception(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.rename(zf.entries[0], zf.entries[1].name) - } - } - - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_equals(oldEntries.map{ |e| e.name }, zf.entries.map{ |e| e.name }) - } - end - - def test_renameToExistingEntryOverwrite - oldEntries = nil - ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } - - gotCalled = false - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true } - } - - assert(gotCalled) - oldEntries.delete_at(0) - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_equals(oldEntries.map{ |e| e.name }, - zf.entries.map{ |e| e.name }) - } - end - - def test_renameNonEntry - nonEntry = "bogusEntry" - targetEntry = "targetEntryName" - zf = ZipFile.new(TEST_ZIP.zipName) - assert(! zf.entries.include?(nonEntry)) - assert_exception(ZipNoSuchEntryError) { - zf.rename(nonEntry, targetEntry) - } - zf.commit - assert(! zf.entries.include?(targetEntry)) - ensure - zf.close - end - - def test_renameEntryToExistingEntry - entry1, entry2, *remaining = TEST_ZIP.entryNames - zf = ZipFile.new(TEST_ZIP.zipName) - assert_exception(ZipEntryExistsError) { - zf.rename(entry1, entry2) - } - ensure - zf.close - end - - def test_replace - unchangedEntries = TEST_ZIP.entryNames.dup - entryToReplace = unchangedEntries.delete_at(2) - newEntrySrcFilename = "ziptest.rb" - - zf = ZipFile.new(TEST_ZIP.zipName) - zf.replace(entryToReplace, newEntrySrcFilename) - - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zipName) - AssertEntry::assertContents(newEntrySrcFilename, - zfRead.getInputStream(entryToReplace) { |is| is.read }) - zfRead.close - end - - def test_replaceNonEntry - entryToReplace = "nonExistingEntryname" - ZipFile.open(TEST_ZIP.zipName) { - |zf| - assert_exception(ZipNoSuchEntryError) { - zf.replace(entryToReplace, "ziptest.rb") - } - } - end - - def test_commit - newName = "renamedFirst" - zf = ZipFile.new(TEST_ZIP.zipName) - oldName = zf.entries.first - zf.rename(oldName, newName) - zf.commit - - zfRead = ZipFile.new(TEST_ZIP.zipName) - assert(zfRead.entries.detect { |e| e.name == newName } != nil) - assert(zfRead.entries.detect { |e| e.name == oldName } == nil) - zfRead.close - - zf.close - end - - # This test tests that after commit, you - # can delete the file you used to add the entry to the zip file - # with - def test_commitUseZipEntry - File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt") - zf = ZipFile.open(TEST_ZIP.zipName) - zf.add("okToDelete.txt", "okToDelete.txt") - assertContains(zf, "okToDelete.txt") - zf.commit - File.move("okToDelete.txt", "okToDeleteMoved.txt") - assertContains(zf, "okToDelete.txt", "okToDeleteMoved.txt") - end - -# def test_close -# zf = ZipFile.new(TEST_ZIP.zipName) -# zf.close -# assert_exception(IOError) { -# zf.extract(TEST_ZIP.entryNames.first, "hullubullu") -# } -# end - - def test_compound1 - renamedName = "renamedName" - originalEntries = [] - begin - zf = ZipFile.new(TEST_ZIP.zipName) - originalEntries = zf.entries.dup - - assertNotContains(zf, TestFiles::RANDOM_ASCII_FILE1) - zf.add(TestFiles::RANDOM_ASCII_FILE1, - TestFiles::RANDOM_ASCII_FILE1) - assertContains(zf, TestFiles::RANDOM_ASCII_FILE1) - - zf.rename(zf.entries[0], renamedName) - assertContains(zf, renamedName) - - TestFiles::BINARY_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assertContains(zf, filename) - } - - assertContains(zf, originalEntries.last.to_s) - zf.remove(originalEntries.last.to_s) - assertNotContains(zf, originalEntries.last.to_s) - - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zipName) - assertContains(zfRead, TestFiles::RANDOM_ASCII_FILE1) - assertContains(zfRead, renamedName) - TestFiles::BINARY_TEST_FILES.each { - |filename| - assertContains(zfRead, filename) - } - assertNotContains(zfRead, originalEntries.last.to_s) - ensure - zfRead.close - end - end - - def test_compound2 - begin - zf = ZipFile.new(TEST_ZIP.zipName) - originalEntries = zf.entries.dup - - originalEntries.each { - |entry| - zf.remove(entry) - assertNotContains(zf, entry) - } - assert(zf.entries.empty?) - - TestFiles::ASCII_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assertContains(zf, filename) - } - assert_equals(zf.entries.map { |e| e.name }, TestFiles::ASCII_TEST_FILES) - - zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName") - assertNotContains(zf, TestFiles::ASCII_TEST_FILES[0]) - assertContains(zf, "newName") - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zipName) - asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup - asciiTestFiles.shift - asciiTestFiles.each { - |filename| - assertContains(zf, filename) - } - - assertContains(zf, "newName") - ensure - zfRead.close - end - end - - private - def assertContains(zf, entryName, filename = entryName) - assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}") - assertEntryContents(zf, entryName, filename) if File.exists?(filename) - end - - def assertNotContains(zf, entryName) - assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}") - end -end - -class ZipFileExtractTest < CommonZipFileFixture - EXTRACTED_FILENAME = "extEntry" - ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entryNames.reverse - - def setup - super - File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME) - end - - def test_extract - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME) - - assert(File.exists? EXTRACTED_FILENAME) - AssertEntry::assertContents(EXTRACTED_FILENAME, - zf.getInputStream(ENTRY_TO_EXTRACT) { |is| is.read }) - } - end - - def test_extractExists - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - assert_exception(ZipDestinationFileExistsError) { - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) - } - } - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert_equals(writtenText, f.read) - } - end - - def test_extractExistsOverwrite - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - gotCalled = false - ZipFile.open(TEST_ZIP.zipName) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) { gotCalled = true; true } - } - - assert(gotCalled) - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert(writtenText != f.read) - } - end - - def test_extractNonEntry - zf = ZipFile.new(TEST_ZIP.zipName) - assert_exception(ZipNoSuchEntryError) { zf.extract("nonExistingEntry", "nonExistingEntry") } - ensure - zf.close if zf - end - - def test_extractNonEntry2 - outFile = "outfile" - assert_exception(ZipNoSuchEntryError) { - zf = ZipFile.new(TEST_ZIP.zipName) - nonEntry = "hotdog-diddelidoo" - assert(! zf.entries.include?(nonEntry)) - zf.extract(nonEntry, outFile) - zf.close - } - assert(! File.exists?(outFile)) - end - -end - -class ZipFileExtractDirectoryTest < CommonZipFileFixture - TEST_OUT_NAME = "emptyOutDir" - - def openZip(&aProc) - assert(aProc != nil) - ZipFile.open(TestZipFile::TEST_ZIP4.zipName, &aProc) - end - - def extractTestDir(&aProc) - openZip { - |zf| - zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc) - } - end - - def setup - super - - Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME - File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME - end - - def test_extractDirectory - extractTestDir - assert(File.directory? TEST_OUT_NAME) - end - - def test_extractDirectoryExistsAsDir - Dir.mkdir TEST_OUT_NAME - extractTestDir - assert(File.directory? TEST_OUT_NAME) - end - - def test_extractDirectoryExistsAsFile - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - assert_exception(ZipDestinationFileExistsError) { extractTestDir } - end - - def test_extractDirectoryExistsAsFileOverwrite - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - gotCalled = false - extractTestDir { - |entry, destPath| - gotCalled = true - assert_equals(TEST_OUT_NAME, destPath) - assert(entry.isDirectory) - true - } - assert(gotCalled) - assert(File.directory? TEST_OUT_NAME) - end -end - - -TestFiles::createTestFiles(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) -TestZipFile::createTestZips(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) -exit if ARGV.index("recreateonly") != nil - -#require 'runit/cui/testrunner' -#RUNIT::CUI::TestRunner.run(ZipFileTest.suite) - -# Copyright (C) 2002 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/test/data/generated/longBinary.bin b/lib/zip/test/data/generated/longBinary.bin deleted file mode 100644 index df673254c4..0000000000 Binary files a/lib/zip/test/data/generated/longBinary.bin and /dev/null differ diff --git a/lib/zip/test/data/generated/randomAscii1.txt b/lib/zip/test/data/generated/randomAscii1.txt deleted file mode 100644 index b2b472a203..0000000000 --- a/lib/zip/test/data/generated/randomAscii1.txt +++ /dev/null @@ -1 +0,0 @@ -0.040244959211864 \ No newline at end of file diff --git a/lib/zip/test/data/generated/randomAscii2.txt b/lib/zip/test/data/generated/randomAscii2.txt deleted file mode 100644 index 64dc85e2c4..0000000000 --- a/lib/zip/test/data/generated/randomAscii2.txt +++ /dev/null @@ -1 +0,0 @@ -0.917381580665493 \ No newline at end of file diff --git a/lib/zip/test/data/generated/randomAscii3.txt b/lib/zip/test/data/generated/randomAscii3.txt deleted file mode 100644 index c7f3a83bff..0000000000 --- a/lib/zip/test/data/generated/randomAscii3.txt +++ /dev/null @@ -1 +0,0 @@ -0.670572209005379 \ No newline at end of file diff --git a/lib/zip/test/data/generated/randomBinary1.bin b/lib/zip/test/data/generated/randomBinary1.bin deleted file mode 100644 index 593f4708db..0000000000 Binary files a/lib/zip/test/data/generated/randomBinary1.bin and /dev/null differ diff --git a/lib/zip/test/data/generated/randomBinary2.bin b/lib/zip/test/data/generated/randomBinary2.bin deleted file mode 100644 index 593f4708db..0000000000 Binary files a/lib/zip/test/data/generated/randomBinary2.bin and /dev/null differ diff --git a/lib/zip/test/data/generated/short.txt b/lib/zip/test/data/generated/short.txt deleted file mode 100644 index 1c5f8ba2db..0000000000 --- a/lib/zip/test/data/generated/short.txt +++ /dev/null @@ -1 +0,0 @@ -ABCDEF \ No newline at end of file diff --git a/lib/zip/test/data/generated/test1.zip b/lib/zip/test/data/generated/test1.zip deleted file mode 100644 index 2ce05cedf4..0000000000 Binary files a/lib/zip/test/data/generated/test1.zip and /dev/null differ diff --git a/lib/zip/test/data/generated/zipWithDir.zip b/lib/zip/test/data/generated/zipWithDir.zip deleted file mode 100644 index 476120bff1..0000000000 Binary files a/lib/zip/test/data/generated/zipWithDir.zip and /dev/null differ diff --git a/lib/zip/test/data/notzippedruby.rb b/lib/zip/test/data/notzippedruby.rb deleted file mode 100755 index 036d25e92c..0000000000 --- a/lib/zip/test/data/notzippedruby.rb +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env ruby - -class NotZippedRuby - def returnTrue - true - end -end diff --git a/lib/zip/test/data/rubycode.zip b/lib/zip/test/data/rubycode.zip deleted file mode 100644 index 8a68560e63..0000000000 Binary files a/lib/zip/test/data/rubycode.zip and /dev/null differ diff --git a/lib/zip/test/data/rubycode2.zip b/lib/zip/test/data/rubycode2.zip deleted file mode 100644 index 8e1cd08f2d..0000000000 Binary files a/lib/zip/test/data/rubycode2.zip and /dev/null differ diff --git a/lib/zip/test/data/testDirectory.bin b/lib/zip/test/data/testDirectory.bin deleted file mode 100644 index cbdb9f7d74..0000000000 Binary files a/lib/zip/test/data/testDirectory.bin and /dev/null differ diff --git a/lib/zip/test/data/zipWithDirs.zip b/lib/zip/test/data/zipWithDirs.zip deleted file mode 100644 index 4b01f011ae..0000000000 Binary files a/lib/zip/test/data/zipWithDirs.zip and /dev/null differ diff --git a/lib/zip/test/gentestfiles.rb b/lib/zip/test/gentestfiles.rb deleted file mode 100755 index 45116ec5b5..0000000000 --- a/lib/zip/test/gentestfiles.rb +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -class TestFiles - RANDOM_ASCII_FILE1 = "data/generated/randomAscii1.txt" - RANDOM_ASCII_FILE2 = "data/generated/randomAscii2.txt" - RANDOM_ASCII_FILE3 = "data/generated/randomAscii3.txt" - RANDOM_BINARY_FILE1 = "data/generated/randomBinary1.bin" - RANDOM_BINARY_FILE2 = "data/generated/randomBinary2.bin" - - EMPTY_TEST_DIR = "data/generated/emptytestdir" - - ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ] - BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ] - TEST_DIRECTORIES = [ EMPTY_TEST_DIR ] - TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten! - - def TestFiles.create_test_files(recreate) - if (recreate || - ! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) })) - - Dir.mkdir "data/generated" rescue Errno::EEXIST - - ASCII_TEST_FILES.each_with_index { - |filename, index| - create_random_ascii(filename, 1E4 * (index+1)) - } - - BINARY_TEST_FILES.each_with_index { - |filename, index| - create_random_binary(filename, 1E4 * (index+1)) - } - - ensure_dir(EMPTY_TEST_DIR) - end - end - - private - def TestFiles.create_random_ascii(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << rand - end - } - end - - def TestFiles.create_random_binary(filename, size) - File.open(filename, "wb") { - |file| - while (file.tell < size) - file << [rand].pack("V") - end - } - end - - def TestFiles.ensure_dir(name) - if File.exists?(name) - return if File.stat(name).directory? - File.delete(name) - end - Dir.mkdir(name) - end - -end - - - -# For representation and creation of -# test data -class TestZipFile - attr_accessor :zip_name, :entry_names, :comment - - def initialize(zip_name, entry_names, comment = "") - @zip_name=zip_name - @entry_names=entry_names - if "".respond_to? :force_encoding - @entry_names.each {|name| name.force_encoding("ASCII-8BIT")} - end - @comment = comment - end - - def TestZipFile.create_test_zips(recreate) - files = Dir.entries("data/generated") - if (recreate || - ! (files.index(File.basename(TEST_ZIP1.zip_name)) && - files.index(File.basename(TEST_ZIP2.zip_name)) && - files.index(File.basename(TEST_ZIP3.zip_name)) && - files.index(File.basename(TEST_ZIP4.zip_name)) && - files.index("empty.txt") && - files.index("empty_chmod640.txt") && - files.index("short.txt") && - files.index("longAscii.txt") && - files.index("longBinary.bin") )) - raise "failed to create test zip '#{TEST_ZIP1.zip_name}'" unless - system("zip #{TEST_ZIP1.zip_name} data/file2.txt") - raise "failed to remove entry from '#{TEST_ZIP1.zip_name}'" unless - system("zip #{TEST_ZIP1.zip_name} -d data/file2.txt") - - File.open("data/generated/empty.txt", "w") {} - File.open("data/generated/empty_chmod640.txt", "w") { |f| f.chmod(0640) } - - File.open("data/generated/short.txt", "w") { |file| file << "ABCDEF" } - ziptestTxt="" - File.open("data/file2.txt") { |file| ziptestTxt=file.read } - File.open("data/generated/longAscii.txt", "w") { - |file| - while (file.tell < 1E5) - file << ziptestTxt - end - } - - testBinaryPattern="" - File.open("data/generated/empty.zip") { |file| testBinaryPattern=file.read } - testBinaryPattern *= 4 - - File.open("data/generated/longBinary.bin", "wb") { - |file| - while (file.tell < 3E5) - file << testBinaryPattern << rand << "\0" - end - } - raise "failed to create test zip '#{TEST_ZIP2.zip_name}'" unless - system("zip #{TEST_ZIP2.zip_name} #{TEST_ZIP2.entry_names.join(' ')}") - - # without bash system interprets everything after echo as parameters to - # echo including | zip -z ... - raise "failed to add comment to test zip '#{TEST_ZIP2.zip_name}'" unless - system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zip_name}\"") - - raise "failed to create test zip '#{TEST_ZIP3.zip_name}'" unless - system("zip #{TEST_ZIP3.zip_name} #{TEST_ZIP3.entry_names.join(' ')}") - - raise "failed to create test zip '#{TEST_ZIP4.zip_name}'" unless - system("zip #{TEST_ZIP4.zip_name} #{TEST_ZIP4.entry_names.join(' ')}") - end - rescue - raise $!.to_s + - "\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" + - "to create test data. If you don't have it you can download\n" + - "the necessary test files at http://sf.net/projects/rubyzip." - end - - TEST_ZIP1 = TestZipFile.new("data/generated/empty.zip", []) - TEST_ZIP2 = TestZipFile.new("data/generated/5entry.zip", %w{ data/generated/longAscii.txt data/generated/empty.txt data/generated/empty_chmod640.txt data/generated/short.txt data/generated/longBinary.bin}, - "my zip comment") - TEST_ZIP3 = TestZipFile.new("data/generated/test1.zip", %w{ data/file1.txt }) - TEST_ZIP4 = TestZipFile.new("data/generated/zipWithDir.zip", [ "data/file1.txt", - TestFiles::EMPTY_TEST_DIR]) -end - - -END { - TestFiles::create_test_files(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) - TestZipFile::create_test_zips(ARGV.index("recreate") != nil || - ARGV.index("recreateonly") != nil) - exit if ARGV.index("recreateonly") != nil -} diff --git a/lib/zip/test/ioextrastest.rb b/lib/zip/test/ioextrastest.rb deleted file mode 100755 index b18e9db987..0000000000 --- a/lib/zip/test/ioextrastest.rb +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -$: << "../lib" - -require 'test/unit' -require 'zip/ioextras' - -include IOExtras - -class FakeIOTest < Test::Unit::TestCase - class FakeIOUsingClass - include FakeIO - end - - def test_kind_of? - obj = FakeIOUsingClass.new - - assert(obj.kind_of?(Object)) - assert(obj.kind_of?(FakeIOUsingClass)) - assert(obj.kind_of?(IO)) - assert(!obj.kind_of?(Fixnum)) - assert(!obj.kind_of?(String)) - end -end - -class AbstractInputStreamTest < Test::Unit::TestCase - # AbstractInputStream subclass that provides a read method - - TEST_LINES = [ "Hello world#{$/}", - "this is the second line#{$/}", - "this is the last line"] - TEST_STRING = TEST_LINES.join - class TestAbstractInputStream - include AbstractInputStream - def initialize(aString) - super() - @contents = aString - @readPointer = 0 - end - - def read(charsToRead) - retVal=@contents[@readPointer, charsToRead] - @readPointer+=charsToRead - return retVal - end - - def produce_input - read(100) - end - - def input_finished? - @contents[@readPointer] == nil - end - end - - def setup - @io = TestAbstractInputStream.new(TEST_STRING) - end - - def test_gets - assert_equal(TEST_LINES[0], @io.gets) - assert_equal(1, @io.lineno) - assert_equal(TEST_LINES[1], @io.gets) - assert_equal(2, @io.lineno) - assert_equal(TEST_LINES[2], @io.gets) - assert_equal(3, @io.lineno) - assert_equal(nil, @io.gets) - assert_equal(4, @io.lineno) - end - - def test_getsMultiCharSeperator - assert_equal("Hell", @io.gets("ll")) - assert_equal("o world#{$/}this is the second l", @io.gets("d l")) - end - - def test_each_line - lineNumber=0 - @io.each_line { - |line| - assert_equal(TEST_LINES[lineNumber], line) - lineNumber+=1 - } - end - - def test_readlines - assert_equal(TEST_LINES, @io.readlines) - end - - def test_readline - test_gets - begin - @io.readline - fail "EOFError expected" - rescue EOFError - end - end -end - -class AbstractOutputStreamTest < Test::Unit::TestCase - class TestOutputStream - include AbstractOutputStream - - attr_accessor :buffer - - def initialize - @buffer = "" - end - - def << (data) - @buffer << data - self - end - end - - def setup - @outputStream = TestOutputStream.new - - @origCommaSep = $, - @origOutputSep = $\ - end - - def teardown - $, = @origCommaSep - $\ = @origOutputSep - end - - def test_write - count = @outputStream.write("a little string") - assert_equal("a little string", @outputStream.buffer) - assert_equal("a little string".length, count) - - count = @outputStream.write(". a little more") - assert_equal("a little string. a little more", @outputStream.buffer) - assert_equal(". a little more".length, count) - end - - def test_print - $\ = nil # record separator set to nil - @outputStream.print("hello") - assert_equal("hello", @outputStream.buffer) - - @outputStream.print(" world.") - assert_equal("hello world.", @outputStream.buffer) - - @outputStream.print(" You ok ", "out ", "there?") - assert_equal("hello world. You ok out there?", @outputStream.buffer) - - $\ = "\n" - @outputStream.print - assert_equal("hello world. You ok out there?\n", @outputStream.buffer) - - @outputStream.print("I sure hope so!") - assert_equal("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer) - - $, = "X" - @outputStream.buffer = "" - @outputStream.print("monkey", "duck", "zebra") - assert_equal("monkeyXduckXzebra\n", @outputStream.buffer) - - $\ = nil - @outputStream.buffer = "" - @outputStream.print(20) - assert_equal("20", @outputStream.buffer) - end - - def test_printf - @outputStream.printf("%d %04x", 123, 123) - assert_equal("123 007b", @outputStream.buffer) - end - - def test_putc - @outputStream.putc("A") - assert_equal("A", @outputStream.buffer) - @outputStream.putc(65) - assert_equal("AA", @outputStream.buffer) - end - - def test_puts - @outputStream.puts - assert_equal("\n", @outputStream.buffer) - - @outputStream.puts("hello", "world") - assert_equal("\nhello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts("hello\n", "world\n") - assert_equal("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"]) - assert_equal("hello\nworld\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(["hello\n", "world\n"], "bingo") - assert_equal("hello\nworld\nbingo\n", @outputStream.buffer) - - @outputStream.buffer = "" - @outputStream.puts(16, 20, 50, "hello") - assert_equal("16\n20\n50\nhello\n", @outputStream.buffer) - end -end - - -# Copyright (C) 2002-2004 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/test/stdrubyexttest.rb b/lib/zip/test/stdrubyexttest.rb deleted file mode 100755 index f11608f7f3..0000000000 --- a/lib/zip/test/stdrubyexttest.rb +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -$: << "../lib" - -require 'test/unit' -require 'zip/stdrubyext' - -class ModuleTest < Test::Unit::TestCase - - def test_select_map - assert_equal([2, 4, 8, 10], [1, 2, 3, 4, 5].select_map { |e| e == 3 ? nil : 2*e }) - end - -end - -class StringExtensionsTest < Test::Unit::TestCase - - def test_starts_with - assert("hello".starts_with("")) - assert("hello".starts_with("h")) - assert("hello".starts_with("he")) - assert(! "hello".starts_with("hello there")) - assert(! "hello".starts_with(" he")) - - assert_raise(TypeError, "type mismatch: NilClass given") { - "hello".starts_with(nil) - } - end - - def test_ends_with - assert("hello".ends_with("o")) - assert("hello".ends_with("lo")) - assert("hello".ends_with("hello")) - assert(!"howdy".ends_with("o")) - assert(!"howdy".ends_with("oy")) - assert(!"howdy".ends_with("howdy doody")) - assert(!"howdy".ends_with("doody howdy")) - end - - def test_ensure_end - assert_equal("hello!", "hello!".ensure_end("!")) - assert_equal("hello!", "hello!".ensure_end("o!")) - assert_equal("hello!", "hello".ensure_end("!")) - assert_equal("hello!", "hel".ensure_end("lo!")) - end -end - -# Copyright (C) 2002, 2003 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/test/zipfilesystemtest.rb b/lib/zip/test/zipfilesystemtest.rb deleted file mode 100755 index f74e804696..0000000000 --- a/lib/zip/test/zipfilesystemtest.rb +++ /dev/null @@ -1,845 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -$: << "../lib" - -require 'zip/zipfilesystem' -require 'test/unit' -require 'fileutils' - -module ExtraAssertions - - def assert_forwarded(anObject, method, retVal, *expectedArgs) - callArgs = nil - setCallArgsProc = proc { |args| callArgs = args } - anObject.instance_eval <<-"end_eval" - alias #{method}_org #{method} - def #{method}(*args) - ObjectSpace._id2ref(#{setCallArgsProc.object_id}).call(args) - ObjectSpace._id2ref(#{retVal.object_id}) - end - end_eval - - assert_equal(retVal, yield) # Invoke test - assert_equal(expectedArgs, callArgs) - ensure - anObject.instance_eval "undef #{method}; alias #{method} #{method}_org" - end - -end - -include Zip - -class ZipFsFileNonmutatingTest < Test::Unit::TestCase - def setup - @zipFile = ZipFile.new("data/zipWithDirs.zip") - end - - def teardown - @zipFile.close if @zipFile - end - - def test_umask - assert_equal(File.umask, @zipFile.file.umask) - @zipFile.file.umask(0006) - end - - def test_exists? - assert(! @zipFile.file.exists?("notAFile")) - assert(@zipFile.file.exists?("file1")) - assert(@zipFile.file.exists?("dir1")) - assert(@zipFile.file.exists?("dir1/")) - assert(@zipFile.file.exists?("dir1/file12")) - assert(@zipFile.file.exist?("dir1/file12")) # notice, tests exist? alias of exists? ! - - @zipFile.dir.chdir "dir1/" - assert(!@zipFile.file.exists?("file1")) - assert(@zipFile.file.exists?("file12")) - end - - def test_open_read - blockCalled = false - @zipFile.file.open("file1", "r") { - |f| - blockCalled = true - assert_equal("this is the entry 'file1' in my test archive!", - f.readline.chomp) - } - assert(blockCalled) - - blockCalled = false - @zipFile.file.open("file1", "rb") { # test binary flag is ignored - |f| - blockCalled = true - assert_equal("this is the entry 'file1' in my test archive!", - f.readline.chomp) - } - assert(blockCalled) - - blockCalled = false - @zipFile.dir.chdir "dir2" - @zipFile.file.open("file21", "r") { - |f| - blockCalled = true - assert_equal("this is the entry 'dir2/file21' in my test archive!", - f.readline.chomp) - } - assert(blockCalled) - @zipFile.dir.chdir "/" - - assert_raise(Errno::ENOENT) { - @zipFile.file.open("noSuchEntry") - } - - begin - is = @zipFile.file.open("file1") - assert_equal("this is the entry 'file1' in my test archive!", - is.readline.chomp) - ensure - is.close if is - end - end - - def test_new - begin - is = @zipFile.file.new("file1") - assert_equal("this is the entry 'file1' in my test archive!", - is.readline.chomp) - ensure - is.close if is - end - begin - is = @zipFile.file.new("file1") { - fail "should not call block" - } - ensure - is.close if is - end - end - - def test_symlink - assert_raise(NotImplementedError) { - @zipFile.file.symlink("file1", "aSymlink") - } - end - - def test_size - assert_raise(Errno::ENOENT) { @zipFile.file.size("notAFile") } - assert_equal(72, @zipFile.file.size("file1")) - assert_equal(0, @zipFile.file.size("dir2/dir21")) - - assert_equal(72, @zipFile.file.stat("file1").size) - assert_equal(0, @zipFile.file.stat("dir2/dir21").size) - end - - def test_size? - assert_equal(nil, @zipFile.file.size?("notAFile")) - assert_equal(72, @zipFile.file.size?("file1")) - assert_equal(nil, @zipFile.file.size?("dir2/dir21")) - - assert_equal(72, @zipFile.file.stat("file1").size?) - assert_equal(nil, @zipFile.file.stat("dir2/dir21").size?) - end - - - def test_file? - assert(@zipFile.file.file?("file1")) - assert(@zipFile.file.file?("dir2/file21")) - assert(! @zipFile.file.file?("dir1")) - assert(! @zipFile.file.file?("dir1/dir11")) - - assert(@zipFile.file.stat("file1").file?) - assert(@zipFile.file.stat("dir2/file21").file?) - assert(! @zipFile.file.stat("dir1").file?) - assert(! @zipFile.file.stat("dir1/dir11").file?) - end - - include ExtraAssertions - - def test_dirname - assert_forwarded(File, :dirname, "retVal", "a/b/c/d") { - @zipFile.file.dirname("a/b/c/d") - } - end - - def test_basename - assert_forwarded(File, :basename, "retVal", "a/b/c/d") { - @zipFile.file.basename("a/b/c/d") - } - end - - def test_split - assert_forwarded(File, :split, "retVal", "a/b/c/d") { - @zipFile.file.split("a/b/c/d") - } - end - - def test_join - assert_equal("a/b/c", @zipFile.file.join("a/b", "c")) - assert_equal("a/b/c/d", @zipFile.file.join("a/b", "c/d")) - assert_equal("/c/d", @zipFile.file.join("", "c/d")) - assert_equal("a/b/c/d", @zipFile.file.join("a", "b", "c", "d")) - end - - def test_utime - t_now = Time.now - t_bak = @zipFile.file.mtime("file1") - @zipFile.file.utime(t_now, "file1") - assert_equal(t_now, @zipFile.file.mtime("file1")) - @zipFile.file.utime(t_bak, "file1") - assert_equal(t_bak, @zipFile.file.mtime("file1")) - end - - - def assert_always_false(operation) - assert(! @zipFile.file.send(operation, "noSuchFile")) - assert(! @zipFile.file.send(operation, "file1")) - assert(! @zipFile.file.send(operation, "dir1")) - assert(! @zipFile.file.stat("file1").send(operation)) - assert(! @zipFile.file.stat("dir1").send(operation)) - end - - def assert_true_if_entry_exists(operation) - assert(! @zipFile.file.send(operation, "noSuchFile")) - assert(@zipFile.file.send(operation, "file1")) - assert(@zipFile.file.send(operation, "dir1")) - assert(@zipFile.file.stat("file1").send(operation)) - assert(@zipFile.file.stat("dir1").send(operation)) - end - - def test_pipe? - assert_always_false(:pipe?) - end - - def test_blockdev? - assert_always_false(:blockdev?) - end - - def test_symlink? - assert_always_false(:symlink?) - end - - def test_socket? - assert_always_false(:socket?) - end - - def test_chardev? - assert_always_false(:chardev?) - end - - def test_truncate - assert_raise(StandardError, "truncate not supported") { - @zipFile.file.truncate("file1", 100) - } - end - - def assert_e_n_o_e_n_t(operation, args = ["NoSuchFile"]) - assert_raise(Errno::ENOENT) { - @zipFile.file.send(operation, *args) - } - end - - def test_ftype - assert_e_n_o_e_n_t(:ftype) - assert_equal("file", @zipFile.file.ftype("file1")) - assert_equal("directory", @zipFile.file.ftype("dir1/dir11")) - assert_equal("directory", @zipFile.file.ftype("dir1/dir11/")) - end - - def test_link - assert_raise(NotImplementedError) { - @zipFile.file.link("file1", "someOtherString") - } - end - - def test_directory? - assert(! @zipFile.file.directory?("notAFile")) - assert(! @zipFile.file.directory?("file1")) - assert(! @zipFile.file.directory?("dir1/file11")) - assert(@zipFile.file.directory?("dir1")) - assert(@zipFile.file.directory?("dir1/")) - assert(@zipFile.file.directory?("dir2/dir21")) - - assert(! @zipFile.file.stat("file1").directory?) - assert(! @zipFile.file.stat("dir1/file11").directory?) - assert(@zipFile.file.stat("dir1").directory?) - assert(@zipFile.file.stat("dir1/").directory?) - assert(@zipFile.file.stat("dir2/dir21").directory?) - end - - def test_chown - assert_equal(2, @zipFile.file.chown(1,2, "dir1", "file1")) - assert_equal(1, @zipFile.file.stat("dir1").uid) - assert_equal(2, @zipFile.file.stat("dir1").gid) - assert_equal(2, @zipFile.file.chown(nil, nil, "dir1", "file1")) - end - - def test_zero? - assert(! @zipFile.file.zero?("notAFile")) - assert(! @zipFile.file.zero?("file1")) - assert(@zipFile.file.zero?("dir1")) - blockCalled = false - ZipFile.open("data/generated/5entry.zip") { - |zf| - blockCalled = true - assert(zf.file.zero?("data/generated/empty.txt")) - } - assert(blockCalled) - - assert(! @zipFile.file.stat("file1").zero?) - assert(@zipFile.file.stat("dir1").zero?) - blockCalled = false - ZipFile.open("data/generated/5entry.zip") { - |zf| - blockCalled = true - assert(zf.file.stat("data/generated/empty.txt").zero?) - } - assert(blockCalled) - end - - def test_expand_path - ZipFile.open("data/zipWithDirs.zip") { - |zf| - assert_equal("/", zf.file.expand_path(".")) - zf.dir.chdir "dir1" - assert_equal("/dir1", zf.file.expand_path(".")) - assert_equal("/dir1/file12", zf.file.expand_path("file12")) - assert_equal("/", zf.file.expand_path("..")) - assert_equal("/dir2/dir21", zf.file.expand_path("../dir2/dir21")) - } - end - - def test_mtime - assert_equal(Time.at(1027694306), - @zipFile.file.mtime("dir2/file21")) - assert_equal(Time.at(1027690863), - @zipFile.file.mtime("dir2/dir21")) - assert_raise(Errno::ENOENT) { - @zipFile.file.mtime("noSuchEntry") - } - - assert_equal(Time.at(1027694306), - @zipFile.file.stat("dir2/file21").mtime) - assert_equal(Time.at(1027690863), - @zipFile.file.stat("dir2/dir21").mtime) - end - - def test_ctime - assert_nil(@zipFile.file.ctime("file1")) - assert_nil(@zipFile.file.stat("file1").ctime) - end - - def test_atime - assert_nil(@zipFile.file.atime("file1")) - assert_nil(@zipFile.file.stat("file1").atime) - end - - def test_readable? - assert(! @zipFile.file.readable?("noSuchFile")) - assert(@zipFile.file.readable?("file1")) - assert(@zipFile.file.readable?("dir1")) - assert(@zipFile.file.stat("file1").readable?) - assert(@zipFile.file.stat("dir1").readable?) - end - - def test_readable_real? - assert(! @zipFile.file.readable_real?("noSuchFile")) - assert(@zipFile.file.readable_real?("file1")) - assert(@zipFile.file.readable_real?("dir1")) - assert(@zipFile.file.stat("file1").readable_real?) - assert(@zipFile.file.stat("dir1").readable_real?) - end - - def test_writable? - assert(! @zipFile.file.writable?("noSuchFile")) - assert(@zipFile.file.writable?("file1")) - assert(@zipFile.file.writable?("dir1")) - assert(@zipFile.file.stat("file1").writable?) - assert(@zipFile.file.stat("dir1").writable?) - end - - def test_writable_real? - assert(! @zipFile.file.writable_real?("noSuchFile")) - assert(@zipFile.file.writable_real?("file1")) - assert(@zipFile.file.writable_real?("dir1")) - assert(@zipFile.file.stat("file1").writable_real?) - assert(@zipFile.file.stat("dir1").writable_real?) - end - - def test_executable? - assert(! @zipFile.file.executable?("noSuchFile")) - assert(! @zipFile.file.executable?("file1")) - assert(@zipFile.file.executable?("dir1")) - assert(! @zipFile.file.stat("file1").executable?) - assert(@zipFile.file.stat("dir1").executable?) - end - - def test_executable_real? - assert(! @zipFile.file.executable_real?("noSuchFile")) - assert(! @zipFile.file.executable_real?("file1")) - assert(@zipFile.file.executable_real?("dir1")) - assert(! @zipFile.file.stat("file1").executable_real?) - assert(@zipFile.file.stat("dir1").executable_real?) - end - - def test_owned? - assert_true_if_entry_exists(:owned?) - end - - def test_grpowned? - assert_true_if_entry_exists(:grpowned?) - end - - def test_setgid? - assert_always_false(:setgid?) - end - - def test_setuid? - assert_always_false(:setgid?) - end - - def test_sticky? - assert_always_false(:sticky?) - end - - def test_readlink - assert_raise(NotImplementedError) { - @zipFile.file.readlink("someString") - } - end - - def test_stat - s = @zipFile.file.stat("file1") - assert(s.kind_of?(File::Stat)) # It pretends - assert_raise(Errno::ENOENT, "No such file or directory - noSuchFile") { - @zipFile.file.stat("noSuchFile") - } - end - - def test_lstat - assert(@zipFile.file.lstat("file1").file?) - end - - - def test_chmod - assert_raise(Errno::ENOENT, "No such file or directory - noSuchFile") { - @zipFile.file.chmod(0644, "file1", "NoSuchFile") - } - assert_equal(2, @zipFile.file.chmod(0644, "file1", "dir1")) - end - - def test_pipe - assert_raise(NotImplementedError) { - @zipFile.file.pipe - } - end - - def test_foreach - ZipFile.open("data/generated/zipWithDir.zip") { - |zf| - ref = [] - File.foreach("data/file1.txt") { |e| ref << e } - - index = 0 - zf.file.foreach("data/file1.txt") { - |l| - assert_equal(ref[index], l) - index = index.next - } - assert_equal(ref.size, index) - } - - ZipFile.open("data/generated/zipWithDir.zip") { - |zf| - ref = [] - File.foreach("data/file1.txt", " ") { |e| ref << e } - - index = 0 - zf.file.foreach("data/file1.txt", " ") { - |l| - assert_equal(ref[index], l) - index = index.next - } - assert_equal(ref.size, index) - } - end - - def test_popen - if RUBY_PLATFORM =~ /mswin|mingw/i - cmd = 'dir' - else - cmd = 'ls' - end - - assert_equal(File.popen(cmd) { |f| f.read }, - @zipFile.file.popen(cmd) { |f| f.read }) - end - -# Can be added later -# def test_select -# fail "implement test" -# end - - def test_readlines - ZipFile.open("data/generated/zipWithDir.zip") { - |zf| - assert_equal(File.readlines("data/file1.txt"), - zf.file.readlines("data/file1.txt")) - } - end - - def test_read - ZipFile.open("data/generated/zipWithDir.zip") { - |zf| - assert_equal(File.read("data/file1.txt"), - zf.file.read("data/file1.txt")) - } - end - -end - -class ZipFsFileStatTest < Test::Unit::TestCase - - def setup - @zipFile = ZipFile.new("data/zipWithDirs.zip") - end - - def teardown - @zipFile.close if @zipFile - end - - def test_blocks - assert_equal(nil, @zipFile.file.stat("file1").blocks) - end - - def test_ino - assert_equal(0, @zipFile.file.stat("file1").ino) - end - - def test_uid - assert_equal(0, @zipFile.file.stat("file1").uid) - end - - def test_gid - assert_equal(0, @zipFile.file.stat("file1").gid) - end - - def test_ftype - assert_equal("file", @zipFile.file.stat("file1").ftype) - assert_equal("directory", @zipFile.file.stat("dir1").ftype) - end - - def test_mode - assert_equal(0600, @zipFile.file.stat("file1").mode & 0777) - assert_equal(0600, @zipFile.file.stat("file1").mode & 0777) - assert_equal(0755, @zipFile.file.stat("dir1").mode & 0777) - assert_equal(0755, @zipFile.file.stat("dir1").mode & 0777) - end - - def test_dev - assert_equal(0, @zipFile.file.stat("file1").dev) - end - - def test_rdev - assert_equal(0, @zipFile.file.stat("file1").rdev) - end - - def test_rdev_major - assert_equal(0, @zipFile.file.stat("file1").rdev_major) - end - - def test_rdev_minor - assert_equal(0, @zipFile.file.stat("file1").rdev_minor) - end - - def test_nlink - assert_equal(1, @zipFile.file.stat("file1").nlink) - end - - def test_blksize - assert_nil(@zipFile.file.stat("file1").blksize) - end - -end - -class ZipFsFileMutatingTest < Test::Unit::TestCase - TEST_ZIP = "zipWithDirs_copy.zip" - def setup - FileUtils.cp("data/zipWithDirs.zip", TEST_ZIP) - end - - def teardown - end - - def test_delete - do_test_delete_or_unlink(:delete) - end - - def test_unlink - do_test_delete_or_unlink(:unlink) - end - - def test_open_write - ZipFile.open(TEST_ZIP) { - |zf| - - zf.file.open("test_open_write_entry", "w") { - |f| - blockCalled = true - f.write "This is what I'm writing" - } - assert_equal("This is what I'm writing", - zf.file.read("test_open_write_entry")) - - # Test with existing entry - zf.file.open("file1", "wb") { #also check that 'b' option is ignored - |f| - blockCalled = true - f.write "This is what I'm writing too" - } - assert_equal("This is what I'm writing too", - zf.file.read("file1")) - } - end - - def test_rename - ZipFile.open(TEST_ZIP) { - |zf| - assert_raise(Errno::ENOENT, "") { - zf.file.rename("NoSuchFile", "bimse") - } - zf.file.rename("file1", "newNameForFile1") - } - - ZipFile.open(TEST_ZIP) { - |zf| - assert(! zf.file.exists?("file1")) - assert(zf.file.exists?("newNameForFile1")) - } - end - - def do_test_delete_or_unlink(symbol) - ZipFile.open(TEST_ZIP) { - |zf| - assert(zf.file.exists?("dir2/dir21/dir221/file2221")) - zf.file.send(symbol, "dir2/dir21/dir221/file2221") - assert(! zf.file.exists?("dir2/dir21/dir221/file2221")) - - assert(zf.file.exists?("dir1/file11")) - assert(zf.file.exists?("dir1/file12")) - zf.file.send(symbol, "dir1/file11", "dir1/file12") - assert(! zf.file.exists?("dir1/file11")) - assert(! zf.file.exists?("dir1/file12")) - - assert_raise(Errno::ENOENT) { zf.file.send(symbol, "noSuchFile") } - assert_raise(Errno::EISDIR) { zf.file.send(symbol, "dir1/dir11") } - assert_raise(Errno::EISDIR) { zf.file.send(symbol, "dir1/dir11/") } - } - - ZipFile.open(TEST_ZIP) { - |zf| - assert(! zf.file.exists?("dir2/dir21/dir221/file2221")) - assert(! zf.file.exists?("dir1/file11")) - assert(! zf.file.exists?("dir1/file12")) - - assert(zf.file.exists?("dir1/dir11")) - assert(zf.file.exists?("dir1/dir11/")) - } - end - -end - -class ZipFsDirectoryTest < Test::Unit::TestCase - TEST_ZIP = "zipWithDirs_copy.zip" - - def setup - FileUtils.cp("data/zipWithDirs.zip", TEST_ZIP) - end - - def test_delete - ZipFile.open(TEST_ZIP) { - |zf| - assert_raise(Errno::ENOENT, "No such file or directory - NoSuchFile.txt") { - zf.dir.delete("NoSuchFile.txt") - } - assert_raise(Errno::EINVAL, "Invalid argument - file1") { - zf.dir.delete("file1") - } - assert(zf.file.exists?("dir1")) - zf.dir.delete("dir1") - assert(! zf.file.exists?("dir1")) - } - end - - def test_mkdir - ZipFile.open(TEST_ZIP) { - |zf| - assert_raise(Errno::EEXIST, "File exists - dir1") { - zf.dir.mkdir("file1") - } - assert_raise(Errno::EEXIST, "File exists - dir1") { - zf.dir.mkdir("dir1") - } - assert(!zf.file.exists?("newDir")) - zf.dir.mkdir("newDir") - assert(zf.file.directory?("newDir")) - assert(!zf.file.exists?("newDir2")) - zf.dir.mkdir("newDir2", 3485) - assert(zf.file.directory?("newDir2")) - } - end - - def test_pwd_chdir_entries - ZipFile.open(TEST_ZIP) { - |zf| - assert_equal("/", zf.dir.pwd) - - assert_raise(Errno::ENOENT, "No such file or directory - no such dir") { - zf.dir.chdir "no such dir" - } - - assert_raise(Errno::EINVAL, "Invalid argument - file1") { - zf.dir.chdir "file1" - } - - assert_equal(["dir1", "dir2", "file1"].sort, zf.dir.entries(".").sort) - zf.dir.chdir "dir1" - assert_equal("/dir1", zf.dir.pwd) - assert_equal(["dir11", "file11", "file12"], zf.dir.entries(".").sort) - - zf.dir.chdir "../dir2/dir21" - assert_equal("/dir2/dir21", zf.dir.pwd) - assert_equal(["dir221"].sort, zf.dir.entries(".").sort) - } - end - - def test_foreach - ZipFile.open(TEST_ZIP) { - |zf| - - blockCalled = false - assert_raise(Errno::ENOENT, "No such file or directory - noSuchDir") { - zf.dir.foreach("noSuchDir") { |e| blockCalled = true } - } - assert(! blockCalled) - - assert_raise(Errno::ENOTDIR, "Not a directory - file1") { - zf.dir.foreach("file1") { |e| blockCalled = true } - } - assert(! blockCalled) - - entries = [] - zf.dir.foreach(".") { |e| entries << e } - assert_equal(["dir1", "dir2", "file1"].sort, entries.sort) - - entries = [] - zf.dir.foreach("dir1") { |e| entries << e } - assert_equal(["dir11", "file11", "file12"], entries.sort) - } - end - - def test_chroot - ZipFile.open(TEST_ZIP) { - |zf| - assert_raise(NotImplementedError) { - zf.dir.chroot - } - } - end - - # Globbing not supported yet - #def test_glob - # # test alias []-operator too - # fail "implement test" - #end - - def test_open_new - ZipFile.open(TEST_ZIP) { - |zf| - - assert_raise(Errno::ENOTDIR, "Not a directory - file1") { - zf.dir.new("file1") - } - - assert_raise(Errno::ENOENT, "No such file or directory - noSuchFile") { - zf.dir.new("noSuchFile") - } - - d = zf.dir.new(".") - assert_equal(["file1", "dir1", "dir2"].sort, d.entries.sort) - d.close - - zf.dir.open("dir1") { - |dir| - assert_equal(["dir11", "file11", "file12"].sort, dir.entries.sort) - } - } - end - -end - -class ZipFsDirIteratorTest < Test::Unit::TestCase - - FILENAME_ARRAY = [ "f1", "f2", "f3", "f4", "f5", "f6" ] - - def setup - @dirIt = ZipFileSystem::ZipFsDirIterator.new(FILENAME_ARRAY) - end - - def test_close - @dirIt.close - assert_raise(IOError, "closed directory") { - @dirIt.each { |e| p e } - } - assert_raise(IOError, "closed directory") { - @dirIt.read - } - assert_raise(IOError, "closed directory") { - @dirIt.rewind - } - assert_raise(IOError, "closed directory") { - @dirIt.seek(0) - } - assert_raise(IOError, "closed directory") { - @dirIt.tell - } - - end - - def test_each - # Tested through Enumerable.entries - assert_equal(FILENAME_ARRAY, @dirIt.entries) - end - - def test_read - FILENAME_ARRAY.size.times { - |i| - assert_equal(FILENAME_ARRAY[i], @dirIt.read) - } - end - - def test_rewind - @dirIt.read - @dirIt.read - assert_equal(FILENAME_ARRAY[2], @dirIt.read) - @dirIt.rewind - assert_equal(FILENAME_ARRAY[0], @dirIt.read) - end - - def test_tell_seek - @dirIt.read - @dirIt.read - pos = @dirIt.tell - valAtPos = @dirIt.read - @dirIt.read - @dirIt.seek(pos) - assert_equal(valAtPos, @dirIt.read) - end - -end - - -# Copyright (C) 2002, 2003 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/test/ziprequiretest.rb b/lib/zip/test/ziprequiretest.rb deleted file mode 100755 index 68d2c714ed..0000000000 --- a/lib/zip/test/ziprequiretest.rb +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -$: << "../lib" - -require 'test/unit' -require 'zip/ziprequire' - -$: << 'data/rubycode.zip' << 'data/rubycode2.zip' - -class ZipRequireTest < Test::Unit::TestCase - def test_require - assert(require('data/notzippedruby')) - assert(!require('data/notzippedruby')) - - assert(require('zippedruby1')) - assert(!require('zippedruby1')) - - assert(require('zippedruby2')) - assert(!require('zippedruby2')) - - assert(require('zippedruby3')) - assert(!require('zippedruby3')) - - c1 = NotZippedRuby.new - assert(c1.returnTrue) - assert(ZippedRuby1.returnTrue) - assert(!ZippedRuby2.returnFalse) - assert_equal(4, ZippedRuby3.multiplyValues(2, 2)) - end - - def test_get_resource - get_resource("aResource.txt") { - |f| - assert_equal("Nothing exciting in this file!", f.read) - } - end -end - -# Copyright (C) 2002 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/test/ziptest.rb b/lib/zip/test/ziptest.rb deleted file mode 100755 index aa07ffe848..0000000000 --- a/lib/zip/test/ziptest.rb +++ /dev/null @@ -1,1623 +0,0 @@ -#!/usr/bin/env ruby - -$VERBOSE = true - -$: << "../lib" - -require 'test/unit' -require 'fileutils' -require 'zip/zip' -require 'gentestfiles' - -include Zip - - -class ZipEntryTest < Test::Unit::TestCase - TEST_ZIPFILE = "someZipFile.zip" - TEST_COMMENT = "a comment" - TEST_COMPRESSED_SIZE = 1234 - TEST_CRC = 325324 - TEST_EXTRA = "Some data here" - TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED - TEST_NAME = "entry name" - TEST_SIZE = 8432 - TEST_ISDIRECTORY = false - - def test_constructorAndGetters - entry = ZipEntry.new(TEST_ZIPFILE, - TEST_NAME, - TEST_COMMENT, - TEST_EXTRA, - TEST_COMPRESSED_SIZE, - TEST_CRC, - TEST_COMPRESSIONMETHOD, - TEST_SIZE) - - assert_equal(TEST_COMMENT, entry.comment) - assert_equal(TEST_COMPRESSED_SIZE, entry.compressed_size) - assert_equal(TEST_CRC, entry.crc) - assert_instance_of(Zip::ZipExtraField, entry.extra) - assert_equal(TEST_COMPRESSIONMETHOD, entry.compression_method) - assert_equal(TEST_NAME, entry.name) - assert_equal(TEST_SIZE, entry.size) - assert_equal(TEST_ISDIRECTORY, entry.is_directory) - end - - def test_is_directoryAndIsFile - assert(ZipEntry.new(TEST_ZIPFILE, "hello").file?) - assert(! ZipEntry.new(TEST_ZIPFILE, "hello").directory?) - - assert(ZipEntry.new(TEST_ZIPFILE, "dir/hello").file?) - assert(! ZipEntry.new(TEST_ZIPFILE, "dir/hello").directory?) - - assert(ZipEntry.new(TEST_ZIPFILE, "hello/").directory?) - assert(! ZipEntry.new(TEST_ZIPFILE, "hello/").file?) - - assert(ZipEntry.new(TEST_ZIPFILE, "dir/hello/").directory?) - assert(! ZipEntry.new(TEST_ZIPFILE, "dir/hello/").file?) - end - - def test_equality - entry1 = ZipEntry.new("file.zip", "name", "isNotCompared", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extra", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 123, 1234, - ZipEntry::DEFLATED, 10000) - entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 1234, - ZipEntry::DEFLATED, 10000) - entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::DEFLATED, 10000) - entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 10000) - entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", - "something extraXX", 12, 123, - ZipEntry::STORED, 100000) - - assert_equal(entry1, entry1) - assert_equal(entry1, entry2) - - assert(entry2 != entry3) - assert(entry3 != entry4) - assert(entry4 != entry5) - assert(entry5 != entry6) - assert(entry6 != entry7) - assert(entry7 != entry8) - - assert(entry7 != "hello") - assert(entry7 != 12) - end - - def test_compare - assert_equal(0, (ZipEntry.new("zf.zip", "a") <=> ZipEntry.new("zf.zip", "a"))) - assert_equal(1, (ZipEntry.new("zf.zip", "b") <=> ZipEntry.new("zf.zip", "a"))) - assert_equal(-1, (ZipEntry.new("zf.zip", "a") <=> ZipEntry.new("zf.zip", "b"))) - - entries = [ - ZipEntry.new("zf.zip", "5"), - ZipEntry.new("zf.zip", "1"), - ZipEntry.new("zf.zip", "3"), - ZipEntry.new("zf.zip", "4"), - ZipEntry.new("zf.zip", "0"), - ZipEntry.new("zf.zip", "2") - ] - - entries.sort! - assert_equal("0", entries[0].to_s) - assert_equal("1", entries[1].to_s) - assert_equal("2", entries[2].to_s) - assert_equal("3", entries[3].to_s) - assert_equal("4", entries[4].to_s) - assert_equal("5", entries[5].to_s) - end - - def test_parentAsString - entry1 = ZipEntry.new("zf.zip", "aa") - entry2 = ZipEntry.new("zf.zip", "aa/") - entry3 = ZipEntry.new("zf.zip", "aa/bb") - entry4 = ZipEntry.new("zf.zip", "aa/bb/") - entry5 = ZipEntry.new("zf.zip", "aa/bb/cc") - entry6 = ZipEntry.new("zf.zip", "aa/bb/cc/") - - assert_equal(nil, entry1.parent_as_string) - assert_equal(nil, entry2.parent_as_string) - assert_equal("aa/", entry3.parent_as_string) - assert_equal("aa/", entry4.parent_as_string) - assert_equal("aa/bb/", entry5.parent_as_string) - assert_equal("aa/bb/", entry6.parent_as_string) - end - - def test_entry_name_cannot_start_with_slash - assert_raise(ZipEntryNameError) { ZipEntry.new("zf.zip", "/hej/der") } - end -end - -module IOizeString - attr_reader :tell - - def read(count = nil) - @tell ||= 0 - count = size unless count - retVal = slice(@tell, count) - @tell += count - return retVal - end - - def seek(index, offset) - @tell ||= 0 - case offset - when IO::SEEK_END - newPos = size + index - when IO::SEEK_SET - newPos = index - when IO::SEEK_CUR - newPos = @tell + index - else - raise "Error in test method IOizeString::seek" - end - if (newPos < 0 || newPos >= size) - raise Errno::EINVAL - else - @tell=newPos - end - end - - def reset - @tell = 0 - end -end - -class ZipLocalEntryTest < Test::Unit::TestCase - def test_read_local_entryHeaderOfFirstTestZipEntry - File.open(TestZipFile::TEST_ZIP3.zip_name, "rb") { - |file| - entry = ZipEntry.read_local_entry(file) - - assert_equal("", entry.comment) - # Differs from windows and unix because of CR LF - # assert_equal(480, entry.compressed_size) - # assert_equal(0x2a27930f, entry.crc) - # extra field is 21 bytes long - # probably contains some unix attrutes or something - # disabled: assert_equal(nil, entry.extra) - assert_equal(ZipEntry::DEFLATED, entry.compression_method) - assert_equal(TestZipFile::TEST_ZIP3.entry_names[0], entry.name) - assert_equal(File.size(TestZipFile::TEST_ZIP3.entry_names[0]), entry.size) - assert(! entry.is_directory) - } - end - - def test_readDateTime - File.open("data/rubycode.zip", "rb") { - |file| - entry = ZipEntry.read_local_entry(file) - assert_equal("zippedruby1.rb", entry.name) - assert_equal(Time.at(1019261638), entry.time) - } - end - - def test_read_local_entryFromNonZipFile - File.open("data/file2.txt") { - |file| - assert_equal(nil, ZipEntry.read_local_entry(file)) - } - end - - def test_read_local_entryFromTruncatedZipFile - zipFragment="" - File.open(TestZipFile::TEST_ZIP2.zip_name) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes - zipFragment.extend(IOizeString).reset - entry = ZipEntry.new - entry.read_local_entry(zipFragment) - fail "ZipError expected" - rescue ZipError - end - - def test_writeEntry - entry = ZipEntry.new("file.zip", "entryName", "my little comment", - "thisIsSomeExtraInformation", 100, 987654, - ZipEntry::DEFLATED, 400) - write_to_file("localEntryHeader.bin", "centralEntryHeader.bin", entry) - entryReadLocal, entryReadCentral = read_from_file("localEntryHeader.bin", "centralEntryHeader.bin") - compare_local_entry_headers(entry, entryReadLocal) - compare_c_dir_entry_headers(entry, entryReadCentral) - end - - private - def compare_local_entry_headers(entry1, entry2) - assert_equal(entry1.compressed_size , entry2.compressed_size) - assert_equal(entry1.crc , entry2.crc) - assert_equal(entry1.extra , entry2.extra) - assert_equal(entry1.compression_method, entry2.compression_method) - assert_equal(entry1.name , entry2.name) - assert_equal(entry1.size , entry2.size) - assert_equal(entry1.localHeaderOffset, entry2.localHeaderOffset) - end - - def compare_c_dir_entry_headers(entry1, entry2) - compare_local_entry_headers(entry1, entry2) - assert_equal(entry1.comment, entry2.comment) - end - - def write_to_file(localFileName, centralFileName, entry) - File.open(localFileName, "wb") { |f| entry.write_local_entry(f) } - File.open(centralFileName, "wb") { |f| entry.write_c_dir_entry(f) } - end - - def read_from_file(localFileName, centralFileName) - localEntry = nil - cdirEntry = nil - File.open(localFileName, "rb") { |f| localEntry = ZipEntry.read_local_entry(f) } - File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.read_c_dir_entry(f) } - return [localEntry, cdirEntry] - end -end - - -module DecompressorTests - # expects @refText, @refLines and @decompressor - - TEST_FILE="data/file1.txt" - - def setup - @refText="" - File.open(TEST_FILE) { |f| @refText = f.read } - @refLines = @refText.split($/) - end - - def test_readEverything - assert_equal(@refText, @decompressor.sysread) - end - - def test_readInChunks - chunkSize = 5 - while (decompressedChunk = @decompressor.sysread(chunkSize)) - assert_equal(@refText.slice!(0, chunkSize), decompressedChunk) - end - assert_equal(0, @refText.size) - end - - def test_mixingReadsAndProduceInput - # Just some preconditions to make sure we have enough data for this test - assert(@refText.length > 1000) - assert(@refLines.length > 40) - - - assert_equal(@refText[0...100], @decompressor.sysread(100)) - - assert(! @decompressor.input_finished?) - buf = @decompressor.produce_input - assert_equal(@refText[100...(100+buf.length)], buf) - end -end - -class InflaterTest < Test::Unit::TestCase - include DecompressorTests - - def setup - super - @file = File.new("data/file1.txt.deflatedData", "rb") - @decompressor = Inflater.new(@file) - end - - def teardown - @file.close - end -end - - -class PassThruDecompressorTest < Test::Unit::TestCase - include DecompressorTests - def setup - super - @file = File.new(TEST_FILE) - @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE)) - end - - def teardown - @file.close - end -end - - -module AssertEntry - def assert_next_entry(filename, zis) - assert_entry(filename, zis, zis.get_next_entry.name) - end - - def assert_entry(filename, zis, entryName) - assert_equal(filename, entryName) - assert_entryContentsForStream(filename, zis, entryName) - end - - def assert_entryContentsForStream(filename, zis, entryName) - File.open(filename, "rb") { - |file| - expected = file.read - actual = zis.read - if (expected != actual) - if ((expected && actual) && (expected.length > 400 || actual.length > 400)) - zipEntryFilename=entryName+".zipEntry" - File.open(zipEntryFilename, "wb") { |f| f << actual } - fail("File '#{filename}' is different from '#{zipEntryFilename}'") - else - assert_equal(expected, actual) - end - end - } - end - - def AssertEntry.assert_contents(filename, aString) - fileContents = "" - File.open(filename, "rb") { |f| fileContents = f.read } - if (fileContents != aString) - if (fileContents.length > 400 || aString.length > 400) - stringFile = filename + ".other" - File.open(stringFile, "wb") { |f| f << aString } - fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'") - else - assert_equal(fileContents, aString) - end - end - end - - def assert_stream_contents(zis, testZipFile) - assert(zis != nil) - testZipFile.entry_names.each { - |entryName| - assert_next_entry(entryName, zis) - } - assert_equal(nil, zis.get_next_entry) - end - - def assert_test_zip_contents(testZipFile) - ZipInputStream.open(testZipFile.zip_name) { - |zis| - assert_stream_contents(zis, testZipFile) - } - end - - def assert_entryContents(zipFile, entryName, filename = entryName.to_s) - zis = zipFile.get_input_stream(entryName) - assert_entryContentsForStream(filename, zis, entryName) - ensure - zis.close if zis - end -end - - - -class ZipInputStreamTest < Test::Unit::TestCase - include AssertEntry - - def test_new - zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zip_name) - assert_stream_contents(zis, TestZipFile::TEST_ZIP2) - assert_equal(true, zis.eof?) - zis.close - end - - def test_openWithBlock - ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) { - |zis| - assert_stream_contents(zis, TestZipFile::TEST_ZIP2) - assert_equal(true, zis.eof?) - } - end - - def test_openWithoutBlock - zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) - assert_stream_contents(zis, TestZipFile::TEST_ZIP2) - end - - def test_incompleteReads - ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) { - |zis| - entry = zis.get_next_entry # longAscii.txt - assert_equal(false, zis.eof?) - assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], entry.name) - assert zis.gets.length > 0 - assert_equal(false, zis.eof?) - entry = zis.get_next_entry # empty.txt - assert_equal(TestZipFile::TEST_ZIP2.entry_names[1], entry.name) - assert_equal(0, entry.size) - assert_equal(nil, zis.gets) - assert_equal(true, zis.eof?) - entry = zis.get_next_entry # empty_chmod640.txt - assert_equal(TestZipFile::TEST_ZIP2.entry_names[2], entry.name) - assert_equal(0, entry.size) - assert_equal(nil, zis.gets) - assert_equal(true, zis.eof?) - entry = zis.get_next_entry # short.txt - assert_equal(TestZipFile::TEST_ZIP2.entry_names[3], entry.name) - assert zis.gets.length > 0 - entry = zis.get_next_entry # longBinary.bin - assert_equal(TestZipFile::TEST_ZIP2.entry_names[4], entry.name) - assert zis.gets.length > 0 - } - end - - def test_rewind - ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) { - |zis| - e = zis.get_next_entry - assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], e.name) - - # Do a little reading - buf = "" - buf << zis.read(100) - buf << (zis.gets || "") - buf << (zis.gets || "") - assert_equal(false, zis.eof?) - - zis.rewind - - buf2 = "" - buf2 << zis.read(100) - buf2 << (zis.gets || "") - buf2 << (zis.gets || "") - - assert_equal(buf, buf2) - - zis.rewind - assert_equal(false, zis.eof?) - - assert_entry(e.name, zis, e.name) - } - end - - def test_mix_read_and_gets - ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) { - |zis| - e = zis.get_next_entry - assert_equal("#!/usr/bin/env ruby", zis.gets.chomp) - assert_equal(false, zis.eof?) - assert_equal("", zis.gets.chomp) - assert_equal(false, zis.eof?) - assert_equal("$VERBOSE =", zis.read(10)) - assert_equal(false, zis.eof?) - } - end - -end - - -module CrcTest - - class TestOutputStream - include IOExtras::AbstractOutputStream - - attr_accessor :buffer - - def initialize - @buffer = "" - end - - def << (data) - @buffer << data - self - end - end - - def run_crc_test(compressorClass) - str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed." - fakeOut = TestOutputStream.new - - deflater = compressorClass.new(fakeOut) - deflater << str - assert_equal(0x919920fc, deflater.crc) - end -end - - - -class PassThruCompressorTest < Test::Unit::TestCase - include CrcTest - - def test_size - File.open("dummy.txt", "wb") { - |file| - compressor = PassThruCompressor.new(file) - - assert_equal(0, compressor.size) - - t1 = "hello world" - t2 = "" - t3 = "bingo" - - compressor << t1 - assert_equal(compressor.size, t1.size) - - compressor << t2 - assert_equal(compressor.size, t1.size + t2.size) - - compressor << t3 - assert_equal(compressor.size, t1.size + t2.size + t3.size) - } - end - - def test_crc - run_crc_test(PassThruCompressor) - end -end - -class DeflaterTest < Test::Unit::TestCase - include CrcTest - - def test_outputOperator - txt = load_file("data/file2.txt") - deflate(txt, "deflatertest.bin") - inflatedTxt = inflate("deflatertest.bin") - assert_equal(txt, inflatedTxt) - end - - private - def load_file(fileName) - txt = nil - File.open(fileName, "rb") { |f| txt = f.read } - end - - def deflate(data, fileName) - File.open(fileName, "wb") { - |file| - deflater = Deflater.new(file) - deflater << data - deflater.finish - assert_equal(deflater.size, data.size) - file << "trailing data for zlib with -MAX_WBITS" - } - end - - def inflate(fileName) - txt = nil - File.open(fileName, "rb") { - |file| - inflater = Inflater.new(file) - txt = inflater.sysread - } - end - - def test_crc - run_crc_test(Deflater) - end -end - -class ZipOutputStreamTest < Test::Unit::TestCase - include AssertEntry - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zip_name = "output.zip" - - def test_new - zos = ZipOutputStream.new(TEST_ZIP.zip_name) - zos.comment = TEST_ZIP.comment - write_test_zip(zos) - zos.close - assert_test_zip_contents(TEST_ZIP) - end - - def test_open - ZipOutputStream.open(TEST_ZIP.zip_name) { - |zos| - zos.comment = TEST_ZIP.comment - write_test_zip(zos) - } - assert_test_zip_contents(TEST_ZIP) - end - - def test_writingToClosedStream - assert_i_o_error_in_closed_stream { |zos| zos << "hello world" } - assert_i_o_error_in_closed_stream { |zos| zos.puts "hello world" } - assert_i_o_error_in_closed_stream { |zos| zos.write "hello world" } - end - - def test_cannotOpenFile - name = TestFiles::EMPTY_TEST_DIR - begin - zos = ZipOutputStream.open(name) - rescue Exception - assert($!.kind_of?(Errno::EISDIR) || # Linux - $!.kind_of?(Errno::EEXIST) || # Windows/cygwin - $!.kind_of?(Errno::EACCES), # Windows - "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.class}") - end - end - - def test_put_next_entry - stored_text = "hello world in stored text" - entry_name = "file1" - comment = "my comment" - ZipOutputStream.open(TEST_ZIP.zip_name) do - |zos| - zos.put_next_entry(entry_name, comment, nil, ZipEntry::STORED) - zos << stored_text - end - - fdata = File.read(TEST_ZIP.zip_name) - if fdata.respond_to? :force_encoding - fdata.force_encoding("binary") - end - assert(fdata.split("\n").grep(stored_text)) - ZipFile.open(TEST_ZIP.zip_name) do - |zf| - assert_equal(stored_text, zf.read(entry_name)) - end - end - - def assert_i_o_error_in_closed_stream - assert_raise(IOError) { - zos = ZipOutputStream.new("test_putOnClosedStream.zip") - zos.close - yield zos - } - end - - def write_test_zip(zos) - TEST_ZIP.entry_names.each { - |entryName| - zos.put_next_entry(entryName) - File.open(entryName, "rb") { |f| zos.write(f.read) } - } - end -end - - - -module Enumerable - def compare_enumerables(otherEnumerable) - otherAsArray = otherEnumerable.to_a - index=0 - each_with_index { - |element, i| - return false unless yield(element, otherAsArray[i]) - } - return index+1 == otherAsArray.size - end -end - - -class ZipCentralDirectoryEntryTest < Test::Unit::TestCase - - def test_read_from_stream - File.open("data/testDirectory.bin", "rb") { - |file| - entry = ZipEntry.read_c_dir_entry(file) - - assert_equal("longAscii.txt", entry.name) - assert_equal(ZipEntry::DEFLATED, entry.compression_method) - assert_equal(106490, entry.size) - assert_equal(3784, entry.compressed_size) - assert_equal(0xfcd1799c, entry.crc) - assert_equal("", entry.comment) - - entry = ZipEntry.read_c_dir_entry(file) - assert_equal("empty.txt", entry.name) - assert_equal(ZipEntry::STORED, entry.compression_method) - assert_equal(0, entry.size) - assert_equal(0, entry.compressed_size) - assert_equal(0x0, entry.crc) - assert_equal("", entry.comment) - - entry = ZipEntry.read_c_dir_entry(file) - assert_equal("short.txt", entry.name) - assert_equal(ZipEntry::STORED, entry.compression_method) - assert_equal(6, entry.size) - assert_equal(6, entry.compressed_size) - assert_equal(0xbb76fe69, entry.crc) - assert_equal("", entry.comment) - - entry = ZipEntry.read_c_dir_entry(file) - assert_equal("longBinary.bin", entry.name) - assert_equal(ZipEntry::DEFLATED, entry.compression_method) - assert_equal(1000024, entry.size) - assert_equal(70847, entry.compressed_size) - assert_equal(0x10da7d59, entry.crc) - assert_equal("", entry.comment) - - entry = ZipEntry.read_c_dir_entry(file) - assert_equal(nil, entry) -# Fields that are not check by this test: -# version made by 2 bytes -# version needed to extract 2 bytes -# general purpose bit flag 2 bytes -# last mod file time 2 bytes -# last mod file date 2 bytes -# compressed size 4 bytes -# uncompressed size 4 bytes -# disk number start 2 bytes -# internal file attributes 2 bytes -# external file attributes 4 bytes -# relative offset of local header 4 bytes - -# file name (variable size) -# extra field (variable size) -# file comment (variable size) - - } - end - - def test_ReadEntryFromTruncatedZipFile - fragment="" - File.open("data/testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes - fragment.extend(IOizeString) - entry = ZipEntry.new - entry.read_c_dir_entry(fragment) - fail "ZipError expected" - rescue ZipError - end - -end - - -class ZipEntrySetTest < Test::Unit::TestCase - ZIP_ENTRIES = [ - ZipEntry.new("zipfile.zip", "name1", "comment1"), - ZipEntry.new("zipfile.zip", "name2", "comment1"), - ZipEntry.new("zipfile.zip", "name3", "comment1"), - ZipEntry.new("zipfile.zip", "name4", "comment1"), - ZipEntry.new("zipfile.zip", "name5", "comment1"), - ZipEntry.new("zipfile.zip", "name6", "comment1") - ] - - def setup - @zipEntrySet = ZipEntrySet.new(ZIP_ENTRIES) - end - - def test_include - assert(@zipEntrySet.include?(ZIP_ENTRIES.first)) - assert(! @zipEntrySet.include?(ZipEntry.new("different.zip", "different", "aComment"))) - end - - def test_size - assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size) - assert_equal(ZIP_ENTRIES.size, @zipEntrySet.length) - @zipEntrySet << ZipEntry.new("a", "b", "c") - assert_equal(ZIP_ENTRIES.size + 1, @zipEntrySet.length) - end - - def test_add - zes = ZipEntrySet.new - entry1 = ZipEntry.new("zf.zip", "name1") - entry2 = ZipEntry.new("zf.zip", "name2") - zes << entry1 - assert(zes.include?(entry1)) - zes.push(entry2) - assert(zes.include?(entry2)) - end - - def test_delete - assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size) - entry = @zipEntrySet.delete(ZIP_ENTRIES.first) - assert_equal(ZIP_ENTRIES.size - 1, @zipEntrySet.size) - assert_equal(ZIP_ENTRIES.first, entry) - - entry = @zipEntrySet.delete(ZIP_ENTRIES.first) - assert_equal(ZIP_ENTRIES.size - 1, @zipEntrySet.size) - assert_nil(entry) - end - - def test_each - # Tested indirectly via each_with_index - count = 0 - @zipEntrySet.each_with_index { - |entry, index| - assert(ZIP_ENTRIES.include?(entry)) - count = count.succ - } - assert_equal(ZIP_ENTRIES.size, count) - end - - def test_entries - assert_equal(ZIP_ENTRIES.sort, @zipEntrySet.entries.sort) - end - - def test_compound - newEntry = ZipEntry.new("zf.zip", "new entry", "new entry's comment") - assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size) - @zipEntrySet << newEntry - assert_equal(ZIP_ENTRIES.size + 1, @zipEntrySet.size) - assert(@zipEntrySet.include?(newEntry)) - - @zipEntrySet.delete(newEntry) - assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size) - end - - def test_dup - copy = @zipEntrySet.dup - assert_equal(@zipEntrySet, copy) - - # demonstrate that this is a deep copy - copy.entries[0].name = "a totally different name" - assert(@zipEntrySet != copy) - end - - def test_parent - entries = [ - ZipEntry.new("zf.zip", "a"), - ZipEntry.new("zf.zip", "a/"), - ZipEntry.new("zf.zip", "a/b"), - ZipEntry.new("zf.zip", "a/b/"), - ZipEntry.new("zf.zip", "a/b/c"), - ZipEntry.new("zf.zip", "a/b/c/") - ] - entrySet = ZipEntrySet.new(entries) - - assert_equal(nil, entrySet.parent(entries[0])) - assert_equal(nil, entrySet.parent(entries[1])) - assert_equal(entries[1], entrySet.parent(entries[2])) - assert_equal(entries[1], entrySet.parent(entries[3])) - assert_equal(entries[3], entrySet.parent(entries[4])) - assert_equal(entries[3], entrySet.parent(entries[5])) - end - - def test_glob - res = @zipEntrySet.glob('name[2-4]') - assert_equal(3, res.size) - assert_equal(ZIP_ENTRIES[1,3], res) - end - - def test_glob2 - entries = [ - ZipEntry.new("zf.zip", "a/"), - ZipEntry.new("zf.zip", "a/b/b1"), - ZipEntry.new("zf.zip", "a/b/c/"), - ZipEntry.new("zf.zip", "a/b/c/c1") - ] - entrySet = ZipEntrySet.new(entries) - - assert_equal(entries[0,1], entrySet.glob("*")) -# assert_equal(entries[FIXME], entrySet.glob("**")) -# res = entrySet.glob('a*') -# assert_equal(entries.size, res.size) -# assert_equal(entrySet.map { |e| e.name }, res.map { |e| e.name }) - end -end - - -class ZipCentralDirectoryTest < Test::Unit::TestCase - - def test_read_from_stream - File.open(TestZipFile::TEST_ZIP2.zip_name, "rb") { - |zipFile| - cdir = ZipCentralDirectory.read_from_stream(zipFile) - assert_equal(TestZipFile::TEST_ZIP2.entry_names.size, cdir.size) - cdir.entries.sort.compare_enumerables(TestZipFile::TEST_ZIP2.entry_names.sort) { - |cdirEntry, testEntryName| - assert(cdirEntry.name == testEntryName) - } - assert_equal(TestZipFile::TEST_ZIP2.comment, cdir.comment) - } - end - - def test_readFromInvalidStream - File.open("data/file2.txt", "rb") { - |zipFile| - cdir = ZipCentralDirectory.new - cdir.read_from_stream(zipFile) - } - fail "ZipError expected!" - rescue ZipError - end - - def test_ReadFromTruncatedZipFile - fragment="" - File.open("data/testDirectory.bin") { |f| fragment = f.read } - fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete - fragment.extend(IOizeString) - entry = ZipCentralDirectory.new - entry.read_from_stream(fragment) - fail "ZipError expected" - rescue ZipError - end - - def test_write_to_stream - entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ] - cdir = ZipCentralDirectory.new(entries, "my zip comment") - File.open("cdirtest.bin", "wb") { |f| cdir.write_to_stream(f) } - cdirReadback = ZipCentralDirectory.new - File.open("cdirtest.bin", "rb") { |f| cdirReadback.read_from_stream(f) } - - assert_equal(cdir.entries.sort, cdirReadback.entries.sort) - end - - def test_equality - cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "my zip comment") - cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "secondEntryName"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, - "somethingExtra"), - ZipEntry.new("file.zip", "lastEntry.txt") ], - "comment?") - assert_equal(cdir1, cdir1) - assert_equal(cdir1, cdir2) - - assert(cdir1 != cdir3) - assert(cdir2 != cdir3) - assert(cdir2 != cdir3) - assert(cdir3 != cdir4) - - assert(cdir3 != "hello") - end -end - - -class BasicZipFileTest < Test::Unit::TestCase - include AssertEntry - - def setup - @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zip_name) - @testEntryNameIndex=0 - end - - def test_entries - assert_equal(TestZipFile::TEST_ZIP2.entry_names.sort, - @zipFile.entries.entries.sort.map {|e| e.name} ) - end - - def test_each - count = 0 - visited = {} - @zipFile.each { - |entry| - assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name)) - assert(! visited.include?(entry.name)) - visited[entry.name] = nil - count = count.succ - } - assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count) - end - - def test_foreach - count = 0 - visited = {} - ZipFile.foreach(TestZipFile::TEST_ZIP2.zip_name) { - |entry| - assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name)) - assert(! visited.include?(entry.name)) - visited[entry.name] = nil - count = count.succ - } - assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count) - end - - def test_get_input_stream - count = 0 - visited = {} - @zipFile.each { - |entry| - assert_entry(entry.name, @zipFile.get_input_stream(entry), entry.name) - assert(! visited.include?(entry.name)) - visited[entry.name] = nil - count = count.succ - } - assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count) - end - - def test_get_input_streamBlock - fileAndEntryName = @zipFile.entries.first.name - @zipFile.get_input_stream(fileAndEntryName) { - |zis| - assert_entryContentsForStream(fileAndEntryName, - zis, - fileAndEntryName) - } - end -end - -module CommonZipFileFixture - include AssertEntry - - EMPTY_FILENAME = "emptyZipFile.zip" - - TEST_ZIP = TestZipFile::TEST_ZIP2.clone - TEST_ZIP.zip_name = "5entry_copy.zip" - - def setup - File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME) - FileUtils.cp(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name) - end -end - -class ZipFileTest < Test::Unit::TestCase - include CommonZipFileFixture - - def test_createFromScratch - comment = "a short comment" - - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.get_output_stream("myFile") { |os| os.write "myFile contains just this" } - zf.mkdir("dir1") - zf.comment = comment - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equal(comment, zfRead.comment) - assert_equal(2, zfRead.entries.length) - end - - def test_get_output_stream - entryCount = nil - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - entryCount = zf.size - zf.get_output_stream('newEntry.txt') { - |os| - os.write "Putting stuff in newEntry.txt" - } - assert_equal(entryCount+1, zf.size) - assert_equal("Putting stuff in newEntry.txt", zf.read("newEntry.txt")) - - zf.get_output_stream(zf.get_entry('data/generated/empty.txt')) { - |os| - os.write "Putting stuff in data/generated/empty.txt" - } - assert_equal(entryCount+1, zf.size) - assert_equal("Putting stuff in data/generated/empty.txt", zf.read("data/generated/empty.txt")) - - zf.get_output_stream('entry.bin') { - |os| - os.write(File.open('data/generated/5entry.zip', 'rb').read) - } - } - - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - assert_equal(entryCount+2, zf.size) - assert_equal("Putting stuff in newEntry.txt", zf.read("newEntry.txt")) - assert_equal("Putting stuff in data/generated/empty.txt", zf.read("data/generated/empty.txt")) - assert_equal(File.open('data/generated/5entry.zip', 'rb').read, zf.read("entry.bin")) - } - end - - def test_add - srcFile = "data/file2.txt" - entryName = "newEntryName.rb" - assert(File.exists?(srcFile)) - zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) - zf.add(entryName, srcFile) - zf.close - - zfRead = ZipFile.new(EMPTY_FILENAME) - assert_equal("", zfRead.comment) - assert_equal(1, zfRead.entries.length) - assert_equal(entryName, zfRead.entries.first.name) - AssertEntry.assert_contents(srcFile, - zfRead.get_input_stream(entryName) { |zis| zis.read }) - end - - def test_addExistingEntryName - assert_raise(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - zf.add(zf.entries.first.name, "data/file2.txt") - } - } - end - - def test_addExistingEntryNameReplace - gotCalled = false - replacedEntry = nil - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - replacedEntry = zf.entries.first.name - zf.add(replacedEntry, "data/file2.txt") { gotCalled = true; true } - } - assert(gotCalled) - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - assert_contains(zf, replacedEntry, "data/file2.txt") - } - end - - def test_addDirectory - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR) - } - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" } - assert(dirEntry.is_directory) - } - end - - def test_remove - entryToRemove, *remainingEntries = TEST_ZIP.entry_names - - FileUtils.cp(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name) - - zf = ZipFile.new(TEST_ZIP.zip_name) - assert(zf.entries.map { |e| e.name }.include?(entryToRemove)) - zf.remove(entryToRemove) - assert(! zf.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equal(zf.entries.map {|x| x.name }.sort, remainingEntries.sort) - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zip_name) - assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove)) - assert_equal(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort) - zfRead.close - end - - def test_rename - entryToRename, *remainingEntries = TEST_ZIP.entry_names - - zf = ZipFile.new(TEST_ZIP.zip_name) - assert(zf.entries.map { |e| e.name }.include?(entryToRename)) - - contents = zf.read(entryToRename) - newName = "changed entry name" - assert(! zf.entries.map { |e| e.name }.include?(newName)) - - zf.rename(entryToRename, newName) - assert(zf.entries.map { |e| e.name }.include?(newName)) - - assert_equal(contents, zf.read(newName)) - - zf.close - - zfRead = ZipFile.new(TEST_ZIP.zip_name) - assert(zfRead.entries.map { |e| e.name }.include?(newName)) - assert_equal(contents, zf.read(newName)) - zfRead.close - end - - def test_renameToExistingEntry - oldEntries = nil - ZipFile.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries } - - assert_raise(ZipEntryExistsError) { - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - zf.rename(zf.entries[0], zf.entries[1].name) - } - } - - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - assert_equal(oldEntries.sort.map{ |e| e.name }, zf.entries.sort.map{ |e| e.name }) - } - end - - def test_renameToExistingEntryOverwrite - oldEntries = nil - ZipFile.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries } - - gotCalled = false - renamedEntryName = nil - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - renamedEntryName = zf.entries[0].name - zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true } - } - - assert(gotCalled) - oldEntries.delete_if { |e| e.name == renamedEntryName } - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - assert_equal(oldEntries.sort.map{ |e| e.name }, - zf.entries.sort.map{ |e| e.name }) - } - end - - def test_renameNonEntry - nonEntry = "bogusEntry" - target_entry = "target_entryName" - zf = ZipFile.new(TEST_ZIP.zip_name) - assert(! zf.entries.include?(nonEntry)) - assert_raise(Errno::ENOENT) { - zf.rename(nonEntry, target_entry) - } - zf.commit - assert(! zf.entries.include?(target_entry)) - ensure - zf.close - end - - def test_renameEntryToExistingEntry - entry1, entry2, *remaining = TEST_ZIP.entry_names - zf = ZipFile.new(TEST_ZIP.zip_name) - assert_raise(ZipEntryExistsError) { - zf.rename(entry1, entry2) - } - ensure - zf.close - end - - def test_replace - entryToReplace = TEST_ZIP.entry_names[2] - newEntrySrcFilename = "data/file2.txt" - zf = ZipFile.new(TEST_ZIP.zip_name) - zf.replace(entryToReplace, newEntrySrcFilename) - - zf.close - zfRead = ZipFile.new(TEST_ZIP.zip_name) - AssertEntry::assert_contents(newEntrySrcFilename, - zfRead.get_input_stream(entryToReplace) { |is| is.read }) - AssertEntry::assert_contents(TEST_ZIP.entry_names[0], - zfRead.get_input_stream(TEST_ZIP.entry_names[0]) { |is| is.read }) - AssertEntry::assert_contents(TEST_ZIP.entry_names[1], - zfRead.get_input_stream(TEST_ZIP.entry_names[1]) { |is| is.read }) - AssertEntry::assert_contents(TEST_ZIP.entry_names[3], - zfRead.get_input_stream(TEST_ZIP.entry_names[3]) { |is| is.read }) - zfRead.close - end - - def test_replaceNonEntry - entryToReplace = "nonExistingEntryname" - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - assert_raise(Errno::ENOENT) { - zf.replace(entryToReplace, "data/file2.txt") - } - } - end - - def test_commit - newName = "renamedFirst" - zf = ZipFile.new(TEST_ZIP.zip_name) - oldName = zf.entries.first - zf.rename(oldName, newName) - zf.commit - - zfRead = ZipFile.new(TEST_ZIP.zip_name) - assert(zfRead.entries.detect { |e| e.name == newName } != nil) - assert(zfRead.entries.detect { |e| e.name == oldName } == nil) - zfRead.close - - zf.close - end - - # This test tests that after commit, you - # can delete the file you used to add the entry to the zip file - # with - def test_commitUseZipEntry - FileUtils.cp(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt") - zf = ZipFile.open(TEST_ZIP.zip_name) - zf.add("okToDelete.txt", "okToDelete.txt") - assert_contains(zf, "okToDelete.txt") - zf.commit - File.rename("okToDelete.txt", "okToDeleteMoved.txt") - assert_contains(zf, "okToDelete.txt", "okToDeleteMoved.txt") - end - -# def test_close -# zf = ZipFile.new(TEST_ZIP.zip_name) -# zf.close -# assert_raise(IOError) { -# zf.extract(TEST_ZIP.entry_names.first, "hullubullu") -# } -# end - - def test_compound1 - renamedName = "renamedName" - originalEntries = [] - begin - zf = ZipFile.new(TEST_ZIP.zip_name) - originalEntries = zf.entries.dup - - assert_not_contains(zf, TestFiles::RANDOM_ASCII_FILE1) - zf.add(TestFiles::RANDOM_ASCII_FILE1, - TestFiles::RANDOM_ASCII_FILE1) - assert_contains(zf, TestFiles::RANDOM_ASCII_FILE1) - - zf.rename(zf.entries[0], renamedName) - assert_contains(zf, renamedName) - - TestFiles::BINARY_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assert_contains(zf, filename) - } - - assert_contains(zf, originalEntries.last.to_s) - zf.remove(originalEntries.last.to_s) - assert_not_contains(zf, originalEntries.last.to_s) - - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zip_name) - assert_contains(zfRead, TestFiles::RANDOM_ASCII_FILE1) - assert_contains(zfRead, renamedName) - TestFiles::BINARY_TEST_FILES.each { - |filename| - assert_contains(zfRead, filename) - } - assert_not_contains(zfRead, originalEntries.last.to_s) - ensure - zfRead.close - end - end - - def test_compound2 - begin - zf = ZipFile.new(TEST_ZIP.zip_name) - originalEntries = zf.entries.dup - - originalEntries.each { - |entry| - zf.remove(entry) - assert_not_contains(zf, entry) - } - assert(zf.entries.empty?) - - TestFiles::ASCII_TEST_FILES.each { - |filename| - zf.add(filename, filename) - assert_contains(zf, filename) - } - assert_equal(zf.entries.sort.map { |e| e.name }, TestFiles::ASCII_TEST_FILES) - - zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName") - assert_not_contains(zf, TestFiles::ASCII_TEST_FILES[0]) - assert_contains(zf, "newName") - ensure - zf.close - end - begin - zfRead = ZipFile.new(TEST_ZIP.zip_name) - asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup - asciiTestFiles.shift - asciiTestFiles.each { - |filename| - assert_contains(zf, filename) - } - - assert_contains(zf, "newName") - ensure - zfRead.close - end - end - - private - def assert_contains(zf, entryName, filename = entryName) - assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}") - assert_entryContents(zf, entryName, filename) if File.exists?(filename) - end - - def assert_not_contains(zf, entryName) - assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}") - end -end - -class ZipFileExtractTest < Test::Unit::TestCase - include CommonZipFileFixture - EXTRACTED_FILENAME = "extEntry" - ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entry_names.reverse - - def setup - super - File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME) - end - - def test_extract - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME) - - assert(File.exists?(EXTRACTED_FILENAME)) - AssertEntry::assert_contents(EXTRACTED_FILENAME, - zf.get_input_stream(ENTRY_TO_EXTRACT) { |is| is.read }) - - - File::unlink(EXTRACTED_FILENAME) - - entry = zf.get_entry(ENTRY_TO_EXTRACT) - entry.extract(EXTRACTED_FILENAME) - - assert(File.exists?(EXTRACTED_FILENAME)) - AssertEntry::assert_contents(EXTRACTED_FILENAME, - entry.get_input_stream() { |is| is.read }) - - } - end - - def test_extractExists - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - assert_raise(ZipDestinationFileExistsError) { - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) - } - } - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert_equal(writtenText, f.read) - } - end - - def test_extractExistsOverwrite - writtenText = "written text" - File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } - - gotCalledCorrectly = false - ZipFile.open(TEST_ZIP.zip_name) { - |zf| - zf.extract(zf.entries.first, EXTRACTED_FILENAME) { - |entry, extractLoc| - gotCalledCorrectly = zf.entries.first == entry && - extractLoc == EXTRACTED_FILENAME - true - } - } - - assert(gotCalledCorrectly) - File.open(EXTRACTED_FILENAME, "r") { - |f| - assert(writtenText != f.read) - } - end - - def test_extractNonEntry - zf = ZipFile.new(TEST_ZIP.zip_name) - assert_raise(Errno::ENOENT) { zf.extract("nonExistingEntry", "nonExistingEntry") } - ensure - zf.close if zf - end - - def test_extractNonEntry2 - outFile = "outfile" - assert_raise(Errno::ENOENT) { - zf = ZipFile.new(TEST_ZIP.zip_name) - nonEntry = "hotdog-diddelidoo" - assert(! zf.entries.include?(nonEntry)) - zf.extract(nonEntry, outFile) - zf.close - } - assert(! File.exists?(outFile)) - end - -end - -class ZipFileExtractDirectoryTest < Test::Unit::TestCase - include CommonZipFileFixture - TEST_OUT_NAME = "emptyOutDir" - - def open_zip(&aProc) - assert(aProc != nil) - ZipFile.open(TestZipFile::TEST_ZIP4.zip_name, &aProc) - end - - def extract_test_dir(&aProc) - open_zip { - |zf| - zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc) - } - end - - def setup - super - - Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME - File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME - end - - def test_extractDirectory - extract_test_dir - assert(File.directory?(TEST_OUT_NAME)) - end - - def test_extractDirectoryExistsAsDir - Dir.mkdir TEST_OUT_NAME - extract_test_dir - assert(File.directory?(TEST_OUT_NAME)) - end - - def test_extractDirectoryExistsAsFile - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - assert_raise(ZipDestinationFileExistsError) { extract_test_dir } - end - - def test_extractDirectoryExistsAsFileOverwrite - File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } - gotCalled = false - extract_test_dir { - |entry, destPath| - gotCalled = true - assert_equal(TEST_OUT_NAME, destPath) - assert(entry.is_directory) - true - } - assert(gotCalled) - assert(File.directory?(TEST_OUT_NAME)) - end -end - -class ZipExtraFieldTest < Test::Unit::TestCase - def test_new - extra_pure = ZipExtraField.new("") - extra_withstr = ZipExtraField.new("foo") - assert_instance_of(ZipExtraField, extra_pure) - assert_instance_of(ZipExtraField, extra_withstr) - end - - def test_unknownfield - extra = ZipExtraField.new("foo") - assert_equal(extra["Unknown"], "foo") - extra.merge("a") - assert_equal(extra["Unknown"], "fooa") - extra.merge("barbaz") - assert_equal(extra.to_s, "fooabarbaz") - end - - - def test_merge - str = "UT\x5\0\x3\250$\r@Ux\0\0" - extra1 = ZipExtraField.new("") - extra2 = ZipExtraField.new(str) - assert(! extra1.member?("UniversalTime")) - assert(extra2.member?("UniversalTime")) - extra1.merge(str) - assert_equal(extra1["UniversalTime"].mtime, extra2["UniversalTime"].mtime) - end - - def test_length - str = "UT\x5\0\x3\250$\r@Ux\0\0Te\0\0testit" - extra = ZipExtraField.new(str) - assert_equal(extra.local_length, extra.to_local_bin.length) - assert_equal(extra.c_dir_length, extra.to_c_dir_bin.length) - extra.merge("foo") - assert_equal(extra.local_length, extra.to_local_bin.length) - assert_equal(extra.c_dir_length, extra.to_c_dir_bin.length) - end - - - def test_to_s - str = "UT\x5\0\x3\250$\r@Ux\0\0Te\0\0testit" - extra = ZipExtraField.new(str) - assert_instance_of(String, extra.to_s) - - s = extra.to_s - extra.merge("foo") - assert_equal(s.length + 3, extra.to_s.length) - end - - def test_equality - str = "UT\x5\0\x3\250$\r@" - extra1 = ZipExtraField.new(str) - extra2 = ZipExtraField.new(str) - extra3 = ZipExtraField.new(str) - assert_equal(extra1, extra2) - - extra2["UniversalTime"].mtime = Time.now - assert(extra1 != extra2) - - extra3.create("IUnix") - assert(extra1 != extra3) - - extra1.create("IUnix") - assert_equal(extra1, extra3) - end - -end - -# Copyright (C) 2002-2005 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/zip.rb b/lib/zip/zip.rb deleted file mode 100644 index e5d150de96..0000000000 --- a/lib/zip/zip.rb +++ /dev/null @@ -1,1900 +0,0 @@ -# encoding: ASCII-8BIT -require 'delegate' - -begin - require 'iconv' -rescue ::LoadError -end - -require 'singleton' -require 'tempfile' -require 'fileutils' -require 'stringio' -require 'zlib' -require 'zip/stdrubyext' -require 'zip/ioextras' - -if Tempfile.superclass == SimpleDelegator - require 'zip/tempfile_bugfixed' - Tempfile = BugFix::Tempfile -end - -module Zlib #:nodoc:all - if ! const_defined? :MAX_WBITS - MAX_WBITS = Zlib::Deflate.MAX_WBITS - end -end - -module Zip - - VERSION = '0.9.4' - - RUBY_MINOR_VERSION = RUBY_VERSION.split(".")[1].to_i - - RUNNING_ON_WINDOWS = /mswin32|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM - - # Ruby 1.7.x compatibility - # In ruby 1.6.x and 1.8.0 reading from an empty stream returns - # an empty string the first time and then nil. - # not so in 1.7.x - EMPTY_FILE_RETURNS_EMPTY_STRING_FIRST = RUBY_MINOR_VERSION != 7 - - # ZipInputStream is the basic class for reading zip entries in a - # zip file. It is possible to create a ZipInputStream object directly, - # passing the zip file name to the constructor, but more often than not - # the ZipInputStream will be obtained from a ZipFile (perhaps using the - # ZipFileSystem interface) object for a particular entry in the zip - # archive. - # - # A ZipInputStream inherits IOExtras::AbstractInputStream in order - # to provide an IO-like interface for reading from a single zip - # entry. Beyond methods for mimicking an IO-object it contains - # the method get_next_entry for iterating through the entries of - # an archive. get_next_entry returns a ZipEntry object that describes - # the zip entry the ZipInputStream is currently reading from. - # - # Example that creates a zip archive with ZipOutputStream and reads it - # back again with a ZipInputStream. - # - # require 'zip/zip' - # - # Zip::ZipOutputStream::open("my.zip") { - # |io| - # - # io.put_next_entry("first_entry.txt") - # io.write "Hello world!" - # - # io.put_next_entry("adir/first_entry.txt") - # io.write "Hello again!" - # } - # - # - # Zip::ZipInputStream::open("my.zip") { - # |io| - # - # while (entry = io.get_next_entry) - # puts "Contents of #{entry.name}: '#{io.read}'" - # end - # } - # - # java.util.zip.ZipInputStream is the original inspiration for this - # class. - - class ZipInputStream - include IOExtras::AbstractInputStream - - # Opens the indicated zip file. An exception is thrown - # if the specified offset in the specified filename is - # not a local zip entry header. - def initialize(filename, offset = 0) - super() - @archiveIO = File.open(filename, "rb") - @archiveIO.seek(offset, IO::SEEK_SET) - @decompressor = NullDecompressor.instance - @currentEntry = nil - end - - def close - @archiveIO.close - end - - # Same as #initialize but if a block is passed the opened - # stream is passed to the block and closed when the block - # returns. - def ZipInputStream.open(filename) - return new(filename) unless block_given? - - zio = new(filename) - yield zio - ensure - zio.close if zio - end - - # Returns a ZipEntry object. It is necessary to call this - # method on a newly created ZipInputStream before reading from - # the first entry in the archive. Returns nil when there are - # no more entries. - - def get_next_entry - @archiveIO.seek(@currentEntry.next_header_offset, - IO::SEEK_SET) if @currentEntry - open_entry - end - - # Rewinds the stream to the beginning of the current entry - def rewind - return if @currentEntry.nil? - @lineno = 0 - @archiveIO.seek(@currentEntry.localHeaderOffset, - IO::SEEK_SET) - open_entry - end - - # Modeled after IO.sysread - def sysread(numberOfBytes = nil, buf = nil) - @decompressor.sysread(numberOfBytes, buf) - end - - def eof - @outputBuffer.empty? && @decompressor.eof - end - alias :eof? :eof - - protected - - def open_entry - @currentEntry = ZipEntry.read_local_entry(@archiveIO) - if (@currentEntry == nil) - @decompressor = NullDecompressor.instance - elsif @currentEntry.compression_method == ZipEntry::STORED - @decompressor = PassThruDecompressor.new(@archiveIO, @currentEntry.size) - elsif @currentEntry.compression_method == ZipEntry::DEFLATED - @decompressor = Inflater.new(@archiveIO) - else - raise ZipCompressionMethodError, "Unsupported compression method #{@currentEntry.compression_method}" - end - flush - return @currentEntry - end - - def produce_input - @decompressor.produce_input - end - - def input_finished? - @decompressor.input_finished? - end - end - - - - class Decompressor #:nodoc:all - CHUNK_SIZE=32768 - def initialize(inputStream) - super() - @inputStream=inputStream - end - end - - class Inflater < Decompressor #:nodoc:all - def initialize(inputStream) - super - @zlibInflater = Zlib::Inflate.new(-Zlib::MAX_WBITS) - @outputBuffer="" - @hasReturnedEmptyString = ! EMPTY_FILE_RETURNS_EMPTY_STRING_FIRST - end - - def sysread(numberOfBytes = nil, buf = nil) - readEverything = (numberOfBytes == nil) - while (readEverything || @outputBuffer.length < numberOfBytes) - break if internal_input_finished? - @outputBuffer << internal_produce_input(buf) - end - return value_when_finished if @outputBuffer.length==0 && input_finished? - endIndex= numberOfBytes==nil ? @outputBuffer.length : numberOfBytes - return @outputBuffer.slice!(0...endIndex) - end - - def produce_input - if (@outputBuffer.empty?) - return internal_produce_input - else - return @outputBuffer.slice!(0...(@outputBuffer.length)) - end - end - - # to be used with produce_input, not read (as read may still have more data cached) - # is data cached anywhere other than @outputBuffer? the comment above may be wrong - def input_finished? - @outputBuffer.empty? && internal_input_finished? - end - alias :eof :input_finished? - alias :eof? :input_finished? - - private - - def internal_produce_input(buf = nil) - retried = 0 - begin - @zlibInflater.inflate(@inputStream.read(Decompressor::CHUNK_SIZE, buf)) - rescue Zlib::BufError - raise if (retried >= 5) # how many times should we retry? - retried += 1 - retry - end - end - - def internal_input_finished? - @zlibInflater.finished? - end - - # TODO: Specialize to handle different behaviour in ruby > 1.7.0 ? - def value_when_finished # mimic behaviour of ruby File object. - return nil if @hasReturnedEmptyString - @hasReturnedEmptyString=true - return "" - end - end - - class PassThruDecompressor < Decompressor #:nodoc:all - def initialize(inputStream, charsToRead) - super inputStream - @charsToRead = charsToRead - @readSoFar = 0 - @hasReturnedEmptyString = ! EMPTY_FILE_RETURNS_EMPTY_STRING_FIRST - end - - # TODO: Specialize to handle different behaviour in ruby > 1.7.0 ? - def sysread(numberOfBytes = nil, buf = nil) - if input_finished? - hasReturnedEmptyStringVal=@hasReturnedEmptyString - @hasReturnedEmptyString=true - return "" unless hasReturnedEmptyStringVal - return nil - end - - if (numberOfBytes == nil || @readSoFar+numberOfBytes > @charsToRead) - numberOfBytes = @charsToRead-@readSoFar - end - @readSoFar += numberOfBytes - @inputStream.read(numberOfBytes, buf) - end - - def produce_input - sysread(Decompressor::CHUNK_SIZE) - end - - def input_finished? - (@readSoFar >= @charsToRead) - end - alias :eof :input_finished? - alias :eof? :input_finished? - end - - class NullDecompressor #:nodoc:all - include Singleton - def sysread(numberOfBytes = nil, buf = nil) - nil - end - - def produce_input - nil - end - - def input_finished? - true - end - - def eof - true - end - alias :eof? :eof - end - - class NullInputStream < NullDecompressor #:nodoc:all - include IOExtras::AbstractInputStream - end - - class ZipEntry - STORED = 0 - DEFLATED = 8 - - FSTYPE_FAT = 0 - FSTYPE_AMIGA = 1 - FSTYPE_VMS = 2 - FSTYPE_UNIX = 3 - FSTYPE_VM_CMS = 4 - FSTYPE_ATARI = 5 - FSTYPE_HPFS = 6 - FSTYPE_MAC = 7 - FSTYPE_Z_SYSTEM = 8 - FSTYPE_CPM = 9 - FSTYPE_TOPS20 = 10 - FSTYPE_NTFS = 11 - FSTYPE_QDOS = 12 - FSTYPE_ACORN = 13 - FSTYPE_VFAT = 14 - FSTYPE_MVS = 15 - FSTYPE_BEOS = 16 - FSTYPE_TANDEM = 17 - FSTYPE_THEOS = 18 - FSTYPE_MAC_OSX = 19 - FSTYPE_ATHEOS = 30 - - FSTYPES = { - FSTYPE_FAT => 'FAT'.freeze, - FSTYPE_AMIGA => 'Amiga'.freeze, - FSTYPE_VMS => 'VMS (Vax or Alpha AXP)'.freeze, - FSTYPE_UNIX => 'Unix'.freeze, - FSTYPE_VM_CMS => 'VM/CMS'.freeze, - FSTYPE_ATARI => 'Atari ST'.freeze, - FSTYPE_HPFS => 'OS/2 or NT HPFS'.freeze, - FSTYPE_MAC => 'Macintosh'.freeze, - FSTYPE_Z_SYSTEM => 'Z-System'.freeze, - FSTYPE_CPM => 'CP/M'.freeze, - FSTYPE_TOPS20 => 'TOPS-20'.freeze, - FSTYPE_NTFS => 'NTFS'.freeze, - FSTYPE_QDOS => 'SMS/QDOS'.freeze, - FSTYPE_ACORN => 'Acorn RISC OS'.freeze, - FSTYPE_VFAT => 'Win32 VFAT'.freeze, - FSTYPE_MVS => 'MVS'.freeze, - FSTYPE_BEOS => 'BeOS'.freeze, - FSTYPE_TANDEM => 'Tandem NSK'.freeze, - FSTYPE_THEOS => 'Theos'.freeze, - FSTYPE_MAC_OSX => 'Mac OS/X (Darwin)'.freeze, - FSTYPE_ATHEOS => 'AtheOS'.freeze, - }.freeze - - attr_accessor :comment, :compressed_size, :crc, :extra, :compression_method, - :name, :size, :localHeaderOffset, :zipfile, :fstype, :externalFileAttributes, :gp_flags, :header_signature - - attr_accessor :follow_symlinks - attr_accessor :restore_times, :restore_permissions, :restore_ownership - attr_accessor :unix_uid, :unix_gid, :unix_perms - - attr_reader :ftype, :filepath # :nodoc: - - # Returns the character encoding used for name and comment - def name_encoding - (@gp_flags & 0b100000000000) != 0 ? "utf8" : "CP437//" - end - - - # Converts string encoding - def encode_string(str, src, dst) - if str.respond_to?(:encode) - str.encode(dst, { :invalid => :replace, :undef => :replace, :replace => '' }) - else - begin - Iconv.conv(dst, src, str) - rescue - raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)" - end - end - end - - # Returns the name in the encoding specified by enc - def name_in(enc) - encode_string(@name, name_encoding, enc) - end - - # Returns the comment in the encoding specified by enc - def comment_in(enc) - encode_string(@comment, name_encoding, enc) - end - - def initialize(zipfile = "", name = "", comment = "", extra = "", - compressed_size = 0, crc = 0, - compression_method = ZipEntry::DEFLATED, size = 0, - time = Time.now) - super() - if name.starts_with("/") - raise ZipEntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /" - end - @localHeaderOffset = 0 - @local_header_size = 0 - @internalFileAttributes = 1 - @externalFileAttributes = 0 - @version = 52 # this library's version - @ftype = nil # unspecified or unknown - @filepath = nil - if Zip::RUNNING_ON_WINDOWS - @fstype = FSTYPE_FAT - else - @fstype = FSTYPE_UNIX - end - @zipfile = zipfile - @comment = comment - @compressed_size = compressed_size - @crc = crc - @extra = extra - @compression_method = compression_method - @name = name - @size = size - @time = time - - @follow_symlinks = false - - @restore_times = true - @restore_permissions = false - @restore_ownership = false - -# BUG: need an extra field to support uid/gid's - @unix_uid = nil - @unix_gid = nil - @unix_perms = nil -# @posix_acl = nil -# @ntfs_acl = nil - - if name_is_directory? - @ftype = :directory - else - @ftype = :file - end - - unless ZipExtraField === @extra - @extra = ZipExtraField.new(@extra.to_s) - end - end - - def time - if @extra["UniversalTime"] - @extra["UniversalTime"].mtime - else - # Atandard time field in central directory has local time - # under archive creator. Then, we can't get timezone. - @time - end - end - alias :mtime :time - - def time=(aTime) - unless @extra.member?("UniversalTime") - @extra.create("UniversalTime") - end - @extra["UniversalTime"].mtime = aTime - @time = aTime - end - - # Returns +true+ if the entry is a directory. - def directory? - raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype - @ftype == :directory - end - alias :is_directory :directory? - - # Returns +true+ if the entry is a file. - def file? - raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype - @ftype == :file - end - - # Returns +true+ if the entry is a symlink. - def symlink? - raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype - @ftype == :symlink - end - - def name_is_directory? #:nodoc:all - (%r{\/$} =~ @name) != nil - end - - def local_entry_offset #:nodoc:all - localHeaderOffset + @local_header_size - end - - def calculate_local_header_size #:nodoc:all - LOCAL_ENTRY_STATIC_HEADER_LENGTH + (@name ? @name.size : 0) + (@extra ? @extra.local_size : 0) - end - - def cdir_header_size #:nodoc:all - CDIR_ENTRY_STATIC_HEADER_LENGTH + (@name ? @name.size : 0) + - (@extra ? @extra.c_dir_size : 0) + (@comment ? @comment.size : 0) - end - - def next_header_offset #:nodoc:all - local_entry_offset + self.compressed_size - end - - # Extracts entry to file destPath (defaults to @name). - def extract(destPath = @name, &onExistsProc) - onExistsProc ||= proc { false } - - if directory? - create_directory(destPath, &onExistsProc) - elsif file? - write_file(destPath, &onExistsProc) - elsif symlink? - create_symlink(destPath, &onExistsProc) - else - raise RuntimeError, "unknown file type #{self.inspect}" - end - - self - end - - def to_s - @name - end - - protected - - def ZipEntry.read_zip_short(io) # :nodoc: - io.read(2).unpack('v')[0] - end - - def ZipEntry.read_zip_long(io) # :nodoc: - io.read(4).unpack('V')[0] - end - public - - LOCAL_ENTRY_SIGNATURE = 0x04034b50 - LOCAL_ENTRY_STATIC_HEADER_LENGTH = 30 - LOCAL_ENTRY_TRAILING_DESCRIPTOR_LENGTH = 4+4+4 - VERSION_NEEDED_TO_EXTRACT = 10 - - def read_local_entry(io) #:nodoc:all - @localHeaderOffset = io.tell - staticSizedFieldsBuf = io.read(LOCAL_ENTRY_STATIC_HEADER_LENGTH) - unless (staticSizedFieldsBuf.size==LOCAL_ENTRY_STATIC_HEADER_LENGTH) - raise ZipError, "Premature end of file. Not enough data for zip entry local header" - end - - @header_signature , - @version , - @fstype , - @gp_flags , - @compression_method, - lastModTime , - lastModDate , - @crc , - @compressed_size , - @size , - nameLength , - extraLength = staticSizedFieldsBuf.unpack('VCCvvvvVVVvv') - - unless (@header_signature == LOCAL_ENTRY_SIGNATURE) - raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'" - end - set_time(lastModDate, lastModTime) - - - @name = io.read(nameLength) - extra = io.read(extraLength) - - if (extra && extra.length != extraLength) - raise ZipError, "Truncated local zip entry header" - else - if ZipExtraField === @extra - @extra.merge(extra) - else - @extra = ZipExtraField.new(extra) - end - end - @local_header_size = calculate_local_header_size - end - - def ZipEntry.read_local_entry(io) - entry = new(io.path) - entry.read_local_entry(io) - return entry - rescue ZipError - return nil - end - - def write_local_entry(io) #:nodoc:all - @localHeaderOffset = io.tell - - io << - [LOCAL_ENTRY_SIGNATURE , - VERSION_NEEDED_TO_EXTRACT , # version needed to extract - 0 , # @gp_flags , - @compression_method , - @time.to_binary_dos_time , # @lastModTime , - @time.to_binary_dos_date , # @lastModDate , - @crc , - @compressed_size , - @size , - @name ? @name.length : 0, - @extra? @extra.local_length : 0 ].pack('VvvvvvVVVvv') - io << @name - io << (@extra ? @extra.to_local_bin : "") - end - - CENTRAL_DIRECTORY_ENTRY_SIGNATURE = 0x02014b50 - CDIR_ENTRY_STATIC_HEADER_LENGTH = 46 - - def read_c_dir_entry(io) #:nodoc:all - staticSizedFieldsBuf = io.read(CDIR_ENTRY_STATIC_HEADER_LENGTH) - unless (staticSizedFieldsBuf.size == CDIR_ENTRY_STATIC_HEADER_LENGTH) - raise ZipError, "Premature end of file. Not enough data for zip cdir entry header" - end - - @header_signature , - @version , # version of encoding software - @fstype , # filesystem type - @versionNeededToExtract, - @gp_flags , - @compression_method , - lastModTime , - lastModDate , - @crc , - @compressed_size , - @size , - nameLength , - extraLength , - commentLength , - diskNumberStart , - @internalFileAttributes, - @externalFileAttributes, - @localHeaderOffset , - @name , - @extra , - @comment = staticSizedFieldsBuf.unpack('VCCvvvvvVVVvvvvvVV') - - unless (@header_signature == CENTRAL_DIRECTORY_ENTRY_SIGNATURE) - raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'" - end - set_time(lastModDate, lastModTime) - - @name = io.read(nameLength) - if ZipExtraField === @extra - @extra.merge(io.read(extraLength)) - else - @extra = ZipExtraField.new(io.read(extraLength)) - end - @comment = io.read(commentLength) - unless (@comment && @comment.length == commentLength) - raise ZipError, "Truncated cdir zip entry header" - end - - case @fstype - when FSTYPE_UNIX - @unix_perms = (@externalFileAttributes >> 16) & 07777 - - case (@externalFileAttributes >> 28) - when 04 - @ftype = :directory - when 010 - @ftype = :file - when 012 - @ftype = :symlink - else - raise ZipInternalError, "unknown file type #{'0%o' % (@externalFileAttributes >> 28)}" - end - else - if name_is_directory? - @ftype = :directory - else - @ftype = :file - end - end - @local_header_size = calculate_local_header_size - end - - def ZipEntry.read_c_dir_entry(io) #:nodoc:all - entry = new(io.path) - entry.read_c_dir_entry(io) - return entry - rescue ZipError - return nil - end - - def file_stat(path) # :nodoc: - if @follow_symlinks - return File::stat(path) - else - return File::lstat(path) - end - end - - def get_extra_attributes_from_path(path) # :nodoc: - unless Zip::RUNNING_ON_WINDOWS - stat = file_stat(path) - @unix_uid = stat.uid - @unix_gid = stat.gid - @unix_perms = stat.mode & 07777 - end - end - - def set_extra_attributes_on_path(destPath) # :nodoc: - return unless (file? or directory?) - - case @fstype - when FSTYPE_UNIX - # BUG: does not update timestamps into account - # ignore setuid/setgid bits by default. honor if @restore_ownership - unix_perms_mask = 01777 - unix_perms_mask = 07777 if (@restore_ownership) - FileUtils::chmod(@unix_perms & unix_perms_mask, destPath) if (@restore_permissions && @unix_perms) - FileUtils::chown(@unix_uid, @unix_gid, destPath) if (@restore_ownership && @unix_uid && @unix_gid && Process::egid == 0) - # File::utimes() - end - end - - def write_c_dir_entry(io) #:nodoc:all - case @fstype - when FSTYPE_UNIX - ft = nil - case @ftype - when :file - ft = 010 - @unix_perms ||= 0644 - when :directory - ft = 004 - @unix_perms ||= 0755 - when :symlink - ft = 012 - @unix_perms ||= 0755 - else - raise ZipInternalError, "unknown file type #{self.inspect}" - end - - @externalFileAttributes = (ft << 12 | (@unix_perms & 07777)) << 16 - end - - io << - [CENTRAL_DIRECTORY_ENTRY_SIGNATURE, - @version , # version of encoding software - @fstype , # filesystem type - VERSION_NEEDED_TO_EXTRACT , # @versionNeededToExtract , - 0 , # @gp_flags , - @compression_method , - @time.to_binary_dos_time , # @lastModTime , - @time.to_binary_dos_date , # @lastModDate , - @crc , - @compressed_size , - @size , - @name ? @name.length : 0 , - @extra ? @extra.c_dir_length : 0 , - @comment ? comment.length : 0 , - 0 , # disk number start - @internalFileAttributes , # file type (binary=0, text=1) - @externalFileAttributes , # native filesystem attributes - @localHeaderOffset , - @name , - @extra , - @comment ].pack('VCCvvvvvVVVvvvvvVV') - - io << @name - io << (@extra ? @extra.to_c_dir_bin : "") - io << @comment - end - - def == (other) - return false unless other.class == self.class - # Compares contents of local entry and exposed fields - (@compression_method == other.compression_method && - @crc == other.crc && - @compressed_size == other.compressed_size && - @size == other.size && - @name == other.name && - @extra == other.extra && - @filepath == other.filepath && - self.time.dos_equals(other.time)) - end - - def <=> (other) - return to_s <=> other.to_s - end - - # Returns an IO like object for the given ZipEntry. - # Warning: may behave weird with symlinks. - def get_input_stream(&aProc) - if @ftype == :directory - return yield(NullInputStream.instance) if block_given? - return NullInputStream.instance - elsif @filepath - case @ftype - when :file - return File.open(@filepath, "rb", &aProc) - - when :symlink - linkpath = File::readlink(@filepath) - stringio = StringIO.new(linkpath) - return yield(stringio) if block_given? - return stringio - else - raise "unknown @ftype #{@ftype}" - end - else - zis = ZipInputStream.new(@zipfile, localHeaderOffset) - zis.get_next_entry - if block_given? - begin - return yield(zis) - ensure - zis.close - end - else - return zis - end - end - end - - def gather_fileinfo_from_srcpath(srcPath) # :nodoc: - stat = file_stat(srcPath) - case stat.ftype - when 'file' - if name_is_directory? - raise ArgumentError, - "entry name '#{newEntry}' indicates directory entry, but "+ - "'#{srcPath}' is not a directory" - end - @ftype = :file - when 'directory' - if ! name_is_directory? - @name += "/" - end - @ftype = :directory - when 'link' - if name_is_directory? - raise ArgumentError, - "entry name '#{newEntry}' indicates directory entry, but "+ - "'#{srcPath}' is not a directory" - end - @ftype = :symlink - else - raise RuntimeError, "unknown file type: #{srcPath.inspect} #{stat.inspect}" - end - - @filepath = srcPath - get_extra_attributes_from_path(@filepath) - end - - def write_to_zip_output_stream(aZipOutputStream) #:nodoc:all - if @ftype == :directory - aZipOutputStream.put_next_entry(self) - elsif @filepath - aZipOutputStream.put_next_entry(self) - get_input_stream { |is| IOExtras.copy_stream(aZipOutputStream, is) } - else - aZipOutputStream.copy_raw_entry(self) - end - end - - def parent_as_string - entry_name = name.chomp("/") - slash_index = entry_name.rindex("/") - slash_index ? entry_name.slice(0, slash_index+1) : nil - end - - def get_raw_input_stream(&aProc) - File.open(@zipfile, "rb", &aProc) - end - - private - - def set_time(binaryDosDate, binaryDosTime) - @time = Time.parse_binary_dos_format(binaryDosDate, binaryDosTime) - rescue ArgumentError - puts "Invalid date/time in zip entry" - end - - def write_file(destPath, continueOnExistsProc = proc { false }) - if File.exists?(destPath) && ! yield(self, destPath) - raise ZipDestinationFileExistsError, - "Destination '#{destPath}' already exists" - end - File.open(destPath, "wb") do |os| - get_input_stream do |is| - set_extra_attributes_on_path(destPath) - - buf = '' - while buf = is.sysread(Decompressor::CHUNK_SIZE, buf) - os << buf - end - end - end - end - - def create_directory(destPath) - if File.directory? destPath - return - elsif File.exists? destPath - if block_given? && yield(self, destPath) - FileUtils::rm_f destPath - else - raise ZipDestinationFileExistsError, - "Cannot create directory '#{destPath}'. "+ - "A file already exists with that name" - end - end - Dir.mkdir destPath - set_extra_attributes_on_path(destPath) - end - -# BUG: create_symlink() does not use &onExistsProc - def create_symlink(destPath) - stat = nil - begin - stat = File::lstat(destPath) - rescue Errno::ENOENT - end - - io = get_input_stream - linkto = io.read - - if stat - if stat.symlink? - if File::readlink(destPath) == linkto - return - else - raise ZipDestinationFileExistsError, - "Cannot create symlink '#{destPath}'. "+ - "A symlink already exists with that name" - end - else - raise ZipDestinationFileExistsError, - "Cannot create symlink '#{destPath}'. "+ - "A file already exists with that name" - end - end - - File::symlink(linkto, destPath) - end - end - - - # ZipOutputStream is the basic class for writing zip files. It is - # possible to create a ZipOutputStream object directly, passing - # the zip file name to the constructor, but more often than not - # the ZipOutputStream will be obtained from a ZipFile (perhaps using the - # ZipFileSystem interface) object for a particular entry in the zip - # archive. - # - # A ZipOutputStream inherits IOExtras::AbstractOutputStream in order - # to provide an IO-like interface for writing to a single zip - # entry. Beyond methods for mimicking an IO-object it contains - # the method put_next_entry that closes the current entry - # and creates a new. - # - # Please refer to ZipInputStream for example code. - # - # java.util.zip.ZipOutputStream is the original inspiration for this - # class. - - class ZipOutputStream - include IOExtras::AbstractOutputStream - - attr_accessor :comment - - # Opens the indicated zip file. If a file with that name already - # exists it will be overwritten. - def initialize(fileName) - super() - @fileName = fileName - @outputStream = File.new(@fileName, "wb") - @entrySet = ZipEntrySet.new - @compressor = NullCompressor.instance - @closed = false - @currentEntry = nil - @comment = nil - end - - # Same as #initialize but if a block is passed the opened - # stream is passed to the block and closed when the block - # returns. - def ZipOutputStream.open(fileName) - return new(fileName) unless block_given? - zos = new(fileName) - yield zos - ensure - zos.close if zos - end - - # Closes the stream and writes the central directory to the zip file - def close - return if @closed - finalize_current_entry - update_local_headers - write_central_directory - @outputStream.close - @closed = true - end - - # Closes the current entry and opens a new for writing. - # +entry+ can be a ZipEntry object or a string. - def put_next_entry(entryname, comment = nil, extra = nil, compression_method = ZipEntry::DEFLATED, level = Zlib::DEFAULT_COMPRESSION) - raise ZipError, "zip stream is closed" if @closed - new_entry = ZipEntry.new(@fileName, entryname.to_s) - new_entry.comment = comment if !comment.nil? - if (!extra.nil?) - new_entry.extra = ZipExtraField === extra ? extra : ZipExtraField.new(extra.to_s) - end - new_entry.compression_method = compression_method - init_next_entry(new_entry, level) - @currentEntry = new_entry - end - - def copy_raw_entry(entry) - entry = entry.dup - raise ZipError, "zip stream is closed" if @closed - raise ZipError, "entry is not a ZipEntry" if !entry.kind_of?(ZipEntry) - finalize_current_entry - @entrySet << entry - src_pos = entry.local_entry_offset - entry.write_local_entry(@outputStream) - @compressor = NullCompressor.instance - entry.get_raw_input_stream { - |is| - is.seek(src_pos, IO::SEEK_SET) - IOExtras.copy_stream_n(@outputStream, is, entry.compressed_size) - } - @compressor = NullCompressor.instance - @currentEntry = nil - end - - private - def finalize_current_entry - return unless @currentEntry - finish - @currentEntry.compressed_size = @outputStream.tell - @currentEntry.localHeaderOffset - - @currentEntry.calculate_local_header_size - @currentEntry.size = @compressor.size - @currentEntry.crc = @compressor.crc - @currentEntry = nil - @compressor = NullCompressor.instance - end - - def init_next_entry(entry, level = Zlib::DEFAULT_COMPRESSION) - finalize_current_entry - @entrySet << entry - entry.write_local_entry(@outputStream) - @compressor = get_compressor(entry, level) - end - - def get_compressor(entry, level) - case entry.compression_method - when ZipEntry::DEFLATED then Deflater.new(@outputStream, level) - when ZipEntry::STORED then PassThruCompressor.new(@outputStream) - else raise ZipCompressionMethodError, - "Invalid compression method: '#{entry.compression_method}'" - end - end - - def update_local_headers - pos = @outputStream.tell - @entrySet.each { - |entry| - @outputStream.pos = entry.localHeaderOffset - entry.write_local_entry(@outputStream) - } - @outputStream.pos = pos - end - - def write_central_directory - cdir = ZipCentralDirectory.new(@entrySet, @comment) - cdir.write_to_stream(@outputStream) - end - - protected - - def finish - @compressor.finish - end - - public - # Modeled after IO.<< - def << (data) - @compressor << data - end - end - - - class Compressor #:nodoc:all - def finish - end - end - - class PassThruCompressor < Compressor #:nodoc:all - def initialize(outputStream) - super() - @outputStream = outputStream - @crc = Zlib::crc32 - @size = 0 - end - - def << (data) - val = data.to_s - @crc = Zlib::crc32(val, @crc) - @size += val.size - @outputStream << val - end - - attr_reader :size, :crc - end - - class NullCompressor < Compressor #:nodoc:all - include Singleton - - def << (data) - raise IOError, "closed stream" - end - - attr_reader :size, :compressed_size - end - - class Deflater < Compressor #:nodoc:all - def initialize(outputStream, level = Zlib::DEFAULT_COMPRESSION) - super() - @outputStream = outputStream - @zlibDeflater = Zlib::Deflate.new(level, -Zlib::MAX_WBITS) - @size = 0 - @crc = Zlib::crc32 - end - - def << (data) - val = data.to_s - @crc = Zlib::crc32(val, @crc) - @size += val.size - @outputStream << @zlibDeflater.deflate(data) - end - - def finish - until @zlibDeflater.finished? - @outputStream << @zlibDeflater.finish - end - end - - attr_reader :size, :crc - end - - - class ZipEntrySet #:nodoc:all - include Enumerable - - def initialize(anEnumerable = []) - super() - @entrySet = {} - anEnumerable.each { |o| push(o) } - end - - def include?(entry) - @entrySet.include?(entry.to_s) - end - - def <<(entry) - @entrySet[entry.to_s] = entry - end - alias :push :<< - - def size - @entrySet.size - end - alias :length :size - - def delete(entry) - @entrySet.delete(entry.to_s) ? entry : nil - end - - def each(&aProc) - @entrySet.values.each(&aProc) - end - - def entries - @entrySet.values - end - - # deep clone - def dup - newZipEntrySet = ZipEntrySet.new(@entrySet.values.map { |e| e.dup }) - end - - def == (other) - return false unless other.kind_of?(ZipEntrySet) - return @entrySet == other.entrySet - end - - def parent(entry) - @entrySet[entry.parent_as_string] - end - - def glob(pattern, flags = File::FNM_PATHNAME|File::FNM_DOTMATCH) - entries.select { - |entry| - File.fnmatch(pattern, entry.name.chomp('/'), flags) - } - end - -#TODO attr_accessor :auto_create_directories - protected - attr_accessor :entrySet - end - - - class ZipCentralDirectory - include Enumerable - - END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x06054b50 - MAX_END_OF_CENTRAL_DIRECTORY_STRUCTURE_SIZE = 65536 + 18 - STATIC_EOCD_SIZE = 22 - - attr_reader :comment - - # Returns an Enumerable containing the entries. - def entries - @entrySet.entries - end - - def initialize(entries = ZipEntrySet.new, comment = "") #:nodoc: - super() - @entrySet = entries.kind_of?(ZipEntrySet) ? entries : ZipEntrySet.new(entries) - @comment = comment - end - - def write_to_stream(io) #:nodoc: - offset = io.tell - @entrySet.each { |entry| entry.write_c_dir_entry(io) } - write_e_o_c_d(io, offset) - end - - def write_e_o_c_d(io, offset) #:nodoc: - io << - [END_OF_CENTRAL_DIRECTORY_SIGNATURE, - 0 , # @numberOfThisDisk - 0 , # @numberOfDiskWithStartOfCDir - @entrySet? @entrySet.size : 0 , - @entrySet? @entrySet.size : 0 , - cdir_size , - offset , - @comment ? @comment.length : 0 ].pack('VvvvvVVv') - io << @comment - end - private :write_e_o_c_d - - def cdir_size #:nodoc: - # does not include eocd - @entrySet.inject(0) { |value, entry| entry.cdir_header_size + value } - end - private :cdir_size - - def read_e_o_c_d(io) #:nodoc: - buf = get_e_o_c_d(io) - @numberOfThisDisk = ZipEntry::read_zip_short(buf) - @numberOfDiskWithStartOfCDir = ZipEntry::read_zip_short(buf) - @totalNumberOfEntriesInCDirOnThisDisk = ZipEntry::read_zip_short(buf) - @size = ZipEntry::read_zip_short(buf) - @sizeInBytes = ZipEntry::read_zip_long(buf) - @cdirOffset = ZipEntry::read_zip_long(buf) - commentLength = ZipEntry::read_zip_short(buf) - @comment = buf.read(commentLength) - # remove trailing \n symbol - buf.chomp! - raise ZipError, "Zip consistency problem while reading eocd structure" unless buf.size == 0 - end - - def read_central_directory_entries(io) #:nodoc: - begin - io.seek(@cdirOffset, IO::SEEK_SET) - rescue Errno::EINVAL - raise ZipError, "Zip consistency problem while reading central directory entry" - end - @entrySet = ZipEntrySet.new - @size.times { - @entrySet << ZipEntry.read_c_dir_entry(io) - } - end - - def read_from_stream(io) #:nodoc: - read_e_o_c_d(io) - read_central_directory_entries(io) - end - - def get_e_o_c_d(io) #:nodoc: - begin - io.seek(-MAX_END_OF_CENTRAL_DIRECTORY_STRUCTURE_SIZE, IO::SEEK_END) - rescue Errno::EINVAL - io.seek(0, IO::SEEK_SET) - rescue Errno::EFBIG # FreeBSD 4.9 raise Errno::EFBIG instead of Errno::EINVAL - io.seek(0, IO::SEEK_SET) - end - - # 'buf = io.read' substituted with lump of code to work around FreeBSD 4.5 issue - retried = false - buf = nil - begin - buf = io.read - rescue Errno::EFBIG # FreeBSD 4.5 may raise Errno::EFBIG - raise if (retried) - retried = true - - io.seek(0, IO::SEEK_SET) - retry - end - - sigIndex = buf.rindex([END_OF_CENTRAL_DIRECTORY_SIGNATURE].pack('V')) - raise ZipError, "Zip end of central directory signature not found" unless sigIndex - buf=buf.slice!((sigIndex+4)...(buf.size)) - def buf.read(count) - slice!(0, count) - end - return buf - end - - # For iterating over the entries. - def each(&proc) - @entrySet.each(&proc) - end - - # Returns the number of entries in the central directory (and - # consequently in the zip archive). - def size - @entrySet.size - end - - def ZipCentralDirectory.read_from_stream(io) #:nodoc: - cdir = new - cdir.read_from_stream(io) - return cdir - rescue ZipError - return nil - end - - def == (other) #:nodoc: - return false unless other.kind_of?(ZipCentralDirectory) - @entrySet.entries.sort == other.entries.sort && comment == other.comment - end - end - - - class ZipError < StandardError ; end - - class ZipEntryExistsError < ZipError; end - class ZipDestinationFileExistsError < ZipError; end - class ZipCompressionMethodError < ZipError; end - class ZipEntryNameError < ZipError; end - class ZipInternalError < ZipError; end - - # ZipFile is modeled after java.util.zip.ZipFile from the Java SDK. - # The most important methods are those inherited from - # ZipCentralDirectory for accessing information about the entries in - # the archive and methods such as get_input_stream and - # get_output_stream for reading from and writing entries to the - # archive. The class includes a few convenience methods such as - # #extract for extracting entries to the filesystem, and #remove, - # #replace, #rename and #mkdir for making simple modifications to - # the archive. - # - # Modifications to a zip archive are not committed until #commit or - # #close is called. The method #open accepts a block following - # the pattern from File.open offering a simple way to - # automatically close the archive when the block returns. - # - # The following example opens zip archive my.zip - # (creating it if it doesn't exist) and adds an entry - # first.txt and a directory entry a_dir - # to it. - # - # require 'zip/zip' - # - # Zip::ZipFile.open("my.zip", Zip::ZipFile::CREATE) { - # |zipfile| - # zipfile.get_output_stream("first.txt") { |f| f.puts "Hello from ZipFile" } - # zipfile.mkdir("a_dir") - # } - # - # The next example reopens my.zip writes the contents of - # first.txt to standard out and deletes the entry from - # the archive. - # - # require 'zip/zip' - # - # Zip::ZipFile.open("my.zip", Zip::ZipFile::CREATE) { - # |zipfile| - # puts zipfile.read("first.txt") - # zipfile.remove("first.txt") - # } - # - # ZipFileSystem offers an alternative API that emulates ruby's - # interface for accessing the filesystem, ie. the File and Dir classes. - - class ZipFile < ZipCentralDirectory - - CREATE = 1 - - attr_reader :name - - # default -> false - attr_accessor :restore_ownership - # default -> false - attr_accessor :restore_permissions - # default -> true - attr_accessor :restore_times - - # Opens a zip archive. Pass true as the second parameter to create - # a new archive if it doesn't exist already. - def initialize(fileName, create = nil) - super() - @name = fileName - @comment = "" - if (File.exists?(fileName)) - File.open(name, "rb") { |f| read_from_stream(f) } - elsif (create) - @entrySet = ZipEntrySet.new - else - raise ZipError, "File #{fileName} not found" - end - @create = create - @storedEntries = @entrySet.dup - - @restore_ownership = false - @restore_permissions = false - @restore_times = true - end - - # Same as #new. If a block is passed the ZipFile object is passed - # to the block and is automatically closed afterwards just as with - # ruby's builtin File.open method. - def ZipFile.open(fileName, create = nil) - zf = ZipFile.new(fileName, create) - if block_given? - begin - yield zf - ensure - zf.close - end - else - zf - end - end - - # Returns the zip files comment, if it has one - attr_accessor :comment - - # Iterates over the contents of the ZipFile. This is more efficient - # than using a ZipInputStream since this methods simply iterates - # through the entries in the central directory structure in the archive - # whereas ZipInputStream jumps through the entire archive accessing the - # local entry headers (which contain the same information as the - # central directory). - def ZipFile.foreach(aZipFileName, &block) - ZipFile.open(aZipFileName) { - |zipFile| - zipFile.each(&block) - } - end - - # Returns an input stream to the specified entry. If a block is passed - # the stream object is passed to the block and the stream is automatically - # closed afterwards just as with ruby's builtin File.open method. - def get_input_stream(entry, &aProc) - get_entry(entry).get_input_stream(&aProc) - end - - # Returns an output stream to the specified entry. If a block is passed - # the stream object is passed to the block and the stream is automatically - # closed afterwards just as with ruby's builtin File.open method. - def get_output_stream(entry, &aProc) - newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@name, entry.to_s) - if newEntry.directory? - raise ArgumentError, - "cannot open stream to directory entry - '#{newEntry}'" - end - zipStreamableEntry = ZipStreamableStream.new(newEntry) - @entrySet << zipStreamableEntry - zipStreamableEntry.get_output_stream(&aProc) - end - - # Returns the name of the zip archive - def to_s - @name - end - - # Returns a string containing the contents of the specified entry - def read(entry) - get_input_stream(entry) { |is| is.read } - end - - # Convenience method for adding the contents of a file to the archive - def add(entry, srcPath, &continueOnExistsProc) - continueOnExistsProc ||= proc { false } - check_entry_exists(entry, continueOnExistsProc, "add") - newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@name, entry.to_s) - newEntry.gather_fileinfo_from_srcpath(srcPath) - @entrySet << newEntry - end - - # Removes the specified entry. - def remove(entry) - @entrySet.delete(get_entry(entry)) - end - - # Renames the specified entry. - def rename(entry, newName, &continueOnExistsProc) - foundEntry = get_entry(entry) - check_entry_exists(newName, continueOnExistsProc, "rename") - @entrySet.delete(foundEntry) - foundEntry.name = newName - @entrySet << foundEntry - end - - # Replaces the specified entry with the contents of srcPath (from - # the file system). - def replace(entry, srcPath) - check_file(srcPath) - add(remove(entry), srcPath) - end - - # Extracts entry to file destPath. - def extract(entry, destPath, &onExistsProc) - onExistsProc ||= proc { false } - foundEntry = get_entry(entry) - foundEntry.extract(destPath, &onExistsProc) - end - - # Commits changes that has been made since the previous commit to - # the zip archive. - def commit - return if ! commit_required? - on_success_replace(name) { - |tmpFile| - ZipOutputStream.open(tmpFile) { - |zos| - - @entrySet.each { |e| e.write_to_zip_output_stream(zos) } - zos.comment = comment - } - true - } - initialize(name) - end - - # Closes the zip file committing any changes that has been made. - def close - commit - end - - # Returns true if any changes has been made to this archive since - # the previous commit - def commit_required? - return @entrySet != @storedEntries || @create == ZipFile::CREATE - end - - # Searches for entry with the specified name. Returns nil if - # no entry is found. See also get_entry - def find_entry(entry) - @entrySet.detect { - |e| - e.name.sub(/\/$/, "") == entry.to_s.sub(/\/$/, "") - } - end - - # Searches for an entry just as find_entry, but throws Errno::ENOENT - # if no entry is found. - def get_entry(entry) - selectedEntry = find_entry(entry) - unless selectedEntry - raise Errno::ENOENT, entry - end - selectedEntry.restore_ownership = @restore_ownership - selectedEntry.restore_permissions = @restore_permissions - selectedEntry.restore_times = @restore_times - - return selectedEntry - end - - # Creates a directory - def mkdir(entryName, permissionInt = 0755) - if find_entry(entryName) - raise Errno::EEXIST, "File exists - #{entryName}" - end - @entrySet << ZipStreamableDirectory.new(@name, entryName.to_s.ensure_end("/"), nil, permissionInt) - end - - private - - def is_directory(newEntry, srcPath) - srcPathIsDirectory = File.directory?(srcPath) - if newEntry.is_directory && ! srcPathIsDirectory - raise ArgumentError, - "entry name '#{newEntry}' indicates directory entry, but "+ - "'#{srcPath}' is not a directory" - elsif ! newEntry.is_directory && srcPathIsDirectory - newEntry.name += "/" - end - return newEntry.is_directory && srcPathIsDirectory - end - - def check_entry_exists(entryName, continueOnExistsProc, procedureName) - continueOnExistsProc ||= proc { false } - if @entrySet.detect { |e| e.name == entryName } - if continueOnExistsProc.call - remove get_entry(entryName) - else - raise ZipEntryExistsError, - procedureName+" failed. Entry #{entryName} already exists" - end - end - end - - def check_file(path) - unless File.readable? path - raise Errno::ENOENT, path - end - end - - def on_success_replace(aFilename) - tmpfile = get_tempfile - tmpFilename = tmpfile.path - tmpfile.close - if yield tmpFilename - File.rename(tmpFilename, name) - end - end - - def get_tempfile - tempFile = Tempfile.new(File.basename(name), File.dirname(name)) - tempFile.binmode - tempFile - end - - end - - class ZipStreamableDirectory < ZipEntry - def initialize(zipfile, entry, srcPath = nil, permissionInt = nil) - super(zipfile, entry) - - @ftype = :directory - entry.get_extra_attributes_from_path(srcPath) if (srcPath) - @unix_perms = permissionInt if (permissionInt) - end - end - - class ZipStreamableStream < DelegateClass(ZipEntry) #nodoc:all - def initialize(entry) - super(entry) - @tempFile = Tempfile.new(File.basename(name), File.dirname(zipfile)) - @tempFile.binmode - end - - def get_output_stream - if block_given? - begin - yield(@tempFile) - ensure - @tempFile.close - end - else - @tempFile - end - end - - def get_input_stream - if ! @tempFile.closed? - raise StandardError, "cannot open entry for reading while its open for writing - #{name}" - end - @tempFile.open # reopens tempfile from top - @tempFile.binmode - if block_given? - begin - yield(@tempFile) - ensure - @tempFile.close - end - else - @tempFile - end - end - - def write_to_zip_output_stream(aZipOutputStream) - aZipOutputStream.put_next_entry(self) - get_input_stream { |is| IOExtras.copy_stream(aZipOutputStream, is) } - end - end - - class ZipExtraField < Hash - ID_MAP = {} - - # Meta class for extra fields - class Generic - def self.register_map - if self.const_defined?(:HEADER_ID) - ID_MAP[self.const_get(:HEADER_ID)] = self - end - end - - def self.name - self.to_s.split("::")[-1] - end - - # return field [size, content] or false - def initial_parse(binstr) - if ! binstr - # If nil, start with empty. - return false - elsif binstr[0,2] != self.class.const_get(:HEADER_ID) - $stderr.puts "Warning: weired extra feild header ID. skip parsing" - return false - end - [binstr[2,2].unpack("v")[0], binstr[4..-1]] - end - - def ==(other) - self.class != other.class and return false - each { |k, v| - v != other[k] and return false - } - true - end - - def to_local_bin - s = pack_for_local - self.class.const_get(:HEADER_ID) + [s.length].pack("v") + s - end - - def to_c_dir_bin - s = pack_for_c_dir - self.class.const_get(:HEADER_ID) + [s.length].pack("v") + s - end - end - - # Info-ZIP Additional timestamp field - class UniversalTime < Generic - HEADER_ID = "UT" - register_map - - def initialize(binstr = nil) - @ctime = nil - @mtime = nil - @atime = nil - @flag = nil - binstr and merge(binstr) - end - attr_accessor :atime, :ctime, :mtime, :flag - - def merge(binstr) - binstr == "" and return - size, content = initial_parse(binstr) - size or return - @flag, mtime, atime, ctime = content.unpack("CVVV") - mtime and @mtime ||= Time.at(mtime) - atime and @atime ||= Time.at(atime) - ctime and @ctime ||= Time.at(ctime) - end - - def ==(other) - @mtime == other.mtime && - @atime == other.atime && - @ctime == other.ctime - end - - def pack_for_local - s = [@flag].pack("C") - @flag & 1 != 0 and s << [@mtime.to_i].pack("V") - @flag & 2 != 0 and s << [@atime.to_i].pack("V") - @flag & 4 != 0 and s << [@ctime.to_i].pack("V") - s - end - - def pack_for_c_dir - s = [@flag].pack("C") - @flag & 1 == 1 and s << [@mtime.to_i].pack("V") - s - end - end - - # Info-ZIP Extra for UNIX uid/gid - class IUnix < Generic - HEADER_ID = "Ux" - register_map - - def initialize(binstr = nil) - @uid = 0 - @gid = 0 - binstr and merge(binstr) - end - attr_accessor :uid, :gid - - def merge(binstr) - binstr == "" and return - size, content = initial_parse(binstr) - # size: 0 for central direcotry. 4 for local header - return if(! size || size == 0) - uid, gid = content.unpack("vv") - @uid ||= uid - @gid ||= gid - end - - def ==(other) - @uid == other.uid && - @gid == other.gid - end - - def pack_for_local - [@uid, @gid].pack("vv") - end - - def pack_for_c_dir - "" - end - end - - ## start main of ZipExtraField < Hash - def initialize(binstr = nil) - binstr and merge(binstr) - end - - def merge(binstr) - binstr == "" and return - i = 0 - while i < binstr.length - id = binstr[i,2] - len = binstr[i+2,2].to_s.unpack("v")[0] - if id && ID_MAP.member?(id) - field_name = ID_MAP[id].name - if self.member?(field_name) - self[field_name].mergea(binstr[i, len+4]) - else - field_obj = ID_MAP[id].new(binstr[i, len+4]) - self[field_name] = field_obj - end - elsif id - unless self["Unknown"] - s = "" - class << s - alias_method :to_c_dir_bin, :to_s - alias_method :to_local_bin, :to_s - end - self["Unknown"] = s - end - if ! len || len+4 > binstr[i..-1].length - self["Unknown"] << binstr[i..-1] - break; - end - self["Unknown"] << binstr[i, len+4] - end - i += len+4 - end - end - - def create(name) - field_class = nil - ID_MAP.each { |id, klass| - if klass.name == name - field_class = klass - break - end - } - if ! field_class - raise ZipError, "Unknown extra field '#{name}'" - end - self[name] = field_class.new() - end - - def to_local_bin - s = "" - each { |k, v| - s << v.to_local_bin - } - s - end - alias :to_s :to_local_bin - - def to_c_dir_bin - s = "" - each { |k, v| - s << v.to_c_dir_bin - } - s - end - - def c_dir_length - to_c_dir_bin.length - end - def local_length - to_local_bin.length - end - alias :c_dir_size :c_dir_length - alias :local_size :local_length - alias :length :local_length - alias :size :local_length - end # end ZipExtraField - -end # Zip namespace module - - - -# Copyright (C) 2002, 2003 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/zipfilesystem.rb b/lib/zip/zipfilesystem.rb deleted file mode 100644 index 565ce2b3a0..0000000000 --- a/lib/zip/zipfilesystem.rb +++ /dev/null @@ -1,611 +0,0 @@ -# encoding: ASCII-8BIT -require 'zip/zip' - -module Zip - - # The ZipFileSystem API provides an API for accessing entries in - # a zip archive that is similar to ruby's builtin File and Dir - # classes. - # - # Requiring 'zip/zipfilesystem' includes this module in ZipFile - # making the methods in this module available on ZipFile objects. - # - # Using this API the following example creates a new zip file - # my.zip containing a normal entry with the name - # first.txt, a directory entry named mydir - # and finally another normal entry named second.txt - # - # require 'zip/zipfilesystem' - # - # Zip::ZipFile.open("my.zip", Zip::ZipFile::CREATE) { - # |zipfile| - # zipfile.file.open("first.txt", "w") { |f| f.puts "Hello world" } - # zipfile.dir.mkdir("mydir") - # zipfile.file.open("mydir/second.txt", "w") { |f| f.puts "Hello again" } - # } - # - # Reading is as easy as writing, as the following example shows. The - # example writes the contents of first.txt from zip archive - # my.zip to standard out. - # - # require 'zip/zipfilesystem' - # - # Zip::ZipFile.open("my.zip") { - # |zipfile| - # puts zipfile.file.read("first.txt") - # } - - module ZipFileSystem - - def initialize # :nodoc: - mappedZip = ZipFileNameMapper.new(self) - @zipFsDir = ZipFsDir.new(mappedZip) - @zipFsFile = ZipFsFile.new(mappedZip) - @zipFsDir.file = @zipFsFile - @zipFsFile.dir = @zipFsDir - end - - # Returns a ZipFsDir which is much like ruby's builtin Dir (class) - # object, except it works on the ZipFile on which this method is - # invoked - def dir - @zipFsDir - end - - # Returns a ZipFsFile which is much like ruby's builtin File (class) - # object, except it works on the ZipFile on which this method is - # invoked - def file - @zipFsFile - end - - # Instances of this class are normally accessed via the accessor - # ZipFile::file. An instance of ZipFsFile behaves like ruby's - # builtin File (class) object, except it works on ZipFile entries. - # - # The individual methods are not documented due to their - # similarity with the methods in File - class ZipFsFile - - attr_writer :dir -# protected :dir - - class ZipFsStat - def initialize(zipFsFile, entryName) - @zipFsFile = zipFsFile - @entryName = entryName - end - - def forward_invoke(msg) - @zipFsFile.send(msg, @entryName) - end - - def kind_of?(t) - super || t == ::File::Stat - end - - forward_message :forward_invoke, :file?, :directory?, :pipe?, :chardev? - forward_message :forward_invoke, :symlink?, :socket?, :blockdev? - forward_message :forward_invoke, :readable?, :readable_real? - forward_message :forward_invoke, :writable?, :writable_real? - forward_message :forward_invoke, :executable?, :executable_real? - forward_message :forward_invoke, :sticky?, :owned?, :grpowned? - forward_message :forward_invoke, :setuid?, :setgid? - forward_message :forward_invoke, :zero? - forward_message :forward_invoke, :size, :size? - forward_message :forward_invoke, :mtime, :atime, :ctime - - def blocks; nil; end - - def get_entry - @zipFsFile.__send__(:get_entry, @entryName) - end - private :get_entry - - def gid - e = get_entry - if e.extra.member? "IUnix" - e.extra["IUnix"].gid || 0 - else - 0 - end - end - - def uid - e = get_entry - if e.extra.member? "IUnix" - e.extra["IUnix"].uid || 0 - else - 0 - end - end - - def ino; 0; end - - def dev; 0; end - - def rdev; 0; end - - def rdev_major; 0; end - - def rdev_minor; 0; end - - def ftype - if file? - return "file" - elsif directory? - return "directory" - else - raise StandardError, "Unknown file type" - end - end - - def nlink; 1; end - - def blksize; nil; end - - def mode - e = get_entry - if e.fstype == 3 - e.externalFileAttributes >> 16 - else - 33206 # 33206 is equivalent to -rw-rw-rw- - end - end - end - - def initialize(mappedZip) - @mappedZip = mappedZip - end - - def get_entry(fileName) - if ! exists?(fileName) - raise Errno::ENOENT, "No such file or directory - #{fileName}" - end - @mappedZip.find_entry(fileName) - end - private :get_entry - - def unix_mode_cmp(fileName, mode) - begin - e = get_entry(fileName) - e.fstype == 3 && ((e.externalFileAttributes >> 16) & mode ) != 0 - rescue Errno::ENOENT - false - end - end - private :unix_mode_cmp - - def exists?(fileName) - expand_path(fileName) == "/" || @mappedZip.find_entry(fileName) != nil - end - alias :exist? :exists? - - # Permissions not implemented, so if the file exists it is accessible - alias owned? exists? - alias grpowned? exists? - - def readable?(fileName) - unix_mode_cmp(fileName, 0444) - end - alias readable_real? readable? - - def writable?(fileName) - unix_mode_cmp(fileName, 0222) - end - alias writable_real? writable? - - def executable?(fileName) - unix_mode_cmp(fileName, 0111) - end - alias executable_real? executable? - - def setuid?(fileName) - unix_mode_cmp(fileName, 04000) - end - - def setgid?(fileName) - unix_mode_cmp(fileName, 02000) - end - - def sticky?(fileName) - unix_mode_cmp(fileName, 01000) - end - - def umask(*args) - ::File.umask(*args) - end - - def truncate(fileName, len) - raise StandardError, "truncate not supported" - end - - def directory?(fileName) - entry = @mappedZip.find_entry(fileName) - expand_path(fileName) == "/" || (entry != nil && entry.directory?) - end - - def open(fileName, openMode = "r", &block) - openMode.gsub!("b", "") # ignore b option - case openMode - when "r" - @mappedZip.get_input_stream(fileName, &block) - when "w" - @mappedZip.get_output_stream(fileName, &block) - else - raise StandardError, "openmode '#{openMode} not supported" unless openMode == "r" - end - end - - def new(fileName, openMode = "r") - open(fileName, openMode) - end - - def size(fileName) - @mappedZip.get_entry(fileName).size - end - - # Returns nil for not found and nil for directories - def size?(fileName) - entry = @mappedZip.find_entry(fileName) - return (entry == nil || entry.directory?) ? nil : entry.size - end - - def chown(ownerInt, groupInt, *filenames) - filenames.each { |fileName| - e = get_entry(fileName) - unless e.extra.member?("IUnix") - e.extra.create("IUnix") - end - e.extra["IUnix"].uid = ownerInt - e.extra["IUnix"].gid = groupInt - } - filenames.size - end - - def chmod (modeInt, *filenames) - filenames.each { |fileName| - e = get_entry(fileName) - e.fstype = 3 # force convertion filesystem type to unix - e.externalFileAttributes = modeInt << 16 - } - filenames.size - end - - def zero?(fileName) - sz = size(fileName) - sz == nil || sz == 0 - rescue Errno::ENOENT - false - end - - def file?(fileName) - entry = @mappedZip.find_entry(fileName) - entry != nil && entry.file? - end - - def dirname(fileName) - ::File.dirname(fileName) - end - - def basename(fileName) - ::File.basename(fileName) - end - - def split(fileName) - ::File.split(fileName) - end - - def join(*fragments) - ::File.join(*fragments) - end - - def utime(modifiedTime, *fileNames) - fileNames.each { |fileName| - get_entry(fileName).time = modifiedTime - } - end - - def mtime(fileName) - @mappedZip.get_entry(fileName).mtime - end - - def atime(fileName) - e = get_entry(fileName) - if e.extra.member? "UniversalTime" - e.extra["UniversalTime"].atime - else - nil - end - end - - def ctime(fileName) - e = get_entry(fileName) - if e.extra.member? "UniversalTime" - e.extra["UniversalTime"].ctime - else - nil - end - end - - def pipe?(filename) - false - end - - def blockdev?(filename) - false - end - - def chardev?(filename) - false - end - - def symlink?(fileName) - false - end - - def socket?(fileName) - false - end - - def ftype(fileName) - @mappedZip.get_entry(fileName).directory? ? "directory" : "file" - end - - def readlink(fileName) - raise NotImplementedError, "The readlink() function is not implemented" - end - - def symlink(fileName, symlinkName) - raise NotImplementedError, "The symlink() function is not implemented" - end - - def link(fileName, symlinkName) - raise NotImplementedError, "The link() function is not implemented" - end - - def pipe - raise NotImplementedError, "The pipe() function is not implemented" - end - - def stat(fileName) - if ! exists?(fileName) - raise Errno::ENOENT, fileName - end - ZipFsStat.new(self, fileName) - end - - alias lstat stat - - def readlines(fileName) - open(fileName) { |is| is.readlines } - end - - def read(fileName) - @mappedZip.read(fileName) - end - - def popen(*args, &aProc) - File.popen(*args, &aProc) - end - - def foreach(fileName, aSep = $/, &aProc) - open(fileName) { |is| is.each_line(aSep, &aProc) } - end - - def delete(*args) - args.each { - |fileName| - if directory?(fileName) - raise Errno::EISDIR, "Is a directory - \"#{fileName}\"" - end - @mappedZip.remove(fileName) - } - end - - def rename(fileToRename, newName) - @mappedZip.rename(fileToRename, newName) { true } - end - - alias :unlink :delete - - def expand_path(aPath) - @mappedZip.expand_path(aPath) - end - end - - # Instances of this class are normally accessed via the accessor - # ZipFile::dir. An instance of ZipFsDir behaves like ruby's - # builtin Dir (class) object, except it works on ZipFile entries. - # - # The individual methods are not documented due to their - # similarity with the methods in Dir - class ZipFsDir - - def initialize(mappedZip) - @mappedZip = mappedZip - end - - attr_writer :file - - def new(aDirectoryName) - ZipFsDirIterator.new(entries(aDirectoryName)) - end - - def open(aDirectoryName) - dirIt = new(aDirectoryName) - if block_given? - begin - yield(dirIt) - return nil - ensure - dirIt.close - end - end - dirIt - end - - def pwd; @mappedZip.pwd; end - alias getwd pwd - - def chdir(aDirectoryName) - unless @file.stat(aDirectoryName).directory? - raise Errno::EINVAL, "Invalid argument - #{aDirectoryName}" - end - @mappedZip.pwd = @file.expand_path(aDirectoryName) - end - - def entries(aDirectoryName) - entries = [] - foreach(aDirectoryName) { |e| entries << e } - entries - end - - def foreach(aDirectoryName) - unless @file.stat(aDirectoryName).directory? - raise Errno::ENOTDIR, aDirectoryName - end - path = @file.expand_path(aDirectoryName).ensure_end("/") - - subDirEntriesRegex = Regexp.new("^#{path}([^/]+)$") - @mappedZip.each { - |fileName| - match = subDirEntriesRegex.match(fileName) - yield(match[1]) unless match == nil - } - end - - def delete(entryName) - unless @file.stat(entryName).directory? - raise Errno::EINVAL, "Invalid argument - #{entryName}" - end - @mappedZip.remove(entryName) - end - alias rmdir delete - alias unlink delete - - def mkdir(entryName, permissionInt = 0755) - @mappedZip.mkdir(entryName, permissionInt) - end - - def chroot(*args) - raise NotImplementedError, "The chroot() function is not implemented" - end - - end - - class ZipFsDirIterator # :nodoc:all - include Enumerable - - def initialize(arrayOfFileNames) - @fileNames = arrayOfFileNames - @index = 0 - end - - def close - @fileNames = nil - end - - def each(&aProc) - raise IOError, "closed directory" if @fileNames == nil - @fileNames.each(&aProc) - end - - def read - raise IOError, "closed directory" if @fileNames == nil - @fileNames[(@index+=1)-1] - end - - def rewind - raise IOError, "closed directory" if @fileNames == nil - @index = 0 - end - - def seek(anIntegerPosition) - raise IOError, "closed directory" if @fileNames == nil - @index = anIntegerPosition - end - - def tell - raise IOError, "closed directory" if @fileNames == nil - @index - end - end - - # All access to ZipFile from ZipFsFile and ZipFsDir goes through a - # ZipFileNameMapper, which has one responsibility: ensure - class ZipFileNameMapper # :nodoc:all - include Enumerable - - def initialize(zipFile) - @zipFile = zipFile - @pwd = "/" - end - - attr_accessor :pwd - - def find_entry(fileName) - @zipFile.find_entry(expand_to_entry(fileName)) - end - - def get_entry(fileName) - @zipFile.get_entry(expand_to_entry(fileName)) - end - - def get_input_stream(fileName, &aProc) - @zipFile.get_input_stream(expand_to_entry(fileName), &aProc) - end - - def get_output_stream(fileName, &aProc) - @zipFile.get_output_stream(expand_to_entry(fileName), &aProc) - end - - def read(fileName) - @zipFile.read(expand_to_entry(fileName)) - end - - def remove(fileName) - @zipFile.remove(expand_to_entry(fileName)) - end - - def rename(fileName, newName, &continueOnExistsProc) - @zipFile.rename(expand_to_entry(fileName), expand_to_entry(newName), - &continueOnExistsProc) - end - - def mkdir(fileName, permissionInt = 0755) - @zipFile.mkdir(expand_to_entry(fileName), permissionInt) - end - - # Turns entries into strings and adds leading / - # and removes trailing slash on directories - def each - @zipFile.each { - |e| - yield("/"+e.to_s.chomp("/")) - } - end - - def expand_path(aPath) - expanded = aPath.starts_with("/") ? aPath : @pwd.ensure_end("/") + aPath - expanded.gsub!(/\/\.(\/|$)/, "") - expanded.gsub!(/[^\/]+\/\.\.(\/|$)/, "") - expanded.empty? ? "/" : expanded - end - - private - - def expand_to_entry(aPath) - expand_path(aPath).lchop - end - end - end - - class ZipFile - include ZipFileSystem - end -end - -# Copyright (C) 2002, 2003 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license. diff --git a/lib/zip/ziprequire.rb b/lib/zip/ziprequire.rb deleted file mode 100644 index a3b1261c20..0000000000 --- a/lib/zip/ziprequire.rb +++ /dev/null @@ -1,90 +0,0 @@ -# With ziprequire you can load ruby modules from a zip file. This means -# ruby's module include path can include zip-files. -# -# The following example creates a zip file with a single entry -# log/simplelog.rb that contains a single function -# simpleLog: -# -# require 'zip/zipfilesystem' -# -# Zip::ZipFile.open("my.zip", true) { -# |zf| -# zf.file.open("log/simplelog.rb", "w") { -# |f| -# f.puts "def simpleLog(v)" -# f.puts ' Kernel.puts "INFO: #{v}"' -# f.puts "end" -# } -# } -# -# To use the ruby module stored in the zip archive simply require -# zip/ziprequire and include the my.zip zip -# file in the module search path. The following command shows one -# way to do this: -# -# ruby -rzip/ziprequire -Imy.zip -e " require 'log/simplelog'; simpleLog 'Hello world' " - -#$: << 'data/rubycode.zip' << 'data/rubycode2.zip' - - -require 'zip/zip' - -class ZipList #:nodoc:all - def initialize(zipFileList) - @zipFileList = zipFileList - end - - def get_input_stream(entry, &aProc) - @zipFileList.each { - |zfName| - Zip::ZipFile.open(zfName) { - |zf| - begin - return zf.get_input_stream(entry, &aProc) - rescue Errno::ENOENT - end - } - } - raise Errno::ENOENT, - "No matching entry found in zip files '#{@zipFileList.join(', ')}' "+ - " for '#{entry}'" - end -end - - -module Kernel #:nodoc:all - alias :oldRequire :require - - def require(moduleName) - zip_require(moduleName) || oldRequire(moduleName) - end - - def zip_require(moduleName) - return false if already_loaded?(moduleName) - get_resource(ensure_rb_extension(moduleName)) { - |zis| - eval(zis.read); $" << moduleName - } - return true - rescue Errno::ENOENT => ex - return false - end - - def get_resource(resourceName, &aProc) - zl = ZipList.new($:.grep(/\.zip$/)) - zl.get_input_stream(resourceName, &aProc) - end - - def already_loaded?(moduleName) - moduleRE = Regexp.new("^"+moduleName+"(\.rb|\.so|\.dll|\.o)?$") - $".detect { |e| e =~ moduleRE } != nil - end - - def ensure_rb_extension(aString) - aString.sub(/(\.rb)?$/i, ".rb") - end -end - -# Copyright (C) 2002 Thomas Sondergaard -# rubyzip is free software; you can redistribute it and/or -# modify it under the terms of the ruby license.