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