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  }