2013-07-19 14:59:04 -04:00
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
2013-07-29 02:51:21 -04:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2018-01-19 00:09:53 -05:00
|
|
|
"runtime"
|
2014-04-22 00:28:47 -04:00
|
|
|
"strings"
|
2013-07-19 14:59:04 -04:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2014-04-22 00:30:49 -04:00
|
|
|
func TestChooseString(t *testing.T) {
|
|
|
|
cases := []struct {
|
2014-04-26 14:12:43 -04:00
|
|
|
Input []string
|
2014-04-22 00:30:49 -04:00
|
|
|
Output string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
[]string{"", "foo", ""},
|
|
|
|
"foo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
[]string{"", "foo", "bar"},
|
|
|
|
"foo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
[]string{"", "", ""},
|
|
|
|
"",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range cases {
|
|
|
|
result := ChooseString(tc.Input...)
|
|
|
|
if result != tc.Output {
|
|
|
|
t.Fatalf("bad: %#v", tc.Input)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-09 21:08:06 -05:00
|
|
|
func TestValidatedURL(t *testing.T) {
|
2016-04-05 17:51:17 -04:00
|
|
|
// Invalid URL: has hex code in host
|
2018-01-09 21:08:06 -05:00
|
|
|
_, err := ValidatedURL("http://what%20.com")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected err : %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invalid: unsupported scheme
|
|
|
|
_, err = ValidatedURL("ftp://host.com/path")
|
2016-04-05 17:51:17 -04:00
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expected err : %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Valid: http
|
2018-01-09 21:08:06 -05:00
|
|
|
u, err := ValidatedURL("HTTP://packer.io/path")
|
2016-04-05 17:51:17 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if u != "http://packer.io/path" {
|
|
|
|
t.Fatalf("bad: %s", u)
|
|
|
|
}
|
2013-07-29 03:09:48 -04:00
|
|
|
|
2018-01-05 14:06:26 -05:00
|
|
|
cases := []struct {
|
|
|
|
InputString string
|
|
|
|
OutputURL string
|
|
|
|
ErrExpected bool
|
|
|
|
}{
|
|
|
|
// Invalid URL: has hex code in host
|
|
|
|
{"http://what%20.com", "", true},
|
|
|
|
// Valid: http
|
|
|
|
{"HTTP://packer.io/path", "http://packer.io/path", false},
|
|
|
|
// No path
|
|
|
|
{"HTTP://packer.io", "http://packer.io", false},
|
|
|
|
// Invalid: unsupported scheme
|
|
|
|
{"ftp://host.com/path", "", true},
|
2013-07-29 03:09:48 -04:00
|
|
|
}
|
|
|
|
|
2018-01-05 14:06:26 -05:00
|
|
|
for _, tc := range cases {
|
2018-01-09 21:08:06 -05:00
|
|
|
u, err := ValidatedURL(tc.InputString)
|
2018-01-05 14:06:26 -05:00
|
|
|
if u != tc.OutputURL {
|
|
|
|
t.Fatal(fmt.Sprintf("Error with URL %s: got %s but expected %s",
|
|
|
|
tc.InputString, tc.OutputURL, u))
|
|
|
|
}
|
|
|
|
if (err != nil) != tc.ErrExpected {
|
|
|
|
if tc.ErrExpected == true {
|
|
|
|
t.Fatal(fmt.Sprintf("Error with URL %s: we expected "+
|
2018-01-09 21:08:06 -05:00
|
|
|
"ValidatedURL to return an error but didn't get one.",
|
2018-01-05 14:06:26 -05:00
|
|
|
tc.InputString))
|
|
|
|
} else {
|
|
|
|
t.Fatal(fmt.Sprintf("Error with URL %s: we did not expect an "+
|
2018-01-09 21:08:06 -05:00
|
|
|
" error from ValidatedURL but we got: %s",
|
2018-01-05 14:06:26 -05:00
|
|
|
tc.InputString, err))
|
|
|
|
}
|
|
|
|
}
|
2013-07-29 03:09:48 -04:00
|
|
|
}
|
2013-07-29 02:51:21 -04:00
|
|
|
}
|
|
|
|
|
2018-01-19 00:08:22 -05:00
|
|
|
func GetNativePathToTestFixtures(t *testing.T) string {
|
|
|
|
const path = "./test-fixtures"
|
|
|
|
res, err := filepath.Abs(path)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err converting test-fixtures path into an absolute path : %s", err)
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetPortablePathToTestFixtures(t *testing.T) string {
|
|
|
|
res := GetNativePathToTestFixtures(t)
|
|
|
|
return filepath.ToSlash(res)
|
|
|
|
}
|
|
|
|
|
2018-01-09 19:11:29 -05:00
|
|
|
func TestDownloadableURL_WindowsFiles(t *testing.T) {
|
|
|
|
if runtime.GOOS == "windows" {
|
2018-01-19 00:08:22 -05:00
|
|
|
portablepath := GetPortablePathToTestFixtures(t)
|
|
|
|
nativepath := GetNativePathToTestFixtures(t)
|
|
|
|
|
2018-01-09 19:11:29 -05:00
|
|
|
dirCases := []struct {
|
|
|
|
InputString string
|
|
|
|
OutputURL string
|
|
|
|
ErrExpected bool
|
|
|
|
}{ // TODO: add different directories
|
|
|
|
{
|
2018-01-19 00:08:22 -05:00
|
|
|
fmt.Sprintf("%s\\SomeDir\\myfile.txt", nativepath),
|
|
|
|
fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
|
2018-01-09 19:11:29 -05:00
|
|
|
false,
|
|
|
|
},
|
2018-01-19 00:08:22 -05:00
|
|
|
{ // without the drive makes this native path a relative file:// uri
|
|
|
|
"test-fixtures\\SomeDir\\myfile.txt",
|
|
|
|
fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
|
|
|
|
false,
|
2018-01-09 19:11:29 -05:00
|
|
|
},
|
2018-01-19 00:08:22 -05:00
|
|
|
{ // without the drive makes this native path a relative file:// uri
|
|
|
|
"test-fixtures/SomeDir/myfile.txt",
|
|
|
|
fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
|
|
|
|
false,
|
2018-01-09 19:11:29 -05:00
|
|
|
},
|
2018-01-19 00:08:22 -05:00
|
|
|
{ // UNC paths being promoted to smb:// uri scheme.
|
|
|
|
fmt.Sprintf("\\\\localhost\\C$\\%s\\SomeDir\\myfile.txt", nativepath),
|
|
|
|
fmt.Sprintf("smb://localhost/C$/%s/SomeDir/myfile.txt", portablepath),
|
|
|
|
false,
|
2018-01-09 20:14:32 -05:00
|
|
|
},
|
2018-01-19 00:08:22 -05:00
|
|
|
{ // Absolute uri (incorrect slash type)
|
|
|
|
fmt.Sprintf("file:///%s\\SomeDir\\myfile.txt", nativepath),
|
|
|
|
fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
|
2018-01-09 19:11:29 -05:00
|
|
|
false,
|
|
|
|
},
|
2018-01-19 00:08:22 -05:00
|
|
|
{ // Absolute uri (existing and mis-spelled)
|
|
|
|
fmt.Sprintf("file:///%s/Somedir/myfile.txt", nativepath),
|
|
|
|
fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Absolute path (non-existing)
|
|
|
|
"\\absolute\\path\\to\\non-existing\\file.txt",
|
|
|
|
"file:///absolute/path/to/non-existing/file.txt",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Absolute paths (existing)
|
|
|
|
fmt.Sprintf("%s/SomeDir/myfile.txt", nativepath),
|
|
|
|
fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Relative path (non-existing)
|
|
|
|
"./nonexisting/relative/path/to/file.txt",
|
|
|
|
"file://./nonexisting/relative/path/to/file.txt",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Relative path (existing)
|
|
|
|
"./test-fixtures/SomeDir/myfile.txt",
|
|
|
|
fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Absolute uri (existing and with `/` prefix)
|
|
|
|
fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
|
|
|
|
fmt.Sprintf("file:///%s/SomeDir/myfile.txt", portablepath),
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Absolute uri (non-existing and with `/` prefix)
|
|
|
|
"file:///path/to/non-existing/file.txt",
|
|
|
|
"file:///path/to/non-existing/file.txt",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Absolute uri (non-existing and missing `/` prefix)
|
|
|
|
"file://path/to/non-existing/file.txt",
|
|
|
|
"file://path/to/non-existing/file.txt",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Absolute uri and volume (non-existing and with `/` prefix)
|
|
|
|
"file:///T:/path/to/non-existing/file.txt",
|
|
|
|
"file:///T:/path/to/non-existing/file.txt",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // Absolute uri and volume (non-existing and missing `/` prefix)
|
|
|
|
"file://T:/path/to/non-existing/file.txt",
|
|
|
|
"file://T:/path/to/non-existing/file.txt",
|
2018-01-09 19:11:29 -05:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
// Run through test cases to make sure they all parse correctly
|
2018-01-19 00:08:22 -05:00
|
|
|
for idx, tc := range dirCases {
|
2018-01-09 19:11:29 -05:00
|
|
|
u, err := DownloadableURL(tc.InputString)
|
|
|
|
if (err != nil) != tc.ErrExpected {
|
2018-01-19 00:08:22 -05:00
|
|
|
t.Fatalf("Test Case %d failed: Expected err = %#v, err = %#v, input = %s",
|
|
|
|
idx, tc.ErrExpected, err, tc.InputString)
|
2018-01-09 19:11:29 -05:00
|
|
|
}
|
|
|
|
if u != tc.OutputURL {
|
2018-01-19 00:08:22 -05:00
|
|
|
t.Fatalf("Test Case %d failed: Expected %s but received %s from input %s",
|
|
|
|
idx, tc.OutputURL, u, tc.InputString)
|
2018-01-09 19:11:29 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-29 02:51:21 -04:00
|
|
|
func TestDownloadableURL_FilePaths(t *testing.T) {
|
|
|
|
tf, err := ioutil.TempFile("", "packer")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("tempfile err: %s", err)
|
|
|
|
}
|
|
|
|
defer os.Remove(tf.Name())
|
|
|
|
tf.Close()
|
|
|
|
|
2013-07-29 03:06:21 -04:00
|
|
|
tfPath, err := filepath.EvalSymlinks(tf.Name())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("tempfile err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tfPath = filepath.Clean(tfPath)
|
2014-04-22 00:28:47 -04:00
|
|
|
filePrefix := "file://"
|
|
|
|
|
2018-01-19 00:08:22 -05:00
|
|
|
// If we're running windows, then absolute URIs are `/`-prefixed.
|
|
|
|
platformPrefix := ""
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
platformPrefix = "/"
|
|
|
|
}
|
|
|
|
|
2013-07-29 02:51:21 -04:00
|
|
|
// Relative filepath. We run this test in a func so that
|
|
|
|
// the defers run right away.
|
|
|
|
func() {
|
|
|
|
wd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("getwd err: %s", err)
|
|
|
|
}
|
|
|
|
|
2013-07-29 03:06:21 -04:00
|
|
|
err = os.Chdir(filepath.Dir(tfPath))
|
2013-07-29 02:51:21 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("chdir err: %s", err)
|
|
|
|
}
|
|
|
|
defer os.Chdir(wd)
|
|
|
|
|
2013-07-29 03:06:21 -04:00
|
|
|
filename := filepath.Base(tfPath)
|
2013-07-29 02:51:21 -04:00
|
|
|
u, err := DownloadableURL(filename)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2018-01-19 00:08:22 -05:00
|
|
|
expected := fmt.Sprintf("%s%s%s",
|
2018-01-06 20:46:52 -05:00
|
|
|
filePrefix,
|
2018-01-19 00:08:22 -05:00
|
|
|
platformPrefix,
|
2018-01-06 20:46:52 -05:00
|
|
|
strings.Replace(tfPath, `\`, `/`, -1))
|
2014-04-22 00:28:47 -04:00
|
|
|
if u != expected {
|
|
|
|
t.Fatalf("unexpected: %#v != %#v", u, expected)
|
2013-07-29 02:51:21 -04:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Test some cases with and without a schema prefix
|
2018-01-19 00:08:22 -05:00
|
|
|
for _, prefix := range []string{"", filePrefix + platformPrefix} {
|
2013-07-29 02:51:21 -04:00
|
|
|
// Nonexistent file
|
|
|
|
_, err = DownloadableURL(prefix + "i/dont/exist")
|
2013-12-06 21:36:16 -05:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
2013-07-29 02:51:21 -04:00
|
|
|
}
|
|
|
|
|
2018-01-19 00:08:22 -05:00
|
|
|
// Good file (absolute)
|
2013-07-29 03:06:21 -04:00
|
|
|
u, err := DownloadableURL(prefix + tfPath)
|
2013-07-29 02:51:21 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2018-01-19 00:08:22 -05:00
|
|
|
expected := fmt.Sprintf("%s%s%s",
|
2014-04-22 00:28:47 -04:00
|
|
|
filePrefix,
|
2018-01-19 00:08:22 -05:00
|
|
|
platformPrefix,
|
2014-04-22 00:28:47 -04:00
|
|
|
strings.Replace(tfPath, `\`, `/`, -1))
|
|
|
|
if u != expected {
|
|
|
|
t.Fatalf("unexpected: %s != %s", u, expected)
|
2013-07-29 02:51:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-10-11 06:50:08 -04:00
|
|
|
|
2018-02-02 21:29:10 -05:00
|
|
|
func TestFileExistsLocally(t *testing.T) {
|
2018-01-19 00:08:22 -05:00
|
|
|
portablepath := GetPortablePathToTestFixtures(t)
|
2018-01-10 19:44:27 -05:00
|
|
|
|
2018-01-19 00:08:22 -05:00
|
|
|
dirCases := []struct {
|
|
|
|
Input string
|
|
|
|
Output bool
|
|
|
|
}{
|
|
|
|
// file exists locally
|
2018-02-02 21:36:08 -05:00
|
|
|
{fmt.Sprintf("file://%s/SomeDir/myfile.txt", portablepath), true},
|
2018-02-02 21:29:10 -05:00
|
|
|
// remote protocols short-circuit and are considered to exist locally
|
2018-01-19 00:08:22 -05:00
|
|
|
{"https://myfile.iso", true},
|
2018-02-02 21:29:10 -05:00
|
|
|
// non-existent protocols do not exist and hence fail
|
|
|
|
{"nonexistent-protocol://myfile.iso", false},
|
2018-01-19 00:08:22 -05:00
|
|
|
// file does not exist locally
|
|
|
|
{"file:///C/i/dont/exist", false},
|
|
|
|
}
|
|
|
|
// Run through test cases to make sure they all parse correctly
|
|
|
|
for _, tc := range dirCases {
|
|
|
|
fileOK := FileExistsLocally(tc.Input)
|
2018-02-02 21:29:10 -05:00
|
|
|
if fileOK != tc.Output {
|
2018-01-19 00:08:22 -05:00
|
|
|
t.Fatalf("Test Case failed: Expected %#v, received = %#v, input = %s",
|
|
|
|
tc.Output, fileOK, tc.Input)
|
2018-01-10 19:44:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-11 06:50:08 -04:00
|
|
|
func TestScrubConfig(t *testing.T) {
|
|
|
|
type Inner struct {
|
|
|
|
Baz string
|
|
|
|
}
|
|
|
|
type Local struct {
|
|
|
|
Foo string
|
|
|
|
Bar string
|
|
|
|
Inner
|
|
|
|
}
|
|
|
|
c := Local{"foo", "bar", Inner{"bar"}}
|
|
|
|
expect := "Config: {Foo:foo Bar:<Filtered> Inner:{Baz:<Filtered>}}"
|
|
|
|
conf := ScrubConfig(c, c.Bar)
|
|
|
|
if conf != expect {
|
|
|
|
t.Fatalf("got %s, expected %s", conf, expect)
|
|
|
|
}
|
|
|
|
}
|