github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/common/download_test.go (about) 1 package common 2 3 import ( 4 "crypto/md5" 5 "encoding/hex" 6 "fmt" 7 "io/ioutil" 8 "net/http" 9 "net/http/httptest" 10 "os" 11 "runtime" 12 "testing" 13 ) 14 15 func TestDownloadClientVerifyChecksum(t *testing.T) { 16 tf, err := ioutil.TempFile("", "packer") 17 if err != nil { 18 t.Fatalf("tempfile error: %s", err) 19 } 20 defer os.Remove(tf.Name()) 21 22 // "foo" 23 checksum, err := hex.DecodeString("acbd18db4cc2f85cedef654fccc4a4d8") 24 if err != nil { 25 t.Fatalf("decode err: %s", err) 26 } 27 28 // Write the file 29 tf.Write([]byte("foo")) 30 tf.Close() 31 32 config := &DownloadConfig{ 33 Hash: md5.New(), 34 Checksum: checksum, 35 } 36 37 d := NewDownloadClient(config) 38 result, err := d.VerifyChecksum(tf.Name()) 39 if err != nil { 40 t.Fatalf("Verify err: %s", err) 41 } 42 43 if !result { 44 t.Fatal("didn't verify") 45 } 46 } 47 48 func TestDownloadClient_basic(t *testing.T) { 49 tf, _ := ioutil.TempFile("", "packer") 50 tf.Close() 51 os.Remove(tf.Name()) 52 53 ts := httptest.NewServer(http.FileServer(http.Dir("./test-fixtures/root"))) 54 defer ts.Close() 55 56 client := NewDownloadClient(&DownloadConfig{ 57 Url: ts.URL + "/basic.txt", 58 TargetPath: tf.Name(), 59 }) 60 61 path, err := client.Get() 62 if err != nil { 63 t.Fatalf("err: %s", err) 64 } 65 66 raw, err := ioutil.ReadFile(path) 67 if err != nil { 68 t.Fatalf("err: %s", err) 69 } 70 71 if string(raw) != "hello\n" { 72 t.Fatalf("bad: %s", string(raw)) 73 } 74 } 75 76 func TestDownloadClient_checksumBad(t *testing.T) { 77 checksum, err := hex.DecodeString("b2946ac92492d2347c6235b4d2611184") 78 if err != nil { 79 t.Fatalf("err: %s", err) 80 } 81 82 tf, _ := ioutil.TempFile("", "packer") 83 tf.Close() 84 os.Remove(tf.Name()) 85 86 ts := httptest.NewServer(http.FileServer(http.Dir("./test-fixtures/root"))) 87 defer ts.Close() 88 89 client := NewDownloadClient(&DownloadConfig{ 90 Url: ts.URL + "/basic.txt", 91 TargetPath: tf.Name(), 92 Hash: HashForType("md5"), 93 Checksum: checksum, 94 }) 95 if _, err := client.Get(); err == nil { 96 t.Fatal("should error") 97 } 98 } 99 100 func TestDownloadClient_checksumGood(t *testing.T) { 101 checksum, err := hex.DecodeString("b1946ac92492d2347c6235b4d2611184") 102 if err != nil { 103 t.Fatalf("err: %s", err) 104 } 105 106 tf, _ := ioutil.TempFile("", "packer") 107 tf.Close() 108 os.Remove(tf.Name()) 109 110 ts := httptest.NewServer(http.FileServer(http.Dir("./test-fixtures/root"))) 111 defer ts.Close() 112 113 client := NewDownloadClient(&DownloadConfig{ 114 Url: ts.URL + "/basic.txt", 115 TargetPath: tf.Name(), 116 Hash: HashForType("md5"), 117 Checksum: checksum, 118 }) 119 path, err := client.Get() 120 if err != nil { 121 t.Fatalf("err: %s", err) 122 } 123 124 raw, err := ioutil.ReadFile(path) 125 if err != nil { 126 t.Fatalf("err: %s", err) 127 } 128 129 if string(raw) != "hello\n" { 130 t.Fatalf("bad: %s", string(raw)) 131 } 132 } 133 134 func TestDownloadClient_checksumNoDownload(t *testing.T) { 135 checksum, err := hex.DecodeString("3740570a423feec44c2a759225a9fcf9") 136 if err != nil { 137 t.Fatalf("err: %s", err) 138 } 139 140 ts := httptest.NewServer(http.FileServer(http.Dir("./test-fixtures/root"))) 141 defer ts.Close() 142 143 client := NewDownloadClient(&DownloadConfig{ 144 Url: ts.URL + "/basic.txt", 145 TargetPath: "./test-fixtures/root/another.txt", 146 Hash: HashForType("md5"), 147 Checksum: checksum, 148 }) 149 path, err := client.Get() 150 if err != nil { 151 t.Fatalf("err: %s", err) 152 } 153 154 raw, err := ioutil.ReadFile(path) 155 if err != nil { 156 t.Fatalf("err: %s", err) 157 } 158 159 // If this says "hello" it means we downloaded it. We faked out 160 // the downloader above by giving it the checksum for "another", but 161 // requested the download of "hello" 162 if string(raw) != "another\n" { 163 t.Fatalf("bad: %s", string(raw)) 164 } 165 } 166 167 func TestDownloadClient_resume(t *testing.T) { 168 tf, _ := ioutil.TempFile("", "packer") 169 tf.Write([]byte("w")) 170 tf.Close() 171 172 ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { 173 if r.Method == "HEAD" { 174 rw.Header().Set("Accept-Ranges", "bytes") 175 rw.WriteHeader(204) 176 return 177 } 178 179 http.ServeFile(rw, r, "./test-fixtures/root/basic.txt") 180 })) 181 defer ts.Close() 182 183 client := NewDownloadClient(&DownloadConfig{ 184 Url: ts.URL, 185 TargetPath: tf.Name(), 186 }) 187 path, err := client.Get() 188 if err != nil { 189 t.Fatalf("err: %s", err) 190 } 191 192 raw, err := ioutil.ReadFile(path) 193 if err != nil { 194 t.Fatalf("err: %s", err) 195 } 196 197 if string(raw) != "wello\n" { 198 t.Fatalf("bad: %s", string(raw)) 199 } 200 } 201 202 func TestDownloadClient_usesDefaultUserAgent(t *testing.T) { 203 tf, err := ioutil.TempFile("", "packer") 204 if err != nil { 205 t.Fatalf("tempfile error: %s", err) 206 } 207 defer os.Remove(tf.Name()) 208 209 defaultUserAgent := "" 210 asserted := false 211 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 212 if defaultUserAgent == "" { 213 defaultUserAgent = r.UserAgent() 214 } else { 215 incomingUserAgent := r.UserAgent() 216 if incomingUserAgent != defaultUserAgent { 217 t.Fatalf("Expected user agent %s, got: %s", defaultUserAgent, incomingUserAgent) 218 } 219 220 asserted = true 221 } 222 })) 223 224 req, err := http.NewRequest("GET", server.URL, nil) 225 if err != nil { 226 t.Fatal(err) 227 } 228 229 httpClient := &http.Client{ 230 Transport: &http.Transport{ 231 Proxy: http.ProxyFromEnvironment, 232 }, 233 } 234 235 _, err = httpClient.Do(req) 236 if err != nil { 237 t.Fatal(err) 238 } 239 240 config := &DownloadConfig{ 241 Url: server.URL, 242 TargetPath: tf.Name(), 243 } 244 245 client := NewDownloadClient(config) 246 _, err = client.Get() 247 if err != nil { 248 t.Fatal(err) 249 } 250 251 if !asserted { 252 t.Fatal("User-Agent never observed") 253 } 254 } 255 256 func TestDownloadClient_setsUserAgent(t *testing.T) { 257 tf, err := ioutil.TempFile("", "packer") 258 if err != nil { 259 t.Fatalf("tempfile error: %s", err) 260 } 261 defer os.Remove(tf.Name()) 262 263 asserted := false 264 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 265 asserted = true 266 if r.UserAgent() != "fancy user agent" { 267 t.Fatalf("Expected useragent fancy user agent, got: %s", r.UserAgent()) 268 } 269 })) 270 config := &DownloadConfig{ 271 Url: server.URL, 272 TargetPath: tf.Name(), 273 UserAgent: "fancy user agent", 274 } 275 276 client := NewDownloadClient(config) 277 _, err = client.Get() 278 if err != nil { 279 t.Fatal(err) 280 } 281 282 if !asserted { 283 t.Fatal("HTTP request never made") 284 } 285 } 286 287 func TestHashForType(t *testing.T) { 288 if h := HashForType("md5"); h == nil { 289 t.Fatalf("md5 hash is nil") 290 } else { 291 h.Write([]byte("foo")) 292 result := h.Sum(nil) 293 294 expected := "acbd18db4cc2f85cedef654fccc4a4d8" 295 actual := hex.EncodeToString(result) 296 if actual != expected { 297 t.Fatalf("bad hash: %s", actual) 298 } 299 } 300 301 if h := HashForType("sha1"); h == nil { 302 t.Fatalf("sha1 hash is nil") 303 } else { 304 h.Write([]byte("foo")) 305 result := h.Sum(nil) 306 307 expected := "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" 308 actual := hex.EncodeToString(result) 309 if actual != expected { 310 t.Fatalf("bad hash: %s", actual) 311 } 312 } 313 314 if h := HashForType("sha256"); h == nil { 315 t.Fatalf("sha256 hash is nil") 316 } else { 317 h.Write([]byte("foo")) 318 result := h.Sum(nil) 319 320 expected := "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae" 321 actual := hex.EncodeToString(result) 322 if actual != expected { 323 t.Fatalf("bad hash: %s", actual) 324 } 325 } 326 327 if h := HashForType("sha512"); h == nil { 328 t.Fatalf("sha512 hash is nil") 329 } else { 330 h.Write([]byte("foo")) 331 result := h.Sum(nil) 332 333 expected := "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7" 334 actual := hex.EncodeToString(result) 335 if actual != expected { 336 t.Fatalf("bad hash: %s", actual) 337 } 338 } 339 340 if HashForType("fake") != nil { 341 t.Fatalf("fake hash is not nil") 342 } 343 } 344 345 // TestDownloadFileUrl tests a special case where we use a local file for 346 // iso_url. In this case we can still verify the checksum but we should not 347 // delete the file if the checksum fails. Instead we'll just error and let the 348 // user fix the checksum. 349 func TestDownloadFileUrl(t *testing.T) { 350 cwd, err := os.Getwd() 351 if err != nil { 352 t.Fatalf("Unable to detect working directory: %s", err) 353 } 354 355 // source_path is a file path and source is a network path 356 sourcePath := fmt.Sprintf("%s/test-fixtures/fileurl/%s", cwd, "cake") 357 358 filePrefix := "file://" 359 if runtime.GOOS == "windows" { 360 filePrefix += "/" 361 } 362 363 source := fmt.Sprintf(filePrefix + sourcePath) 364 t.Logf("Trying to download %s", source) 365 366 config := &DownloadConfig{ 367 Url: source, 368 // This should be wrong. We want to make sure we don't delete 369 Checksum: []byte("nope"), 370 Hash: HashForType("sha256"), 371 CopyFile: false, 372 } 373 374 client := NewDownloadClient(config) 375 376 // Verify that we fail to match the checksum 377 _, err = client.Get() 378 if err.Error() != "checksums didn't match expected: 6e6f7065" { 379 t.Fatalf("Unexpected failure; expected checksum not to match") 380 } 381 382 if _, err = os.Stat(sourcePath); err != nil { 383 t.Errorf("Could not stat source file: %s", sourcePath) 384 } 385 386 }