github.com/wilsonge/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 }