github.com/jonasi/terraform@v0.6.10-0.20160125170522-e865c342cc1f/config/lang/eval_test.go (about) 1 package lang 2 3 import ( 4 "reflect" 5 "strconv" 6 "testing" 7 8 "github.com/hashicorp/terraform/config/lang/ast" 9 ) 10 11 func TestEval(t *testing.T) { 12 cases := []struct { 13 Input string 14 Scope *ast.BasicScope 15 Error bool 16 Result interface{} 17 ResultType ast.Type 18 }{ 19 { 20 "foo", 21 nil, 22 false, 23 "foo", 24 ast.TypeString, 25 }, 26 27 { 28 "foo $${bar}", 29 nil, 30 false, 31 "foo ${bar}", 32 ast.TypeString, 33 }, 34 35 { 36 "foo ${bar}", 37 &ast.BasicScope{ 38 VarMap: map[string]ast.Variable{ 39 "bar": ast.Variable{ 40 Value: "baz", 41 Type: ast.TypeString, 42 }, 43 }, 44 }, 45 false, 46 "foo baz", 47 ast.TypeString, 48 }, 49 50 { 51 "foo ${42+1}", 52 nil, 53 false, 54 "foo 43", 55 ast.TypeString, 56 }, 57 58 { 59 "foo ${42-1}", 60 nil, 61 false, 62 "foo 41", 63 ast.TypeString, 64 }, 65 66 { 67 "foo ${42*2}", 68 nil, 69 false, 70 "foo 84", 71 ast.TypeString, 72 }, 73 74 { 75 "foo ${42/2}", 76 nil, 77 false, 78 "foo 21", 79 ast.TypeString, 80 }, 81 82 { 83 "foo ${42%4}", 84 nil, 85 false, 86 "foo 2", 87 ast.TypeString, 88 }, 89 90 { 91 "foo ${42.0+1.0}", 92 nil, 93 false, 94 "foo 43", 95 ast.TypeString, 96 }, 97 98 { 99 "foo ${42.0+1}", 100 nil, 101 false, 102 "foo 43", 103 ast.TypeString, 104 }, 105 106 { 107 "foo ${42+1.0}", 108 nil, 109 false, 110 "foo 43", 111 ast.TypeString, 112 }, 113 114 { 115 "foo ${42+2*2}", 116 nil, 117 false, 118 "foo 88", 119 ast.TypeString, 120 }, 121 122 { 123 "foo ${42+(2*2)}", 124 nil, 125 false, 126 "foo 46", 127 ast.TypeString, 128 }, 129 130 { 131 "foo ${bar+1}", 132 &ast.BasicScope{ 133 VarMap: map[string]ast.Variable{ 134 "bar": ast.Variable{ 135 Value: 41, 136 Type: ast.TypeInt, 137 }, 138 }, 139 }, 140 false, 141 "foo 42", 142 ast.TypeString, 143 }, 144 145 { 146 "foo ${bar+1}", 147 &ast.BasicScope{ 148 VarMap: map[string]ast.Variable{ 149 "bar": ast.Variable{ 150 Value: "41", 151 Type: ast.TypeString, 152 }, 153 }, 154 }, 155 false, 156 "foo 42", 157 ast.TypeString, 158 }, 159 160 { 161 "foo ${bar+baz}", 162 &ast.BasicScope{ 163 VarMap: map[string]ast.Variable{ 164 "bar": ast.Variable{ 165 Value: "41", 166 Type: ast.TypeString, 167 }, 168 "baz": ast.Variable{ 169 Value: "1", 170 Type: ast.TypeString, 171 }, 172 }, 173 }, 174 false, 175 "foo 42", 176 ast.TypeString, 177 }, 178 179 { 180 "foo ${rand()}", 181 &ast.BasicScope{ 182 FuncMap: map[string]ast.Function{ 183 "rand": ast.Function{ 184 ReturnType: ast.TypeString, 185 Callback: func([]interface{}) (interface{}, error) { 186 return "42", nil 187 }, 188 }, 189 }, 190 }, 191 false, 192 "foo 42", 193 ast.TypeString, 194 }, 195 196 { 197 `foo ${rand("foo", "bar")}`, 198 &ast.BasicScope{ 199 FuncMap: map[string]ast.Function{ 200 "rand": ast.Function{ 201 ReturnType: ast.TypeString, 202 Variadic: true, 203 VariadicType: ast.TypeString, 204 Callback: func(args []interface{}) (interface{}, error) { 205 var result string 206 for _, a := range args { 207 result += a.(string) 208 } 209 return result, nil 210 }, 211 }, 212 }, 213 }, 214 false, 215 "foo foobar", 216 ast.TypeString, 217 }, 218 219 // Testing implicit type conversions 220 221 { 222 "foo ${bar}", 223 &ast.BasicScope{ 224 VarMap: map[string]ast.Variable{ 225 "bar": ast.Variable{ 226 Value: 42, 227 Type: ast.TypeInt, 228 }, 229 }, 230 }, 231 false, 232 "foo 42", 233 ast.TypeString, 234 }, 235 236 { 237 `foo ${foo("42")}`, 238 &ast.BasicScope{ 239 FuncMap: map[string]ast.Function{ 240 "foo": ast.Function{ 241 ArgTypes: []ast.Type{ast.TypeInt}, 242 ReturnType: ast.TypeString, 243 Callback: func(args []interface{}) (interface{}, error) { 244 return strconv.FormatInt(int64(args[0].(int)), 10), nil 245 }, 246 }, 247 }, 248 }, 249 false, 250 "foo 42", 251 ast.TypeString, 252 }, 253 254 // Multiline 255 { 256 "foo ${42+\n1.0}", 257 nil, 258 false, 259 "foo 43", 260 ast.TypeString, 261 }, 262 263 { 264 "foo ${-46}", 265 nil, 266 false, 267 "foo -46", 268 ast.TypeString, 269 }, 270 271 { 272 "foo ${-46 + 5}", 273 nil, 274 false, 275 "foo -41", 276 ast.TypeString, 277 }, 278 279 { 280 "foo ${46 + -5}", 281 nil, 282 false, 283 "foo 41", 284 ast.TypeString, 285 }, 286 287 { 288 "foo ${-bar}", 289 &ast.BasicScope{ 290 VarMap: map[string]ast.Variable{ 291 "bar": ast.Variable{ 292 Value: 41, 293 Type: ast.TypeInt, 294 }, 295 }, 296 }, 297 false, 298 "foo -41", 299 ast.TypeString, 300 }, 301 302 { 303 "foo ${5 + -bar}", 304 &ast.BasicScope{ 305 VarMap: map[string]ast.Variable{ 306 "bar": ast.Variable{ 307 Value: 41, 308 Type: ast.TypeInt, 309 }, 310 }, 311 }, 312 false, 313 "foo -36", 314 ast.TypeString, 315 }, 316 } 317 318 for _, tc := range cases { 319 node, err := Parse(tc.Input) 320 if err != nil { 321 t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input) 322 } 323 324 out, outType, err := Eval(node, &EvalConfig{GlobalScope: tc.Scope}) 325 if err != nil != tc.Error { 326 t.Fatalf("Error: %s\n\nInput: %s", err, tc.Input) 327 } 328 if outType != tc.ResultType { 329 t.Fatalf("Bad: %s\n\nInput: %s", outType, tc.Input) 330 } 331 if !reflect.DeepEqual(out, tc.Result) { 332 t.Fatalf("Bad: %#v\n\nInput: %s", out, tc.Input) 333 } 334 } 335 }