github.com/HashDataInc/packer@v1.3.2/common/config_test.go (about)

     1  package common
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  func TestChooseString(t *testing.T) {
    14  	cases := []struct {
    15  		Input  []string
    16  		Output string
    17  	}{
    18  		{
    19  			[]string{"", "foo", ""},
    20  			"foo",
    21  		},
    22  		{
    23  			[]string{"", "foo", "bar"},
    24  			"foo",
    25  		},
    26  		{
    27  			[]string{"", "", ""},
    28  			"",
    29  		},
    30  	}
    31  
    32  	for _, tc := range cases {
    33  		result := ChooseString(tc.Input...)
    34  		if result != tc.Output {
    35  			t.Fatalf("bad: %#v", tc.Input)
    36  		}
    37  	}
    38  }
    39  
    40  func TestValidatedURL(t *testing.T) {
    41  	// Invalid URL: has hex code in host
    42  	_, err := ValidatedURL("http://what%20.com")
    43  	if err == nil {
    44  		t.Fatalf("expected err : %s", err)
    45  	}
    46  
    47  	// Invalid: unsupported scheme
    48  	_, err = ValidatedURL("ftp://host.com/path")
    49  	if err == nil {
    50  		t.Fatalf("expected err : %s", err)
    51  	}
    52  
    53  	// Valid: http
    54  	u, err := ValidatedURL("HTTP://packer.io/path")
    55  	if err != nil {
    56  		t.Fatalf("err: %s", err)
    57  	}
    58  
    59  	if u != "http://packer.io/path" {
    60  		t.Fatalf("bad: %s", u)
    61  	}
    62  
    63  	cases := []struct {
    64  		InputString string
    65  		OutputURL   string
    66  		ErrExpected bool
    67  	}{
    68  		// Invalid URL: has hex code in host
    69  		{"http://what%20.com", "", true},
    70  		// Valid: http
    71  		{"HTTP://packer.io/path", "http://packer.io/path", false},
    72  		// No path
    73  		{"HTTP://packer.io", "http://packer.io", false},
    74  		// Invalid: unsupported scheme
    75  		{"ftp://host.com/path", "", true},
    76  	}
    77  
    78  	for _, tc := range cases {
    79  		u, err := ValidatedURL(tc.InputString)
    80  		if u != tc.OutputURL {
    81  			t.Fatal(fmt.Sprintf("Error with URL %s: got %s but expected %s",
    82  				tc.InputString, tc.OutputURL, u))
    83  		}
    84  		if (err != nil) != tc.ErrExpected {
    85  			if tc.ErrExpected == true {
    86  				t.Fatal(fmt.Sprintf("Error with URL %s: we expected "+
    87  					"ValidatedURL to return an error but didn't get one.",
    88  					tc.InputString))
    89  			} else {
    90  				t.Fatal(fmt.Sprintf("Error with URL %s: we did not expect an "+
    91  					" error from ValidatedURL but we got: %s",
    92  					tc.InputString, err))
    93  			}
    94  		}
    95  	}
    96  }
    97  
    98  func GetNativePathToTestFixtures(t *testing.T) string {
    99  	const path = "./test-fixtures"
   100  	res, err := filepath.Abs(path)
   101  	if err != nil {
   102  		t.Fatalf("err converting test-fixtures path into an absolute path : %s", err)
   103  	}
   104  	return res
   105  }
   106  
   107  func GetPortablePathToTestFixtures(t *testing.T) string {
   108  	res := GetNativePathToTestFixtures(t)
   109  	return filepath.ToSlash(res)
   110  }
   111  
   112  func TestDownloadableURL_WindowsFiles(t *testing.T) {
   113  	if runtime.GOOS == "windows" {
   114  		portablepath := GetPortablePathToTestFixtures(t)
   115  		nativepath := GetNativePathToTestFixtures(t)
   116  
   117  		dirCases := []struct {
   118  			InputString string
   119  			OutputURL   string
   120  			ErrExpected bool
   121  		}{ // TODO: add different directories
   122  			{
   123  				fmt.Sprintf("%s\\SomeDir\\myfile.txt", nativepath),
   124  				fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
   125  				false,
   126  			},
   127  			{ // without the drive makes this native path a relative file:// uri
   128  				"test-fixtures\\SomeDir\\myfile.txt",
   129  				fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
   130  				false,
   131  			},
   132  			{ // without the drive makes this native path a relative file:// uri
   133  				"test-fixtures/SomeDir/myfile.txt",
   134  				fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
   135  				false,
   136  			},
   137  			{ // UNC paths being promoted to smb:// uri scheme.
   138  				fmt.Sprintf("\\\\localhost\\C$\\%s\\SomeDir\\myfile.txt", nativepath),
   139  				fmt.Sprintf("smb://localhost/C$/%s/SomeDir/myfile.txt", portablepath),
   140  				false,
   141  			},
   142  			{ // Absolute uri (incorrect slash type)
   143  				fmt.Sprintf("file:///%s\\SomeDir\\myfile.txt", nativepath),
   144  				fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
   145  				false,
   146  			},
   147  			{ // Absolute uri (existing and mis-spelled)
   148  				fmt.Sprintf("file:///%s/Somedir/myfile.txt", nativepath),
   149  				fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
   150  				false,
   151  			},
   152  			{ // Absolute path (non-existing)
   153  				"\\absolute\\path\\to\\non-existing\\file.txt",
   154  				"file:///absolute/path/to/non-existing/file.txt",
   155  				false,
   156  			},
   157  			{ // Absolute paths (existing)
   158  				fmt.Sprintf("%s/SomeDir/myfile.txt", nativepath),
   159  				fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
   160  				false,
   161  			},
   162  			{ // Relative path (non-existing)
   163  				"./nonexisting/relative/path/to/file.txt",
   164  				"file://./nonexisting/relative/path/to/file.txt",
   165  				false,
   166  			},
   167  			{ // Relative path (existing)
   168  				"./test-fixtures/SomeDir/myfile.txt",
   169  				fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
   170  				false,
   171  			},
   172  			{ // Absolute uri (existing and with `/` prefix)
   173  				fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
   174  				fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
   175  				false,
   176  			},
   177  			{ // Absolute uri (non-existing and with `/` prefix)
   178  				"file:///path/to/non-existing/file.txt",
   179  				"file:///path/to/non-existing/file.txt",
   180  				false,
   181  			},
   182  			{ // Absolute uri (non-existing and missing `/` prefix)
   183  				"file://path/to/non-existing/file.txt",
   184  				"file://path/to/non-existing/file.txt",
   185  				false,
   186  			},
   187  			{ // Absolute uri and volume (non-existing and with `/` prefix)
   188  				"file:///T:/path/to/non-existing/file.txt",
   189  				"file:///T:/path/to/non-existing/file.txt",
   190  				false,
   191  			},
   192  			{ // Absolute uri and volume (non-existing and missing `/` prefix)
   193  				"file://T:/path/to/non-existing/file.txt",
   194  				"file://T:/path/to/non-existing/file.txt",
   195  				false,
   196  			},
   197  		}
   198  		// Run through test cases to make sure they all parse correctly
   199  		for idx, tc := range dirCases {
   200  			u, err := DownloadableURL(tc.InputString)
   201  			if (err != nil) != tc.ErrExpected {
   202  				t.Fatalf("Test Case %d failed: Expected err = %#v, err = %#v, input = %s",
   203  					idx, tc.ErrExpected, err, tc.InputString)
   204  			}
   205  			if u != tc.OutputURL {
   206  				t.Fatalf("Test Case %d failed: Expected %s but received %s from input %s",
   207  					idx, tc.OutputURL, u, tc.InputString)
   208  			}
   209  		}
   210  	}
   211  }
   212  
   213  func TestDownloadableURL_FilePaths(t *testing.T) {
   214  	tf, err := ioutil.TempFile("", "packer")
   215  	if err != nil {
   216  		t.Fatalf("tempfile err: %s", err)
   217  	}
   218  	defer os.Remove(tf.Name())
   219  	tf.Close()
   220  
   221  	tfPath, err := filepath.EvalSymlinks(tf.Name())
   222  	if err != nil {
   223  		t.Fatalf("tempfile err: %s", err)
   224  	}
   225  
   226  	tfPath = filepath.Clean(tfPath)
   227  	filePrefix := "file://"
   228  
   229  	// If we're running windows, then absolute URIs are `/`-prefixed.
   230  	platformPrefix := ""
   231  	if runtime.GOOS == "windows" {
   232  		platformPrefix = "/"
   233  	}
   234  
   235  	// Relative filepath. We run this test in a func so that
   236  	// the defers run right away.
   237  	func() {
   238  		wd, err := os.Getwd()
   239  		if err != nil {
   240  			t.Fatalf("getwd err: %s", err)
   241  		}
   242  
   243  		err = os.Chdir(filepath.Dir(tfPath))
   244  		if err != nil {
   245  			t.Fatalf("chdir err: %s", err)
   246  		}
   247  		defer os.Chdir(wd)
   248  
   249  		filename := filepath.Base(tfPath)
   250  		u, err := DownloadableURL(filename)
   251  		if err != nil {
   252  			t.Fatalf("err: %s", err)
   253  		}
   254  
   255  		expected := fmt.Sprintf("%s%s%s",
   256  			filePrefix,
   257  			platformPrefix,
   258  			strings.Replace(tfPath, `\`, `/`, -1))
   259  		if u != expected {
   260  			t.Fatalf("unexpected: %#v != %#v", u, expected)
   261  		}
   262  	}()
   263  
   264  	// Test some cases with and without a schema prefix
   265  	for _, prefix := range []string{"", filePrefix + platformPrefix} {
   266  		// Nonexistent file
   267  		_, err = DownloadableURL(prefix + "i/dont/exist")
   268  		if err != nil {
   269  			t.Fatalf("err: %s", err)
   270  		}
   271  
   272  		// Good file (absolute)
   273  		u, err := DownloadableURL(prefix + tfPath)
   274  		if err != nil {
   275  			t.Fatalf("err: %s", err)
   276  		}
   277  
   278  		expected := fmt.Sprintf("%s%s%s",
   279  			filePrefix,
   280  			platformPrefix,
   281  			strings.Replace(tfPath, `\`, `/`, -1))
   282  		if u != expected {
   283  			t.Fatalf("unexpected: %s != %s", u, expected)
   284  		}
   285  	}
   286  }
   287  
   288  func TestFileExistsLocally(t *testing.T) {
   289  	portablepath := GetPortablePathToTestFixtures(t)
   290  
   291  	dirCases := []struct {
   292  		Input  string
   293  		Output bool
   294  	}{
   295  		// file exists locally
   296  		{fmt.Sprintf("file://%s/SomeDir/myfile.txt", portablepath), true},
   297  		// remote protocols short-circuit and are considered to exist locally
   298  		{"https://myfile.iso", true},
   299  		// non-existent protocols do not exist and hence fail
   300  		{"nonexistent-protocol://myfile.iso", false},
   301  		// file does not exist locally
   302  		{"file:///C/i/dont/exist", false},
   303  	}
   304  	// Run through test cases to make sure they all parse correctly
   305  	for _, tc := range dirCases {
   306  		fileOK := FileExistsLocally(tc.Input)
   307  		if fileOK != tc.Output {
   308  			t.Fatalf("Test Case failed: Expected %#v, received = %#v, input = %s",
   309  				tc.Output, fileOK, tc.Input)
   310  		}
   311  	}
   312  }