github.com/richardbowden/terraform@v0.6.12-0.20160901200758-30ea22c25211/builtin/providers/template/datasource_template_file_test.go (about) 1 package template 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "strings" 8 "sync" 9 "testing" 10 11 r "github.com/hashicorp/terraform/helper/resource" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 var testProviders = map[string]terraform.ResourceProvider{ 16 "template": Provider(), 17 } 18 19 func TestTemplateRendering(t *testing.T) { 20 var cases = []struct { 21 vars string 22 template string 23 want string 24 }{ 25 {`{}`, `ABC`, `ABC`}, 26 {`{a="foo"}`, `$${a}`, `foo`}, 27 {`{a="hello"}`, `$${replace(a, "ello", "i")}`, `hi`}, 28 {`{}`, `${1+2+3}`, `6`}, 29 {`{a=1, b=2}`, `$${a+b}`, `3`}, 30 {`{a=0.1, b=0.2}`, `$${0+((a+b)*10)}`, `3`}, 31 } 32 33 for _, tt := range cases { 34 r.UnitTest(t, r.TestCase{ 35 Providers: testProviders, 36 Steps: []r.TestStep{ 37 r.TestStep{ 38 Config: testTemplateConfig(tt.template, tt.vars), 39 Check: func(s *terraform.State) error { 40 got := s.RootModule().Outputs["rendered"] 41 if tt.want != got.Value { 42 return fmt.Errorf("template:\n%s\nvars:\n%s\ngot:\n%s\nwant:\n%s\n", tt.template, tt.vars, got, tt.want) 43 } 44 return nil 45 }, 46 }, 47 }, 48 }) 49 } 50 } 51 52 func TestValidateTemplateAttribute(t *testing.T) { 53 file, err := ioutil.TempFile("", "testtemplate") 54 if err != nil { 55 t.Fatal(err) 56 } 57 file.WriteString("Hello world.") 58 file.Close() 59 defer os.Remove(file.Name()) 60 61 ws, es := validateTemplateAttribute(file.Name(), "test") 62 63 if len(es) != 0 { 64 t.Fatalf("Unexpected errors: %#v", es) 65 } 66 67 if len(ws) != 1 { 68 t.Fatalf("Expected 1 warning, got %d", len(ws)) 69 } 70 71 if !strings.Contains(ws[0], "Specifying a path directly is deprecated") { 72 t.Fatalf("Expected warning about path, got: %s", ws[0]) 73 } 74 } 75 76 func TestValidateVarsAttribute(t *testing.T) { 77 cases := map[string]struct { 78 Vars map[string]interface{} 79 ExpectErr string 80 }{ 81 "lists are invalid": { 82 map[string]interface{}{ 83 "list": []interface{}{}, 84 }, 85 `vars: cannot contain non-primitives`, 86 }, 87 "maps are invalid": { 88 map[string]interface{}{ 89 "map": map[string]interface{}{}, 90 }, 91 `vars: cannot contain non-primitives`, 92 }, 93 "strings, integers, floats, and bools are AOK": { 94 map[string]interface{}{ 95 "string": "foo", 96 "int": 1, 97 "bool": true, 98 "float": float64(1.0), 99 }, 100 ``, 101 }, 102 } 103 104 for tn, tc := range cases { 105 _, es := validateVarsAttribute(tc.Vars, "vars") 106 if len(es) > 0 { 107 if tc.ExpectErr == "" { 108 t.Fatalf("%s: expected no err, got: %#v", tn, es) 109 } 110 if !strings.Contains(es[0].Error(), tc.ExpectErr) { 111 t.Fatalf("%s: expected\n%s\nto contain\n%s", tn, es[0], tc.ExpectErr) 112 } 113 } else if tc.ExpectErr != "" { 114 t.Fatalf("%s: expected err containing %q, got none!", tn, tc.ExpectErr) 115 } 116 } 117 } 118 119 // This test covers a panic due to config.Func formerly being a 120 // shared map, causing multiple template_file resources to try and 121 // accessing it parallel during their lang.Eval() runs. 122 // 123 // Before fix, test fails under `go test -race` 124 func TestTemplateSharedMemoryRace(t *testing.T) { 125 var wg sync.WaitGroup 126 for i := 0; i < 100; i++ { 127 wg.Add(1) 128 go func(t *testing.T, i int) { 129 out, err := execute("don't panic!", map[string]interface{}{}) 130 if err != nil { 131 t.Fatalf("err: %s", err) 132 } 133 if out != "don't panic!" { 134 t.Fatalf("bad output: %s", out) 135 } 136 wg.Done() 137 }(t, i) 138 } 139 wg.Wait() 140 } 141 142 func testTemplateConfig(template, vars string) string { 143 return fmt.Sprintf(` 144 data "template_file" "t0" { 145 template = "%s" 146 vars = %s 147 } 148 output "rendered" { 149 value = "${data.template_file.t0.rendered}" 150 }`, template, vars) 151 }