Commit 04262986 authored by Joe Tsai's avatar Joe Tsai Committed by Joe Tsai

archive/tar: compact slices in tests

Took this opportunity to also embed tables in the functions
that they are actually used in and other stylistic cleanups.

There was no logical changes to the tests.

Change-Id: Ifa724060532175f6f4407d6cedc841891efd8f7b
Reviewed-on: https://go-review.googlesource.com/31436
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 5378dd77
This diff is collapsed.
...@@ -135,9 +135,8 @@ type headerRoundTripTest struct { ...@@ -135,9 +135,8 @@ type headerRoundTripTest struct {
} }
func TestHeaderRoundTrip(t *testing.T) { func TestHeaderRoundTrip(t *testing.T) {
golden := []headerRoundTripTest{ vectors := []headerRoundTripTest{{
// regular file. // regular file.
{
h: &Header{ h: &Header{
Name: "test.txt", Name: "test.txt",
Mode: 0644 | c_ISREG, Mode: 0644 | c_ISREG,
...@@ -146,9 +145,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -146,9 +145,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeReg, Typeflag: TypeReg,
}, },
fm: 0644, fm: 0644,
}, }, {
// symbolic link. // symbolic link.
{
h: &Header{ h: &Header{
Name: "link.txt", Name: "link.txt",
Mode: 0777 | c_ISLNK, Mode: 0777 | c_ISLNK,
...@@ -157,9 +155,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -157,9 +155,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeSymlink, Typeflag: TypeSymlink,
}, },
fm: 0777 | os.ModeSymlink, fm: 0777 | os.ModeSymlink,
}, }, {
// character device node. // character device node.
{
h: &Header{ h: &Header{
Name: "dev/null", Name: "dev/null",
Mode: 0666 | c_ISCHR, Mode: 0666 | c_ISCHR,
...@@ -168,9 +165,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -168,9 +165,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeChar, Typeflag: TypeChar,
}, },
fm: 0666 | os.ModeDevice | os.ModeCharDevice, fm: 0666 | os.ModeDevice | os.ModeCharDevice,
}, }, {
// block device node. // block device node.
{
h: &Header{ h: &Header{
Name: "dev/sda", Name: "dev/sda",
Mode: 0660 | c_ISBLK, Mode: 0660 | c_ISBLK,
...@@ -179,9 +175,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -179,9 +175,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeBlock, Typeflag: TypeBlock,
}, },
fm: 0660 | os.ModeDevice, fm: 0660 | os.ModeDevice,
}, }, {
// directory. // directory.
{
h: &Header{ h: &Header{
Name: "dir/", Name: "dir/",
Mode: 0755 | c_ISDIR, Mode: 0755 | c_ISDIR,
...@@ -190,9 +185,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -190,9 +185,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeDir, Typeflag: TypeDir,
}, },
fm: 0755 | os.ModeDir, fm: 0755 | os.ModeDir,
}, }, {
// fifo node. // fifo node.
{
h: &Header{ h: &Header{
Name: "dev/initctl", Name: "dev/initctl",
Mode: 0600 | c_ISFIFO, Mode: 0600 | c_ISFIFO,
...@@ -201,9 +195,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -201,9 +195,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeFifo, Typeflag: TypeFifo,
}, },
fm: 0600 | os.ModeNamedPipe, fm: 0600 | os.ModeNamedPipe,
}, }, {
// setuid. // setuid.
{
h: &Header{ h: &Header{
Name: "bin/su", Name: "bin/su",
Mode: 0755 | c_ISREG | c_ISUID, Mode: 0755 | c_ISREG | c_ISUID,
...@@ -212,9 +205,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -212,9 +205,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeReg, Typeflag: TypeReg,
}, },
fm: 0755 | os.ModeSetuid, fm: 0755 | os.ModeSetuid,
}, }, {
// setguid. // setguid.
{
h: &Header{ h: &Header{
Name: "group.txt", Name: "group.txt",
Mode: 0750 | c_ISREG | c_ISGID, Mode: 0750 | c_ISREG | c_ISGID,
...@@ -223,9 +215,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -223,9 +215,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeReg, Typeflag: TypeReg,
}, },
fm: 0750 | os.ModeSetgid, fm: 0750 | os.ModeSetgid,
}, }, {
// sticky. // sticky.
{
h: &Header{ h: &Header{
Name: "sticky.txt", Name: "sticky.txt",
Mode: 0600 | c_ISREG | c_ISVTX, Mode: 0600 | c_ISREG | c_ISVTX,
...@@ -234,9 +225,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -234,9 +225,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeReg, Typeflag: TypeReg,
}, },
fm: 0600 | os.ModeSticky, fm: 0600 | os.ModeSticky,
}, }, {
// hard link. // hard link.
{
h: &Header{ h: &Header{
Name: "hard.txt", Name: "hard.txt",
Mode: 0644 | c_ISREG, Mode: 0644 | c_ISREG,
...@@ -246,9 +236,8 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -246,9 +236,8 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeLink, Typeflag: TypeLink,
}, },
fm: 0644, fm: 0644,
}, }, {
// More information. // More information.
{
h: &Header{ h: &Header{
Name: "info.txt", Name: "info.txt",
Mode: 0600 | c_ISREG, Mode: 0600 | c_ISREG,
...@@ -261,64 +250,63 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -261,64 +250,63 @@ func TestHeaderRoundTrip(t *testing.T) {
Typeflag: TypeReg, Typeflag: TypeReg,
}, },
fm: 0600, fm: 0600,
}, }}
}
for i, g := range golden { for i, v := range vectors {
fi := g.h.FileInfo() fi := v.h.FileInfo()
h2, err := FileInfoHeader(fi, "") h2, err := FileInfoHeader(fi, "")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
continue continue
} }
if strings.Contains(fi.Name(), "/") { if strings.Contains(fi.Name(), "/") {
t.Errorf("FileInfo of %q contains slash: %q", g.h.Name, fi.Name()) t.Errorf("FileInfo of %q contains slash: %q", v.h.Name, fi.Name())
} }
name := path.Base(g.h.Name) name := path.Base(v.h.Name)
if fi.IsDir() { if fi.IsDir() {
name += "/" name += "/"
} }
if got, want := h2.Name, name; got != want { if got, want := h2.Name, name; got != want {
t.Errorf("i=%d: Name: got %v, want %v", i, got, want) t.Errorf("i=%d: Name: got %v, want %v", i, got, want)
} }
if got, want := h2.Size, g.h.Size; got != want { if got, want := h2.Size, v.h.Size; got != want {
t.Errorf("i=%d: Size: got %v, want %v", i, got, want) t.Errorf("i=%d: Size: got %v, want %v", i, got, want)
} }
if got, want := h2.Uid, g.h.Uid; got != want { if got, want := h2.Uid, v.h.Uid; got != want {
t.Errorf("i=%d: Uid: got %d, want %d", i, got, want) t.Errorf("i=%d: Uid: got %d, want %d", i, got, want)
} }
if got, want := h2.Gid, g.h.Gid; got != want { if got, want := h2.Gid, v.h.Gid; got != want {
t.Errorf("i=%d: Gid: got %d, want %d", i, got, want) t.Errorf("i=%d: Gid: got %d, want %d", i, got, want)
} }
if got, want := h2.Uname, g.h.Uname; got != want { if got, want := h2.Uname, v.h.Uname; got != want {
t.Errorf("i=%d: Uname: got %q, want %q", i, got, want) t.Errorf("i=%d: Uname: got %q, want %q", i, got, want)
} }
if got, want := h2.Gname, g.h.Gname; got != want { if got, want := h2.Gname, v.h.Gname; got != want {
t.Errorf("i=%d: Gname: got %q, want %q", i, got, want) t.Errorf("i=%d: Gname: got %q, want %q", i, got, want)
} }
if got, want := h2.Linkname, g.h.Linkname; got != want { if got, want := h2.Linkname, v.h.Linkname; got != want {
t.Errorf("i=%d: Linkname: got %v, want %v", i, got, want) t.Errorf("i=%d: Linkname: got %v, want %v", i, got, want)
} }
if got, want := h2.Typeflag, g.h.Typeflag; got != want { if got, want := h2.Typeflag, v.h.Typeflag; got != want {
t.Logf("%#v %#v", g.h, fi.Sys()) t.Logf("%#v %#v", v.h, fi.Sys())
t.Errorf("i=%d: Typeflag: got %q, want %q", i, got, want) t.Errorf("i=%d: Typeflag: got %q, want %q", i, got, want)
} }
if got, want := h2.Mode, g.h.Mode; got != want { if got, want := h2.Mode, v.h.Mode; got != want {
t.Errorf("i=%d: Mode: got %o, want %o", i, got, want) t.Errorf("i=%d: Mode: got %o, want %o", i, got, want)
} }
if got, want := fi.Mode(), g.fm; got != want { if got, want := fi.Mode(), v.fm; got != want {
t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want) t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want)
} }
if got, want := h2.AccessTime, g.h.AccessTime; got != want { if got, want := h2.AccessTime, v.h.AccessTime; got != want {
t.Errorf("i=%d: AccessTime: got %v, want %v", i, got, want) t.Errorf("i=%d: AccessTime: got %v, want %v", i, got, want)
} }
if got, want := h2.ChangeTime, g.h.ChangeTime; got != want { if got, want := h2.ChangeTime, v.h.ChangeTime; got != want {
t.Errorf("i=%d: ChangeTime: got %v, want %v", i, got, want) t.Errorf("i=%d: ChangeTime: got %v, want %v", i, got, want)
} }
if got, want := h2.ModTime, g.h.ModTime; got != want { if got, want := h2.ModTime, v.h.ModTime; got != want {
t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want) t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want)
} }
if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h { if sysh, ok := fi.Sys().(*Header); !ok || sysh != v.h {
t.Errorf("i=%d: Sys didn't return original *Header", i) t.Errorf("i=%d: Sys didn't return original *Header", i)
} }
} }
......
...@@ -18,25 +18,60 @@ import ( ...@@ -18,25 +18,60 @@ import (
"time" "time"
) )
type writerTestEntry struct { // Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
header *Header func bytestr(offset int, b []byte) string {
contents string const rowLen = 32
s := fmt.Sprintf("%04x ", offset)
for _, ch := range b {
switch {
case '0' <= ch && ch <= '9', 'A' <= ch && ch <= 'Z', 'a' <= ch && ch <= 'z':
s += fmt.Sprintf(" %c", ch)
default:
s += fmt.Sprintf(" %02x", ch)
}
}
return s
} }
type writerTest struct { // Render a pseudo-diff between two blocks of bytes.
file string // filename of expected output func bytediff(a []byte, b []byte) string {
entries []*writerTestEntry const rowLen = 32
s := fmt.Sprintf("(%d bytes vs. %d bytes)\n", len(a), len(b))
for offset := 0; len(a)+len(b) > 0; offset += rowLen {
na, nb := rowLen, rowLen
if na > len(a) {
na = len(a)
}
if nb > len(b) {
nb = len(b)
}
sa := bytestr(offset, a[0:na])
sb := bytestr(offset, b[0:nb])
if sa != sb {
s += fmt.Sprintf("-%v\n+%v\n", sa, sb)
}
a = a[na:]
b = b[nb:]
}
return s
} }
var writerTests = []*writerTest{ func TestWriter(t *testing.T) {
type entry struct {
header *Header
contents string
}
vectors := []struct {
file string // filename of expected output
entries []*entry
}{{
// The writer test file was produced with this command: // The writer test file was produced with this command:
// tar (GNU tar) 1.26 // tar (GNU tar) 1.26
// ln -s small.txt link.txt // ln -s small.txt link.txt
// tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt // tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
{
file: "testdata/writer.tar", file: "testdata/writer.tar",
entries: []*writerTestEntry{ entries: []*entry{{
{
header: &Header{ header: &Header{
Name: "small.txt", Name: "small.txt",
Mode: 0640, Mode: 0640,
...@@ -49,8 +84,7 @@ var writerTests = []*writerTest{ ...@@ -49,8 +84,7 @@ var writerTests = []*writerTest{
Gname: "eng", Gname: "eng",
}, },
contents: "Kilts", contents: "Kilts",
}, }, {
{
header: &Header{ header: &Header{
Name: "small2.txt", Name: "small2.txt",
Mode: 0640, Mode: 0640,
...@@ -63,8 +97,7 @@ var writerTests = []*writerTest{ ...@@ -63,8 +97,7 @@ var writerTests = []*writerTest{
Gname: "eng", Gname: "eng",
}, },
contents: "Google.com\n", contents: "Google.com\n",
}, }, {
{
header: &Header{ header: &Header{
Name: "link.txt", Name: "link.txt",
Mode: 0777, Mode: 0777,
...@@ -78,16 +111,13 @@ var writerTests = []*writerTest{ ...@@ -78,16 +111,13 @@ var writerTests = []*writerTest{
Gname: "strings", Gname: "strings",
}, },
// no contents // no contents
}, }},
}, }, {
},
// The truncated test file was produced using these commands: // The truncated test file was produced using these commands:
// dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt // dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
// tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar // tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
{
file: "testdata/writer-big.tar", file: "testdata/writer-big.tar",
entries: []*writerTestEntry{ entries: []*entry{{
{
header: &Header{ header: &Header{
Name: "tmp/16gig.txt", Name: "tmp/16gig.txt",
Mode: 0640, Mode: 0640,
...@@ -101,16 +131,13 @@ var writerTests = []*writerTest{ ...@@ -101,16 +131,13 @@ var writerTests = []*writerTest{
}, },
// fake contents // fake contents
contents: strings.Repeat("\x00", 4<<10), contents: strings.Repeat("\x00", 4<<10),
}, }},
}, }, {
},
// The truncated test file was produced using these commands: // The truncated test file was produced using these commands:
// dd if=/dev/zero bs=1048576 count=16384 > (longname/)*15 /16gig.txt // dd if=/dev/zero bs=1048576 count=16384 > (longname/)*15 /16gig.txt
// tar -b 1 -c -f- (longname/)*15 /16gig.txt | dd bs=512 count=8 > writer-big-long.tar // tar -b 1 -c -f- (longname/)*15 /16gig.txt | dd bs=512 count=8 > writer-big-long.tar
{
file: "testdata/writer-big-long.tar", file: "testdata/writer-big-long.tar",
entries: []*writerTestEntry{ entries: []*entry{{
{
header: &Header{ header: &Header{
Name: strings.Repeat("longname/", 15) + "16gig.txt", Name: strings.Repeat("longname/", 15) + "16gig.txt",
Mode: 0644, Mode: 0644,
...@@ -124,15 +151,12 @@ var writerTests = []*writerTest{ ...@@ -124,15 +151,12 @@ var writerTests = []*writerTest{
}, },
// fake contents // fake contents
contents: strings.Repeat("\x00", 4<<10), contents: strings.Repeat("\x00", 4<<10),
}, }},
}, }, {
},
// This file was produced using gnu tar 1.17 // This file was produced using gnu tar 1.17
// gnutar -b 4 --format=ustar (longname/)*15 + file.txt // gnutar -b 4 --format=ustar (longname/)*15 + file.txt
{
file: "testdata/ustar.tar", file: "testdata/ustar.tar",
entries: []*writerTestEntry{ entries: []*entry{{
{
header: &Header{ header: &Header{
Name: strings.Repeat("longname/", 15) + "file.txt", Name: strings.Repeat("longname/", 15) + "file.txt",
Mode: 0644, Mode: 0644,
...@@ -145,17 +169,14 @@ var writerTests = []*writerTest{ ...@@ -145,17 +169,14 @@ var writerTests = []*writerTest{
Gname: "staff", Gname: "staff",
}, },
contents: "hello\n", contents: "hello\n",
}, }},
}, }, {
},
// This file was produced using gnu tar 1.26 // This file was produced using gnu tar 1.26
// echo "Slartibartfast" > file.txt // echo "Slartibartfast" > file.txt
// ln file.txt hard.txt // ln file.txt hard.txt
// tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt // tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt
{
file: "testdata/hardlink.tar", file: "testdata/hardlink.tar",
entries: []*writerTestEntry{ entries: []*entry{{
{
header: &Header{ header: &Header{
Name: "file.txt", Name: "file.txt",
Mode: 0644, Mode: 0644,
...@@ -168,8 +189,7 @@ var writerTests = []*writerTest{ ...@@ -168,8 +189,7 @@ var writerTests = []*writerTest{
Gname: "users", Gname: "users",
}, },
contents: "Slartibartfast\n", contents: "Slartibartfast\n",
}, }, {
{
header: &Header{ header: &Header{
Name: "hard.txt", Name: "hard.txt",
Mode: 0644, Mode: 0644,
...@@ -183,53 +203,12 @@ var writerTests = []*writerTest{ ...@@ -183,53 +203,12 @@ var writerTests = []*writerTest{
Gname: "users", Gname: "users",
}, },
// no contents // no contents
}, }},
}, }}
},
}
// Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
func bytestr(offset int, b []byte) string {
const rowLen = 32
s := fmt.Sprintf("%04x ", offset)
for _, ch := range b {
switch {
case '0' <= ch && ch <= '9', 'A' <= ch && ch <= 'Z', 'a' <= ch && ch <= 'z':
s += fmt.Sprintf(" %c", ch)
default:
s += fmt.Sprintf(" %02x", ch)
}
}
return s
}
// Render a pseudo-diff between two blocks of bytes.
func bytediff(a []byte, b []byte) string {
const rowLen = 32
s := fmt.Sprintf("(%d bytes vs. %d bytes)\n", len(a), len(b))
for offset := 0; len(a)+len(b) > 0; offset += rowLen {
na, nb := rowLen, rowLen
if na > len(a) {
na = len(a)
}
if nb > len(b) {
nb = len(b)
}
sa := bytestr(offset, a[0:na])
sb := bytestr(offset, b[0:nb])
if sa != sb {
s += fmt.Sprintf("-%v\n+%v\n", sa, sb)
}
a = a[na:]
b = b[nb:]
}
return s
}
func TestWriter(t *testing.T) {
testLoop: testLoop:
for i, test := range writerTests { for i, v := range vectors {
expected, err := ioutil.ReadFile(test.file) expected, err := ioutil.ReadFile(v.file)
if err != nil { if err != nil {
t.Errorf("test %d: Unexpected error: %v", i, err) t.Errorf("test %d: Unexpected error: %v", i, err)
continue continue
...@@ -238,7 +217,7 @@ testLoop: ...@@ -238,7 +217,7 @@ testLoop:
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB
big := false big := false
for j, entry := range test.entries { for j, entry := range v.entries {
big = big || entry.header.Size > 1<<10 big = big || entry.header.Size > 1<<10
if err := tw.WriteHeader(entry.header); err != nil { if err := tw.WriteHeader(entry.header); err != nil {
t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err) t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err)
...@@ -575,9 +554,9 @@ func TestWriteAfterClose(t *testing.T) { ...@@ -575,9 +554,9 @@ func TestWriteAfterClose(t *testing.T) {
} }
func TestSplitUSTARPath(t *testing.T) { func TestSplitUSTARPath(t *testing.T) {
var sr = strings.Repeat sr := strings.Repeat
var vectors = []struct { vectors := []struct {
input string // Input path input string // Input path
prefix string // Expected output prefix prefix string // Expected output prefix
suffix string // Expected output suffix suffix string // Expected output suffix
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment