diff options
Diffstat (limited to 'test/rubygems/test_gem_package_tar_reader_entry.rb')
-rw-r--r-- | test/rubygems/test_gem_package_tar_reader_entry.rb | 238 |
1 files changed, 222 insertions, 16 deletions
diff --git a/test/rubygems/test_gem_package_tar_reader_entry.rb b/test/rubygems/test_gem_package_tar_reader_entry.rb index 1be5870146..67ab7922b5 100644 --- a/test/rubygems/test_gem_package_tar_reader_entry.rb +++ b/test/rubygems/test_gem_package_tar_reader_entry.rb @@ -1,17 +1,17 @@ # frozen_string_literal: true -require_relative 'package/tar_test_case' -require 'rubygems/package' + +require_relative "package/tar_test_case" +require "rubygems/package" class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase def setup super - @contents = ('a'..'z').to_a.join * 100 + @contents = ("a".."z").to_a.join * 100 @tar = String.new @tar << tar_file_header("lib/foo", "", 0, @contents.size, Time.now) - @tar << @contents - @tar << "\0" * (512 - (@tar.size % 512)) + @tar << tar_file_contents(@contents) @entry = util_entry @tar end @@ -21,8 +21,39 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase super end - def close_util_entry(entry) - entry.instance_variable_get(:@io).close! + def test_open + io = TempIO.new @tar + header = Gem::Package::TarHeader.from io + retval = Gem::Package::TarReader::Entry.open header, io, &:getc + assert_equal "a", retval + assert_equal @tar.size, io.pos, "should have read to end of entry" + ensure + io&.close! + end + + def test_open_closes_entry + io = TempIO.new @tar + header = Gem::Package::TarHeader.from io + entry = nil + Gem::Package::TarReader::Entry.open header, io do |e| + entry = e + end + assert entry.closed? + assert_raise(IOError) { entry.getc } + ensure + io&.close! + end + + def test_open_returns_entry + io = TempIO.new @tar + header = Gem::Package::TarHeader.from io + entry = Gem::Package::TarReader::Entry.open header, io + refute entry.closed? + assert_equal "a", entry.getc + assert_nil entry.close + assert entry.closed? + ensure + io&.close! end def test_bytes_read @@ -43,19 +74,19 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase assert @entry.bytes_read e = assert_raise(IOError) { @entry.eof? } - assert_equal 'closed Gem::Package::TarReader::Entry', e.message + assert_equal "closed Gem::Package::TarReader::Entry", e.message e = assert_raise(IOError) { @entry.getc } - assert_equal 'closed Gem::Package::TarReader::Entry', e.message + assert_equal "closed Gem::Package::TarReader::Entry", e.message e = assert_raise(IOError) { @entry.pos } - assert_equal 'closed Gem::Package::TarReader::Entry', e.message + assert_equal "closed Gem::Package::TarReader::Entry", e.message e = assert_raise(IOError) { @entry.read } - assert_equal 'closed Gem::Package::TarReader::Entry', e.message + assert_equal "closed Gem::Package::TarReader::Entry", e.message e = assert_raise(IOError) { @entry.rewind } - assert_equal 'closed Gem::Package::TarReader::Entry', e.message + assert_equal "closed Gem::Package::TarReader::Entry", e.message end def test_closed_eh @@ -71,7 +102,7 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase end def test_full_name - assert_equal 'lib/foo', @entry.full_name + assert_equal "lib/foo", @entry.full_name end def test_full_name_null @@ -82,11 +113,11 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase @entry.full_name end - assert_equal 'tar is corrupt, name contains null byte', e.message + assert_equal "tar is corrupt, name contains null byte", e.message end def test_getc - assert_equal ?a, @entry.getc + assert_equal "a", @entry.getc end def test_directory_eh @@ -125,6 +156,18 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase assert_equal @contents, @entry.read end + def test_consecutive_read + expected = StringIO.new(@contents) + assert_equal expected.read, @entry.read + assert_equal expected.read, @entry.read + end + + def test_consecutive_read_bytes_past_eof + expected = StringIO.new(@contents) + assert_equal expected.read, @entry.read + assert_equal expected.read(1), @entry.read(1) + end + def test_read_big assert_equal @contents, @entry.read(@contents.size * 2) end @@ -133,13 +176,64 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase assert_equal @contents[0...100], @entry.read(100) end + def test_read_remaining + @entry.read(100) + assert_equal @contents[100..-1], @entry.read + end + def test_readpartial + assert_equal @contents[0...100], @entry.readpartial(100) + end + + def test_readpartial_to_eof + assert_equal @contents, @entry.readpartial(4096) + assert @entry.eof? + end + + def test_read_partial_buffer + buffer = "".b + @entry.readpartial(100, buffer) + assert_equal @contents[0...100], buffer + end + + def test_readpartial_past_eof + @entry.readpartial(@contents.size) + assert @entry.eof? assert_raise(EOFError) do - @entry.read(@contents.size) @entry.readpartial(1) end end + def test_read_corrupted_tar + corrupt_tar = String.new + corrupt_tar << tar_file_header("lib/foo", "", 0, 100, Time.now) + corrupt_tar << tar_file_contents("") + corrupt_entry = util_entry corrupt_tar + + assert_equal "", corrupt_entry.read(0) + assert_equal "", corrupt_entry.read, "IO.read without len should return empty string (even though it's at an unpexpected EOF)" + + corrupt_entry.rewind + + assert_nil corrupt_entry.read(100), "IO.read with len should return nil as per IO.read docs" + ensure + close_util_entry(corrupt_entry) if corrupt_entry + end + + def test_readpartial_corrupted_tar + corrupt_tar = String.new + corrupt_tar << tar_file_header("lib/foo", "", 0, 100, Time.now) + corrupt_tar << tar_file_contents("") + + corrupt_entry = util_entry corrupt_tar + + assert_raise EOFError do + corrupt_entry.readpartial(100) + end + ensure + close_util_entry(corrupt_entry) if corrupt_entry + end + def test_rewind char = @entry.getc @@ -149,4 +243,116 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase assert_equal char, @entry.getc end + + def test_seek + @entry.seek(50) + assert_equal 50, @entry.pos + assert_equal @contents[50..-1], @entry.read, "read remaining after seek" + @entry.seek(-50, IO::SEEK_CUR) + assert_equal @contents.size - 50, @entry.pos + assert_equal @contents[-50..-1], @entry.read, "read after stepping back 50 from the end" + @entry.seek(0, IO::SEEK_SET) + assert_equal 0, @entry.pos + assert_equal @contents, @entry.read, "read from beginning" + @entry.seek(-10, IO::SEEK_END) + assert_equal @contents.size - 10, @entry.pos + assert_equal @contents[-10..-1], @entry.read, "read from end" + end + + def test_read_zero + expected = StringIO.new("") + assert_equal expected.read(0), @entry.read(0) + end + + def test_readpartial_zero + expected = StringIO.new("") + assert_equal expected.readpartial(0), @entry.readpartial(0) + end + + def test_zero_byte_file_read + zero_entry = util_entry(tar_file_header("foo", "", 0, 0, Time.now)) + expected = StringIO.new("") + assert_equal expected.read, zero_entry.read + ensure + close_util_entry(zero_entry) if zero_entry + end + + def test_zero_byte_file_readpartial + zero_entry = util_entry(tar_file_header("foo", "", 0, 0, Time.now)) + expected = StringIO.new("") + assert_equal expected.readpartial(0), zero_entry.readpartial(0) + ensure + close_util_entry(zero_entry) if zero_entry + end + + def test_read_from_gzip_io + tgz = util_gzip(@tar) + + Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio| + entry = util_entry(gzio) + assert_equal @contents, entry.read + entry.rewind + assert_equal @contents, entry.read, "second read after rewind should read same contents" + end + end + + def test_read_from_gzip_io_with_non_zero_offset + contents2 = ("0".."9").to_a.join * 100 + @tar << tar_file_header("lib/bar", "", 0, contents2.size, Time.now) + @tar << tar_file_contents(contents2) + + tgz = util_gzip(@tar) + + Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio| + util_entry(gzio).close # skip the first entry so io.pos is not 0, preventing easy rewind + entry = util_entry(gzio) + + assert_equal contents2, entry.read + entry.rewind + assert_equal contents2, entry.read, "second read after rewind should read same contents" + end + end + + def test_seek_in_gzip_io_with_non_zero_offset + contents2 = ("0".."9").to_a.join * 100 + @tar << tar_file_header("lib/bar", "", 0, contents2.size, Time.now) + @tar << tar_file_contents(contents2) + + tgz = util_gzip(@tar) + + Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio| + util_entry(gzio).close # skip the first entry so io.pos is not 0 + entry = util_entry(gzio) + + entry.seek(50) + assert_equal 50, entry.pos + assert_equal contents2[50..-1], entry.read, "read remaining after seek" + entry.seek(-50, IO::SEEK_CUR) + assert_equal contents2.size - 50, entry.pos + assert_equal contents2[-50..-1], entry.read, "read after stepping back 50 from the end" + entry.seek(0, IO::SEEK_SET) + assert_equal 0, entry.pos + assert_equal contents2, entry.read, "read from beginning" + entry.seek(-10, IO::SEEK_END) + assert_equal contents2.size - 10, entry.pos + assert_equal contents2[-10..-1], entry.read, "read from end" + assert_equal contents2.size, entry.pos + end + end + + def test_seek_in_gzip_io_corrupted + @tar << tar_file_header("lib/bar", "", 0, 100, Time.now) + @tar << tar_file_contents("") + + tgz = util_gzip(@tar) + + Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio| + util_entry(gzio).close # skip the first entry so io.pos is not 0 + entry = util_entry(gzio) + + assert_raise EOFError do + entry.seek(50) + end + end + end end |