Home | History | Annotate | Download | only in tar
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package tar
      6 
      7 import (
      8 	"math"
      9 	"strings"
     10 	"testing"
     11 	"time"
     12 )
     13 
     14 func TestFitsInBase256(t *testing.T) {
     15 	vectors := []struct {
     16 		in    int64
     17 		width int
     18 		ok    bool
     19 	}{
     20 		{+1, 8, true},
     21 		{0, 8, true},
     22 		{-1, 8, true},
     23 		{1 << 56, 8, false},
     24 		{(1 << 56) - 1, 8, true},
     25 		{-1 << 56, 8, true},
     26 		{(-1 << 56) - 1, 8, false},
     27 		{121654, 8, true},
     28 		{-9849849, 8, true},
     29 		{math.MaxInt64, 9, true},
     30 		{0, 9, true},
     31 		{math.MinInt64, 9, true},
     32 		{math.MaxInt64, 12, true},
     33 		{0, 12, true},
     34 		{math.MinInt64, 12, true},
     35 	}
     36 
     37 	for _, v := range vectors {
     38 		ok := fitsInBase256(v.width, v.in)
     39 		if ok != v.ok {
     40 			t.Errorf("fitsInBase256(%d, %d): got %v, want %v", v.in, v.width, ok, v.ok)
     41 		}
     42 	}
     43 }
     44 
     45 func TestParseNumeric(t *testing.T) {
     46 	vectors := []struct {
     47 		in   string
     48 		want int64
     49 		ok   bool
     50 	}{
     51 		// Test base-256 (binary) encoded values.
     52 		{"", 0, true},
     53 		{"\x80", 0, true},
     54 		{"\x80\x00", 0, true},
     55 		{"\x80\x00\x00", 0, true},
     56 		{"\xbf", (1 << 6) - 1, true},
     57 		{"\xbf\xff", (1 << 14) - 1, true},
     58 		{"\xbf\xff\xff", (1 << 22) - 1, true},
     59 		{"\xff", -1, true},
     60 		{"\xff\xff", -1, true},
     61 		{"\xff\xff\xff", -1, true},
     62 		{"\xc0", -1 * (1 << 6), true},
     63 		{"\xc0\x00", -1 * (1 << 14), true},
     64 		{"\xc0\x00\x00", -1 * (1 << 22), true},
     65 		{"\x87\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
     66 		{"\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
     67 		{"\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
     68 		{"\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
     69 		{"\x80\x7f\xff\xff\xff\xff\xff\xff\xff", math.MaxInt64, true},
     70 		{"\x80\x80\x00\x00\x00\x00\x00\x00\x00", 0, false},
     71 		{"\xff\x80\x00\x00\x00\x00\x00\x00\x00", math.MinInt64, true},
     72 		{"\xff\x7f\xff\xff\xff\xff\xff\xff\xff", 0, false},
     73 		{"\xf5\xec\xd1\xc7\x7e\x5f\x26\x48\x81\x9f\x8f\x9b", 0, false},
     74 
     75 		// Test base-8 (octal) encoded values.
     76 		{"0000000\x00", 0, true},
     77 		{" \x0000000\x00", 0, true},
     78 		{" \x0000003\x00", 3, true},
     79 		{"00000000227\x00", 0227, true},
     80 		{"032033\x00 ", 032033, true},
     81 		{"320330\x00 ", 0320330, true},
     82 		{"0000660\x00 ", 0660, true},
     83 		{"\x00 0000660\x00 ", 0660, true},
     84 		{"0123456789abcdef", 0, false},
     85 		{"0123456789\x00abcdef", 0, false},
     86 		{"01234567\x0089abcdef", 342391, true},
     87 		{"0123\x7e\x5f\x264123", 0, false},
     88 	}
     89 
     90 	for _, v := range vectors {
     91 		var p parser
     92 		got := p.parseNumeric([]byte(v.in))
     93 		ok := (p.err == nil)
     94 		if ok != v.ok {
     95 			if v.ok {
     96 				t.Errorf("parseNumeric(%q): got parsing failure, want success", v.in)
     97 			} else {
     98 				t.Errorf("parseNumeric(%q): got parsing success, want failure", v.in)
     99 			}
    100 		}
    101 		if ok && got != v.want {
    102 			t.Errorf("parseNumeric(%q): got %d, want %d", v.in, got, v.want)
    103 		}
    104 	}
    105 }
    106 
    107 func TestFormatNumeric(t *testing.T) {
    108 	vectors := []struct {
    109 		in   int64
    110 		want string
    111 		ok   bool
    112 	}{
    113 		// Test base-8 (octal) encoded values.
    114 		{0, "0\x00", true},
    115 		{7, "7\x00", true},
    116 		{8, "\x80\x08", true},
    117 		{077, "77\x00", true},
    118 		{0100, "\x80\x00\x40", true},
    119 		{0, "0000000\x00", true},
    120 		{0123, "0000123\x00", true},
    121 		{07654321, "7654321\x00", true},
    122 		{07777777, "7777777\x00", true},
    123 		{010000000, "\x80\x00\x00\x00\x00\x20\x00\x00", true},
    124 		{0, "00000000000\x00", true},
    125 		{000001234567, "00001234567\x00", true},
    126 		{076543210321, "76543210321\x00", true},
    127 		{012345670123, "12345670123\x00", true},
    128 		{077777777777, "77777777777\x00", true},
    129 		{0100000000000, "\x80\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00", true},
    130 		{math.MaxInt64, "777777777777777777777\x00", true},
    131 
    132 		// Test base-256 (binary) encoded values.
    133 		{-1, "\xff", true},
    134 		{-1, "\xff\xff", true},
    135 		{-1, "\xff\xff\xff", true},
    136 		{(1 << 0), "0", false},
    137 		{(1 << 8) - 1, "\x80\xff", true},
    138 		{(1 << 8), "0\x00", false},
    139 		{(1 << 16) - 1, "\x80\xff\xff", true},
    140 		{(1 << 16), "00\x00", false},
    141 		{-1 * (1 << 0), "\xff", true},
    142 		{-1*(1<<0) - 1, "0", false},
    143 		{-1 * (1 << 8), "\xff\x00", true},
    144 		{-1*(1<<8) - 1, "0\x00", false},
    145 		{-1 * (1 << 16), "\xff\x00\x00", true},
    146 		{-1*(1<<16) - 1, "00\x00", false},
    147 		{537795476381659745, "0000000\x00", false},
    148 		{537795476381659745, "\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", true},
    149 		{-615126028225187231, "0000000\x00", false},
    150 		{-615126028225187231, "\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", true},
    151 		{math.MaxInt64, "0000000\x00", false},
    152 		{math.MaxInt64, "\x80\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff", true},
    153 		{math.MinInt64, "0000000\x00", false},
    154 		{math.MinInt64, "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
    155 		{math.MaxInt64, "\x80\x7f\xff\xff\xff\xff\xff\xff\xff", true},
    156 		{math.MinInt64, "\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
    157 	}
    158 
    159 	for _, v := range vectors {
    160 		var f formatter
    161 		got := make([]byte, len(v.want))
    162 		f.formatNumeric(got, v.in)
    163 		ok := (f.err == nil)
    164 		if ok != v.ok {
    165 			if v.ok {
    166 				t.Errorf("formatNumeric(%d): got formatting failure, want success", v.in)
    167 			} else {
    168 				t.Errorf("formatNumeric(%d): got formatting success, want failure", v.in)
    169 			}
    170 		}
    171 		if string(got) != v.want {
    172 			t.Errorf("formatNumeric(%d): got %q, want %q", v.in, got, v.want)
    173 		}
    174 	}
    175 }
    176 
    177 func TestFitsInOctal(t *testing.T) {
    178 	vectors := []struct {
    179 		input int64
    180 		width int
    181 		ok    bool
    182 	}{
    183 		{-1, 1, false},
    184 		{-1, 2, false},
    185 		{-1, 3, false},
    186 		{0, 1, true},
    187 		{0 + 1, 1, false},
    188 		{0, 2, true},
    189 		{07, 2, true},
    190 		{07 + 1, 2, false},
    191 		{0, 4, true},
    192 		{0777, 4, true},
    193 		{0777 + 1, 4, false},
    194 		{0, 8, true},
    195 		{07777777, 8, true},
    196 		{07777777 + 1, 8, false},
    197 		{0, 12, true},
    198 		{077777777777, 12, true},
    199 		{077777777777 + 1, 12, false},
    200 		{math.MaxInt64, 22, true},
    201 		{012345670123, 12, true},
    202 		{01564164, 12, true},
    203 		{-012345670123, 12, false},
    204 		{-01564164, 12, false},
    205 		{-1564164, 30, false},
    206 	}
    207 
    208 	for _, v := range vectors {
    209 		ok := fitsInOctal(v.width, v.input)
    210 		if ok != v.ok {
    211 			t.Errorf("checkOctal(%d, %d): got %v, want %v", v.input, v.width, ok, v.ok)
    212 		}
    213 	}
    214 }
    215 
    216 func TestParsePAXTime(t *testing.T) {
    217 	vectors := []struct {
    218 		in   string
    219 		want time.Time
    220 		ok   bool
    221 	}{
    222 		{"1350244992.023960108", time.Unix(1350244992, 23960108), true},
    223 		{"1350244992.02396010", time.Unix(1350244992, 23960100), true},
    224 		{"1350244992.0239601089", time.Unix(1350244992, 23960108), true},
    225 		{"1350244992.3", time.Unix(1350244992, 300000000), true},
    226 		{"1350244992", time.Unix(1350244992, 0), true},
    227 		{"-1.000000001", time.Unix(-1, -1e0+0e0), true},
    228 		{"-1.000001", time.Unix(-1, -1e3+0e0), true},
    229 		{"-1.001000", time.Unix(-1, -1e6+0e0), true},
    230 		{"-1", time.Unix(-1, -0e0+0e0), true},
    231 		{"-1.999000", time.Unix(-1, -1e9+1e6), true},
    232 		{"-1.999999", time.Unix(-1, -1e9+1e3), true},
    233 		{"-1.999999999", time.Unix(-1, -1e9+1e0), true},
    234 		{"0.000000001", time.Unix(0, 1e0+0e0), true},
    235 		{"0.000001", time.Unix(0, 1e3+0e0), true},
    236 		{"0.001000", time.Unix(0, 1e6+0e0), true},
    237 		{"0", time.Unix(0, 0e0), true},
    238 		{"0.999000", time.Unix(0, 1e9-1e6), true},
    239 		{"0.999999", time.Unix(0, 1e9-1e3), true},
    240 		{"0.999999999", time.Unix(0, 1e9-1e0), true},
    241 		{"1.000000001", time.Unix(+1, +1e0-0e0), true},
    242 		{"1.000001", time.Unix(+1, +1e3-0e0), true},
    243 		{"1.001000", time.Unix(+1, +1e6-0e0), true},
    244 		{"1", time.Unix(+1, +0e0-0e0), true},
    245 		{"1.999000", time.Unix(+1, +1e9-1e6), true},
    246 		{"1.999999", time.Unix(+1, +1e9-1e3), true},
    247 		{"1.999999999", time.Unix(+1, +1e9-1e0), true},
    248 		{"-1350244992.023960108", time.Unix(-1350244992, -23960108), true},
    249 		{"-1350244992.02396010", time.Unix(-1350244992, -23960100), true},
    250 		{"-1350244992.0239601089", time.Unix(-1350244992, -23960108), true},
    251 		{"-1350244992.3", time.Unix(-1350244992, -300000000), true},
    252 		{"-1350244992", time.Unix(-1350244992, 0), true},
    253 		{"", time.Time{}, false},
    254 		{"0", time.Unix(0, 0), true},
    255 		{"1.", time.Unix(1, 0), true},
    256 		{"0.0", time.Unix(0, 0), true},
    257 		{".5", time.Time{}, false},
    258 		{"-1.3", time.Unix(-1, -3e8), true},
    259 		{"-1.0", time.Unix(-1, -0e0), true},
    260 		{"-0.0", time.Unix(-0, -0e0), true},
    261 		{"-0.1", time.Unix(-0, -1e8), true},
    262 		{"-0.01", time.Unix(-0, -1e7), true},
    263 		{"-0.99", time.Unix(-0, -99e7), true},
    264 		{"-0.98", time.Unix(-0, -98e7), true},
    265 		{"-1.1", time.Unix(-1, -1e8), true},
    266 		{"-1.01", time.Unix(-1, -1e7), true},
    267 		{"-2.99", time.Unix(-2, -99e7), true},
    268 		{"-5.98", time.Unix(-5, -98e7), true},
    269 		{"-", time.Time{}, false},
    270 		{"+", time.Time{}, false},
    271 		{"-1.-1", time.Time{}, false},
    272 		{"99999999999999999999999999999999999999999999999", time.Time{}, false},
    273 		{"0.123456789abcdef", time.Time{}, false},
    274 		{"foo", time.Time{}, false},
    275 		{"\x00", time.Time{}, false},
    276 		{".", time.Time{}, false}, // Unicode numbers (U+1D7EC to U+1D7F5)
    277 		{"9876543210", time.Time{}, false}, // Unicode period (U+FE52)
    278 	}
    279 
    280 	for _, v := range vectors {
    281 		ts, err := parsePAXTime(v.in)
    282 		ok := (err == nil)
    283 		if v.ok != ok {
    284 			if v.ok {
    285 				t.Errorf("parsePAXTime(%q): got parsing failure, want success", v.in)
    286 			} else {
    287 				t.Errorf("parsePAXTime(%q): got parsing success, want failure", v.in)
    288 			}
    289 		}
    290 		if ok && !ts.Equal(v.want) {
    291 			t.Errorf("parsePAXTime(%q): got (%ds %dns), want (%ds %dns)",
    292 				v.in, ts.Unix(), ts.Nanosecond(), v.want.Unix(), v.want.Nanosecond())
    293 		}
    294 	}
    295 }
    296 
    297 func TestFormatPAXTime(t *testing.T) {
    298 	vectors := []struct {
    299 		sec, nsec int64
    300 		want      string
    301 	}{
    302 		{1350244992, 0, "1350244992"},
    303 		{1350244992, 300000000, "1350244992.3"},
    304 		{1350244992, 23960100, "1350244992.0239601"},
    305 		{1350244992, 23960108, "1350244992.023960108"},
    306 		{+1, +1E9 - 1E0, "1.999999999"},
    307 		{+1, +1E9 - 1E3, "1.999999"},
    308 		{+1, +1E9 - 1E6, "1.999"},
    309 		{+1, +0E0 - 0E0, "1"},
    310 		{+1, +1E6 - 0E0, "1.001"},
    311 		{+1, +1E3 - 0E0, "1.000001"},
    312 		{+1, +1E0 - 0E0, "1.000000001"},
    313 		{0, 1E9 - 1E0, "0.999999999"},
    314 		{0, 1E9 - 1E3, "0.999999"},
    315 		{0, 1E9 - 1E6, "0.999"},
    316 		{0, 0E0, "0"},
    317 		{0, 1E6 + 0E0, "0.001"},
    318 		{0, 1E3 + 0E0, "0.000001"},
    319 		{0, 1E0 + 0E0, "0.000000001"},
    320 		{-1, -1E9 + 1E0, "-1.999999999"},
    321 		{-1, -1E9 + 1E3, "-1.999999"},
    322 		{-1, -1E9 + 1E6, "-1.999"},
    323 		{-1, -0E0 + 0E0, "-1"},
    324 		{-1, -1E6 + 0E0, "-1.001"},
    325 		{-1, -1E3 + 0E0, "-1.000001"},
    326 		{-1, -1E0 + 0E0, "-1.000000001"},
    327 		{-1350244992, 0, "-1350244992"},
    328 		{-1350244992, -300000000, "-1350244992.3"},
    329 		{-1350244992, -23960100, "-1350244992.0239601"},
    330 		{-1350244992, -23960108, "-1350244992.023960108"},
    331 	}
    332 
    333 	for _, v := range vectors {
    334 		got := formatPAXTime(time.Unix(v.sec, v.nsec))
    335 		if got != v.want {
    336 			t.Errorf("formatPAXTime(%ds, %dns): got %q, want %q",
    337 				v.sec, v.nsec, got, v.want)
    338 		}
    339 	}
    340 }
    341 
    342 func TestParsePAXRecord(t *testing.T) {
    343 	medName := strings.Repeat("CD", 50)
    344 	longName := strings.Repeat("AB", 100)
    345 
    346 	vectors := []struct {
    347 		in      string
    348 		wantRes string
    349 		wantKey string
    350 		wantVal string
    351 		ok      bool
    352 	}{
    353 		{"6 k=v\n\n", "\n", "k", "v", true},
    354 		{"19 path=/etc/hosts\n", "", "path", "/etc/hosts", true},
    355 		{"210 path=" + longName + "\nabc", "abc", "path", longName, true},
    356 		{"110 path=" + medName + "\n", "", "path", medName, true},
    357 		{"9 foo=ba\n", "", "foo", "ba", true},
    358 		{"11 foo=bar\n\x00", "\x00", "foo", "bar", true},
    359 		{"18 foo=b=\nar=\n==\x00\n", "", "foo", "b=\nar=\n==\x00", true},
    360 		{"27 foo=hello9 foo=ba\nworld\n", "", "foo", "hello9 foo=ba\nworld", true},
    361 		{"27 =ab\nmeow mix", "meow mix", "", "ab", true},
    362 		{"17 \x00hello=\x00world\n", "17 \x00hello=\x00world\n", "", "", false},
    363 		{"1 k=1\n", "1 k=1\n", "", "", false},
    364 		{"6 k~1\n", "6 k~1\n", "", "", false},
    365 		{"6_k=1\n", "6_k=1\n", "", "", false},
    366 		{"6 k=1 ", "6 k=1 ", "", "", false},
    367 		{"632 k=1\n", "632 k=1\n", "", "", false},
    368 		{"16 longkeyname=hahaha\n", "16 longkeyname=hahaha\n", "", "", false},
    369 		{"3 somelongkey=\n", "3 somelongkey=\n", "", "", false},
    370 		{"50 tooshort=\n", "50 tooshort=\n", "", "", false},
    371 	}
    372 
    373 	for _, v := range vectors {
    374 		key, val, res, err := parsePAXRecord(v.in)
    375 		ok := (err == nil)
    376 		if ok != v.ok {
    377 			if v.ok {
    378 				t.Errorf("parsePAXRecord(%q): got parsing failure, want success", v.in)
    379 			} else {
    380 				t.Errorf("parsePAXRecord(%q): got parsing success, want failure", v.in)
    381 			}
    382 		}
    383 		if v.ok && (key != v.wantKey || val != v.wantVal) {
    384 			t.Errorf("parsePAXRecord(%q): got (%q: %q), want (%q: %q)",
    385 				v.in, key, val, v.wantKey, v.wantVal)
    386 		}
    387 		if res != v.wantRes {
    388 			t.Errorf("parsePAXRecord(%q): got residual %q, want residual %q",
    389 				v.in, res, v.wantRes)
    390 		}
    391 	}
    392 }
    393 
    394 func TestFormatPAXRecord(t *testing.T) {
    395 	medName := strings.Repeat("CD", 50)
    396 	longName := strings.Repeat("AB", 100)
    397 
    398 	vectors := []struct {
    399 		inKey string
    400 		inVal string
    401 		want  string
    402 		ok    bool
    403 	}{
    404 		{"k", "v", "6 k=v\n", true},
    405 		{"path", "/etc/hosts", "19 path=/etc/hosts\n", true},
    406 		{"path", longName, "210 path=" + longName + "\n", true},
    407 		{"path", medName, "110 path=" + medName + "\n", true},
    408 		{"foo", "ba", "9 foo=ba\n", true},
    409 		{"foo", "bar", "11 foo=bar\n", true},
    410 		{"foo", "b=\nar=\n==\x00", "18 foo=b=\nar=\n==\x00\n", true},
    411 		{"foo", "hello9 foo=ba\nworld", "27 foo=hello9 foo=ba\nworld\n", true},
    412 		{"", "ab", "27 =ab\n", true},
    413 		{"xhello", "\x00world", "17 xhello=\x00world\n", true},
    414 		{"path", "null\x00", "", false},
    415 		{"null\x00", "value", "", false},
    416 		{paxSchilyXattr + "key", "null\x00", "26 SCHILY.xattr.key=null\x00\n", true},
    417 	}
    418 
    419 	for _, v := range vectors {
    420 		got, err := formatPAXRecord(v.inKey, v.inVal)
    421 		ok := (err == nil)
    422 		if ok != v.ok {
    423 			if v.ok {
    424 				t.Errorf("formatPAXRecord(%q, %q): got format failure, want success", v.inKey, v.inVal)
    425 			} else {
    426 				t.Errorf("formatPAXRecord(%q, %q): got format success, want failure", v.inKey, v.inVal)
    427 			}
    428 		}
    429 		if got != v.want {
    430 			t.Errorf("formatPAXRecord(%q, %q): got %q, want %q",
    431 				v.inKey, v.inVal, got, v.want)
    432 		}
    433 	}
    434 }
    435