1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
package getter
import (
"crypto/md5"
"encoding/hex"
"io"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"runtime"
"sort"
"strings"
"time"
"github.com/mitchellh/go-testing-interface"
)
// TestDecompressCase is a single test case for testing decompressors
type TestDecompressCase struct {
Input string // Input is the complete path to the input file
Dir bool // Dir is whether or not we're testing directory mode
Err bool // Err is whether we expect an error or not
DirList []string // DirList is the list of files for Dir mode
FileMD5 string // FileMD5 is the expected MD5 for a single file
Mtime *time.Time // Mtime is the optionally expected mtime for a single file (or all files if in Dir mode)
}
// TestDecompressor is a helper function for testing generic decompressors.
func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) {
for _, tc := range cases {
t.Logf("Testing: %s", tc.Input)
// Temporary dir to store stuff
td, err := ioutil.TempDir("", "getter")
if err != nil {
t.Fatalf("err: %s", err)
}
// Destination is always joining result so that we have a new path
dst := filepath.Join(td, "subdir", "result")
// We use a function so defers work
func() {
defer os.RemoveAll(td)
// Decompress
err := d.Decompress(dst, tc.Input, tc.Dir)
if (err != nil) != tc.Err {
t.Fatalf("err %s: %s", tc.Input, err)
}
if tc.Err {
return
}
// If it isn't a directory, then check for a single file
if !tc.Dir {
fi, err := os.Stat(dst)
if err != nil {
t.Fatalf("err %s: %s", tc.Input, err)
}
if fi.IsDir() {
t.Fatalf("err %s: expected file, got directory", tc.Input)
}
if tc.FileMD5 != "" {
actual := testMD5(t, dst)
expected := tc.FileMD5
if actual != expected {
t.Fatalf("err %s: expected MD5 %s, got %s", tc.Input, expected, actual)
}
}
if tc.Mtime != nil {
actual := fi.ModTime()
if tc.Mtime.Unix() > 0 {
expected := *tc.Mtime
if actual != expected {
t.Fatalf("err %s: expected mtime '%s' for %s, got '%s'", tc.Input, expected.String(), dst, actual.String())
}
} else if actual.Unix() <= 0 {
t.Fatalf("err %s: expected mtime to be > 0, got '%s'", actual.String())
}
}
return
}
// Convert expected for windows
expected := tc.DirList
if runtime.GOOS == "windows" {
for i, v := range expected {
expected[i] = strings.Replace(v, "/", "\\", -1)
}
}
// Directory, check for the correct contents
actual := testListDir(t, dst)
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual, expected)
}
// Check for correct atime/mtime
for _, dir := range actual {
path := filepath.Join(dst, dir)
if tc.Mtime != nil {
fi, err := os.Stat(path)
if err != nil {
t.Fatalf("err: %s", err)
}
actual := fi.ModTime()
if tc.Mtime.Unix() > 0 {
expected := *tc.Mtime
if actual != expected {
t.Fatalf("err %s: expected mtime '%s' for %s, got '%s'", tc.Input, expected.String(), path, actual.String())
}
} else if actual.Unix() < 0 {
t.Fatalf("err %s: expected mtime to be > 0, got '%s'", actual.String())
}
}
}
}()
}
}
func testListDir(t testing.T, path string) []string {
var result []string
err := filepath.Walk(path, func(sub string, info os.FileInfo, err error) error {
if err != nil {
return err
}
sub = strings.TrimPrefix(sub, path)
if sub == "" {
return nil
}
sub = sub[1:] // Trim the leading path sep.
// If it is a dir, add trailing sep
if info.IsDir() {
sub += string(os.PathSeparator)
}
result = append(result, sub)
return nil
})
if err != nil {
t.Fatalf("err: %s", err)
}
sort.Strings(result)
return result
}
func testMD5(t testing.T, path string) string {
f, err := os.Open(path)
if err != nil {
t.Fatalf("err: %s", err)
}
defer f.Close()
h := md5.New()
_, err = io.Copy(h, f)
if err != nil {
t.Fatalf("err: %s", err)
}
result := h.Sum(nil)
return hex.EncodeToString(result)
}
|