github.com/medzin/terraform@v0.11.11/config/hcl2_shim_util_test.go (about)

     1  package config
     2  
     3  import (
     4  	"testing"
     5  
     6  	hcl2 "github.com/hashicorp/hcl2/hcl"
     7  	hcl2syntax "github.com/hashicorp/hcl2/hcl/hclsyntax"
     8  	"github.com/zclconf/go-cty/cty"
     9  )
    10  
    11  func TestHCL2InterpolationFuncs(t *testing.T) {
    12  	// This is not a comprehensive test of all the functions (they are tested
    13  	// in interpolation_funcs_test.go already) but rather just calling a
    14  	// representative set via the HCL2 API to verify that the HCL2-to-HIL
    15  	// function shim is working as expected.
    16  	tests := []struct {
    17  		Expr string
    18  		Want cty.Value
    19  		Err  bool
    20  	}{
    21  		{
    22  			`upper("hello")`,
    23  			cty.StringVal("HELLO"),
    24  			false,
    25  		},
    26  		{
    27  			`abs(-2)`,
    28  			cty.NumberIntVal(2),
    29  			false,
    30  		},
    31  		{
    32  			`abs(-2.5)`,
    33  			cty.NumberFloatVal(2.5),
    34  			false,
    35  		},
    36  		{
    37  			`cidrsubnet("")`,
    38  			cty.DynamicVal,
    39  			true, // not enough arguments
    40  		},
    41  		{
    42  			`cidrsubnet("10.1.0.0/16", 8, 2)`,
    43  			cty.StringVal("10.1.2.0/24"),
    44  			false,
    45  		},
    46  		{
    47  			`concat([])`,
    48  			// Since HIL doesn't maintain element type information for list
    49  			// types, HCL2 can't either without elements to sniff.
    50  			cty.ListValEmpty(cty.DynamicPseudoType),
    51  			false,
    52  		},
    53  		{
    54  			`concat([], [])`,
    55  			cty.ListValEmpty(cty.DynamicPseudoType),
    56  			false,
    57  		},
    58  		{
    59  			`concat(["a"], ["b", "c"])`,
    60  			cty.ListVal([]cty.Value{
    61  				cty.StringVal("a"),
    62  				cty.StringVal("b"),
    63  				cty.StringVal("c"),
    64  			}),
    65  			false,
    66  		},
    67  		{
    68  			`list()`,
    69  			cty.ListValEmpty(cty.DynamicPseudoType),
    70  			false,
    71  		},
    72  		{
    73  			`list("a", "b", "c")`,
    74  			cty.ListVal([]cty.Value{
    75  				cty.StringVal("a"),
    76  				cty.StringVal("b"),
    77  				cty.StringVal("c"),
    78  			}),
    79  			false,
    80  		},
    81  		{
    82  			`list(list("a"), list("b"), list("c"))`,
    83  			// The types emerge here in a bit of a strange tangle because of
    84  			// the guesswork we do when trying to recover lost information from
    85  			// HIL, but the rest of the language doesn't really care whether
    86  			// we use lists or tuples here as long as we are consistent with
    87  			// the type system invariants.
    88  			cty.ListVal([]cty.Value{
    89  				cty.TupleVal([]cty.Value{cty.StringVal("a")}),
    90  				cty.TupleVal([]cty.Value{cty.StringVal("b")}),
    91  				cty.TupleVal([]cty.Value{cty.StringVal("c")}),
    92  			}),
    93  			false,
    94  		},
    95  		{
    96  			`list(list("a"), "b")`,
    97  			cty.DynamicVal,
    98  			true, // inconsistent types
    99  		},
   100  		{
   101  			`length([])`,
   102  			cty.NumberIntVal(0),
   103  			false,
   104  		},
   105  		{
   106  			`length([2])`,
   107  			cty.NumberIntVal(1),
   108  			false,
   109  		},
   110  		{
   111  			`jsonencode(2)`,
   112  			cty.StringVal(`2`),
   113  			false,
   114  		},
   115  		{
   116  			`jsonencode(true)`,
   117  			cty.StringVal(`true`),
   118  			false,
   119  		},
   120  		{
   121  			`jsonencode("foo")`,
   122  			cty.StringVal(`"foo"`),
   123  			false,
   124  		},
   125  		{
   126  			`jsonencode({})`,
   127  			cty.StringVal(`{}`),
   128  			false,
   129  		},
   130  		{
   131  			`jsonencode([1])`,
   132  			cty.StringVal(`[1]`),
   133  			false,
   134  		},
   135  		{
   136  			`jsondecode("{}")`,
   137  			cty.EmptyObjectVal,
   138  			false,
   139  		},
   140  		{
   141  			`jsondecode("[5, true]")[0]`,
   142  			cty.NumberIntVal(5),
   143  			false,
   144  		},
   145  	}
   146  
   147  	for _, test := range tests {
   148  		t.Run(test.Expr, func(t *testing.T) {
   149  			expr, diags := hcl2syntax.ParseExpression([]byte(test.Expr), "", hcl2.Pos{Line: 1, Column: 1})
   150  			if len(diags) != 0 {
   151  				for _, diag := range diags {
   152  					t.Logf("- %s", diag)
   153  				}
   154  				t.Fatalf("unexpected diagnostics while parsing expression")
   155  			}
   156  
   157  			got, diags := expr.Value(&hcl2.EvalContext{
   158  				Functions: hcl2InterpolationFuncs(),
   159  			})
   160  			gotErr := diags.HasErrors()
   161  			if gotErr != test.Err {
   162  				if test.Err {
   163  					t.Errorf("expected errors but got none")
   164  				} else {
   165  					t.Errorf("unexpected errors")
   166  					for _, diag := range diags {
   167  						t.Logf("- %s", diag)
   168  					}
   169  				}
   170  			}
   171  			if !got.RawEquals(test.Want) {
   172  				t.Errorf("wrong result\nexpr: %s\ngot:  %#v\nwant: %#v", test.Expr, got, test.Want)
   173  			}
   174  		})
   175  	}
   176  }