1require 'rubygems/test_case' 2require 'rubygems/package' 3 4## 5# A test case for Gem::Package::Tar* classes 6 7class Gem::Package::TarTestCase < Gem::TestCase 8 9 def ASCIIZ(str, length) 10 str + "\0" * (length - str.length) 11 end 12 13 def SP(s) 14 s + " " 15 end 16 17 def SP_Z(s) 18 s + " \0" 19 end 20 21 def Z(s) 22 s + "\0" 23 end 24 25 def assert_headers_equal(expected, actual) 26 expected = expected.to_s unless String === expected 27 actual = actual.to_s unless String === actual 28 29 fields = %w[ 30 name 100 31 mode 8 32 uid 8 33 gid 8 34 size 12 35 mtime 12 36 checksum 8 37 typeflag 1 38 linkname 100 39 magic 6 40 version 2 41 uname 32 42 gname 32 43 devmajor 8 44 devminor 8 45 prefix 155 46 ] 47 48 offset = 0 49 50 until fields.empty? do 51 name = fields.shift 52 length = fields.shift.to_i 53 54 if name == "checksum" then 55 chksum_off = offset 56 offset += length 57 next 58 end 59 60 assert_equal expected[offset, length], actual[offset, length], 61 "Field #{name} of the tar header differs." 62 63 offset += length 64 end 65 66 assert_equal expected[chksum_off, 8], actual[chksum_off, 8] 67 end 68 69 def calc_checksum(header) 70 sum = header.unpack("C*").inject{|s,a| s + a} 71 SP(Z(to_oct(sum, 6))) 72 end 73 74 def header(type, fname, dname, length, mode, checksum = nil) 75 checksum ||= " " * 8 76 77 arr = [ # struct tarfile_entry_posix 78 ASCIIZ(fname, 100), # char name[100]; ASCII + (Z unless filled) 79 Z(to_oct(mode, 7)), # char mode[8]; 0 padded, octal null 80 Z(to_oct(0, 7)), # char uid[8]; ditto 81 Z(to_oct(0, 7)), # char gid[8]; ditto 82 Z(to_oct(length, 11)), # char size[12]; 0 padded, octal, null 83 Z(to_oct(0, 11)), # char mtime[12]; 0 padded, octal, null 84 checksum, # char checksum[8]; 0 padded, octal, null, space 85 type, # char typeflag[1]; file: "0" dir: "5" 86 "\0" * 100, # char linkname[100]; ASCII + (Z unless filled) 87 "ustar\0", # char magic[6]; "ustar\0" 88 "00", # char version[2]; "00" 89 ASCIIZ("wheel", 32), # char uname[32]; ASCIIZ 90 ASCIIZ("wheel", 32), # char gname[32]; ASCIIZ 91 Z(to_oct(0, 7)), # char devmajor[8]; 0 padded, octal, null 92 Z(to_oct(0, 7)), # char devminor[8]; 0 padded, octal, null 93 ASCIIZ(dname, 155) # char prefix[155]; ASCII + (Z unless filled) 94 ] 95 96 format = "C100C8C8C8C12C12C8CC100C6C2C32C32C8C8C155" 97 h = if RUBY_VERSION >= "1.9" then 98 arr.join 99 else 100 arr = arr.join("").split(//).map{|x| x[0]} 101 arr.pack format 102 end 103 ret = h + "\0" * (512 - h.size) 104 assert_equal(512, ret.size) 105 ret 106 end 107 108 def tar_dir_header(name, prefix, mode) 109 h = header("5", name, prefix, 0, mode) 110 checksum = calc_checksum(h) 111 header("5", name, prefix, 0, mode, checksum) 112 end 113 114 def tar_file_header(fname, dname, mode, length) 115 h = header("0", fname, dname, length, mode) 116 checksum = calc_checksum(h) 117 header("0", fname, dname, length, mode, checksum) 118 end 119 120 def to_oct(n, pad_size) 121 "%0#{pad_size}o" % n 122 end 123 124 def util_entry(tar) 125 io = TempIO.new tar 126 127 header = Gem::Package::TarHeader.from io 128 129 Gem::Package::TarReader::Entry.new header, io 130 end 131 132 def util_dir_entry 133 util_entry tar_dir_header("foo", "bar", 0) 134 end 135 136end 137 138