rubyzip 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubyzip might be problematic. Click here for more details.
- checksums.yaml +6 -14
- data/README.md +173 -42
- data/Rakefile +10 -5
- data/TODO +0 -1
- data/lib/zip/central_directory.rb +55 -24
- data/lib/zip/compressor.rb +0 -0
- data/lib/zip/constants.rb +4 -2
- data/lib/zip/crypto/encryption.rb +11 -0
- data/lib/zip/crypto/null_encryption.rb +45 -0
- data/lib/zip/crypto/traditional_encryption.rb +99 -0
- data/lib/zip/decompressor.rb +2 -2
- data/lib/zip/deflater.rb +11 -6
- data/lib/zip/dos_time.rb +4 -5
- data/lib/zip/entry.rb +159 -97
- data/lib/zip/entry_set.rb +18 -18
- data/lib/zip/errors.rb +15 -6
- data/lib/zip/extra_field/generic.rb +8 -8
- data/lib/zip/extra_field/ntfs.rb +90 -0
- data/lib/zip/extra_field/old_unix.rb +44 -0
- data/lib/zip/extra_field/universal_time.rb +14 -14
- data/lib/zip/extra_field/unix.rb +8 -9
- data/lib/zip/extra_field/zip64.rb +44 -6
- data/lib/zip/extra_field/zip64_placeholder.rb +16 -0
- data/lib/zip/extra_field.rb +20 -8
- data/lib/zip/file.rb +126 -114
- data/lib/zip/filesystem.rb +140 -139
- data/lib/zip/inflater.rb +10 -9
- data/lib/zip/input_stream.rb +105 -80
- data/lib/zip/ioextras/abstract_input_stream.rb +15 -12
- data/lib/zip/ioextras/abstract_output_stream.rb +0 -2
- data/lib/zip/ioextras.rb +1 -3
- data/lib/zip/null_compressor.rb +2 -2
- data/lib/zip/null_decompressor.rb +4 -4
- data/lib/zip/null_input_stream.rb +2 -1
- data/lib/zip/output_stream.rb +57 -43
- data/lib/zip/pass_thru_compressor.rb +4 -4
- data/lib/zip/pass_thru_decompressor.rb +4 -5
- data/lib/zip/streamable_directory.rb +2 -2
- data/lib/zip/streamable_stream.rb +22 -13
- data/lib/zip/version.rb +1 -1
- data/lib/zip.rb +11 -2
- data/samples/example.rb +30 -40
- data/samples/example_filesystem.rb +16 -18
- data/samples/example_recursive.rb +35 -27
- data/samples/{gtkRubyzip.rb → gtk_ruby_zip.rb} +25 -27
- data/samples/qtzip.rb +19 -28
- data/samples/write_simple.rb +12 -13
- data/samples/zipfind.rb +29 -37
- data/test/basic_zip_file_test.rb +60 -0
- data/test/case_sensitivity_test.rb +69 -0
- data/test/central_directory_entry_test.rb +69 -0
- data/test/central_directory_test.rb +100 -0
- data/test/crypto/null_encryption_test.rb +53 -0
- data/test/crypto/traditional_encryption_test.rb +80 -0
- data/test/data/WarnInvalidDate.zip +0 -0
- data/test/data/file1.txt +46 -0
- data/test/data/file1.txt.deflatedData +0 -0
- data/test/data/file2.txt +1504 -0
- data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
- data/test/data/globTest/foo.txt +0 -0
- data/test/data/globTest/food.txt +0 -0
- data/test/data/globTest.zip +0 -0
- data/test/data/mimetype +1 -0
- data/test/data/notzippedruby.rb +7 -0
- data/test/data/ntfs.zip +0 -0
- data/test/data/oddExtraField.zip +0 -0
- data/test/data/rubycode.zip +0 -0
- data/test/data/rubycode2.zip +0 -0
- data/test/data/test.xls +0 -0
- data/test/data/testDirectory.bin +0 -0
- data/test/data/zip64-sample.zip +0 -0
- data/test/data/zipWithDirs.zip +0 -0
- data/test/data/zipWithEncryption.zip +0 -0
- data/test/deflater_test.rb +65 -0
- data/test/encryption_test.rb +42 -0
- data/test/entry_set_test.rb +152 -0
- data/test/entry_test.rb +163 -0
- data/test/errors_test.rb +34 -0
- data/test/extra_field_test.rb +76 -0
- data/test/file_extract_directory_test.rb +54 -0
- data/test/file_extract_test.rb +83 -0
- data/test/file_permissions_test.rb +69 -0
- data/test/file_split_test.rb +57 -0
- data/test/file_test.rb +563 -0
- data/test/filesystem/dir_iterator_test.rb +58 -0
- data/test/filesystem/directory_test.rb +121 -0
- data/test/filesystem/file_mutating_test.rb +88 -0
- data/test/filesystem/file_nonmutating_test.rb +508 -0
- data/test/filesystem/file_stat_test.rb +64 -0
- data/test/gentestfiles.rb +122 -0
- data/test/inflater_test.rb +14 -0
- data/test/input_stream_test.rb +182 -0
- data/test/ioextras/abstract_input_stream_test.rb +102 -0
- data/test/ioextras/abstract_output_stream_test.rb +106 -0
- data/test/ioextras/fake_io_test.rb +18 -0
- data/test/local_entry_test.rb +154 -0
- data/test/output_stream_test.rb +128 -0
- data/test/pass_thru_compressor_test.rb +30 -0
- data/test/pass_thru_decompressor_test.rb +14 -0
- data/test/samples/example_recursive_test.rb +37 -0
- data/test/settings_test.rb +95 -0
- data/test/test_helper.rb +221 -0
- data/test/unicode_file_names_and_comments_test.rb +50 -0
- data/test/zip64_full_test.rb +51 -0
- data/test/zip64_support_test.rb +14 -0
- metadata +198 -22
- data/NEWS +0 -182
data/test/data/file2.txt
ADDED
@@ -0,0 +1,1504 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$VERBOSE = true
|
4
|
+
|
5
|
+
require 'rubyunit'
|
6
|
+
require 'zip'
|
7
|
+
|
8
|
+
include Zip
|
9
|
+
|
10
|
+
Dir.chdir "test"
|
11
|
+
|
12
|
+
class AbstractInputStreamTest < RUNIT::TestCase
|
13
|
+
# AbstractInputStream subclass that provides a read method
|
14
|
+
|
15
|
+
TEST_LINES = [ "Hello world#{$/}",
|
16
|
+
"this is the second line#{$/}",
|
17
|
+
"this is the last line"]
|
18
|
+
TEST_STRING = TEST_LINES.join
|
19
|
+
class TestAbstractInputStream
|
20
|
+
include AbstractInputStream
|
21
|
+
def initialize(aString)
|
22
|
+
@contents = aString
|
23
|
+
@readPointer = 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def read(charsToRead)
|
27
|
+
retVal=@contents[@readPointer, charsToRead]
|
28
|
+
@readPointer+=charsToRead
|
29
|
+
return retVal
|
30
|
+
end
|
31
|
+
|
32
|
+
def produceInput
|
33
|
+
read(100)
|
34
|
+
end
|
35
|
+
|
36
|
+
def inputFinished?
|
37
|
+
@contents[@readPointer] == nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup
|
42
|
+
@io = TestAbstractInputStream.new(TEST_STRING)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_gets
|
46
|
+
assert_equals(TEST_LINES[0], @io.gets)
|
47
|
+
assert_equals(TEST_LINES[1], @io.gets)
|
48
|
+
assert_equals(TEST_LINES[2], @io.gets)
|
49
|
+
assert_equals(nil, @io.gets)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_getsMultiCharSeperator
|
53
|
+
assert_equals("Hell", @io.gets("ll"))
|
54
|
+
assert_equals("o world#{$/}this is the second l", @io.gets("d l"))
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_each_line
|
58
|
+
lineNumber=0
|
59
|
+
@io.each_line {
|
60
|
+
|line|
|
61
|
+
assert_equals(TEST_LINES[lineNumber], line)
|
62
|
+
lineNumber+=1
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_readlines
|
67
|
+
assert_equals(TEST_LINES, @io.readlines)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_readline
|
71
|
+
test_gets
|
72
|
+
begin
|
73
|
+
@io.readline
|
74
|
+
fail "EOFError expected"
|
75
|
+
rescue EOFError
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class ZipEntryTest < RUNIT::TestCase
|
81
|
+
TEST_ZIPFILE = "someZipFile.zip"
|
82
|
+
TEST_COMMENT = "a comment"
|
83
|
+
TEST_COMPRESSED_SIZE = 1234
|
84
|
+
TEST_CRC = 325324
|
85
|
+
TEST_EXTRA = "Some data here"
|
86
|
+
TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED
|
87
|
+
TEST_NAME = "entry name"
|
88
|
+
TEST_SIZE = 8432
|
89
|
+
TEST_ISDIRECTORY = false
|
90
|
+
|
91
|
+
def test_constructorAndGetters
|
92
|
+
entry = ZipEntry.new(TEST_ZIPFILE,
|
93
|
+
TEST_NAME,
|
94
|
+
TEST_COMMENT,
|
95
|
+
TEST_EXTRA,
|
96
|
+
TEST_COMPRESSED_SIZE,
|
97
|
+
TEST_CRC,
|
98
|
+
TEST_COMPRESSIONMETHOD,
|
99
|
+
TEST_SIZE)
|
100
|
+
|
101
|
+
assert_equals(TEST_COMMENT, entry.comment)
|
102
|
+
assert_equals(TEST_COMPRESSED_SIZE, entry.compressedSize)
|
103
|
+
assert_equals(TEST_CRC, entry.crc)
|
104
|
+
assert_equals(TEST_EXTRA, entry.extra)
|
105
|
+
assert_equals(TEST_COMPRESSIONMETHOD, entry.compressionMethod)
|
106
|
+
assert_equals(TEST_NAME, entry.name)
|
107
|
+
assert_equals(TEST_SIZE, entry.size)
|
108
|
+
assert_equals(TEST_ISDIRECTORY, entry.isDirectory)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_equality
|
112
|
+
entry1 = ZipEntry.new("file.zip", "name", "isNotCompared",
|
113
|
+
"something extra", 123, 1234,
|
114
|
+
ZipEntry::DEFLATED, 10000)
|
115
|
+
entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX",
|
116
|
+
"something extra", 123, 1234,
|
117
|
+
ZipEntry::DEFLATED, 10000)
|
118
|
+
entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
|
119
|
+
"something extra", 123, 1234,
|
120
|
+
ZipEntry::DEFLATED, 10000)
|
121
|
+
entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
|
122
|
+
"something extraXX", 123, 1234,
|
123
|
+
ZipEntry::DEFLATED, 10000)
|
124
|
+
entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
|
125
|
+
"something extraXX", 12, 1234,
|
126
|
+
ZipEntry::DEFLATED, 10000)
|
127
|
+
entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
|
128
|
+
"something extraXX", 12, 123,
|
129
|
+
ZipEntry::DEFLATED, 10000)
|
130
|
+
entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
|
131
|
+
"something extraXX", 12, 123,
|
132
|
+
ZipEntry::STORED, 10000)
|
133
|
+
entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
|
134
|
+
"something extraXX", 12, 123,
|
135
|
+
ZipEntry::STORED, 100000)
|
136
|
+
|
137
|
+
assert_equals(entry1, entry1)
|
138
|
+
assert_equals(entry1, entry2)
|
139
|
+
|
140
|
+
assert(entry2 != entry3)
|
141
|
+
assert(entry3 != entry4)
|
142
|
+
assert(entry4 != entry5)
|
143
|
+
assert(entry5 != entry6)
|
144
|
+
assert(entry6 != entry7)
|
145
|
+
assert(entry7 != entry8)
|
146
|
+
|
147
|
+
assert(entry7 != "hello")
|
148
|
+
assert(entry7 != 12)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
module IOizeString
|
153
|
+
attr_reader :tell
|
154
|
+
|
155
|
+
def read(count = nil)
|
156
|
+
@tell ||= 0
|
157
|
+
count = size unless count
|
158
|
+
retVal = slice(@tell, count)
|
159
|
+
@tell += count
|
160
|
+
return retVal
|
161
|
+
end
|
162
|
+
|
163
|
+
def seek(index, offset)
|
164
|
+
@tell ||= 0
|
165
|
+
case offset
|
166
|
+
when IO::SEEK_END
|
167
|
+
newPos = size + index
|
168
|
+
when IO::SEEK_SET
|
169
|
+
newPos = index
|
170
|
+
when IO::SEEK_CUR
|
171
|
+
newPos = @tell + index
|
172
|
+
else
|
173
|
+
raise "Error in test method IOizeString::seek"
|
174
|
+
end
|
175
|
+
if (newPos < 0 || newPos >= size)
|
176
|
+
raise Errno::EINVAL
|
177
|
+
else
|
178
|
+
@tell=newPos
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def reset
|
183
|
+
@tell = 0
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class ZipLocalEntryTest < RUNIT::TestCase
|
188
|
+
def test_readLocalEntryHeaderOfFirstTestZipEntry
|
189
|
+
File.open(TestZipFile::TEST_ZIP3.zipName) {
|
190
|
+
|file|
|
191
|
+
entry = ZipEntry.readLocalEntry(file)
|
192
|
+
|
193
|
+
assert_equal("", entry.comment)
|
194
|
+
# Differs from windows and unix because of CR LF
|
195
|
+
# assert_equal(480, entry.compressedSize)
|
196
|
+
# assert_equal(0x2a27930f, entry.crc)
|
197
|
+
# extra field is 21 bytes long
|
198
|
+
# probably contains some unix attrutes or something
|
199
|
+
# disabled: assert_equal(nil, entry.extra)
|
200
|
+
assert_equal(ZipEntry::DEFLATED, entry.compressionMethod)
|
201
|
+
assert_equal(TestZipFile::TEST_ZIP3.entryNames[0], entry.name)
|
202
|
+
assert_equal(File.size(TestZipFile::TEST_ZIP3.entryNames[0]), entry.size)
|
203
|
+
assert(! entry.isDirectory)
|
204
|
+
}
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_readLocalEntryFromNonZipFile
|
208
|
+
File.open("ziptest.rb") {
|
209
|
+
|file|
|
210
|
+
assert_equals(nil, ZipEntry.readLocalEntry(file))
|
211
|
+
}
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_readLocalEntryFromTruncatedZipFile
|
215
|
+
zipFragment=""
|
216
|
+
File.open(TestZipFile::TEST_ZIP2.zipName) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes
|
217
|
+
zipFragment.extend(IOizeString).reset
|
218
|
+
entry = ZipEntry.new
|
219
|
+
entry.readLocalEntry(zipFragment)
|
220
|
+
fail "ZipError expected"
|
221
|
+
rescue ZipError
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_writeEntry
|
225
|
+
entry = ZipEntry.new("file.zip", "entryName", "my little comment",
|
226
|
+
"thisIsSomeExtraInformation", 100, 987654,
|
227
|
+
ZipEntry::DEFLATED, 400)
|
228
|
+
writeToFile("localEntryHeader.bin", "centralEntryHeader.bin", entry)
|
229
|
+
entryReadLocal, entryReadCentral = readFromFile("localEntryHeader.bin", "centralEntryHeader.bin")
|
230
|
+
compareLocalEntryHeaders(entry, entryReadLocal)
|
231
|
+
compareCDirEntryHeaders(entry, entryReadCentral)
|
232
|
+
end
|
233
|
+
|
234
|
+
private
|
235
|
+
def compareLocalEntryHeaders(entry1, entry2)
|
236
|
+
assert_equals(entry1.compressedSize , entry2.compressedSize)
|
237
|
+
assert_equals(entry1.crc , entry2.crc)
|
238
|
+
assert_equals(entry1.extra , entry2.extra)
|
239
|
+
assert_equals(entry1.compressionMethod, entry2.compressionMethod)
|
240
|
+
assert_equals(entry1.name , entry2.name)
|
241
|
+
assert_equals(entry1.size , entry2.size)
|
242
|
+
assert_equals(entry1.localHeaderOffset, entry2.localHeaderOffset)
|
243
|
+
end
|
244
|
+
|
245
|
+
def compareCDirEntryHeaders(entry1, entry2)
|
246
|
+
compareLocalEntryHeaders(entry1, entry2)
|
247
|
+
assert_equals(entry1.comment, entry2.comment)
|
248
|
+
end
|
249
|
+
|
250
|
+
def writeToFile(localFileName, centralFileName, entry)
|
251
|
+
File.open(localFileName, "wb") { |f| entry.writeLocalEntry(f) }
|
252
|
+
File.open(centralFileName, "wb") { |f| entry.writeCDirEntry(f) }
|
253
|
+
end
|
254
|
+
|
255
|
+
def readFromFile(localFileName, centralFileName)
|
256
|
+
localEntry = nil
|
257
|
+
cdirEntry = nil
|
258
|
+
File.open(localFileName, "rb") { |f| localEntry = ZipEntry.readLocalEntry(f) }
|
259
|
+
File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.readCDirEntry(f) }
|
260
|
+
return [localEntry, cdirEntry]
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
|
265
|
+
module DecompressorTests
|
266
|
+
# expects @refText and @decompressor
|
267
|
+
|
268
|
+
def test_readEverything
|
269
|
+
assert_equals(@refText, @decompressor.read)
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_readInChunks
|
273
|
+
chunkSize = 5
|
274
|
+
while (decompressedChunk = @decompressor.read(chunkSize))
|
275
|
+
assert_equals(@refText.slice!(0, chunkSize), decompressedChunk)
|
276
|
+
end
|
277
|
+
assert_equals(0, @refText.size)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
class InflaterTest < RUNIT::TestCase
|
282
|
+
include DecompressorTests
|
283
|
+
|
284
|
+
def setup
|
285
|
+
@file = File.new("file1.txt.deflatedData", "rb")
|
286
|
+
@refText=""
|
287
|
+
File.open("file1.txt") { |f| @refText = f.read }
|
288
|
+
@decompressor = Inflater.new(@file)
|
289
|
+
end
|
290
|
+
|
291
|
+
def teardown
|
292
|
+
@file.close
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
|
297
|
+
class PassThruDecompressorTest < RUNIT::TestCase
|
298
|
+
include DecompressorTests
|
299
|
+
TEST_FILE="file1.txt"
|
300
|
+
def setup
|
301
|
+
@file = File.new(TEST_FILE)
|
302
|
+
@refText=""
|
303
|
+
File.open(TEST_FILE) { |f| @refText = f.read }
|
304
|
+
@decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE))
|
305
|
+
end
|
306
|
+
|
307
|
+
def teardown
|
308
|
+
@file.close
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
|
313
|
+
module AssertEntry
|
314
|
+
def assertNextEntry(filename, zis)
|
315
|
+
assertEntry(filename, zis, zis.getNextEntry.name)
|
316
|
+
end
|
317
|
+
|
318
|
+
def assertEntry(filename, zis, entryName)
|
319
|
+
assert_equals(filename, entryName)
|
320
|
+
assertEntryContentsForStream(filename, zis, entryName)
|
321
|
+
end
|
322
|
+
|
323
|
+
def assertEntryContentsForStream(filename, zis, entryName)
|
324
|
+
File.open(filename, "rb") {
|
325
|
+
|file|
|
326
|
+
expected = file.read
|
327
|
+
actual = zis.read
|
328
|
+
if (expected != actual)
|
329
|
+
if (expected.length > 400 || actual.length > 400)
|
330
|
+
zipEntryFilename=entryName+".zipEntry"
|
331
|
+
File.open(zipEntryFilename, "wb") { |file| file << actual }
|
332
|
+
fail("File '#{filename}' is different from '#{zipEntryFilename}'")
|
333
|
+
else
|
334
|
+
assert_equals(expected, actual)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
}
|
338
|
+
end
|
339
|
+
|
340
|
+
def AssertEntry.assertContents(filename, aString)
|
341
|
+
fileContents = ""
|
342
|
+
File.open(filename, "rb") { |f| fileContents = f.read }
|
343
|
+
if (fileContents != aString)
|
344
|
+
if (expected.length > 400 || actual.length > 400)
|
345
|
+
stringFile = filename + ".other"
|
346
|
+
File.open(stringFile, "wb") { |f| f << aString }
|
347
|
+
fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'")
|
348
|
+
else
|
349
|
+
assert_equals(expected, actual)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def assertStreamContents(zis, testZipFile)
|
355
|
+
assert(zis != nil)
|
356
|
+
testZipFile.entryNames.each {
|
357
|
+
|entryName|
|
358
|
+
assertNextEntry(entryName, zis)
|
359
|
+
}
|
360
|
+
assert_equals(nil, zis.getNextEntry)
|
361
|
+
end
|
362
|
+
|
363
|
+
def assertTestZipContents(testZipFile)
|
364
|
+
ZipInputStream.open(testZipFile.zipName) {
|
365
|
+
|zis|
|
366
|
+
assertStreamContents(zis, testZipFile)
|
367
|
+
}
|
368
|
+
end
|
369
|
+
|
370
|
+
def assertEntryContents(zipFile, entryName, filename = entryName.to_s)
|
371
|
+
zis = zipFile.getInputStream(entryName)
|
372
|
+
assertEntryContentsForStream(filename, zis, entryName)
|
373
|
+
ensure
|
374
|
+
zis.close if zis
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
|
379
|
+
|
380
|
+
class ZipInputStreamTest < RUNIT::TestCase
|
381
|
+
include AssertEntry
|
382
|
+
|
383
|
+
def test_new
|
384
|
+
zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zipName)
|
385
|
+
assertStreamContents(zis, TestZipFile::TEST_ZIP2)
|
386
|
+
zis.close
|
387
|
+
end
|
388
|
+
|
389
|
+
def test_openWithBlock
|
390
|
+
ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) {
|
391
|
+
|zis|
|
392
|
+
assertStreamContents(zis, TestZipFile::TEST_ZIP2)
|
393
|
+
}
|
394
|
+
end
|
395
|
+
|
396
|
+
def test_openWithoutBlock
|
397
|
+
zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName)
|
398
|
+
assertStreamContents(zis, TestZipFile::TEST_ZIP2)
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_incompleteReads
|
402
|
+
ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) {
|
403
|
+
|zis|
|
404
|
+
entry = zis.getNextEntry
|
405
|
+
assert_equals(TestZipFile::TEST_ZIP2.entryNames[0], entry.name)
|
406
|
+
assert zis.gets.length > 0
|
407
|
+
entry = zis.getNextEntry
|
408
|
+
assert_equals(TestZipFile::TEST_ZIP2.entryNames[1], entry.name)
|
409
|
+
assert_equals(0, entry.size)
|
410
|
+
assert_equals(nil, zis.gets)
|
411
|
+
entry = zis.getNextEntry
|
412
|
+
assert_equals(TestZipFile::TEST_ZIP2.entryNames[2], entry.name)
|
413
|
+
assert zis.gets.length > 0
|
414
|
+
entry = zis.getNextEntry
|
415
|
+
assert_equals(TestZipFile::TEST_ZIP2.entryNames[3], entry.name)
|
416
|
+
assert zis.gets.length > 0
|
417
|
+
}
|
418
|
+
end
|
419
|
+
|
420
|
+
end
|
421
|
+
|
422
|
+
class TestFiles
|
423
|
+
RANDOM_ASCII_FILE1 = "randomAscii1.txt"
|
424
|
+
RANDOM_ASCII_FILE2 = "randomAscii2.txt"
|
425
|
+
RANDOM_ASCII_FILE3 = "randomAscii3.txt"
|
426
|
+
RANDOM_BINARY_FILE1 = "randomBinary1.bin"
|
427
|
+
RANDOM_BINARY_FILE2 = "randomBinary2.bin"
|
428
|
+
|
429
|
+
EMPTY_TEST_DIR = "emptytestdir"
|
430
|
+
|
431
|
+
ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ]
|
432
|
+
BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ]
|
433
|
+
TEST_DIRECTORIES = [ EMPTY_TEST_DIR ]
|
434
|
+
TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten!
|
435
|
+
|
436
|
+
def TestFiles.createTestFiles(recreate)
|
437
|
+
if (recreate ||
|
438
|
+
! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) }))
|
439
|
+
|
440
|
+
ASCII_TEST_FILES.each_with_index {
|
441
|
+
|filename, index|
|
442
|
+
createRandomAscii(filename, 1E4 * (index+1))
|
443
|
+
}
|
444
|
+
|
445
|
+
BINARY_TEST_FILES.each_with_index {
|
446
|
+
|filename, index|
|
447
|
+
createRandomBinary(filename, 1E4 * (index+1))
|
448
|
+
}
|
449
|
+
|
450
|
+
ensureDir(EMPTY_TEST_DIR)
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
private
|
455
|
+
def TestFiles.createRandomAscii(filename, size)
|
456
|
+
File.open(filename, "wb") {
|
457
|
+
|file|
|
458
|
+
while (file.tell < size)
|
459
|
+
file << rand
|
460
|
+
end
|
461
|
+
}
|
462
|
+
end
|
463
|
+
|
464
|
+
def TestFiles.createRandomBinary(filename, size)
|
465
|
+
File.open(filename, "wb") {
|
466
|
+
|file|
|
467
|
+
while (file.tell < size)
|
468
|
+
file << rand.to_a.pack("V")
|
469
|
+
end
|
470
|
+
}
|
471
|
+
end
|
472
|
+
|
473
|
+
def TestFiles.ensureDir(name)
|
474
|
+
if File.exists?(name)
|
475
|
+
return if File.stat(name).directory?
|
476
|
+
File.delete(name)
|
477
|
+
end
|
478
|
+
Dir.mkdir(name)
|
479
|
+
end
|
480
|
+
|
481
|
+
end
|
482
|
+
|
483
|
+
# For representation and creation of
|
484
|
+
# test data
|
485
|
+
class TestZipFile
|
486
|
+
attr_accessor :zipName, :entryNames, :comment
|
487
|
+
|
488
|
+
def initialize(zipName, entryNames, comment = "")
|
489
|
+
@zipName=zipName
|
490
|
+
@entryNames=entryNames
|
491
|
+
@comment = comment
|
492
|
+
end
|
493
|
+
|
494
|
+
def TestZipFile.createTestZips(recreate)
|
495
|
+
files = Dir.entries(".")
|
496
|
+
if (recreate ||
|
497
|
+
! (files.index(TEST_ZIP1.zipName) &&
|
498
|
+
files.index(TEST_ZIP2.zipName) &&
|
499
|
+
files.index(TEST_ZIP3.zipName) &&
|
500
|
+
files.index(TEST_ZIP4.zipName) &&
|
501
|
+
files.index("empty.txt") &&
|
502
|
+
files.index("short.txt") &&
|
503
|
+
files.index("longAscii.txt") &&
|
504
|
+
files.index("longBinary.bin") ))
|
505
|
+
raise "failed to create test zip '#{TEST_ZIP1.zipName}'" unless
|
506
|
+
system("zip #{TEST_ZIP1.zipName} ziptest.rb")
|
507
|
+
raise "failed to remove entry from '#{TEST_ZIP1.zipName}'" unless
|
508
|
+
system("zip #{TEST_ZIP1.zipName} -d ziptest.rb")
|
509
|
+
|
510
|
+
File.open("empty.txt", "w") {}
|
511
|
+
|
512
|
+
File.open("short.txt", "w") { |file| file << "ABCDEF" }
|
513
|
+
ziptestTxt=""
|
514
|
+
File.open("ziptest.rb") { |file| ziptestTxt=file.read }
|
515
|
+
File.open("longAscii.txt", "w") {
|
516
|
+
|file|
|
517
|
+
while (file.tell < 1E5)
|
518
|
+
file << ziptestTxt
|
519
|
+
end
|
520
|
+
}
|
521
|
+
|
522
|
+
testBinaryPattern=""
|
523
|
+
File.open("empty.zip") { |file| testBinaryPattern=file.read }
|
524
|
+
testBinaryPattern *= 4
|
525
|
+
|
526
|
+
File.open("longBinary.bin", "wb") {
|
527
|
+
|file|
|
528
|
+
while (file.tell < 3E5)
|
529
|
+
file << testBinaryPattern << rand
|
530
|
+
end
|
531
|
+
}
|
532
|
+
raise "failed to create test zip '#{TEST_ZIP2.zipName}'" unless
|
533
|
+
system("zip #{TEST_ZIP2.zipName} #{TEST_ZIP2.entryNames.join(' ')}")
|
534
|
+
|
535
|
+
# without bash system interprets everything after echo as parameters to
|
536
|
+
# echo including | zip -z ...
|
537
|
+
raise "failed to add comment to test zip '#{TEST_ZIP2.zipName}'" unless
|
538
|
+
system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zipName}\"")
|
539
|
+
|
540
|
+
raise "failed to create test zip '#{TEST_ZIP3.zipName}'" unless
|
541
|
+
system("zip #{TEST_ZIP3.zipName} #{TEST_ZIP3.entryNames.join(' ')}")
|
542
|
+
|
543
|
+
raise "failed to create test zip '#{TEST_ZIP4.zipName}'" unless
|
544
|
+
system("zip #{TEST_ZIP4.zipName} #{TEST_ZIP4.entryNames.join(' ')}")
|
545
|
+
end
|
546
|
+
rescue
|
547
|
+
raise $!.to_s +
|
548
|
+
"\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" +
|
549
|
+
"to create test data. If you don't have it you can download\n" +
|
550
|
+
"the necessary test files at http://sf.net/projects/rubyzip."
|
551
|
+
end
|
552
|
+
|
553
|
+
TEST_ZIP1 = TestZipFile.new("empty.zip", [])
|
554
|
+
TEST_ZIP2 = TestZipFile.new("4entry.zip", %w{ longAscii.txt empty.txt short.txt longBinary.bin},
|
555
|
+
"my zip comment")
|
556
|
+
TEST_ZIP3 = TestZipFile.new("test1.zip", %w{ file1.txt })
|
557
|
+
TEST_ZIP4 = TestZipFile.new("zipWithDir.zip", [ "file1.txt",
|
558
|
+
TestFiles::EMPTY_TEST_DIR])
|
559
|
+
end
|
560
|
+
|
561
|
+
|
562
|
+
class AbstractOutputStreamTest < RUNIT::TestCase
|
563
|
+
class TestOutputStream
|
564
|
+
include AbstractOutputStream
|
565
|
+
|
566
|
+
attr_accessor :buffer
|
567
|
+
|
568
|
+
def initialize
|
569
|
+
@buffer = ""
|
570
|
+
end
|
571
|
+
|
572
|
+
def << (data)
|
573
|
+
@buffer << data
|
574
|
+
self
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
578
|
+
def setup
|
579
|
+
@outputStream = TestOutputStream.new
|
580
|
+
|
581
|
+
@origCommaSep = $,
|
582
|
+
@origOutputSep = $\
|
583
|
+
end
|
584
|
+
|
585
|
+
def teardown
|
586
|
+
$, = @origCommaSep
|
587
|
+
$\ = @origOutputSep
|
588
|
+
end
|
589
|
+
|
590
|
+
def test_write
|
591
|
+
count = @outputStream.write("a little string")
|
592
|
+
assert_equals("a little string", @outputStream.buffer)
|
593
|
+
assert_equals("a little string".length, count)
|
594
|
+
|
595
|
+
count = @outputStream.write(". a little more")
|
596
|
+
assert_equals("a little string. a little more", @outputStream.buffer)
|
597
|
+
assert_equals(". a little more".length, count)
|
598
|
+
end
|
599
|
+
|
600
|
+
def test_print
|
601
|
+
$\ = nil # record separator set to nil
|
602
|
+
@outputStream.print("hello")
|
603
|
+
assert_equals("hello", @outputStream.buffer)
|
604
|
+
|
605
|
+
@outputStream.print(" world.")
|
606
|
+
assert_equals("hello world.", @outputStream.buffer)
|
607
|
+
|
608
|
+
@outputStream.print(" You ok ", "out ", "there?")
|
609
|
+
assert_equals("hello world. You ok out there?", @outputStream.buffer)
|
610
|
+
|
611
|
+
$\ = "\n"
|
612
|
+
@outputStream.print
|
613
|
+
assert_equals("hello world. You ok out there?\n", @outputStream.buffer)
|
614
|
+
|
615
|
+
@outputStream.print("I sure hope so!")
|
616
|
+
assert_equals("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer)
|
617
|
+
|
618
|
+
$, = "X"
|
619
|
+
@outputStream.buffer = ""
|
620
|
+
@outputStream.print("monkey", "duck", "zebra")
|
621
|
+
assert_equals("monkeyXduckXzebra\n", @outputStream.buffer)
|
622
|
+
|
623
|
+
$\ = nil
|
624
|
+
@outputStream.buffer = ""
|
625
|
+
@outputStream.print(20)
|
626
|
+
assert_equals("20", @outputStream.buffer)
|
627
|
+
end
|
628
|
+
|
629
|
+
def test_printf
|
630
|
+
@outputStream.printf("%d %04x", 123, 123)
|
631
|
+
assert_equals("123 007b", @outputStream.buffer)
|
632
|
+
end
|
633
|
+
|
634
|
+
def test_putc
|
635
|
+
@outputStream.putc("A")
|
636
|
+
assert_equals("A", @outputStream.buffer)
|
637
|
+
@outputStream.putc(65)
|
638
|
+
assert_equals("AA", @outputStream.buffer)
|
639
|
+
end
|
640
|
+
|
641
|
+
def test_puts
|
642
|
+
@outputStream.puts
|
643
|
+
assert_equals("\n", @outputStream.buffer)
|
644
|
+
|
645
|
+
@outputStream.puts("hello", "world")
|
646
|
+
assert_equals("\nhello\nworld\n", @outputStream.buffer)
|
647
|
+
|
648
|
+
@outputStream.buffer = ""
|
649
|
+
@outputStream.puts("hello\n", "world\n")
|
650
|
+
assert_equals("hello\nworld\n", @outputStream.buffer)
|
651
|
+
|
652
|
+
@outputStream.buffer = ""
|
653
|
+
@outputStream.puts(["hello\n", "world\n"])
|
654
|
+
assert_equals("hello\nworld\n", @outputStream.buffer)
|
655
|
+
|
656
|
+
@outputStream.buffer = ""
|
657
|
+
@outputStream.puts(["hello\n", "world\n"], "bingo")
|
658
|
+
assert_equals("hello\nworld\nbingo\n", @outputStream.buffer)
|
659
|
+
|
660
|
+
@outputStream.buffer = ""
|
661
|
+
@outputStream.puts(16, 20, 50, "hello")
|
662
|
+
assert_equals("16\n20\n50\nhello\n", @outputStream.buffer)
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
|
667
|
+
module CrcTest
|
668
|
+
def runCrcTest(compressorClass)
|
669
|
+
str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed."
|
670
|
+
fakeOut = AbstractOutputStreamTest::TestOutputStream.new
|
671
|
+
|
672
|
+
deflater = compressorClass.new(fakeOut)
|
673
|
+
deflater << str
|
674
|
+
assert_equals(0x919920fc, deflater.crc)
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
|
679
|
+
|
680
|
+
class PassThruCompressorTest < RUNIT::TestCase
|
681
|
+
include CrcTest
|
682
|
+
|
683
|
+
def test_size
|
684
|
+
File.open("dummy.txt", "wb") {
|
685
|
+
|file|
|
686
|
+
compressor = PassThruCompressor.new(file)
|
687
|
+
|
688
|
+
assert_equals(0, compressor.size)
|
689
|
+
|
690
|
+
t1 = "hello world"
|
691
|
+
t2 = ""
|
692
|
+
t3 = "bingo"
|
693
|
+
|
694
|
+
compressor << t1
|
695
|
+
assert_equals(compressor.size, t1.size)
|
696
|
+
|
697
|
+
compressor << t2
|
698
|
+
assert_equals(compressor.size, t1.size + t2.size)
|
699
|
+
|
700
|
+
compressor << t3
|
701
|
+
assert_equals(compressor.size, t1.size + t2.size + t3.size)
|
702
|
+
}
|
703
|
+
end
|
704
|
+
|
705
|
+
def test_crc
|
706
|
+
runCrcTest(PassThruCompressor)
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
710
|
+
class DeflaterTest < RUNIT::TestCase
|
711
|
+
include CrcTest
|
712
|
+
|
713
|
+
def test_outputOperator
|
714
|
+
txt = loadFile("ziptest.rb")
|
715
|
+
deflate(txt, "deflatertest.bin")
|
716
|
+
inflatedTxt = inflate("deflatertest.bin")
|
717
|
+
assert_equals(txt, inflatedTxt)
|
718
|
+
end
|
719
|
+
|
720
|
+
private
|
721
|
+
def loadFile(fileName)
|
722
|
+
txt = nil
|
723
|
+
File.open(fileName, "rb") { |f| txt = f.read }
|
724
|
+
end
|
725
|
+
|
726
|
+
def deflate(data, fileName)
|
727
|
+
File.open(fileName, "wb") {
|
728
|
+
|file|
|
729
|
+
deflater = Deflater.new(file)
|
730
|
+
deflater << data
|
731
|
+
deflater.finish
|
732
|
+
assert_equals(deflater.size, data.size)
|
733
|
+
file << "trailing data for zlib with -MAX_WBITS"
|
734
|
+
}
|
735
|
+
end
|
736
|
+
|
737
|
+
def inflate(fileName)
|
738
|
+
txt = nil
|
739
|
+
File.open(fileName, "rb") {
|
740
|
+
|file|
|
741
|
+
inflater = Inflater.new(file)
|
742
|
+
txt = inflater.read
|
743
|
+
}
|
744
|
+
end
|
745
|
+
|
746
|
+
def test_crc
|
747
|
+
runCrcTest(Deflater)
|
748
|
+
end
|
749
|
+
end
|
750
|
+
|
751
|
+
class ZipOutputStreamTest < RUNIT::TestCase
|
752
|
+
include AssertEntry
|
753
|
+
|
754
|
+
TEST_ZIP = TestZipFile::TEST_ZIP2.clone
|
755
|
+
TEST_ZIP.zipName = "output.zip"
|
756
|
+
|
757
|
+
def test_new
|
758
|
+
zos = ZipOutputStream.new(TEST_ZIP.zipName)
|
759
|
+
zos.comment = TEST_ZIP.comment
|
760
|
+
writeTestZip(zos)
|
761
|
+
zos.close
|
762
|
+
assertTestZipContents(TEST_ZIP)
|
763
|
+
end
|
764
|
+
|
765
|
+
def test_open
|
766
|
+
ZipOutputStream.open(TEST_ZIP.zipName) {
|
767
|
+
|zos|
|
768
|
+
zos.comment = TEST_ZIP.comment
|
769
|
+
writeTestZip(zos)
|
770
|
+
}
|
771
|
+
assertTestZipContents(TEST_ZIP)
|
772
|
+
end
|
773
|
+
|
774
|
+
def test_writingToClosedStream
|
775
|
+
assertIOErrorInClosedStream { |zos| zos << "hello world" }
|
776
|
+
assertIOErrorInClosedStream { |zos| zos.puts "hello world" }
|
777
|
+
assertIOErrorInClosedStream { |zos| zos.write "hello world" }
|
778
|
+
end
|
779
|
+
|
780
|
+
def test_cannotOpenFile
|
781
|
+
name = TestFiles::EMPTY_TEST_DIR
|
782
|
+
begin
|
783
|
+
zos = ZipOutputStream.open(name)
|
784
|
+
rescue Exception
|
785
|
+
assert($!.kind_of?(Errno::EISDIR) || # Linux
|
786
|
+
$!.kind_of?(Errno::EEXIST) || # Windows/cygwin
|
787
|
+
$!.kind_of?(Errno::EACCES), # Windows
|
788
|
+
"Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.type}")
|
789
|
+
end
|
790
|
+
end
|
791
|
+
|
792
|
+
def assertIOErrorInClosedStream
|
793
|
+
assert_exception(IOError) {
|
794
|
+
zos = ZipOutputStream.new("test_putOnClosedStream.zip")
|
795
|
+
zos.close
|
796
|
+
yield zos
|
797
|
+
}
|
798
|
+
end
|
799
|
+
|
800
|
+
def writeTestZip(zos)
|
801
|
+
TEST_ZIP.entryNames.each {
|
802
|
+
|entryName|
|
803
|
+
zos.putNextEntry(entryName)
|
804
|
+
File.open(entryName, "rb") { |f| zos.write(f.read) }
|
805
|
+
}
|
806
|
+
end
|
807
|
+
end
|
808
|
+
|
809
|
+
|
810
|
+
|
811
|
+
module Enumerable
|
812
|
+
def compareEnumerables(otherEnumerable)
|
813
|
+
otherAsArray = otherEnumerable.to_a
|
814
|
+
index=0
|
815
|
+
each_with_index {
|
816
|
+
|element, index|
|
817
|
+
return false unless yield(element, otherAsArray[index])
|
818
|
+
}
|
819
|
+
return index+1 == otherAsArray.size
|
820
|
+
end
|
821
|
+
end
|
822
|
+
|
823
|
+
|
824
|
+
class ZipCentralDirectoryEntryTest < RUNIT::TestCase
|
825
|
+
|
826
|
+
def test_readFromStream
|
827
|
+
File.open("testDirectory.bin", "rb") {
|
828
|
+
|file|
|
829
|
+
entry = ZipEntry.readCDirEntry(file)
|
830
|
+
|
831
|
+
assert_equals("longAscii.txt", entry.name)
|
832
|
+
assert_equals(ZipEntry::DEFLATED, entry.compressionMethod)
|
833
|
+
assert_equals(106490, entry.size)
|
834
|
+
assert_equals(3784, entry.compressedSize)
|
835
|
+
assert_equals(0xfcd1799c, entry.crc)
|
836
|
+
assert_equals("", entry.comment)
|
837
|
+
|
838
|
+
entry = ZipEntry.readCDirEntry(file)
|
839
|
+
assert_equals("empty.txt", entry.name)
|
840
|
+
assert_equals(ZipEntry::STORED, entry.compressionMethod)
|
841
|
+
assert_equals(0, entry.size)
|
842
|
+
assert_equals(0, entry.compressedSize)
|
843
|
+
assert_equals(0x0, entry.crc)
|
844
|
+
assert_equals("", entry.comment)
|
845
|
+
|
846
|
+
entry = ZipEntry.readCDirEntry(file)
|
847
|
+
assert_equals("short.txt", entry.name)
|
848
|
+
assert_equals(ZipEntry::STORED, entry.compressionMethod)
|
849
|
+
assert_equals(6, entry.size)
|
850
|
+
assert_equals(6, entry.compressedSize)
|
851
|
+
assert_equals(0xbb76fe69, entry.crc)
|
852
|
+
assert_equals("", entry.comment)
|
853
|
+
|
854
|
+
entry = ZipEntry.readCDirEntry(file)
|
855
|
+
assert_equals("longBinary.bin", entry.name)
|
856
|
+
assert_equals(ZipEntry::DEFLATED, entry.compressionMethod)
|
857
|
+
assert_equals(1000024, entry.size)
|
858
|
+
assert_equals(70847, entry.compressedSize)
|
859
|
+
assert_equals(0x10da7d59, entry.crc)
|
860
|
+
assert_equals("", entry.comment)
|
861
|
+
|
862
|
+
entry = ZipEntry.readCDirEntry(file)
|
863
|
+
assert_equals(nil, entry)
|
864
|
+
# Fields that are not check by this test:
|
865
|
+
# version made by 2 bytes
|
866
|
+
# version needed to extract 2 bytes
|
867
|
+
# general purpose bit flag 2 bytes
|
868
|
+
# last mod file time 2 bytes
|
869
|
+
# last mod file date 2 bytes
|
870
|
+
# compressed size 4 bytes
|
871
|
+
# uncompressed size 4 bytes
|
872
|
+
# disk number start 2 bytes
|
873
|
+
# internal file attributes 2 bytes
|
874
|
+
# external file attributes 4 bytes
|
875
|
+
# relative offset of local header 4 bytes
|
876
|
+
|
877
|
+
# file name (variable size)
|
878
|
+
# extra field (variable size)
|
879
|
+
# file comment (variable size)
|
880
|
+
|
881
|
+
}
|
882
|
+
end
|
883
|
+
|
884
|
+
def test_ReadEntryFromTruncatedZipFile
|
885
|
+
fragment=""
|
886
|
+
File.open("testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes
|
887
|
+
fragment.extend(IOizeString)
|
888
|
+
entry = ZipEntry.new
|
889
|
+
entry.readCDirEntry(fragment)
|
890
|
+
fail "ZipError expected"
|
891
|
+
rescue ZipError
|
892
|
+
end
|
893
|
+
|
894
|
+
end
|
895
|
+
|
896
|
+
class ZipCentralDirectoryTest < RUNIT::TestCase
|
897
|
+
|
898
|
+
def test_readFromStream
|
899
|
+
File.open(TestZipFile::TEST_ZIP2.zipName, "rb") {
|
900
|
+
|zipFile|
|
901
|
+
cdir = ZipCentralDirectory.readFromStream(zipFile)
|
902
|
+
|
903
|
+
assert_equals(TestZipFile::TEST_ZIP2.entryNames.size, cdir.size)
|
904
|
+
assert(cdir.compareEnumerables(TestZipFile::TEST_ZIP2.entryNames) {
|
905
|
+
|cdirEntry, testEntryName|
|
906
|
+
cdirEntry.name == testEntryName
|
907
|
+
})
|
908
|
+
assert_equals(TestZipFile::TEST_ZIP2.comment, cdir.comment)
|
909
|
+
}
|
910
|
+
end
|
911
|
+
|
912
|
+
def test_readFromInvalidStream
|
913
|
+
File.open("ziptest.rb", "rb") {
|
914
|
+
|zipFile|
|
915
|
+
cdir = ZipCentralDirectory.new
|
916
|
+
cdir.readFromStream(zipFile)
|
917
|
+
}
|
918
|
+
fail "ZipError expected!"
|
919
|
+
rescue ZipError
|
920
|
+
end
|
921
|
+
|
922
|
+
def test_ReadFromTruncatedZipFile
|
923
|
+
fragment=""
|
924
|
+
File.open("testDirectory.bin") { |f| fragment = f.read }
|
925
|
+
fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete
|
926
|
+
fragment.extend(IOizeString)
|
927
|
+
entry = ZipCentralDirectory.new
|
928
|
+
entry.readFromStream(fragment)
|
929
|
+
fail "ZipError expected"
|
930
|
+
rescue ZipError
|
931
|
+
end
|
932
|
+
|
933
|
+
def test_writeToStream
|
934
|
+
entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"),
|
935
|
+
ZipEntry.new("file.zip", "secondEntryName"),
|
936
|
+
ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ]
|
937
|
+
cdir = ZipCentralDirectory.new(entries, "my zip comment")
|
938
|
+
File.open("cdirtest.bin", "wb") { |f| cdir.writeToStream(f) }
|
939
|
+
cdirReadback = ZipCentralDirectory.new
|
940
|
+
File.open("cdirtest.bin", "rb") { |f| cdirReadback.readFromStream(f) }
|
941
|
+
|
942
|
+
assert_equals(cdir.entries, cdirReadback.entries)
|
943
|
+
end
|
944
|
+
|
945
|
+
def test_equality
|
946
|
+
cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
|
947
|
+
"somethingExtra"),
|
948
|
+
ZipEntry.new("file.zip", "secondEntryName"),
|
949
|
+
ZipEntry.new("file.zip", "lastEntry.txt") ],
|
950
|
+
"my zip comment")
|
951
|
+
cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
|
952
|
+
"somethingExtra"),
|
953
|
+
ZipEntry.new("file.zip", "secondEntryName"),
|
954
|
+
ZipEntry.new("file.zip", "lastEntry.txt") ],
|
955
|
+
"my zip comment")
|
956
|
+
cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
|
957
|
+
"somethingExtra"),
|
958
|
+
ZipEntry.new("file.zip", "secondEntryName"),
|
959
|
+
ZipEntry.new("file.zip", "lastEntry.txt") ],
|
960
|
+
"comment?")
|
961
|
+
cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
|
962
|
+
"somethingExtra"),
|
963
|
+
ZipEntry.new("file.zip", "lastEntry.txt") ],
|
964
|
+
"comment?")
|
965
|
+
assert_equals(cdir1, cdir1)
|
966
|
+
assert_equals(cdir1, cdir2)
|
967
|
+
|
968
|
+
assert(cdir1 != cdir3)
|
969
|
+
assert(cdir2 != cdir3)
|
970
|
+
assert(cdir2 != cdir3)
|
971
|
+
assert(cdir3 != cdir4)
|
972
|
+
|
973
|
+
assert(cdir3 != "hello")
|
974
|
+
end
|
975
|
+
end
|
976
|
+
|
977
|
+
|
978
|
+
class BasicZipFileTest < RUNIT::TestCase
|
979
|
+
include AssertEntry
|
980
|
+
|
981
|
+
def setup
|
982
|
+
@zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zipName)
|
983
|
+
@testEntryNameIndex=0
|
984
|
+
end
|
985
|
+
|
986
|
+
def nextTestEntryName
|
987
|
+
retVal=TestZipFile::TEST_ZIP2.entryNames[@testEntryNameIndex]
|
988
|
+
@testEntryNameIndex+=1
|
989
|
+
return retVal
|
990
|
+
end
|
991
|
+
|
992
|
+
def test_entries
|
993
|
+
assert_equals(TestZipFile::TEST_ZIP2.entryNames, @zipFile.entries.map {|e| e.name} )
|
994
|
+
end
|
995
|
+
|
996
|
+
def test_each
|
997
|
+
@zipFile.each {
|
998
|
+
|entry|
|
999
|
+
assert_equals(nextTestEntryName, entry.name)
|
1000
|
+
}
|
1001
|
+
assert_equals(4, @testEntryNameIndex)
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
def test_foreach
|
1005
|
+
ZipFile.foreach(TestZipFile::TEST_ZIP2.zipName) {
|
1006
|
+
|entry|
|
1007
|
+
assert_equals(nextTestEntryName, entry.name)
|
1008
|
+
}
|
1009
|
+
assert_equals(4, @testEntryNameIndex)
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
def test_getInputStream
|
1013
|
+
@zipFile.each {
|
1014
|
+
|entry|
|
1015
|
+
assertEntry(nextTestEntryName, @zipFile.getInputStream(entry),
|
1016
|
+
entry.name)
|
1017
|
+
}
|
1018
|
+
assert_equals(4, @testEntryNameIndex)
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
def test_getInputStreamBlock
|
1022
|
+
fileAndEntryName = @zipFile.entries.first.name
|
1023
|
+
@zipFile.getInputStream(fileAndEntryName) {
|
1024
|
+
|zis|
|
1025
|
+
assertEntryContentsForStream(fileAndEntryName,
|
1026
|
+
zis,
|
1027
|
+
fileAndEntryName)
|
1028
|
+
}
|
1029
|
+
end
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
class CommonZipFileFixture < RUNIT::TestCase
|
1033
|
+
include AssertEntry
|
1034
|
+
|
1035
|
+
EMPTY_FILENAME = "emptyZipFile.zip"
|
1036
|
+
|
1037
|
+
TEST_ZIP = TestZipFile::TEST_ZIP2.clone
|
1038
|
+
TEST_ZIP.zipName = "4entry_copy.zip"
|
1039
|
+
|
1040
|
+
def setup
|
1041
|
+
File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME)
|
1042
|
+
File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName)
|
1043
|
+
end
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
class ZipFileTest < CommonZipFileFixture
|
1047
|
+
|
1048
|
+
def test_createFromScratch
|
1049
|
+
comment = "a short comment"
|
1050
|
+
|
1051
|
+
zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE)
|
1052
|
+
zf.comment = comment
|
1053
|
+
zf.close
|
1054
|
+
|
1055
|
+
zfRead = ZipFile.new(EMPTY_FILENAME)
|
1056
|
+
assert_equals(comment, zfRead.comment)
|
1057
|
+
assert_equals(0, zfRead.entries.length)
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
def test_add
|
1061
|
+
srcFile = "ziptest.rb"
|
1062
|
+
entryName = "newEntryName.rb"
|
1063
|
+
assert(File.exists? srcFile)
|
1064
|
+
zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE)
|
1065
|
+
zf.add(entryName, srcFile)
|
1066
|
+
zf.close
|
1067
|
+
|
1068
|
+
zfRead = ZipFile.new(EMPTY_FILENAME)
|
1069
|
+
assert_equals("", zfRead.comment)
|
1070
|
+
assert_equals(1, zfRead.entries.length)
|
1071
|
+
assert_equals(entryName, zfRead.entries.first.name)
|
1072
|
+
AssertEntry.assertContents(srcFile,
|
1073
|
+
zfRead.getInputStream(entryName) { |zis| zis.read })
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
def test_addExistingEntryName
|
1077
|
+
assert_exception(ZipEntryExistsError) {
|
1078
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1079
|
+
|zf|
|
1080
|
+
zf.add(zf.entries.first.name, "ziptest.rb")
|
1081
|
+
}
|
1082
|
+
}
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
def test_addExistingEntryNameReplace
|
1086
|
+
gotCalled = false
|
1087
|
+
replacedEntry = nil
|
1088
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1089
|
+
|zf|
|
1090
|
+
replacedEntry = zf.entries.first.name
|
1091
|
+
zf.add(replacedEntry, "ziptest.rb") { gotCalled = true; true }
|
1092
|
+
}
|
1093
|
+
assert(gotCalled)
|
1094
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1095
|
+
|zf|
|
1096
|
+
assertContains(zf, replacedEntry, "ziptest.rb")
|
1097
|
+
}
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
def test_addDirectory
|
1101
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1102
|
+
|zf|
|
1103
|
+
zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR)
|
1104
|
+
}
|
1105
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1106
|
+
|zf|
|
1107
|
+
dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" }
|
1108
|
+
assert(dirEntry.isDirectory)
|
1109
|
+
}
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
def test_remove
|
1113
|
+
entryToRemove, *remainingEntries = TEST_ZIP.entryNames
|
1114
|
+
|
1115
|
+
File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName)
|
1116
|
+
|
1117
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1118
|
+
assert(zf.entries.map { |e| e.name }.include?(entryToRemove))
|
1119
|
+
zf.remove(entryToRemove)
|
1120
|
+
assert(! zf.entries.map { |e| e.name }.include?(entryToRemove))
|
1121
|
+
assert_equals(zf.entries.map {|x| x.name }.sort, remainingEntries.sort)
|
1122
|
+
zf.close
|
1123
|
+
|
1124
|
+
zfRead = ZipFile.new(TEST_ZIP.zipName)
|
1125
|
+
assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove))
|
1126
|
+
assert_equals(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort)
|
1127
|
+
zfRead.close
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
|
1131
|
+
def test_rename
|
1132
|
+
entryToRename, *remainingEntries = TEST_ZIP.entryNames
|
1133
|
+
|
1134
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1135
|
+
assert(zf.entries.map { |e| e.name }.include? entryToRename)
|
1136
|
+
|
1137
|
+
newName = "changed name"
|
1138
|
+
assert(! zf.entries.map { |e| e.name }.include?(newName))
|
1139
|
+
|
1140
|
+
zf.rename(entryToRename, newName)
|
1141
|
+
assert(zf.entries.map { |e| e.name }.include? newName)
|
1142
|
+
|
1143
|
+
zf.close
|
1144
|
+
|
1145
|
+
zfRead = ZipFile.new(TEST_ZIP.zipName)
|
1146
|
+
assert(zfRead.entries.map { |e| e.name }.include? newName)
|
1147
|
+
zfRead.close
|
1148
|
+
end
|
1149
|
+
|
1150
|
+
def test_renameToExistingEntry
|
1151
|
+
oldEntries = nil
|
1152
|
+
ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries }
|
1153
|
+
|
1154
|
+
assert_exception(ZipEntryExistsError) {
|
1155
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1156
|
+
|zf|
|
1157
|
+
zf.rename(zf.entries[0], zf.entries[1].name)
|
1158
|
+
}
|
1159
|
+
}
|
1160
|
+
|
1161
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1162
|
+
|zf|
|
1163
|
+
assert_equals(oldEntries.map{ |e| e.name }, zf.entries.map{ |e| e.name })
|
1164
|
+
}
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
def test_renameToExistingEntryOverwrite
|
1168
|
+
oldEntries = nil
|
1169
|
+
ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries }
|
1170
|
+
|
1171
|
+
gotCalled = false
|
1172
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1173
|
+
|zf|
|
1174
|
+
zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true }
|
1175
|
+
}
|
1176
|
+
|
1177
|
+
assert(gotCalled)
|
1178
|
+
oldEntries.delete_at(0)
|
1179
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1180
|
+
|zf|
|
1181
|
+
assert_equals(oldEntries.map{ |e| e.name },
|
1182
|
+
zf.entries.map{ |e| e.name })
|
1183
|
+
}
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
def test_renameNonEntry
|
1187
|
+
nonEntry = "bogusEntry"
|
1188
|
+
targetEntry = "targetEntryName"
|
1189
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1190
|
+
assert(! zf.entries.include?(nonEntry))
|
1191
|
+
assert_exception(ZipNoSuchEntryError) {
|
1192
|
+
zf.rename(nonEntry, targetEntry)
|
1193
|
+
}
|
1194
|
+
zf.commit
|
1195
|
+
assert(! zf.entries.include?(targetEntry))
|
1196
|
+
ensure
|
1197
|
+
zf.close
|
1198
|
+
end
|
1199
|
+
|
1200
|
+
def test_renameEntryToExistingEntry
|
1201
|
+
entry1, entry2, *remaining = TEST_ZIP.entryNames
|
1202
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1203
|
+
assert_exception(ZipEntryExistsError) {
|
1204
|
+
zf.rename(entry1, entry2)
|
1205
|
+
}
|
1206
|
+
ensure
|
1207
|
+
zf.close
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
def test_replace
|
1211
|
+
unchangedEntries = TEST_ZIP.entryNames.dup
|
1212
|
+
entryToReplace = unchangedEntries.delete_at(2)
|
1213
|
+
newEntrySrcFilename = "ziptest.rb"
|
1214
|
+
|
1215
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1216
|
+
zf.replace(entryToReplace, newEntrySrcFilename)
|
1217
|
+
|
1218
|
+
zf.close
|
1219
|
+
|
1220
|
+
zfRead = ZipFile.new(TEST_ZIP.zipName)
|
1221
|
+
AssertEntry::assertContents(newEntrySrcFilename,
|
1222
|
+
zfRead.getInputStream(entryToReplace) { |is| is.read })
|
1223
|
+
zfRead.close
|
1224
|
+
end
|
1225
|
+
|
1226
|
+
def test_replaceNonEntry
|
1227
|
+
entryToReplace = "nonExistingEntryname"
|
1228
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1229
|
+
|zf|
|
1230
|
+
assert_exception(ZipNoSuchEntryError) {
|
1231
|
+
zf.replace(entryToReplace, "ziptest.rb")
|
1232
|
+
}
|
1233
|
+
}
|
1234
|
+
end
|
1235
|
+
|
1236
|
+
def test_commit
|
1237
|
+
newName = "renamedFirst"
|
1238
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1239
|
+
oldName = zf.entries.first
|
1240
|
+
zf.rename(oldName, newName)
|
1241
|
+
zf.commit
|
1242
|
+
|
1243
|
+
zfRead = ZipFile.new(TEST_ZIP.zipName)
|
1244
|
+
assert(zfRead.entries.detect { |e| e.name == newName } != nil)
|
1245
|
+
assert(zfRead.entries.detect { |e| e.name == oldName } == nil)
|
1246
|
+
zfRead.close
|
1247
|
+
|
1248
|
+
zf.close
|
1249
|
+
end
|
1250
|
+
|
1251
|
+
# This test tests that after commit, you
|
1252
|
+
# can delete the file you used to add the entry to the zip file
|
1253
|
+
# with
|
1254
|
+
def test_commitUseZipEntry
|
1255
|
+
File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt")
|
1256
|
+
zf = ZipFile.open(TEST_ZIP.zipName)
|
1257
|
+
zf.add("okToDelete.txt", "okToDelete.txt")
|
1258
|
+
assertContains(zf, "okToDelete.txt")
|
1259
|
+
zf.commit
|
1260
|
+
File.move("okToDelete.txt", "okToDeleteMoved.txt")
|
1261
|
+
assertContains(zf, "okToDelete.txt", "okToDeleteMoved.txt")
|
1262
|
+
end
|
1263
|
+
|
1264
|
+
# def test_close
|
1265
|
+
# zf = ZipFile.new(TEST_ZIP.zipName)
|
1266
|
+
# zf.close
|
1267
|
+
# assert_exception(IOError) {
|
1268
|
+
# zf.extract(TEST_ZIP.entryNames.first, "hullubullu")
|
1269
|
+
# }
|
1270
|
+
# end
|
1271
|
+
|
1272
|
+
def test_compound1
|
1273
|
+
renamedName = "renamedName"
|
1274
|
+
originalEntries = []
|
1275
|
+
begin
|
1276
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1277
|
+
originalEntries = zf.entries.dup
|
1278
|
+
|
1279
|
+
assertNotContains(zf, TestFiles::RANDOM_ASCII_FILE1)
|
1280
|
+
zf.add(TestFiles::RANDOM_ASCII_FILE1,
|
1281
|
+
TestFiles::RANDOM_ASCII_FILE1)
|
1282
|
+
assertContains(zf, TestFiles::RANDOM_ASCII_FILE1)
|
1283
|
+
|
1284
|
+
zf.rename(zf.entries[0], renamedName)
|
1285
|
+
assertContains(zf, renamedName)
|
1286
|
+
|
1287
|
+
TestFiles::BINARY_TEST_FILES.each {
|
1288
|
+
|filename|
|
1289
|
+
zf.add(filename, filename)
|
1290
|
+
assertContains(zf, filename)
|
1291
|
+
}
|
1292
|
+
|
1293
|
+
assertContains(zf, originalEntries.last.to_s)
|
1294
|
+
zf.remove(originalEntries.last.to_s)
|
1295
|
+
assertNotContains(zf, originalEntries.last.to_s)
|
1296
|
+
|
1297
|
+
ensure
|
1298
|
+
zf.close
|
1299
|
+
end
|
1300
|
+
begin
|
1301
|
+
zfRead = ZipFile.new(TEST_ZIP.zipName)
|
1302
|
+
assertContains(zfRead, TestFiles::RANDOM_ASCII_FILE1)
|
1303
|
+
assertContains(zfRead, renamedName)
|
1304
|
+
TestFiles::BINARY_TEST_FILES.each {
|
1305
|
+
|filename|
|
1306
|
+
assertContains(zfRead, filename)
|
1307
|
+
}
|
1308
|
+
assertNotContains(zfRead, originalEntries.last.to_s)
|
1309
|
+
ensure
|
1310
|
+
zfRead.close
|
1311
|
+
end
|
1312
|
+
end
|
1313
|
+
|
1314
|
+
def test_compound2
|
1315
|
+
begin
|
1316
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1317
|
+
originalEntries = zf.entries.dup
|
1318
|
+
|
1319
|
+
originalEntries.each {
|
1320
|
+
|entry|
|
1321
|
+
zf.remove(entry)
|
1322
|
+
assertNotContains(zf, entry)
|
1323
|
+
}
|
1324
|
+
assert(zf.entries.empty?)
|
1325
|
+
|
1326
|
+
TestFiles::ASCII_TEST_FILES.each {
|
1327
|
+
|filename|
|
1328
|
+
zf.add(filename, filename)
|
1329
|
+
assertContains(zf, filename)
|
1330
|
+
}
|
1331
|
+
assert_equals(zf.entries.map { |e| e.name }, TestFiles::ASCII_TEST_FILES)
|
1332
|
+
|
1333
|
+
zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName")
|
1334
|
+
assertNotContains(zf, TestFiles::ASCII_TEST_FILES[0])
|
1335
|
+
assertContains(zf, "newName")
|
1336
|
+
ensure
|
1337
|
+
zf.close
|
1338
|
+
end
|
1339
|
+
begin
|
1340
|
+
zfRead = ZipFile.new(TEST_ZIP.zipName)
|
1341
|
+
asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup
|
1342
|
+
asciiTestFiles.shift
|
1343
|
+
asciiTestFiles.each {
|
1344
|
+
|filename|
|
1345
|
+
assertContains(zf, filename)
|
1346
|
+
}
|
1347
|
+
|
1348
|
+
assertContains(zf, "newName")
|
1349
|
+
ensure
|
1350
|
+
zfRead.close
|
1351
|
+
end
|
1352
|
+
end
|
1353
|
+
|
1354
|
+
private
|
1355
|
+
def assertContains(zf, entryName, filename = entryName)
|
1356
|
+
assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}")
|
1357
|
+
assertEntryContents(zf, entryName, filename) if File.exists?(filename)
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
def assertNotContains(zf, entryName)
|
1361
|
+
assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}")
|
1362
|
+
end
|
1363
|
+
end
|
1364
|
+
|
1365
|
+
class ZipFileExtractTest < CommonZipFileFixture
|
1366
|
+
EXTRACTED_FILENAME = "extEntry"
|
1367
|
+
ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entryNames.reverse
|
1368
|
+
|
1369
|
+
def setup
|
1370
|
+
super
|
1371
|
+
File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME)
|
1372
|
+
end
|
1373
|
+
|
1374
|
+
def test_extract
|
1375
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1376
|
+
|zf|
|
1377
|
+
zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME)
|
1378
|
+
|
1379
|
+
assert(File.exists? EXTRACTED_FILENAME)
|
1380
|
+
AssertEntry::assertContents(EXTRACTED_FILENAME,
|
1381
|
+
zf.getInputStream(ENTRY_TO_EXTRACT) { |is| is.read })
|
1382
|
+
}
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
def test_extractExists
|
1386
|
+
writtenText = "written text"
|
1387
|
+
File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) }
|
1388
|
+
|
1389
|
+
assert_exception(ZipDestinationFileExistsError) {
|
1390
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1391
|
+
|zf|
|
1392
|
+
zf.extract(zf.entries.first, EXTRACTED_FILENAME)
|
1393
|
+
}
|
1394
|
+
}
|
1395
|
+
File.open(EXTRACTED_FILENAME, "r") {
|
1396
|
+
|f|
|
1397
|
+
assert_equals(writtenText, f.read)
|
1398
|
+
}
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
def test_extractExistsOverwrite
|
1402
|
+
writtenText = "written text"
|
1403
|
+
File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) }
|
1404
|
+
|
1405
|
+
gotCalled = false
|
1406
|
+
ZipFile.open(TEST_ZIP.zipName) {
|
1407
|
+
|zf|
|
1408
|
+
zf.extract(zf.entries.first, EXTRACTED_FILENAME) { gotCalled = true; true }
|
1409
|
+
}
|
1410
|
+
|
1411
|
+
assert(gotCalled)
|
1412
|
+
File.open(EXTRACTED_FILENAME, "r") {
|
1413
|
+
|f|
|
1414
|
+
assert(writtenText != f.read)
|
1415
|
+
}
|
1416
|
+
end
|
1417
|
+
|
1418
|
+
def test_extractNonEntry
|
1419
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1420
|
+
assert_exception(ZipNoSuchEntryError) { zf.extract("nonExistingEntry", "nonExistingEntry") }
|
1421
|
+
ensure
|
1422
|
+
zf.close if zf
|
1423
|
+
end
|
1424
|
+
|
1425
|
+
def test_extractNonEntry2
|
1426
|
+
outFile = "outfile"
|
1427
|
+
assert_exception(ZipNoSuchEntryError) {
|
1428
|
+
zf = ZipFile.new(TEST_ZIP.zipName)
|
1429
|
+
nonEntry = "hotdog-diddelidoo"
|
1430
|
+
assert(! zf.entries.include?(nonEntry))
|
1431
|
+
zf.extract(nonEntry, outFile)
|
1432
|
+
zf.close
|
1433
|
+
}
|
1434
|
+
assert(! File.exists?(outFile))
|
1435
|
+
end
|
1436
|
+
|
1437
|
+
end
|
1438
|
+
|
1439
|
+
class ZipFileExtractDirectoryTest < CommonZipFileFixture
|
1440
|
+
TEST_OUT_NAME = "emptyOutDir"
|
1441
|
+
|
1442
|
+
def openZip(&aProc)
|
1443
|
+
assert(aProc != nil)
|
1444
|
+
ZipFile.open(TestZipFile::TEST_ZIP4.zipName, &aProc)
|
1445
|
+
end
|
1446
|
+
|
1447
|
+
def extractTestDir(&aProc)
|
1448
|
+
openZip {
|
1449
|
+
|zf|
|
1450
|
+
zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc)
|
1451
|
+
}
|
1452
|
+
end
|
1453
|
+
|
1454
|
+
def setup
|
1455
|
+
super
|
1456
|
+
|
1457
|
+
Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME
|
1458
|
+
File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME
|
1459
|
+
end
|
1460
|
+
|
1461
|
+
def test_extractDirectory
|
1462
|
+
extractTestDir
|
1463
|
+
assert(File.directory? TEST_OUT_NAME)
|
1464
|
+
end
|
1465
|
+
|
1466
|
+
def test_extractDirectoryExistsAsDir
|
1467
|
+
Dir.mkdir TEST_OUT_NAME
|
1468
|
+
extractTestDir
|
1469
|
+
assert(File.directory? TEST_OUT_NAME)
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
def test_extractDirectoryExistsAsFile
|
1473
|
+
File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
|
1474
|
+
assert_exception(ZipDestinationFileExistsError) { extractTestDir }
|
1475
|
+
end
|
1476
|
+
|
1477
|
+
def test_extractDirectoryExistsAsFileOverwrite
|
1478
|
+
File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
|
1479
|
+
gotCalled = false
|
1480
|
+
extractTestDir {
|
1481
|
+
|entry, destPath|
|
1482
|
+
gotCalled = true
|
1483
|
+
assert_equals(TEST_OUT_NAME, destPath)
|
1484
|
+
assert(entry.isDirectory)
|
1485
|
+
true
|
1486
|
+
}
|
1487
|
+
assert(gotCalled)
|
1488
|
+
assert(File.directory? TEST_OUT_NAME)
|
1489
|
+
end
|
1490
|
+
end
|
1491
|
+
|
1492
|
+
|
1493
|
+
TestFiles::createTestFiles(ARGV.index("recreate") != nil ||
|
1494
|
+
ARGV.index("recreateonly") != nil)
|
1495
|
+
TestZipFile::createTestZips(ARGV.index("recreate") != nil ||
|
1496
|
+
ARGV.index("recreateonly") != nil)
|
1497
|
+
exit if ARGV.index("recreateonly") != nil
|
1498
|
+
|
1499
|
+
#require 'runit/cui/testrunner'
|
1500
|
+
#RUNIT::CUI::TestRunner.run(ZipFileTest.suite)
|
1501
|
+
|
1502
|
+
# Copyright (C) 2002 Thomas Sondergaard
|
1503
|
+
# rubyzip is free software; you can redistribute it and/or
|
1504
|
+
# modify it under the terms of the ruby license.
|