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