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))
		}
	}
}
Example #2
0
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)
	}
}
Example #3
0
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)
	}
}
Example #4
0
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
		}
	}
}
Example #5
0
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
		}
	}
}