func TestWriter(t *testing.T) { testLoop: for i, test := range writerTests { expected, err := io.ReadFile(test.file) if err != nil { t.Errorf("test %d: Unexpected error: %v", i, err) continue } buf := new(bytes.Buffer) tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB for j, entry := range test.entries { if err := tw.WriteHeader(entry.header); err != nil { t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err) continue testLoop } if _, err := io.WriteString(tw, entry.contents); err != nil { t.Errorf("test %d, entry %d: Failed writing contents: %v", i, j, err) continue testLoop } } if err := tw.Close(); err != nil { t.Errorf("test %d: Failed closing archive: %v", err) continue testLoop } actual := buf.Bytes() if !bytes.Equal(expected, actual) { t.Errorf("test %d: Incorrect result: (-=expected, +=actual)\n%v", i, bytediff(expected, actual)) } } }
func TestStdCopyHeaderOnly(t *testing.T) { var input, stdout, stderr bytes.Buffer input.Write([]byte{2, 0, 0, 0, 0, 0, 0, 19}) n, err := stdCopy(&stdout, iotest.TruncateWriter(&stderr, 7), &input) if err != io.ErrShortWrite { t.Errorf("stdCopy: wrong error. Want ShortWrite. Got %#v", err) } if n != 0 { t.Errorf("Wrong number of bytes. Want 0. Got %d.", n) } if got := stderr.String(); got != "" { t.Errorf("stdCopy: wrong stderr. Want %q. Got %q.", "", got) } if got := stdout.String(); got != "" { t.Errorf("stdCopy: wrong stdout. Want %q. Got %q.", "", got) } }
func TestStdCopyTruncateWriter(t *testing.T) { var input, stdout, stderr bytes.Buffer input.Write([]byte{2, 0, 0, 0, 0, 0, 0, 19}) input.Write([]byte("something happened!")) n, err := stdCopy(&stdout, iotest.TruncateWriter(&stderr, 7), &input) if err != nil { t.Fatal(err) } if expected := int64(19); n != expected { t.Errorf("Wrong number of bytes. Want %d. Got %d.", expected, n) } if got := stderr.String(); got != "somethi" { t.Errorf("stdCopy: wrong stderr. Want %q. Got %q.", "somethi", got) } if got := stdout.String(); got != "" { t.Errorf("stdCopy: wrong stdout. Want %q. Got %q.", "", got) } }
func TestWriter(t *testing.T) { testLoop: for i, test := range writerTests { expected, err := ioutil.ReadFile(test.file) if err != nil { t.Errorf("test %d: Unexpected error: %v", i, err) continue } buf := new(bytes.Buffer) tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB big := false for j, entry := range test.entries { big = big || entry.header.Size > 1<<10 if err := tw.WriteHeader(entry.header); err != nil { t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err) continue testLoop } if _, err := io.WriteString(tw, entry.contents); err != nil { t.Errorf("test %d, entry %d: Failed writing contents: %v", i, j, err) continue testLoop } } // Only interested in Close failures for the small tests. if err := tw.Close(); err != nil && !big { t.Errorf("test %d: Failed closing archive: %v", i, err) continue testLoop } actual := buf.Bytes() if !bytes.Equal(expected, actual) { t.Errorf("test %d: Incorrect result: (-=expected, +=actual)\n%v", i, bytediff(expected, actual)) } if testing.Short() { // The second test is expensive. break } } }
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: // tar (GNU tar) 1.26 // ln -s small.txt link.txt // tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt file: "testdata/writer.tar", entries: []*entry{{ header: &Header{ Name: "small.txt", Mode: 0640, Uid: 73025, Gid: 5000, Size: 5, ModTime: time.Unix(1246508266, 0), Typeflag: '0', Uname: "dsymonds", Gname: "eng", }, contents: "Kilts", }, { header: &Header{ Name: "small2.txt", Mode: 0640, Uid: 73025, Gid: 5000, Size: 11, ModTime: time.Unix(1245217492, 0), Typeflag: '0', Uname: "dsymonds", Gname: "eng", }, contents: "Google.com\n", }, { header: &Header{ Name: "link.txt", Mode: 0777, Uid: 1000, Gid: 1000, Size: 0, ModTime: time.Unix(1314603082, 0), Typeflag: '2', Linkname: "small.txt", Uname: "strings", Gname: "strings", }, // no contents }}, }, { // The truncated test file was produced using these commands: // 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 file: "testdata/writer-big.tar", entries: []*entry{{ header: &Header{ Name: "tmp/16gig.txt", Mode: 0640, Uid: 73025, Gid: 5000, Size: 16 << 30, ModTime: time.Unix(1254699560, 0), Typeflag: '0', Uname: "dsymonds", Gname: "eng", }, // fake contents contents: strings.Repeat("\x00", 4<<10), }}, }, { // This truncated file was produced using this library. // It was verified to work with GNU tar 1.27.1 and BSD tar 3.1.2. // dd if=/dev/zero bs=1G count=16 >> writer-big-long.tar // gnutar -xvf writer-big-long.tar // bsdtar -xvf writer-big-long.tar // // This file is in PAX format. file: "testdata/writer-big-long.tar", entries: []*entry{{ header: &Header{ Name: strings.Repeat("longname/", 15) + "16gig.txt", Mode: 0644, Uid: 1000, Gid: 1000, Size: 16 << 30, ModTime: time.Unix(1399583047, 0), Typeflag: '0', Uname: "guillaume", Gname: "guillaume", }, // fake contents contents: strings.Repeat("\x00", 4<<10), }}, }, { // TODO(dsnet): The Writer output should match the following file. // To fix an issue (see https://golang.org/issue/12594), we disabled // prefix support, which alters the generated output. /* // This file was produced using gnu tar 1.17 // gnutar -b 4 --format=ustar (longname/)*15 + file.txt file: "testdata/ustar.tar" */ file: "testdata/ustar.issue12594.tar", // This is a valid tar file, but not expected entries: []*entry{{ header: &Header{ Name: strings.Repeat("longname/", 15) + "file.txt", Mode: 0644, Uid: 0765, Gid: 024, Size: 06, ModTime: time.Unix(1360135598, 0), Typeflag: '0', Uname: "shane", Gname: "staff", }, contents: "hello\n", }}, }, { // This file was produced using gnu tar 1.26 // echo "Slartibartfast" > file.txt // ln file.txt hard.txt // tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt file: "testdata/hardlink.tar", entries: []*entry{{ header: &Header{ Name: "file.txt", Mode: 0644, Uid: 1000, Gid: 100, Size: 15, ModTime: time.Unix(1425484303, 0), Typeflag: '0', Uname: "vbatts", Gname: "users", }, contents: "Slartibartfast\n", }, { header: &Header{ Name: "hard.txt", Mode: 0644, Uid: 1000, Gid: 100, Size: 0, ModTime: time.Unix(1425484303, 0), Typeflag: '1', Linkname: "file.txt", Uname: "vbatts", Gname: "users", }, // no contents }}, }} testLoop: for i, v := range vectors { expected, err := ioutil.ReadFile(v.file) if err != nil { t.Errorf("test %d: Unexpected error: %v", i, err) continue } buf := new(bytes.Buffer) tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB big := false for j, entry := range v.entries { big = big || entry.header.Size > 1<<10 if err := tw.WriteHeader(entry.header); err != nil { t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err) continue testLoop } if _, err := io.WriteString(tw, entry.contents); err != nil { t.Errorf("test %d, entry %d: Failed writing contents: %v", i, j, err) continue testLoop } } // Only interested in Close failures for the small tests. if err := tw.Close(); err != nil && !big { t.Errorf("test %d: Failed closing archive: %v", i, err) continue testLoop } actual := buf.Bytes() if !bytes.Equal(expected, actual) { t.Errorf("test %d: Incorrect result: (-=expected, +=actual)\n%v", i, bytediff(expected, actual)) } if testing.Short() { // The second test is expensive. break } } }