github.com/daniellockard/packer@v0.7.6-0.20141210173435-5a9390934716/common/config_test.go (about)

     1  package common
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/mitchellh/mapstructure"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"reflect"
    10  	"runtime"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  func TestCheckUnusedConfig(t *testing.T) {
    16  	md := &mapstructure.Metadata{
    17  		Unused: make([]string, 0),
    18  	}
    19  
    20  	err := CheckUnusedConfig(md)
    21  	if err != nil {
    22  		t.Fatalf("err: %s", err)
    23  	}
    24  
    25  	md.Unused = []string{"foo", "bar"}
    26  	err = CheckUnusedConfig(md)
    27  	if err == nil {
    28  		t.Fatal("should have error")
    29  	}
    30  }
    31  
    32  func TestChooseString(t *testing.T) {
    33  	cases := []struct {
    34  		Input  []string
    35  		Output string
    36  	}{
    37  		{
    38  			[]string{"", "foo", ""},
    39  			"foo",
    40  		},
    41  		{
    42  			[]string{"", "foo", "bar"},
    43  			"foo",
    44  		},
    45  		{
    46  			[]string{"", "", ""},
    47  			"",
    48  		},
    49  	}
    50  
    51  	for _, tc := range cases {
    52  		result := ChooseString(tc.Input...)
    53  		if result != tc.Output {
    54  			t.Fatalf("bad: %#v", tc.Input)
    55  		}
    56  	}
    57  }
    58  
    59  func TestDecodeConfig(t *testing.T) {
    60  	type Local struct {
    61  		Foo string
    62  		Bar string
    63  	}
    64  
    65  	raws := []interface{}{
    66  		map[string]interface{}{
    67  			"foo": "bar",
    68  		},
    69  		map[string]interface{}{
    70  			"bar": "baz",
    71  			"baz": "what",
    72  		},
    73  	}
    74  
    75  	var result Local
    76  	md, err := DecodeConfig(&result, raws...)
    77  	if err != nil {
    78  		t.Fatalf("err: %s", err)
    79  	}
    80  
    81  	if result.Foo != "bar" {
    82  		t.Fatalf("invalid: %#v", result.Foo)
    83  	}
    84  
    85  	if result.Bar != "baz" {
    86  		t.Fatalf("invalid: %#v", result.Bar)
    87  	}
    88  
    89  	if md == nil {
    90  		t.Fatal("metadata should not be nil")
    91  	}
    92  
    93  	if !reflect.DeepEqual(md.Unused, []string{"baz"}) {
    94  		t.Fatalf("unused: %#v", md.Unused)
    95  	}
    96  }
    97  
    98  // This test tests the case that a user var is used for an integer
    99  // configuration.
   100  func TestDecodeConfig_stringToSlice(t *testing.T) {
   101  	type Local struct {
   102  		Val      []string
   103  		EmptyVal []string
   104  	}
   105  
   106  	raw := map[string]interface{}{
   107  		"packer_user_variables": map[string]string{
   108  			"foo": "bar",
   109  		},
   110  
   111  		"val":      "foo,{{user `foo`}}",
   112  		"emptyval": "",
   113  	}
   114  
   115  	var result Local
   116  	_, err := DecodeConfig(&result, raw)
   117  	if err != nil {
   118  		t.Fatalf("err: %s", err)
   119  	}
   120  
   121  	expected := []string{"foo", "bar"}
   122  	if !reflect.DeepEqual(result.Val, expected) {
   123  		t.Fatalf("invalid: %#v", result.Val)
   124  	}
   125  	if len(result.EmptyVal) > 0 {
   126  		t.Fatalf("invalid: %#v", result.EmptyVal)
   127  	}
   128  }
   129  
   130  // This test tests the case that a user var is used for an integer
   131  // configuration.
   132  func TestDecodeConfig_userVarConversion(t *testing.T) {
   133  	type Local struct {
   134  		Val int
   135  	}
   136  
   137  	raw := map[string]interface{}{
   138  		"packer_user_variables": map[string]string{
   139  			"foo": "42",
   140  		},
   141  
   142  		"val": "{{user `foo`}}",
   143  	}
   144  
   145  	var result Local
   146  	_, err := DecodeConfig(&result, raw)
   147  	if err != nil {
   148  		t.Fatalf("err: %s", err)
   149  	}
   150  
   151  	if result.Val != 42 {
   152  		t.Fatalf("invalid: %#v", result.Val)
   153  	}
   154  }
   155  
   156  // This tests the way MessagePack decodes strings (into []uint8) and
   157  // that we can still decode into the proper types.
   158  func TestDecodeConfig_userVarConversionUInt8(t *testing.T) {
   159  	type Local struct {
   160  		Val int
   161  	}
   162  
   163  	raw := map[string]interface{}{
   164  		"packer_user_variables": map[string]string{
   165  			"foo": "42",
   166  		},
   167  
   168  		"val": []uint8("{{user `foo`}}"),
   169  	}
   170  
   171  	var result Local
   172  	_, err := DecodeConfig(&result, raw)
   173  	if err != nil {
   174  		t.Fatalf("err: %s", err)
   175  	}
   176  
   177  	if result.Val != 42 {
   178  		t.Fatalf("invalid: %#v", result.Val)
   179  	}
   180  }
   181  
   182  func TestDownloadableURL(t *testing.T) {
   183  	// Invalid URL: has hex code in host
   184  	_, err := DownloadableURL("http://what%20.com")
   185  	if err == nil {
   186  		t.Fatal("expected err")
   187  	}
   188  
   189  	// Invalid: unsupported scheme
   190  	_, err = DownloadableURL("ftp://host.com/path")
   191  	if err == nil {
   192  		t.Fatal("expected err")
   193  	}
   194  
   195  	// Valid: http
   196  	u, err := DownloadableURL("HTTP://packer.io/path")
   197  	if err != nil {
   198  		t.Fatalf("err: %s", err)
   199  	}
   200  
   201  	if u != "http://packer.io/path" {
   202  		t.Fatalf("bad: %s", u)
   203  	}
   204  
   205  	// No path
   206  	u, err = DownloadableURL("HTTP://packer.io")
   207  	if err != nil {
   208  		t.Fatalf("err: %s", err)
   209  	}
   210  
   211  	if u != "http://packer.io" {
   212  		t.Fatalf("bad: %s", u)
   213  	}
   214  }
   215  
   216  func TestDownloadableURL_FilePaths(t *testing.T) {
   217  	tf, err := ioutil.TempFile("", "packer")
   218  	if err != nil {
   219  		t.Fatalf("tempfile err: %s", err)
   220  	}
   221  	defer os.Remove(tf.Name())
   222  	tf.Close()
   223  
   224  	tfPath, err := filepath.EvalSymlinks(tf.Name())
   225  	if err != nil {
   226  		t.Fatalf("tempfile err: %s", err)
   227  	}
   228  
   229  	tfPath = filepath.Clean(tfPath)
   230  
   231  	filePrefix := "file://"
   232  	if runtime.GOOS == "windows" {
   233  		filePrefix += "/"
   234  	}
   235  
   236  	// Relative filepath. We run this test in a func so that
   237  	// the defers run right away.
   238  	func() {
   239  		wd, err := os.Getwd()
   240  		if err != nil {
   241  			t.Fatalf("getwd err: %s", err)
   242  		}
   243  
   244  		err = os.Chdir(filepath.Dir(tfPath))
   245  		if err != nil {
   246  			t.Fatalf("chdir err: %s", err)
   247  		}
   248  		defer os.Chdir(wd)
   249  
   250  		filename := filepath.Base(tfPath)
   251  		u, err := DownloadableURL(filename)
   252  		if err != nil {
   253  			t.Fatalf("err: %s", err)
   254  		}
   255  
   256  		expected := fmt.Sprintf("%s%s",
   257  			filePrefix,
   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{"", "file://"} {
   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
   273  		u, err := DownloadableURL(prefix + tfPath)
   274  		if err != nil {
   275  			t.Fatalf("err: %s", err)
   276  		}
   277  
   278  		expected := fmt.Sprintf("%s%s",
   279  			filePrefix,
   280  			strings.Replace(tfPath, `\`, `/`, -1))
   281  		if u != expected {
   282  			t.Fatalf("unexpected: %s != %s", u, expected)
   283  		}
   284  	}
   285  }
   286  
   287  func TestScrubConfig(t *testing.T) {
   288  	type Inner struct {
   289  		Baz string
   290  	}
   291  	type Local struct {
   292  		Foo string
   293  		Bar string
   294  		Inner
   295  	}
   296  	c := Local{"foo", "bar", Inner{"bar"}}
   297  	expect := "Config: {Foo:foo Bar:<Filtered> Inner:{Baz:<Filtered>}}"
   298  	conf := ScrubConfig(c, c.Bar)
   299  	if conf != expect {
   300  		t.Fatalf("got %s, expected %s", conf, expect)
   301  	}
   302  }