mirror of
https://github.com/autc04/Retro68.git
synced 2024-12-13 18:34:45 +00:00
178 lines
4.0 KiB
Go
178 lines
4.0 KiB
Go
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package tar
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"testing"
|
||
|
"testing/iotest"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type writerTestEntry struct {
|
||
|
header *Header
|
||
|
contents string
|
||
|
}
|
||
|
|
||
|
type writerTest struct {
|
||
|
file string // filename of expected output
|
||
|
entries []*writerTestEntry
|
||
|
}
|
||
|
|
||
|
var writerTests = []*writerTest{
|
||
|
// 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: []*writerTestEntry{
|
||
|
{
|
||
|
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: []*writerTestEntry{
|
||
|
{
|
||
|
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",
|
||
|
},
|
||
|
// 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:
|
||
|
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
|
||
|
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", 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
|
||
|
}
|
||
|
}
|
||
|
}
|