github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/archive/tar/strconv_test.go (about)

     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-256 (binary) encoded values.
   114  		{-1, "\xff", true},
   115  		{-1, "\xff\xff", true},
   116  		{-1, "\xff\xff\xff", true},
   117  		{(1 << 0), "0", false},
   118  		{(1 << 8) - 1, "\x80\xff", true},
   119  		{(1 << 8), "0\x00", false},
   120  		{(1 << 16) - 1, "\x80\xff\xff", true},
   121  		{(1 << 16), "00\x00", false},
   122  		{-1 * (1 << 0), "\xff", true},
   123  		{-1*(1<<0) - 1, "0", false},
   124  		{-1 * (1 << 8), "\xff\x00", true},
   125  		{-1*(1<<8) - 1, "0\x00", false},
   126  		{-1 * (1 << 16), "\xff\x00\x00", true},
   127  		{-1*(1<<16) - 1, "00\x00", false},
   128  		{537795476381659745, "0000000\x00", false},
   129  		{537795476381659745, "\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", true},
   130  		{-615126028225187231, "0000000\x00", false},
   131  		{-615126028225187231, "\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", true},
   132  		{math.MaxInt64, "0000000\x00", false},
   133  		{math.MaxInt64, "\x80\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff", true},
   134  		{math.MinInt64, "0000000\x00", false},
   135  		{math.MinInt64, "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
   136  		{math.MaxInt64, "\x80\x7f\xff\xff\xff\xff\xff\xff\xff", true},
   137  		{math.MinInt64, "\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
   138  	}
   139  
   140  	for _, v := range vectors {
   141  		var f formatter
   142  		got := make([]byte, len(v.want))
   143  		f.formatNumeric(got, v.in)
   144  		ok := (f.err == nil)
   145  		if ok != v.ok {
   146  			if v.ok {
   147  				t.Errorf("formatNumeric(%d): got formatting failure, want success", v.in)
   148  			} else {
   149  				t.Errorf("formatNumeric(%d): got formatting success, want failure", v.in)
   150  			}
   151  		}
   152  		if string(got) != v.want {
   153  			t.Errorf("formatNumeric(%d): got %q, want %q", v.in, got, v.want)
   154  		}
   155  	}
   156  }
   157  
   158  func TestParsePAXTime(t *testing.T) {
   159  	vectors := []struct {
   160  		in   string
   161  		want time.Time
   162  		ok   bool
   163  	}{
   164  		{"1350244992.023960108", time.Unix(1350244992, 23960108), true},
   165  		{"1350244992.02396010", time.Unix(1350244992, 23960100), true},
   166  		{"1350244992.0239601089", time.Unix(1350244992, 23960108), true},
   167  		{"1350244992.3", time.Unix(1350244992, 300000000), true},
   168  		{"1350244992", time.Unix(1350244992, 0), true},
   169  		{"-1.000000001", time.Unix(-1, -1e0+0e0), true},
   170  		{"-1.000001", time.Unix(-1, -1e3+0e0), true},
   171  		{"-1.001000", time.Unix(-1, -1e6+0e0), true},
   172  		{"-1", time.Unix(-1, -0e0+0e0), true},
   173  		{"-1.999000", time.Unix(-1, -1e9+1e6), true},
   174  		{"-1.999999", time.Unix(-1, -1e9+1e3), true},
   175  		{"-1.999999999", time.Unix(-1, -1e9+1e0), true},
   176  		{"0.000000001", time.Unix(0, 1e0+0e0), true},
   177  		{"0.000001", time.Unix(0, 1e3+0e0), true},
   178  		{"0.001000", time.Unix(0, 1e6+0e0), true},
   179  		{"0", time.Unix(0, 0e0), true},
   180  		{"0.999000", time.Unix(0, 1e9-1e6), true},
   181  		{"0.999999", time.Unix(0, 1e9-1e3), true},
   182  		{"0.999999999", time.Unix(0, 1e9-1e0), true},
   183  		{"1.000000001", time.Unix(+1, +1e0-0e0), true},
   184  		{"1.000001", time.Unix(+1, +1e3-0e0), true},
   185  		{"1.001000", time.Unix(+1, +1e6-0e0), true},
   186  		{"1", time.Unix(+1, +0e0-0e0), true},
   187  		{"1.999000", time.Unix(+1, +1e9-1e6), true},
   188  		{"1.999999", time.Unix(+1, +1e9-1e3), true},
   189  		{"1.999999999", time.Unix(+1, +1e9-1e0), true},
   190  		{"-1350244992.023960108", time.Unix(-1350244992, -23960108), true},
   191  		{"-1350244992.02396010", time.Unix(-1350244992, -23960100), true},
   192  		{"-1350244992.0239601089", time.Unix(-1350244992, -23960108), true},
   193  		{"-1350244992.3", time.Unix(-1350244992, -300000000), true},
   194  		{"-1350244992", time.Unix(-1350244992, 0), true},
   195  		{"", time.Time{}, false},
   196  		{"0", time.Unix(0, 0), true},
   197  		{"1.", time.Unix(1, 0), true},
   198  		{"0.0", time.Unix(0, 0), true},
   199  		{".5", time.Time{}, false},
   200  		{"-1.3", time.Unix(-1, -3e8), true},
   201  		{"-1.0", time.Unix(-1, -0e0), true},
   202  		{"-0.0", time.Unix(-0, -0e0), true},
   203  		{"-0.1", time.Unix(-0, -1e8), true},
   204  		{"-0.01", time.Unix(-0, -1e7), true},
   205  		{"-0.99", time.Unix(-0, -99e7), true},
   206  		{"-0.98", time.Unix(-0, -98e7), true},
   207  		{"-1.1", time.Unix(-1, -1e8), true},
   208  		{"-1.01", time.Unix(-1, -1e7), true},
   209  		{"-2.99", time.Unix(-2, -99e7), true},
   210  		{"-5.98", time.Unix(-5, -98e7), true},
   211  		{"-", time.Time{}, false},
   212  		{"+", time.Time{}, false},
   213  		{"-1.-1", time.Time{}, false},
   214  		{"99999999999999999999999999999999999999999999999", time.Time{}, false},
   215  		{"0.123456789abcdef", time.Time{}, false},
   216  		{"foo", time.Time{}, false},
   217  		{"\x00", time.Time{}, false},
   218  		{"𝟵𝟴𝟳𝟲𝟱.𝟰𝟯𝟮𝟭𝟬", time.Time{}, false}, // Unicode numbers (U+1D7EC to U+1D7F5)
   219  		{"98765﹒43210", time.Time{}, false}, // Unicode period (U+FE52)
   220  	}
   221  
   222  	for _, v := range vectors {
   223  		ts, err := parsePAXTime(v.in)
   224  		ok := (err == nil)
   225  		if v.ok != ok {
   226  			if v.ok {
   227  				t.Errorf("parsePAXTime(%q): got parsing failure, want success", v.in)
   228  			} else {
   229  				t.Errorf("parsePAXTime(%q): got parsing success, want failure", v.in)
   230  			}
   231  		}
   232  		if ok && !ts.Equal(v.want) {
   233  			t.Errorf("parsePAXTime(%q): got (%ds %dns), want (%ds %dns)",
   234  				v.in, ts.Unix(), ts.Nanosecond(), v.want.Unix(), v.want.Nanosecond())
   235  		}
   236  	}
   237  }
   238  
   239  func TestParsePAXRecord(t *testing.T) {
   240  	medName := strings.Repeat("CD", 50)
   241  	longName := strings.Repeat("AB", 100)
   242  
   243  	vectors := []struct {
   244  		in      string
   245  		wantRes string
   246  		wantKey string
   247  		wantVal string
   248  		ok      bool
   249  	}{
   250  		{"6 k=v\n\n", "\n", "k", "v", true},
   251  		{"19 path=/etc/hosts\n", "", "path", "/etc/hosts", true},
   252  		{"210 path=" + longName + "\nabc", "abc", "path", longName, true},
   253  		{"110 path=" + medName + "\n", "", "path", medName, true},
   254  		{"9 foo=ba\n", "", "foo", "ba", true},
   255  		{"11 foo=bar\n\x00", "\x00", "foo", "bar", true},
   256  		{"18 foo=b=\nar=\n==\x00\n", "", "foo", "b=\nar=\n==\x00", true},
   257  		{"27 foo=hello9 foo=ba\nworld\n", "", "foo", "hello9 foo=ba\nworld", true},
   258  		{"27 ☺☻☹=日a本b語ç\nmeow mix", "meow mix", "☺☻☹", "日a本b語ç", true},
   259  		{"17 \x00hello=\x00world\n", "", "\x00hello", "\x00world", true},
   260  		{"1 k=1\n", "1 k=1\n", "", "", false},
   261  		{"6 k~1\n", "6 k~1\n", "", "", false},
   262  		{"6_k=1\n", "6_k=1\n", "", "", false},
   263  		{"6 k=1 ", "6 k=1 ", "", "", false},
   264  		{"632 k=1\n", "632 k=1\n", "", "", false},
   265  		{"16 longkeyname=hahaha\n", "16 longkeyname=hahaha\n", "", "", false},
   266  		{"3 somelongkey=\n", "3 somelongkey=\n", "", "", false},
   267  		{"50 tooshort=\n", "50 tooshort=\n", "", "", false},
   268  	}
   269  
   270  	for _, v := range vectors {
   271  		key, val, res, err := parsePAXRecord(v.in)
   272  		ok := (err == nil)
   273  		if ok != v.ok {
   274  			if v.ok {
   275  				t.Errorf("parsePAXRecord(%q): got parsing failure, want success", v.in)
   276  			} else {
   277  				t.Errorf("parsePAXRecord(%q): got parsing success, want failure", v.in)
   278  			}
   279  		}
   280  		if v.ok && (key != v.wantKey || val != v.wantVal) {
   281  			t.Errorf("parsePAXRecord(%q): got (%q: %q), want (%q: %q)",
   282  				v.in, key, val, v.wantKey, v.wantVal)
   283  		}
   284  		if res != v.wantRes {
   285  			t.Errorf("parsePAXRecord(%q): got residual %q, want residual %q",
   286  				v.in, res, v.wantRes)
   287  		}
   288  	}
   289  }
   290  
   291  func TestFormatPAXRecord(t *testing.T) {
   292  	medName := strings.Repeat("CD", 50)
   293  	longName := strings.Repeat("AB", 100)
   294  
   295  	vectors := []struct {
   296  		inKey string
   297  		inVal string
   298  		want  string
   299  	}{
   300  		{"k", "v", "6 k=v\n"},
   301  		{"path", "/etc/hosts", "19 path=/etc/hosts\n"},
   302  		{"path", longName, "210 path=" + longName + "\n"},
   303  		{"path", medName, "110 path=" + medName + "\n"},
   304  		{"foo", "ba", "9 foo=ba\n"},
   305  		{"foo", "bar", "11 foo=bar\n"},
   306  		{"foo", "b=\nar=\n==\x00", "18 foo=b=\nar=\n==\x00\n"},
   307  		{"foo", "hello9 foo=ba\nworld", "27 foo=hello9 foo=ba\nworld\n"},
   308  		{"☺☻☹", "日a本b語ç", "27 ☺☻☹=日a本b語ç\n"},
   309  		{"\x00hello", "\x00world", "17 \x00hello=\x00world\n"},
   310  	}
   311  
   312  	for _, v := range vectors {
   313  		got := formatPAXRecord(v.inKey, v.inVal)
   314  		if got != v.want {
   315  			t.Errorf("formatPAXRecord(%q, %q): got %q, want %q",
   316  				v.inKey, v.inVal, got, v.want)
   317  		}
   318  	}
   319  }