PageRenderTime 61ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/zip/test/ziptest.rb

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