1505 lines
40 KiB
Text
1505 lines
40 KiB
Text
|
#!/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.
|