PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/test/ziptest.rb

https://github.com/zdennis/rubyzip2
Ruby | 1599 lines | 1364 code | 207 blank | 28 comment | 57 complexity | 2b7d6145c480e7755716aad651f6de9b MD5 | raw file
  1. #!/usr/bin/env ruby
  2. $VERBOSE = true
  3. $: << "../lib"
  4. require 'test/unit'
  5. require 'zip/zip'
  6. require 'gentestfiles'
  7. include Zip
  8. class ZipEntryTest < Test::Unit::TestCase
  9. TEST_ZIPFILE = "someZipFile.zip"
  10. TEST_COMMENT = "a comment"
  11. TEST_COMPRESSED_SIZE = 1234
  12. TEST_CRC = 325324
  13. TEST_EXTRA = "Some data here"
  14. TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED
  15. TEST_NAME = "entry name"
  16. TEST_SIZE = 8432
  17. TEST_ISDIRECTORY = false
  18. def test_constructorAndGetters
  19. entry = ZipEntry.new(TEST_ZIPFILE,
  20. TEST_NAME,
  21. TEST_COMMENT,
  22. TEST_EXTRA,
  23. TEST_COMPRESSED_SIZE,
  24. TEST_CRC,
  25. TEST_COMPRESSIONMETHOD,
  26. TEST_SIZE)
  27. assert_equal(TEST_COMMENT, entry.comment)
  28. assert_equal(TEST_COMPRESSED_SIZE, entry.compressed_size)
  29. assert_equal(TEST_CRC, entry.crc)
  30. assert_instance_of(Zip::ZipExtraField, entry.extra)
  31. assert_equal(TEST_COMPRESSIONMETHOD, entry.compression_method)
  32. assert_equal(TEST_NAME, entry.name)
  33. assert_equal(TEST_SIZE, entry.size)
  34. assert_equal(TEST_ISDIRECTORY, entry.is_directory)
  35. end
  36. def test_is_directoryAndIsFile
  37. assert(ZipEntry.new(TEST_ZIPFILE, "hello").file?)
  38. assert(! ZipEntry.new(TEST_ZIPFILE, "hello").directory?)
  39. assert(ZipEntry.new(TEST_ZIPFILE, "dir/hello").file?)
  40. assert(! ZipEntry.new(TEST_ZIPFILE, "dir/hello").directory?)
  41. assert(ZipEntry.new(TEST_ZIPFILE, "hello/").directory?)
  42. assert(! ZipEntry.new(TEST_ZIPFILE, "hello/").file?)
  43. assert(ZipEntry.new(TEST_ZIPFILE, "dir/hello/").directory?)
  44. assert(! ZipEntry.new(TEST_ZIPFILE, "dir/hello/").file?)
  45. end
  46. def test_equality
  47. entry1 = ZipEntry.new("file.zip", "name", "isNotCompared",
  48. "something extra", 123, 1234,
  49. ZipEntry::DEFLATED, 10000)
  50. entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX",
  51. "something extra", 123, 1234,
  52. ZipEntry::DEFLATED, 10000)
  53. entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
  54. "something extra", 123, 1234,
  55. ZipEntry::DEFLATED, 10000)
  56. entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
  57. "something extraXX", 123, 1234,
  58. ZipEntry::DEFLATED, 10000)
  59. entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
  60. "something extraXX", 12, 1234,
  61. ZipEntry::DEFLATED, 10000)
  62. entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
  63. "something extraXX", 12, 123,
  64. ZipEntry::DEFLATED, 10000)
  65. entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
  66. "something extraXX", 12, 123,
  67. ZipEntry::STORED, 10000)
  68. entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX",
  69. "something extraXX", 12, 123,
  70. ZipEntry::STORED, 100000)
  71. assert_equal(entry1, entry1)
  72. assert_equal(entry1, entry2)
  73. assert(entry2 != entry3)
  74. assert(entry3 != entry4)
  75. assert(entry4 != entry5)
  76. assert(entry5 != entry6)
  77. assert(entry6 != entry7)
  78. assert(entry7 != entry8)
  79. assert(entry7 != "hello")
  80. assert(entry7 != 12)
  81. end
  82. def test_compare
  83. assert_equal(0, (ZipEntry.new("zf.zip", "a") <=> ZipEntry.new("zf.zip", "a")))
  84. assert_equal(1, (ZipEntry.new("zf.zip", "b") <=> ZipEntry.new("zf.zip", "a")))
  85. assert_equal(-1, (ZipEntry.new("zf.zip", "a") <=> ZipEntry.new("zf.zip", "b")))
  86. entries = [
  87. ZipEntry.new("zf.zip", "5"),
  88. ZipEntry.new("zf.zip", "1"),
  89. ZipEntry.new("zf.zip", "3"),
  90. ZipEntry.new("zf.zip", "4"),
  91. ZipEntry.new("zf.zip", "0"),
  92. ZipEntry.new("zf.zip", "2")
  93. ]
  94. entries.sort!
  95. assert_equal("0", entries[0].to_s)
  96. assert_equal("1", entries[1].to_s)
  97. assert_equal("2", entries[2].to_s)
  98. assert_equal("3", entries[3].to_s)
  99. assert_equal("4", entries[4].to_s)
  100. assert_equal("5", entries[5].to_s)
  101. end
  102. def test_parentAsString
  103. entry1 = ZipEntry.new("zf.zip", "aa")
  104. entry2 = ZipEntry.new("zf.zip", "aa/")
  105. entry3 = ZipEntry.new("zf.zip", "aa/bb")
  106. entry4 = ZipEntry.new("zf.zip", "aa/bb/")
  107. entry5 = ZipEntry.new("zf.zip", "aa/bb/cc")
  108. entry6 = ZipEntry.new("zf.zip", "aa/bb/cc/")
  109. assert_equal(nil, entry1.parent_as_string)
  110. assert_equal(nil, entry2.parent_as_string)
  111. assert_equal("aa/", entry3.parent_as_string)
  112. assert_equal("aa/", entry4.parent_as_string)
  113. assert_equal("aa/bb/", entry5.parent_as_string)
  114. assert_equal("aa/bb/", entry6.parent_as_string)
  115. end
  116. def test_entry_name_cannot_start_with_slash
  117. assert_raise(ZipEntryNameError) { ZipEntry.new("zf.zip", "/hej/der") }
  118. end
  119. end
  120. module IOizeString
  121. attr_reader :tell
  122. def read(count = nil)
  123. @tell ||= 0
  124. count = size unless count
  125. retVal = slice(@tell, count)
  126. @tell += count
  127. return retVal
  128. end
  129. def seek(index, offset)
  130. @tell ||= 0
  131. case offset
  132. when IO::SEEK_END
  133. newPos = size + index
  134. when IO::SEEK_SET
  135. newPos = index
  136. when IO::SEEK_CUR
  137. newPos = @tell + index
  138. else
  139. raise "Error in test method IOizeString::seek"
  140. end
  141. if (newPos < 0 || newPos >= size)
  142. raise Errno::EINVAL
  143. else
  144. @tell=newPos
  145. end
  146. end
  147. def reset
  148. @tell = 0
  149. end
  150. end
  151. class ZipLocalEntryTest < Test::Unit::TestCase
  152. def test_read_local_entryHeaderOfFirstTestZipEntry
  153. File.open(TestZipFile::TEST_ZIP3.zip_name, "rb") {
  154. |file|
  155. entry = ZipEntry.read_local_entry(file)
  156. assert_equal("", entry.comment)
  157. # Differs from windows and unix because of CR LF
  158. # assert_equal(480, entry.compressed_size)
  159. # assert_equal(0x2a27930f, entry.crc)
  160. # extra field is 21 bytes long
  161. # probably contains some unix attrutes or something
  162. # disabled: assert_equal(nil, entry.extra)
  163. assert_equal(ZipEntry::DEFLATED, entry.compression_method)
  164. assert_equal(TestZipFile::TEST_ZIP3.entry_names[0], entry.name)
  165. assert_equal(File.size(TestZipFile::TEST_ZIP3.entry_names[0]), entry.size)
  166. assert(! entry.is_directory)
  167. }
  168. end
  169. def test_readDateTime
  170. File.open("data/rubycode.zip", "rb") {
  171. |file|
  172. entry = ZipEntry.read_local_entry(file)
  173. assert_equal("zippedruby1.rb", entry.name)
  174. assert_equal(Time.at(1019261638), entry.time)
  175. }
  176. end
  177. def test_read_local_entryFromNonZipFile
  178. File.open("data/file2.txt") {
  179. |file|
  180. assert_equal(nil, ZipEntry.read_local_entry(file))
  181. }
  182. end
  183. def test_read_local_entryFromTruncatedZipFile
  184. zipFragment=""
  185. File.open(TestZipFile::TEST_ZIP2.zip_name) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes
  186. zipFragment.extend(IOizeString).reset
  187. entry = ZipEntry.new
  188. entry.read_local_entry(zipFragment)
  189. fail "ZipError expected"
  190. rescue ZipError
  191. end
  192. def test_writeEntry
  193. entry = ZipEntry.new("file.zip", "entryName", "my little comment",
  194. "thisIsSomeExtraInformation", 100, 987654,
  195. ZipEntry::DEFLATED, 400)
  196. write_to_file("localEntryHeader.bin", "centralEntryHeader.bin", entry)
  197. entryReadLocal, entryReadCentral = read_from_file("localEntryHeader.bin", "centralEntryHeader.bin")
  198. compare_local_entry_headers(entry, entryReadLocal)
  199. compare_c_dir_entry_headers(entry, entryReadCentral)
  200. end
  201. private
  202. def compare_local_entry_headers(entry1, entry2)
  203. assert_equal(entry1.compressed_size , entry2.compressed_size)
  204. assert_equal(entry1.crc , entry2.crc)
  205. assert_equal(entry1.extra , entry2.extra)
  206. assert_equal(entry1.compression_method, entry2.compression_method)
  207. assert_equal(entry1.name , entry2.name)
  208. assert_equal(entry1.size , entry2.size)
  209. assert_equal(entry1.localHeaderOffset, entry2.localHeaderOffset)
  210. end
  211. def compare_c_dir_entry_headers(entry1, entry2)
  212. compare_local_entry_headers(entry1, entry2)
  213. assert_equal(entry1.comment, entry2.comment)
  214. end
  215. def write_to_file(localFileName, centralFileName, entry)
  216. File.open(localFileName, "wb") { |f| entry.write_local_entry(f) }
  217. File.open(centralFileName, "wb") { |f| entry.write_c_dir_entry(f) }
  218. end
  219. def read_from_file(localFileName, centralFileName)
  220. localEntry = nil
  221. cdirEntry = nil
  222. File.open(localFileName, "rb") { |f| localEntry = ZipEntry.read_local_entry(f) }
  223. File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.read_c_dir_entry(f) }
  224. return [localEntry, cdirEntry]
  225. end
  226. end
  227. module DecompressorTests
  228. # expects @refText, @refLines and @decompressor
  229. TEST_FILE="data/file1.txt"
  230. def setup
  231. @refText=""
  232. File.open(TEST_FILE) { |f| @refText = f.read }
  233. @refLines = @refText.split($/)
  234. end
  235. def test_readEverything
  236. assert_equal(@refText, @decompressor.sysread)
  237. end
  238. def test_readInChunks
  239. chunkSize = 5
  240. while (decompressedChunk = @decompressor.sysread(chunkSize))
  241. assert_equal(@refText.slice!(0, chunkSize), decompressedChunk)
  242. end
  243. assert_equal(0, @refText.size)
  244. end
  245. def test_mixingReadsAndProduceInput
  246. # Just some preconditions to make sure we have enough data for this test
  247. assert(@refText.length > 1000)
  248. assert(@refLines.length > 40)
  249. assert_equal(@refText[0...100], @decompressor.sysread(100))
  250. assert(! @decompressor.input_finished?)
  251. buf = @decompressor.produce_input
  252. assert_equal(@refText[100...(100+buf.length)], buf)
  253. end
  254. end
  255. class InflaterTest < Test::Unit::TestCase
  256. include DecompressorTests
  257. def setup
  258. super
  259. @file = File.new("data/file1.txt.deflatedData", "rb")
  260. @decompressor = Inflater.new(@file)
  261. end
  262. def teardown
  263. @file.close
  264. end
  265. end
  266. class PassThruDecompressorTest < Test::Unit::TestCase
  267. include DecompressorTests
  268. def setup
  269. super
  270. @file = File.new(TEST_FILE)
  271. @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE))
  272. end
  273. def teardown
  274. @file.close
  275. end
  276. end
  277. module AssertEntry
  278. def assert_next_entry(filename, zis)
  279. assert_entry(filename, zis, zis.get_next_entry.name)
  280. end
  281. def assert_entry(filename, zis, entryName)
  282. assert_equal(filename, entryName)
  283. assert_entryContentsForStream(filename, zis, entryName)
  284. end
  285. def assert_entryContentsForStream(filename, zis, entryName)
  286. File.open(filename, "rb") {
  287. |file|
  288. expected = file.read
  289. actual = zis.read
  290. if (expected != actual)
  291. if ((expected && actual) && (expected.length > 400 || actual.length > 400))
  292. zipEntryFilename=entryName+".zipEntry"
  293. File.open(zipEntryFilename, "wb") { |file| file << actual }
  294. fail("File '#{filename}' is different from '#{zipEntryFilename}'")
  295. else
  296. assert_equal(expected, actual)
  297. end
  298. end
  299. }
  300. end
  301. def AssertEntry.assert_contents(filename, aString)
  302. fileContents = ""
  303. File.open(filename, "rb") { |f| fileContents = f.read }
  304. if (fileContents != aString)
  305. if (fileContents.length > 400 || aString.length > 400)
  306. stringFile = filename + ".other"
  307. File.open(stringFile, "wb") { |f| f << aString }
  308. fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'")
  309. else
  310. assert_equal(fileContents, aString)
  311. end
  312. end
  313. end
  314. def assert_stream_contents(zis, testZipFile)
  315. assert(zis != nil)
  316. testZipFile.entry_names.each {
  317. |entryName|
  318. assert_next_entry(entryName, zis)
  319. }
  320. assert_equal(nil, zis.get_next_entry)
  321. end
  322. def assert_test_zip_contents(testZipFile)
  323. ZipInputStream.open(testZipFile.zip_name) {
  324. |zis|
  325. assert_stream_contents(zis, testZipFile)
  326. }
  327. end
  328. def assert_entryContents(zipFile, entryName, filename = entryName.to_s)
  329. zis = zipFile.get_input_stream(entryName)
  330. assert_entryContentsForStream(filename, zis, entryName)
  331. ensure
  332. zis.close if zis
  333. end
  334. end
  335. class ZipInputStreamTest < Test::Unit::TestCase
  336. include AssertEntry
  337. def test_new
  338. zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zip_name)
  339. assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
  340. assert_equal(true, zis.eof?)
  341. zis.close
  342. end
  343. def test_openWithBlock
  344. ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) {
  345. |zis|
  346. assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
  347. assert_equal(true, zis.eof?)
  348. }
  349. end
  350. def test_openWithoutBlock
  351. zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name)
  352. assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
  353. end
  354. def test_incompleteReads
  355. ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) {
  356. |zis|
  357. entry = zis.get_next_entry # longAscii.txt
  358. assert_equal(false, zis.eof?)
  359. assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], entry.name)
  360. assert zis.gets.length > 0
  361. assert_equal(false, zis.eof?)
  362. entry = zis.get_next_entry # empty.txt
  363. assert_equal(TestZipFile::TEST_ZIP2.entry_names[1], entry.name)
  364. assert_equal(0, entry.size)
  365. assert_equal(nil, zis.gets)
  366. assert_equal(true, zis.eof?)
  367. entry = zis.get_next_entry # empty_chmod640.txt
  368. assert_equal(TestZipFile::TEST_ZIP2.entry_names[2], entry.name)
  369. assert_equal(0, entry.size)
  370. assert_equal(nil, zis.gets)
  371. assert_equal(true, zis.eof?)
  372. entry = zis.get_next_entry # short.txt
  373. assert_equal(TestZipFile::TEST_ZIP2.entry_names[3], entry.name)
  374. assert zis.gets.length > 0
  375. entry = zis.get_next_entry # longBinary.bin
  376. assert_equal(TestZipFile::TEST_ZIP2.entry_names[4], entry.name)
  377. assert zis.gets.length > 0
  378. }
  379. end
  380. def test_rewind
  381. ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) {
  382. |zis|
  383. e = zis.get_next_entry
  384. assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], e.name)
  385. # Do a little reading
  386. buf = ""
  387. buf << zis.read(100)
  388. buf << (zis.gets || "")
  389. buf << (zis.gets || "")
  390. assert_equal(false, zis.eof?)
  391. zis.rewind
  392. buf2 = ""
  393. buf2 << zis.read(100)
  394. buf2 << (zis.gets || "")
  395. buf2 << (zis.gets || "")
  396. assert_equal(buf, buf2)
  397. zis.rewind
  398. assert_equal(false, zis.eof?)
  399. assert_entry(e.name, zis, e.name)
  400. }
  401. end
  402. def test_mix_read_and_gets
  403. ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) {
  404. |zis|
  405. e = zis.get_next_entry
  406. assert_equal("#!/usr/bin/env ruby", zis.gets.chomp)
  407. assert_equal(false, zis.eof?)
  408. assert_equal("", zis.gets.chomp)
  409. assert_equal(false, zis.eof?)
  410. assert_equal("$VERBOSE =", zis.read(10))
  411. assert_equal(false, zis.eof?)
  412. }
  413. end
  414. end
  415. module CrcTest
  416. class TestOutputStream
  417. include IOExtras::AbstractOutputStream
  418. attr_accessor :buffer
  419. def initialize
  420. @buffer = ""
  421. end
  422. def << (data)
  423. @buffer << data
  424. self
  425. end
  426. end
  427. def run_crc_test(compressorClass)
  428. str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed."
  429. fakeOut = TestOutputStream.new
  430. deflater = compressorClass.new(fakeOut)
  431. deflater << str
  432. assert_equal(0x919920fc, deflater.crc)
  433. end
  434. end
  435. class PassThruCompressorTest < Test::Unit::TestCase
  436. include CrcTest
  437. def test_size
  438. File.open("dummy.txt", "wb") {
  439. |file|
  440. compressor = PassThruCompressor.new(file)
  441. assert_equal(0, compressor.size)
  442. t1 = "hello world"
  443. t2 = ""
  444. t3 = "bingo"
  445. compressor << t1
  446. assert_equal(compressor.size, t1.size)
  447. compressor << t2
  448. assert_equal(compressor.size, t1.size + t2.size)
  449. compressor << t3
  450. assert_equal(compressor.size, t1.size + t2.size + t3.size)
  451. }
  452. end
  453. def test_crc
  454. run_crc_test(PassThruCompressor)
  455. end
  456. end
  457. class DeflaterTest < Test::Unit::TestCase
  458. include CrcTest
  459. def test_outputOperator
  460. txt = load_file("data/file2.txt")
  461. deflate(txt, "deflatertest.bin")
  462. inflatedTxt = inflate("deflatertest.bin")
  463. assert_equal(txt, inflatedTxt)
  464. end
  465. private
  466. def load_file(fileName)
  467. txt = nil
  468. File.open(fileName, "rb") { |f| txt = f.read }
  469. end
  470. def deflate(data, fileName)
  471. File.open(fileName, "wb") {
  472. |file|
  473. deflater = Deflater.new(file)
  474. deflater << data
  475. deflater.finish
  476. assert_equal(deflater.size, data.size)
  477. file << "trailing data for zlib with -MAX_WBITS"
  478. }
  479. end
  480. def inflate(fileName)
  481. txt = nil
  482. File.open(fileName, "rb") {
  483. |file|
  484. inflater = Inflater.new(file)
  485. txt = inflater.sysread
  486. }
  487. end
  488. def test_crc
  489. run_crc_test(Deflater)
  490. end
  491. end
  492. class ZipOutputStreamTest < Test::Unit::TestCase
  493. include AssertEntry
  494. TEST_ZIP = TestZipFile::TEST_ZIP2.clone
  495. TEST_ZIP.zip_name = "output.zip"
  496. def test_new
  497. zos = ZipOutputStream.new(TEST_ZIP.zip_name)
  498. zos.comment = TEST_ZIP.comment
  499. write_test_zip(zos)
  500. zos.close
  501. assert_test_zip_contents(TEST_ZIP)
  502. end
  503. def test_open
  504. ZipOutputStream.open(TEST_ZIP.zip_name) {
  505. |zos|
  506. zos.comment = TEST_ZIP.comment
  507. write_test_zip(zos)
  508. }
  509. assert_test_zip_contents(TEST_ZIP)
  510. end
  511. def test_writingToClosedStream
  512. assert_i_o_error_in_closed_stream { |zos| zos << "hello world" }
  513. assert_i_o_error_in_closed_stream { |zos| zos.puts "hello world" }
  514. assert_i_o_error_in_closed_stream { |zos| zos.write "hello world" }
  515. end
  516. def test_cannotOpenFile
  517. name = TestFiles::EMPTY_TEST_DIR
  518. begin
  519. zos = ZipOutputStream.open(name)
  520. rescue Exception
  521. assert($!.kind_of?(Errno::EISDIR) || # Linux
  522. $!.kind_of?(Errno::EEXIST) || # Windows/cygwin
  523. $!.kind_of?(Errno::EACCES), # Windows
  524. "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.class}")
  525. end
  526. end
  527. def assert_i_o_error_in_closed_stream
  528. assert_raise(IOError) {
  529. zos = ZipOutputStream.new("test_putOnClosedStream.zip")
  530. zos.close
  531. yield zos
  532. }
  533. end
  534. def write_test_zip(zos)
  535. TEST_ZIP.entry_names.each {
  536. |entryName|
  537. zos.put_next_entry(entryName)
  538. File.open(entryName, "rb") { |f| zos.write(f.read) }
  539. }
  540. end
  541. end
  542. module Enumerable
  543. def compare_enumerables(otherEnumerable)
  544. otherAsArray = otherEnumerable.to_a
  545. index=0
  546. each_with_index {
  547. |element, index|
  548. return false unless yield(element, otherAsArray[index])
  549. }
  550. return index+1 == otherAsArray.size
  551. end
  552. end
  553. class ZipCentralDirectoryEntryTest < Test::Unit::TestCase
  554. def test_read_from_stream
  555. File.open("data/testDirectory.bin", "rb") {
  556. |file|
  557. entry = ZipEntry.read_c_dir_entry(file)
  558. assert_equal("longAscii.txt", entry.name)
  559. assert_equal(ZipEntry::DEFLATED, entry.compression_method)
  560. assert_equal(106490, entry.size)
  561. assert_equal(3784, entry.compressed_size)
  562. assert_equal(0xfcd1799c, entry.crc)
  563. assert_equal("", entry.comment)
  564. entry = ZipEntry.read_c_dir_entry(file)
  565. assert_equal("empty.txt", entry.name)
  566. assert_equal(ZipEntry::STORED, entry.compression_method)
  567. assert_equal(0, entry.size)
  568. assert_equal(0, entry.compressed_size)
  569. assert_equal(0x0, entry.crc)
  570. assert_equal("", entry.comment)
  571. entry = ZipEntry.read_c_dir_entry(file)
  572. assert_equal("short.txt", entry.name)
  573. assert_equal(ZipEntry::STORED, entry.compression_method)
  574. assert_equal(6, entry.size)
  575. assert_equal(6, entry.compressed_size)
  576. assert_equal(0xbb76fe69, entry.crc)
  577. assert_equal("", entry.comment)
  578. entry = ZipEntry.read_c_dir_entry(file)
  579. assert_equal("longBinary.bin", entry.name)
  580. assert_equal(ZipEntry::DEFLATED, entry.compression_method)
  581. assert_equal(1000024, entry.size)
  582. assert_equal(70847, entry.compressed_size)
  583. assert_equal(0x10da7d59, entry.crc)
  584. assert_equal("", entry.comment)
  585. entry = ZipEntry.read_c_dir_entry(file)
  586. assert_equal(nil, entry)
  587. # Fields that are not check by this test:
  588. # version made by 2 bytes
  589. # version needed to extract 2 bytes
  590. # general purpose bit flag 2 bytes
  591. # last mod file time 2 bytes
  592. # last mod file date 2 bytes
  593. # compressed size 4 bytes
  594. # uncompressed size 4 bytes
  595. # disk number start 2 bytes
  596. # internal file attributes 2 bytes
  597. # external file attributes 4 bytes
  598. # relative offset of local header 4 bytes
  599. # file name (variable size)
  600. # extra field (variable size)
  601. # file comment (variable size)
  602. }
  603. end
  604. def test_ReadEntryFromTruncatedZipFile
  605. fragment=""
  606. File.open("data/testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes
  607. fragment.extend(IOizeString)
  608. entry = ZipEntry.new
  609. entry.read_c_dir_entry(fragment)
  610. fail "ZipError expected"
  611. rescue ZipError
  612. end
  613. end
  614. class ZipEntrySetTest < Test::Unit::TestCase
  615. ZIP_ENTRIES = [
  616. ZipEntry.new("zipfile.zip", "name1", "comment1"),
  617. ZipEntry.new("zipfile.zip", "name2", "comment1"),
  618. ZipEntry.new("zipfile.zip", "name3", "comment1"),
  619. ZipEntry.new("zipfile.zip", "name4", "comment1"),
  620. ZipEntry.new("zipfile.zip", "name5", "comment1"),
  621. ZipEntry.new("zipfile.zip", "name6", "comment1")
  622. ]
  623. def setup
  624. @zipEntrySet = ZipEntrySet.new(ZIP_ENTRIES)
  625. end
  626. def test_include
  627. assert(@zipEntrySet.include?(ZIP_ENTRIES.first))
  628. assert(! @zipEntrySet.include?(ZipEntry.new("different.zip", "different", "aComment")))
  629. end
  630. def test_size
  631. assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size)
  632. assert_equal(ZIP_ENTRIES.size, @zipEntrySet.length)
  633. @zipEntrySet << ZipEntry.new("a", "b", "c")
  634. assert_equal(ZIP_ENTRIES.size + 1, @zipEntrySet.length)
  635. end
  636. def test_add
  637. zes = ZipEntrySet.new
  638. entry1 = ZipEntry.new("zf.zip", "name1")
  639. entry2 = ZipEntry.new("zf.zip", "name2")
  640. zes << entry1
  641. assert(zes.include?(entry1))
  642. zes.push(entry2)
  643. assert(zes.include?(entry2))
  644. end
  645. def test_delete
  646. assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size)
  647. entry = @zipEntrySet.delete(ZIP_ENTRIES.first)
  648. assert_equal(ZIP_ENTRIES.size - 1, @zipEntrySet.size)
  649. assert_equal(ZIP_ENTRIES.first, entry)
  650. entry = @zipEntrySet.delete(ZIP_ENTRIES.first)
  651. assert_equal(ZIP_ENTRIES.size - 1, @zipEntrySet.size)
  652. assert_nil(entry)
  653. end
  654. def test_each
  655. # Tested indirectly via each_with_index
  656. count = 0
  657. @zipEntrySet.each_with_index {
  658. |entry, index|
  659. assert(ZIP_ENTRIES.include?(entry))
  660. count = count.succ
  661. }
  662. assert_equal(ZIP_ENTRIES.size, count)
  663. end
  664. def test_entries
  665. assert_equal(ZIP_ENTRIES.sort, @zipEntrySet.entries.sort)
  666. end
  667. def test_compound
  668. newEntry = ZipEntry.new("zf.zip", "new entry", "new entry's comment")
  669. assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size)
  670. @zipEntrySet << newEntry
  671. assert_equal(ZIP_ENTRIES.size + 1, @zipEntrySet.size)
  672. assert(@zipEntrySet.include?(newEntry))
  673. @zipEntrySet.delete(newEntry)
  674. assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size)
  675. end
  676. def test_dup
  677. copy = @zipEntrySet.dup
  678. assert_equal(@zipEntrySet, copy)
  679. # demonstrate that this is a deep copy
  680. copy.entries[0].name = "a totally different name"
  681. assert(@zipEntrySet != copy)
  682. end
  683. def test_parent
  684. entries = [
  685. ZipEntry.new("zf.zip", "a"),
  686. ZipEntry.new("zf.zip", "a/"),
  687. ZipEntry.new("zf.zip", "a/b"),
  688. ZipEntry.new("zf.zip", "a/b/"),
  689. ZipEntry.new("zf.zip", "a/b/c"),
  690. ZipEntry.new("zf.zip", "a/b/c/")
  691. ]
  692. entrySet = ZipEntrySet.new(entries)
  693. assert_equal(nil, entrySet.parent(entries[0]))
  694. assert_equal(nil, entrySet.parent(entries[1]))
  695. assert_equal(entries[1], entrySet.parent(entries[2]))
  696. assert_equal(entries[1], entrySet.parent(entries[3]))
  697. assert_equal(entries[3], entrySet.parent(entries[4]))
  698. assert_equal(entries[3], entrySet.parent(entries[5]))
  699. end
  700. def test_glob
  701. res = @zipEntrySet.glob('name[2-4]')
  702. assert_equal(3, res.size)
  703. assert_equal(ZIP_ENTRIES[1,3], res)
  704. end
  705. def test_glob2
  706. entries = [
  707. ZipEntry.new("zf.zip", "a/"),
  708. ZipEntry.new("zf.zip", "a/b/b1"),
  709. ZipEntry.new("zf.zip", "a/b/c/"),
  710. ZipEntry.new("zf.zip", "a/b/c/c1")
  711. ]
  712. entrySet = ZipEntrySet.new(entries)
  713. assert_equal(entries[0,1], entrySet.glob("*"))
  714. # assert_equal(entries[FIXME], entrySet.glob("**"))
  715. # res = entrySet.glob('a*')
  716. # assert_equal(entries.size, res.size)
  717. # assert_equal(entrySet.map { |e| e.name }, res.map { |e| e.name })
  718. end
  719. end
  720. class ZipCentralDirectoryTest < Test::Unit::TestCase
  721. def test_read_from_stream
  722. File.open(TestZipFile::TEST_ZIP2.zip_name, "rb") {
  723. |zipFile|
  724. cdir = ZipCentralDirectory.read_from_stream(zipFile)
  725. assert_equal(TestZipFile::TEST_ZIP2.entry_names.size, cdir.size)
  726. assert(cdir.entries.sort.compare_enumerables(TestZipFile::TEST_ZIP2.entry_names.sort) {
  727. |cdirEntry, testEntryName|
  728. cdirEntry.name == testEntryName
  729. })
  730. assert_equal(TestZipFile::TEST_ZIP2.comment, cdir.comment)
  731. }
  732. end
  733. def test_readFromInvalidStream
  734. File.open("data/file2.txt", "rb") {
  735. |zipFile|
  736. cdir = ZipCentralDirectory.new
  737. cdir.read_from_stream(zipFile)
  738. }
  739. fail "ZipError expected!"
  740. rescue ZipError
  741. end
  742. def test_ReadFromTruncatedZipFile
  743. fragment=""
  744. File.open("data/testDirectory.bin") { |f| fragment = f.read }
  745. fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete
  746. fragment.extend(IOizeString)
  747. entry = ZipCentralDirectory.new
  748. entry.read_from_stream(fragment)
  749. fail "ZipError expected"
  750. rescue ZipError
  751. end
  752. def test_write_to_stream
  753. entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"),
  754. ZipEntry.new("file.zip", "secondEntryName"),
  755. ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ]
  756. cdir = ZipCentralDirectory.new(entries, "my zip comment")
  757. File.open("cdirtest.bin", "wb") { |f| cdir.write_to_stream(f) }
  758. cdirReadback = ZipCentralDirectory.new
  759. File.open("cdirtest.bin", "rb") { |f| cdirReadback.read_from_stream(f) }
  760. assert_equal(cdir.entries.sort, cdirReadback.entries.sort)
  761. end
  762. def test_equality
  763. cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
  764. "somethingExtra"),
  765. ZipEntry.new("file.zip", "secondEntryName"),
  766. ZipEntry.new("file.zip", "lastEntry.txt") ],
  767. "my zip comment")
  768. cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
  769. "somethingExtra"),
  770. ZipEntry.new("file.zip", "secondEntryName"),
  771. ZipEntry.new("file.zip", "lastEntry.txt") ],
  772. "my zip comment")
  773. cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
  774. "somethingExtra"),
  775. ZipEntry.new("file.zip", "secondEntryName"),
  776. ZipEntry.new("file.zip", "lastEntry.txt") ],
  777. "comment?")
  778. cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil,
  779. "somethingExtra"),
  780. ZipEntry.new("file.zip", "lastEntry.txt") ],
  781. "comment?")
  782. assert_equal(cdir1, cdir1)
  783. assert_equal(cdir1, cdir2)
  784. assert(cdir1 != cdir3)
  785. assert(cdir2 != cdir3)
  786. assert(cdir2 != cdir3)
  787. assert(cdir3 != cdir4)
  788. assert(cdir3 != "hello")
  789. end
  790. end
  791. class BasicZipFileTest < Test::Unit::TestCase
  792. include AssertEntry
  793. def setup
  794. @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zip_name)
  795. @testEntryNameIndex=0
  796. end
  797. def test_entries
  798. assert_equal(TestZipFile::TEST_ZIP2.entry_names.sort,
  799. @zipFile.entries.entries.sort.map {|e| e.name} )
  800. end
  801. def test_each
  802. count = 0
  803. visited = {}
  804. @zipFile.each {
  805. |entry|
  806. assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name))
  807. assert(! visited.include?(entry.name))
  808. visited[entry.name] = nil
  809. count = count.succ
  810. }
  811. assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count)
  812. end
  813. def test_foreach
  814. count = 0
  815. visited = {}
  816. ZipFile.foreach(TestZipFile::TEST_ZIP2.zip_name) {
  817. |entry|
  818. assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name))
  819. assert(! visited.include?(entry.name))
  820. visited[entry.name] = nil
  821. count = count.succ
  822. }
  823. assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count)
  824. end
  825. def test_get_input_stream
  826. count = 0
  827. visited = {}
  828. @zipFile.each {
  829. |entry|
  830. assert_entry(entry.name, @zipFile.get_input_stream(entry), entry.name)
  831. assert(! visited.include?(entry.name))
  832. visited[entry.name] = nil
  833. count = count.succ
  834. }
  835. assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count)
  836. end
  837. def test_get_input_streamBlock
  838. fileAndEntryName = @zipFile.entries.first.name
  839. @zipFile.get_input_stream(fileAndEntryName) {
  840. |zis|
  841. assert_entryContentsForStream(fileAndEntryName,
  842. zis,
  843. fileAndEntryName)
  844. }
  845. end
  846. end
  847. module CommonZipFileFixture
  848. include AssertEntry
  849. EMPTY_FILENAME = "emptyZipFile.zip"
  850. TEST_ZIP = TestZipFile::TEST_ZIP2.clone
  851. TEST_ZIP.zip_name = "5entry_copy.zip"
  852. def setup
  853. FileUtils.rm(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME)
  854. FileUtils.cp(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name)
  855. end
  856. end
  857. class ZipFileTest < Test::Unit::TestCase
  858. include CommonZipFileFixture
  859. def test_createFromScratch
  860. comment = "a short comment"
  861. zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE)
  862. zf.get_output_stream("myFile") { |os| os.write "myFile contains just this" }
  863. zf.mkdir("dir1")
  864. zf.comment = comment
  865. zf.close
  866. zfRead = ZipFile.new(EMPTY_FILENAME)
  867. assert_equal(comment, zfRead.comment)
  868. assert_equal(2, zfRead.entries.length)
  869. end
  870. def test_get_output_stream
  871. entryCount = nil
  872. ZipFile.open(TEST_ZIP.zip_name) {
  873. |zf|
  874. entryCount = zf.size
  875. zf.get_output_stream('newEntry.txt') {
  876. |os|
  877. os.write "Putting stuff in newEntry.txt"
  878. }
  879. assert_equal(entryCount+1, zf.size)
  880. assert_equal("Putting stuff in newEntry.txt", zf.read("newEntry.txt"))
  881. zf.get_output_stream(zf.get_entry('data/generated/empty.txt')) {
  882. |os|
  883. os.write "Putting stuff in data/generated/empty.txt"
  884. }
  885. assert_equal(entryCount+1, zf.size)
  886. assert_equal("Putting stuff in data/generated/empty.txt", zf.read("data/generated/empty.txt"))
  887. zf.get_output_stream('entry.bin') {
  888. |os|
  889. os.write(File.open('data/generated/5entry.zip', 'rb').read)
  890. }
  891. }
  892. ZipFile.open(TEST_ZIP.zip_name) {
  893. |zf|
  894. assert_equal(entryCount+2, zf.size)
  895. assert_equal("Putting stuff in newEntry.txt", zf.read("newEntry.txt"))
  896. assert_equal("Putting stuff in data/generated/empty.txt", zf.read("data/generated/empty.txt"))
  897. assert_equal(File.open('data/generated/5entry.zip', 'rb').read, zf.read("entry.bin"))
  898. }
  899. end
  900. def test_add
  901. srcFile = "data/file2.txt"
  902. entryName = "newEntryName.rb"
  903. assert(File.exists?(srcFile))
  904. zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE)
  905. zf.add(entryName, srcFile)
  906. zf.close
  907. zfRead = ZipFile.new(EMPTY_FILENAME)
  908. assert_equal("", zfRead.comment)
  909. assert_equal(1, zfRead.entries.length)
  910. assert_equal(entryName, zfRead.entries.first.name)
  911. AssertEntry.assert_contents(srcFile,
  912. zfRead.get_input_stream(entryName) { |zis| zis.read })
  913. end
  914. def test_addExistingEntryName
  915. assert_raise(ZipEntryExistsError) {
  916. ZipFile.open(TEST_ZIP.zip_name) {
  917. |zf|
  918. zf.add(zf.entries.first.name, "data/file2.txt")
  919. }
  920. }
  921. end
  922. def test_addExistingEntryNameReplace
  923. gotCalled = false
  924. replacedEntry = nil
  925. ZipFile.open(TEST_ZIP.zip_name) {
  926. |zf|
  927. replacedEntry = zf.entries.first.name
  928. zf.add(replacedEntry, "data/file2.txt") { gotCalled = true; true }
  929. }
  930. assert(gotCalled)
  931. ZipFile.open(TEST_ZIP.zip_name) {
  932. |zf|
  933. assert_contains(zf, replacedEntry, "data/file2.txt")
  934. }
  935. end
  936. def test_addDirectory
  937. ZipFile.open(TEST_ZIP.zip_name) {
  938. |zf|
  939. zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR)
  940. }
  941. ZipFile.open(TEST_ZIP.zip_name) {
  942. |zf|
  943. dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" }
  944. assert(dirEntry.is_directory)
  945. }
  946. end
  947. def test_remove
  948. entryToRemove, *remainingEntries = TEST_ZIP.entry_names
  949. FileUtils.cp(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name)
  950. zf = ZipFile.new(TEST_ZIP.zip_name)
  951. assert(zf.entries.map { |e| e.name }.include?(entryToRemove))
  952. zf.remove(entryToRemove)
  953. assert(! zf.entries.map { |e| e.name }.include?(entryToRemove))
  954. assert_equal(zf.entries.map {|x| x.name }.sort, remainingEntries.sort)
  955. zf.close
  956. zfRead = ZipFile.new(TEST_ZIP.zip_name)
  957. assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove))
  958. assert_equal(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort)
  959. zfRead.close
  960. end
  961. def test_rename
  962. entryToRename, *remainingEntries = TEST_ZIP.entry_names
  963. zf = ZipFile.new(TEST_ZIP.zip_name)
  964. assert(zf.entries.map { |e| e.name }.include?(entryToRename))
  965. newName = "changed name"
  966. assert(! zf.entries.map { |e| e.name }.include?(newName))
  967. zf.rename(entryToRename, newName)
  968. assert(zf.entries.map { |e| e.name }.include?(newName))
  969. zf.close
  970. zfRead = ZipFile.new(TEST_ZIP.zip_name)
  971. assert(zfRead.entries.map { |e| e.name }.include?(newName))
  972. zfRead.close
  973. end
  974. def test_renameToExistingEntry
  975. oldEntries = nil
  976. ZipFile.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries }
  977. assert_raise(ZipEntryExistsError) {
  978. ZipFile.open(TEST_ZIP.zip_name) {
  979. |zf|
  980. zf.rename(zf.entries[0], zf.entries[1].name)
  981. }
  982. }
  983. ZipFile.open(TEST_ZIP.zip_name) {
  984. |zf|
  985. assert_equal(oldEntries.sort.map{ |e| e.name }, zf.entries.sort.map{ |e| e.name })
  986. }
  987. end
  988. def test_renameToExistingEntryOverwrite
  989. oldEntries = nil
  990. ZipFile.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries }
  991. gotCalled = false
  992. renamedEntryName = nil
  993. ZipFile.open(TEST_ZIP.zip_name) {
  994. |zf|
  995. renamedEntryName = zf.entries[0].name
  996. zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true }
  997. }
  998. assert(gotCalled)
  999. oldEntries.delete_if { |e| e.name == renamedEntryName }
  1000. ZipFile.open(TEST_ZIP.zip_name) {
  1001. |zf|
  1002. assert_equal(oldEntries.sort.map{ |e| e.name },
  1003. zf.entries.sort.map{ |e| e.name })
  1004. }
  1005. end
  1006. def test_renameNonEntry
  1007. nonEntry = "bogusEntry"
  1008. target_entry = "target_entryName"
  1009. zf = ZipFile.new(TEST_ZIP.zip_name)
  1010. assert(! zf.entries.include?(nonEntry))
  1011. assert_raise(Errno::ENOENT) {
  1012. zf.rename(nonEntry, target_entry)
  1013. }
  1014. zf.commit
  1015. assert(! zf.entries.include?(target_entry))
  1016. ensure
  1017. zf.close
  1018. end
  1019. def test_renameEntryToExistingEntry
  1020. entry1, entry2, *remaining = TEST_ZIP.entry_names
  1021. zf = ZipFile.new(TEST_ZIP.zip_name)
  1022. assert_raise(ZipEntryExistsError) {
  1023. zf.rename(entry1, entry2)
  1024. }
  1025. ensure
  1026. zf.close
  1027. end
  1028. def test_replace
  1029. entryToReplace = TEST_ZIP.entry_names[2]
  1030. newEntrySrcFilename = "data/file2.txt"
  1031. zf = ZipFile.new(TEST_ZIP.zip_name)
  1032. zf.replace(entryToReplace, newEntrySrcFilename)
  1033. zf.close
  1034. zfRead = ZipFile.new(TEST_ZIP.zip_name)
  1035. AssertEntry::assert_contents(newEntrySrcFilename,
  1036. zfRead.get_input_stream(entryToReplace) { |is| is.read })
  1037. AssertEntry::assert_contents(TEST_ZIP.entry_names[0],
  1038. zfRead.get_input_stream(TEST_ZIP.entry_names[0]) { |is| is.read })
  1039. AssertEntry::assert_contents(TEST_ZIP.entry_names[1],
  1040. zfRead.get_input_stream(TEST_ZIP.entry_names[1]) { |is| is.read })
  1041. AssertEntry::assert_contents(TEST_ZIP.entry_names[3],
  1042. zfRead.get_input_stream(TEST_ZIP.entry_names[3]) { |is| is.read })
  1043. zfRead.close
  1044. end
  1045. def test_replaceNonEntry
  1046. entryToReplace = "nonExistingEntryname"
  1047. ZipFile.open(TEST_ZIP.zip_name) {
  1048. |zf|
  1049. assert_raise(Errno::ENOENT) {
  1050. zf.replace(entryToReplace, "data/file2.txt")
  1051. }
  1052. }
  1053. end
  1054. def test_commit
  1055. newName = "renamedFirst"
  1056. zf = ZipFile.new(TEST_ZIP.zip_name)
  1057. oldName = zf.entries.first
  1058. zf.rename(oldName, newName)
  1059. zf.commit
  1060. zfRead = ZipFile.new(TEST_ZIP.zip_name)
  1061. assert(zfRead.entries.detect { |e| e.name == newName } != nil)
  1062. assert(zfRead.entries.detect { |e| e.name == oldName } == nil)
  1063. zfRead.close
  1064. zf.close
  1065. end
  1066. # This test tests that after commit, you
  1067. # can delete the file you used to add the entry to the zip file
  1068. # with
  1069. def test_commitUseZipEntry
  1070. FileUtils.cp(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt")
  1071. zf = ZipFile.open(TEST_ZIP.zip_name)
  1072. zf.add("okToDelete.txt", "okToDelete.txt")
  1073. assert_contains(zf, "okToDelete.txt")
  1074. zf.commit
  1075. FileUtils.mv("okToDelete.txt", "okToDeleteMoved.txt")
  1076. assert_contains(zf, "okToDelete.txt", "okToDeleteMoved.txt")
  1077. end
  1078. # def test_close
  1079. # zf = ZipFile.new(TEST_ZIP.zip_name)
  1080. # zf.close
  1081. # assert_raise(IOError) {
  1082. # zf.extract(TEST_ZIP.entry_names.first, "hullubullu")
  1083. # }
  1084. # end
  1085. def test_compound1
  1086. renamedName = "renamedName"
  1087. originalEntries = []
  1088. begin
  1089. zf = ZipFile.new(TEST_ZIP.zip_name)
  1090. originalEntries = zf.entries.dup
  1091. assert_not_contains(zf, TestFiles::RANDOM_ASCII_FILE1)
  1092. zf.add(TestFiles::RANDOM_ASCII_FILE1,
  1093. TestFiles::RANDOM_ASCII_FILE1)
  1094. assert_contains(zf, TestFiles::RANDOM_ASCII_FILE1)
  1095. zf.rename(zf.entries[0], renamedName)
  1096. assert_contains(zf, renamedName)
  1097. TestFiles::BINARY_TEST_FILES.each {
  1098. |filename|
  1099. zf.add(filename, filename)
  1100. assert_contains(zf, filename)
  1101. }
  1102. assert_contains(zf, originalEntries.last.to_s)
  1103. zf.remove(originalEntries.last.to_s)
  1104. assert_not_contains(zf, originalEntries.last.to_s)
  1105. ensure
  1106. zf.close
  1107. end
  1108. begin
  1109. zfRead = ZipFile.new(TEST_ZIP.zip_name)
  1110. assert_contains(zfRead, TestFiles::RANDOM_ASCII_FILE1)
  1111. assert_contains(zfRead, renamedName)
  1112. TestFiles::BINARY_TEST_FILES.each {
  1113. |filename|
  1114. assert_contains(zfRead, filename)
  1115. }
  1116. assert_not_contains(zfRead, originalEntries.last.to_s)
  1117. ensure
  1118. zfRead.close
  1119. end
  1120. end
  1121. def test_compound2
  1122. begin
  1123. zf = ZipFile.new(TEST_ZIP.zip_name)
  1124. originalEntries = zf.entries.dup
  1125. originalEntries.each {
  1126. |entry|
  1127. zf.remove(entry)
  1128. assert_not_contains(zf, entry)
  1129. }
  1130. assert(zf.entries.empty?)
  1131. TestFiles::ASCII_TEST_FILES.each {
  1132. |filename|
  1133. zf.add(filename, filename)
  1134. assert_contains(zf, filename)
  1135. }
  1136. assert_equal(zf.entries.sort.map { |e| e.name }, TestFiles::ASCII_TEST_FILES)
  1137. zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName")
  1138. assert_not_contains(zf, TestFiles::ASCII_TEST_FILES[0])
  1139. assert_contains(zf, "newName")
  1140. ensure
  1141. zf.close
  1142. end
  1143. begin
  1144. zfRead = ZipFile.new(TEST_ZIP.zip_name)
  1145. asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup
  1146. asciiTestFiles.shift
  1147. asciiTestFiles.each {
  1148. |filename|
  1149. assert_contains(zf, filename)
  1150. }
  1151. assert_contains(zf, "newName")
  1152. ensure
  1153. zfRead.close
  1154. end
  1155. end
  1156. private
  1157. def assert_contains(zf, entryName, filename = entryName)
  1158. assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}")
  1159. assert_entryContents(zf, entryName, filename) if File.exists?(filename)
  1160. end
  1161. def assert_not_contains(zf, entryName)
  1162. assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}")
  1163. end
  1164. end
  1165. class ZipFileExtractTest < Test::Unit::TestCase
  1166. include CommonZipFileFixture
  1167. EXTRACTED_FILENAME = "extEntry"
  1168. ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entry_names.reverse
  1169. def setup
  1170. super
  1171. FileUtils.rm(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME)
  1172. end
  1173. def test_extract
  1174. ZipFile.open(TEST_ZIP.zip_name) {
  1175. |zf|
  1176. zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME)
  1177. assert(File.exists?(EXTRACTED_FILENAME))
  1178. AssertEntry::assert_contents(EXTRACTED_FILENAME,
  1179. zf.get_input_stream(ENTRY_TO_EXTRACT) { |is| is.read })
  1180. File::unlink(EXTRACTED_FILENAME)
  1181. entry = zf.get_entry(ENTRY_TO_EXTRACT)
  1182. entry.extract(EXTRACTED_FILENAME)
  1183. assert(File.exists?(EXTRACTED_FILENAME))
  1184. AssertEntry::assert_contents(EXTRACTED_FILENAME,
  1185. entry.get_input_stream() { |is| is.read })
  1186. }
  1187. end
  1188. def test_extractExists
  1189. writtenText = "written text"
  1190. File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) }
  1191. assert_raise(ZipDestinationFileExistsError) {
  1192. ZipFile.open(TEST_ZIP.zip_name) {
  1193. |zf|
  1194. zf.extract(zf.entries.first, EXTRACTED_FILENAME)
  1195. }
  1196. }
  1197. File.open(EXTRACTED_FILENAME, "r") {
  1198. |f|
  1199. assert_equal(writtenText, f.read)
  1200. }
  1201. end
  1202. def test_extractExistsOverwrite
  1203. writtenText = "written text"
  1204. File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) }
  1205. gotCalledCorrectly = false
  1206. ZipFile.open(TEST_ZIP.zip_name) {
  1207. |zf|
  1208. zf.extract(zf.entries.first, EXTRACTED_FILENAME) {
  1209. |entry, extractLoc|
  1210. gotCalledCorrectly = zf.entries.first == entry &&
  1211. extractLoc == EXTRACTED_FILENAME
  1212. true
  1213. }
  1214. }
  1215. assert(gotCalledCorrectly)
  1216. File.open(EXTRACTED_FILENAME, "r") {
  1217. |f|
  1218. assert(writtenText != f.read)
  1219. }
  1220. end
  1221. def test_extractNonEntry
  1222. zf = ZipFile.new(TEST_ZIP.zip_name)
  1223. assert_raise(Errno::ENOENT) { zf.extract("nonExistingEntry", "nonExistingEntry") }
  1224. ensure
  1225. zf.close if zf
  1226. end
  1227. def test_extractNonEntry2
  1228. outFile = "outfile"
  1229. assert_raise(Errno::ENOENT) {
  1230. zf = ZipFile.new(TEST_ZIP.zip_name)
  1231. nonEntry = "hotdog-diddelidoo"
  1232. assert(! zf.entries.include?(nonEntry))
  1233. zf.extract(nonEntry, outFile)
  1234. zf.close
  1235. }
  1236. assert(! File.exists?(outFile))
  1237. end
  1238. end
  1239. class ZipFileExtractDirectoryTest < Test::Unit::TestCase
  1240. include CommonZipFileFixture
  1241. TEST_OUT_NAME = "emptyOutDir"
  1242. def open_zip(&aProc)
  1243. assert(aProc != nil)
  1244. ZipFile.open(TestZipFile::TEST_ZIP4.zip_name, &aProc)
  1245. end
  1246. def extract_test_dir(&aProc)
  1247. open_zip {
  1248. |zf|
  1249. zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc)
  1250. }
  1251. end
  1252. def setup
  1253. super
  1254. Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME
  1255. FileUtils.rm(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME
  1256. end
  1257. def test_extractDirectory
  1258. extract_test_dir
  1259. assert(File.directory?(TEST_OUT_NAME))
  1260. end
  1261. def test_extractDirectoryExistsAsDir
  1262. Dir.mkdir TEST_OUT_NAME
  1263. extract_test_dir
  1264. assert(File.directory?(TEST_OUT_NAME))
  1265. end
  1266. def test_extractDirectoryExistsAsFile
  1267. File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
  1268. assert_raise(ZipDestinationFileExistsError) { extract_test_dir }
  1269. end
  1270. def test_extractDirectoryExistsAsFileOverwrite
  1271. File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
  1272. gotCalled = false
  1273. extract_test_dir {
  1274. |entry, destPath|
  1275. gotCalled = true
  1276. assert_equal(TEST_OUT_NAME, destPath)
  1277. assert(entry.is_directory)
  1278. true
  1279. }
  1280. assert(gotCalled)
  1281. assert(File.directory?(TEST_OUT_NAME))
  1282. end
  1283. end
  1284. class ZipExtraFieldTest < Test::Unit::TestCase
  1285. def test_new
  1286. extra_pure = ZipExtraField.new("")
  1287. extra_withstr = ZipExtraField.new("foo")
  1288. assert_instance_of(ZipExtraField, extra_pure)
  1289. assert_instance_of(ZipExtraField, extra_withstr)
  1290. end
  1291. def test_unknownfield
  1292. extra = ZipExtraField.new("foo")
  1293. assert_equal(extra["Unknown"], "foo")
  1294. extra.merge("a")
  1295. assert_equal(extra["Unknown"], "fooa")
  1296. extra.merge("barbaz")
  1297. assert_equal(extra.to_s, "fooabarbaz")
  1298. end
  1299. def test_merge
  1300. str = "UT\x5\0\x3\250$\r@Ux\0\0"
  1301. extra1 = ZipExtraField.new("")
  1302. extra2 = ZipExtraField.new(str)
  1303. assert(! extra1.member?("UniversalTime"))
  1304. assert(extra2.member?("UniversalTime"))
  1305. extra1.merge(str)
  1306. assert_equal(extra1["UniversalTime"].mtime, extra2["UniversalTime"].mtime)
  1307. end
  1308. def test_length
  1309. str = "UT\x5\0\x3\250$\r@Ux\0\0Te\0\0testit"
  1310. extra = ZipExtraField.new(str)
  1311. assert_equal(extra.local_length, extra.to_local_bin.length)
  1312. assert_equal(extra.c_dir_length, extra.to_c_dir_bin.length)
  1313. extra.merge("foo")
  1314. assert_equal(extra.local_length, extra.to_local_bin.length)
  1315. assert_equal(extra.c_dir_length, extra.to_c_dir_bin.length)
  1316. end
  1317. def test_to_s
  1318. str = "UT\x5\0\x3\250$\r@Ux\0\0Te\0\0testit"
  1319. extra = ZipExtraField.new(str)
  1320. assert_instance_of(String, extra.to_s)
  1321. s = extra.to_s
  1322. extra.merge("foo")
  1323. assert_equal(s.length + 3, extra.to_s.length)
  1324. end
  1325. def test_equality
  1326. str = "UT\x5\0\x3\250$\r@"
  1327. extra1 = ZipExtraField.new(str)
  1328. extra2 = ZipExtraField.new(str)
  1329. extra3 = ZipExtraField.new(str)
  1330. assert_equal(extra1, extra2)
  1331. extra2["UniversalTime"].mtime = Time.now
  1332. assert(extra1 != extra2)
  1333. extra3.create("IUnix")
  1334. assert(extra1 != extra3)
  1335. extra1.create("IUnix")
  1336. assert_equal(extra1, extra3)
  1337. end
  1338. end
  1339. # Copyright (C) 2002-2005 Thomas Sondergaard
  1340. # rubyzip is free software; you can redistribute it and/or
  1341. # modify it under the terms of the ruby license.