github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/configs/hcl2shim/values_test.go (about)

     1  package hcl2shim
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/muratcelep/terraform/not-internal/configs/configschema"
     9  	"github.com/zclconf/go-cty/cty"
    10  )
    11  
    12  func TestConfigValueFromHCL2Block(t *testing.T) {
    13  	tests := []struct {
    14  		Input  cty.Value
    15  		Schema *configschema.Block
    16  		Want   map[string]interface{}
    17  	}{
    18  		{
    19  			cty.ObjectVal(map[string]cty.Value{
    20  				"name": cty.StringVal("Ermintrude"),
    21  				"age":  cty.NumberIntVal(19),
    22  				"address": cty.ObjectVal(map[string]cty.Value{
    23  					"street": cty.ListVal([]cty.Value{cty.StringVal("421 Shoreham Loop")}),
    24  					"city":   cty.StringVal("Fridgewater"),
    25  					"state":  cty.StringVal("MA"),
    26  					"zip":    cty.StringVal("91037"),
    27  				}),
    28  			}),
    29  			&configschema.Block{
    30  				Attributes: map[string]*configschema.Attribute{
    31  					"name": {Type: cty.String, Optional: true},
    32  					"age":  {Type: cty.Number, Optional: true},
    33  				},
    34  				BlockTypes: map[string]*configschema.NestedBlock{
    35  					"address": {
    36  						Nesting: configschema.NestingSingle,
    37  						Block: configschema.Block{
    38  							Attributes: map[string]*configschema.Attribute{
    39  								"street": {Type: cty.List(cty.String), Optional: true},
    40  								"city":   {Type: cty.String, Optional: true},
    41  								"state":  {Type: cty.String, Optional: true},
    42  								"zip":    {Type: cty.String, Optional: true},
    43  							},
    44  						},
    45  					},
    46  				},
    47  			},
    48  			map[string]interface{}{
    49  				"name": "Ermintrude",
    50  				"age":  int(19),
    51  				"address": map[string]interface{}{
    52  					"street": []interface{}{"421 Shoreham Loop"},
    53  					"city":   "Fridgewater",
    54  					"state":  "MA",
    55  					"zip":    "91037",
    56  				},
    57  			},
    58  		},
    59  		{
    60  			cty.ObjectVal(map[string]cty.Value{
    61  				"name": cty.StringVal("Ermintrude"),
    62  				"age":  cty.NumberIntVal(19),
    63  				"address": cty.NullVal(cty.Object(map[string]cty.Type{
    64  					"street": cty.List(cty.String),
    65  					"city":   cty.String,
    66  					"state":  cty.String,
    67  					"zip":    cty.String,
    68  				})),
    69  			}),
    70  			&configschema.Block{
    71  				Attributes: map[string]*configschema.Attribute{
    72  					"name": {Type: cty.String, Optional: true},
    73  					"age":  {Type: cty.Number, Optional: true},
    74  				},
    75  				BlockTypes: map[string]*configschema.NestedBlock{
    76  					"address": {
    77  						Nesting: configschema.NestingSingle,
    78  						Block: configschema.Block{
    79  							Attributes: map[string]*configschema.Attribute{
    80  								"street": {Type: cty.List(cty.String), Optional: true},
    81  								"city":   {Type: cty.String, Optional: true},
    82  								"state":  {Type: cty.String, Optional: true},
    83  								"zip":    {Type: cty.String, Optional: true},
    84  							},
    85  						},
    86  					},
    87  				},
    88  			},
    89  			map[string]interface{}{
    90  				"name": "Ermintrude",
    91  				"age":  int(19),
    92  			},
    93  		},
    94  		{
    95  			cty.ObjectVal(map[string]cty.Value{
    96  				"name": cty.StringVal("Ermintrude"),
    97  				"age":  cty.NumberIntVal(19),
    98  				"address": cty.ObjectVal(map[string]cty.Value{
    99  					"street": cty.ListVal([]cty.Value{cty.StringVal("421 Shoreham Loop")}),
   100  					"city":   cty.StringVal("Fridgewater"),
   101  					"state":  cty.StringVal("MA"),
   102  					"zip":    cty.NullVal(cty.String), // should be omitted altogether in result
   103  				}),
   104  			}),
   105  			&configschema.Block{
   106  				Attributes: map[string]*configschema.Attribute{
   107  					"name": {Type: cty.String, Optional: true},
   108  					"age":  {Type: cty.Number, Optional: true},
   109  				},
   110  				BlockTypes: map[string]*configschema.NestedBlock{
   111  					"address": {
   112  						Nesting: configschema.NestingSingle,
   113  						Block: configschema.Block{
   114  							Attributes: map[string]*configschema.Attribute{
   115  								"street": {Type: cty.List(cty.String), Optional: true},
   116  								"city":   {Type: cty.String, Optional: true},
   117  								"state":  {Type: cty.String, Optional: true},
   118  								"zip":    {Type: cty.String, Optional: true},
   119  							},
   120  						},
   121  					},
   122  				},
   123  			},
   124  			map[string]interface{}{
   125  				"name": "Ermintrude",
   126  				"age":  int(19),
   127  				"address": map[string]interface{}{
   128  					"street": []interface{}{"421 Shoreham Loop"},
   129  					"city":   "Fridgewater",
   130  					"state":  "MA",
   131  				},
   132  			},
   133  		},
   134  		{
   135  			cty.ObjectVal(map[string]cty.Value{
   136  				"address": cty.ListVal([]cty.Value{cty.EmptyObjectVal}),
   137  			}),
   138  			&configschema.Block{
   139  				BlockTypes: map[string]*configschema.NestedBlock{
   140  					"address": {
   141  						Nesting: configschema.NestingList,
   142  						Block:   configschema.Block{},
   143  					},
   144  				},
   145  			},
   146  			map[string]interface{}{
   147  				"address": []interface{}{
   148  					map[string]interface{}{},
   149  				},
   150  			},
   151  		},
   152  		{
   153  			cty.ObjectVal(map[string]cty.Value{
   154  				"address": cty.ListValEmpty(cty.EmptyObject), // should be omitted altogether in result
   155  			}),
   156  			&configschema.Block{
   157  				BlockTypes: map[string]*configschema.NestedBlock{
   158  					"address": {
   159  						Nesting: configschema.NestingList,
   160  						Block:   configschema.Block{},
   161  					},
   162  				},
   163  			},
   164  			map[string]interface{}{},
   165  		},
   166  		{
   167  			cty.ObjectVal(map[string]cty.Value{
   168  				"address": cty.SetVal([]cty.Value{cty.EmptyObjectVal}),
   169  			}),
   170  			&configschema.Block{
   171  				BlockTypes: map[string]*configschema.NestedBlock{
   172  					"address": {
   173  						Nesting: configschema.NestingSet,
   174  						Block:   configschema.Block{},
   175  					},
   176  				},
   177  			},
   178  			map[string]interface{}{
   179  				"address": []interface{}{
   180  					map[string]interface{}{},
   181  				},
   182  			},
   183  		},
   184  		{
   185  			cty.ObjectVal(map[string]cty.Value{
   186  				"address": cty.SetValEmpty(cty.EmptyObject),
   187  			}),
   188  			&configschema.Block{
   189  				BlockTypes: map[string]*configschema.NestedBlock{
   190  					"address": {
   191  						Nesting: configschema.NestingSet,
   192  						Block:   configschema.Block{},
   193  					},
   194  				},
   195  			},
   196  			map[string]interface{}{},
   197  		},
   198  		{
   199  			cty.ObjectVal(map[string]cty.Value{
   200  				"address": cty.MapVal(map[string]cty.Value{"foo": cty.EmptyObjectVal}),
   201  			}),
   202  			&configschema.Block{
   203  				BlockTypes: map[string]*configschema.NestedBlock{
   204  					"address": {
   205  						Nesting: configschema.NestingMap,
   206  						Block:   configschema.Block{},
   207  					},
   208  				},
   209  			},
   210  			map[string]interface{}{
   211  				"address": map[string]interface{}{
   212  					"foo": map[string]interface{}{},
   213  				},
   214  			},
   215  		},
   216  		{
   217  			cty.ObjectVal(map[string]cty.Value{
   218  				"address": cty.MapValEmpty(cty.EmptyObject),
   219  			}),
   220  			&configschema.Block{
   221  				BlockTypes: map[string]*configschema.NestedBlock{
   222  					"address": {
   223  						Nesting: configschema.NestingMap,
   224  						Block:   configschema.Block{},
   225  					},
   226  				},
   227  			},
   228  			map[string]interface{}{},
   229  		},
   230  		{
   231  			cty.NullVal(cty.EmptyObject),
   232  			&configschema.Block{},
   233  			nil,
   234  		},
   235  	}
   236  
   237  	for _, test := range tests {
   238  		t.Run(fmt.Sprintf("%#v", test.Input), func(t *testing.T) {
   239  			got := ConfigValueFromHCL2Block(test.Input, test.Schema)
   240  			if !reflect.DeepEqual(got, test.Want) {
   241  				t.Errorf("wrong result\ninput: %#v\ngot:   %#v\nwant:  %#v", test.Input, got, test.Want)
   242  			}
   243  		})
   244  	}
   245  }
   246  
   247  func TestConfigValueFromHCL2(t *testing.T) {
   248  	tests := []struct {
   249  		Input cty.Value
   250  		Want  interface{}
   251  	}{
   252  		{
   253  			cty.True,
   254  			true,
   255  		},
   256  		{
   257  			cty.False,
   258  			false,
   259  		},
   260  		{
   261  			cty.NumberIntVal(12),
   262  			int(12),
   263  		},
   264  		{
   265  			cty.NumberFloatVal(12.5),
   266  			float64(12.5),
   267  		},
   268  		{
   269  			cty.StringVal("hello world"),
   270  			"hello world",
   271  		},
   272  		{
   273  			cty.ObjectVal(map[string]cty.Value{
   274  				"name": cty.StringVal("Ermintrude"),
   275  				"age":  cty.NumberIntVal(19),
   276  				"address": cty.ObjectVal(map[string]cty.Value{
   277  					"street": cty.ListVal([]cty.Value{cty.StringVal("421 Shoreham Loop")}),
   278  					"city":   cty.StringVal("Fridgewater"),
   279  					"state":  cty.StringVal("MA"),
   280  					"zip":    cty.StringVal("91037"),
   281  				}),
   282  			}),
   283  			map[string]interface{}{
   284  				"name": "Ermintrude",
   285  				"age":  int(19),
   286  				"address": map[string]interface{}{
   287  					"street": []interface{}{"421 Shoreham Loop"},
   288  					"city":   "Fridgewater",
   289  					"state":  "MA",
   290  					"zip":    "91037",
   291  				},
   292  			},
   293  		},
   294  		{
   295  			cty.MapVal(map[string]cty.Value{
   296  				"foo": cty.StringVal("bar"),
   297  				"bar": cty.StringVal("baz"),
   298  			}),
   299  			map[string]interface{}{
   300  				"foo": "bar",
   301  				"bar": "baz",
   302  			},
   303  		},
   304  		{
   305  			cty.TupleVal([]cty.Value{
   306  				cty.StringVal("foo"),
   307  				cty.True,
   308  			}),
   309  			[]interface{}{
   310  				"foo",
   311  				true,
   312  			},
   313  		},
   314  		{
   315  			cty.NullVal(cty.String),
   316  			nil,
   317  		},
   318  		{
   319  			cty.UnknownVal(cty.String),
   320  			UnknownVariableValue,
   321  		},
   322  	}
   323  
   324  	for _, test := range tests {
   325  		t.Run(fmt.Sprintf("%#v", test.Input), func(t *testing.T) {
   326  			got := ConfigValueFromHCL2(test.Input)
   327  			if !reflect.DeepEqual(got, test.Want) {
   328  				t.Errorf("wrong result\ninput: %#v\ngot:   %#v\nwant:  %#v", test.Input, got, test.Want)
   329  			}
   330  		})
   331  	}
   332  }
   333  
   334  func TestHCL2ValueFromConfigValue(t *testing.T) {
   335  	tests := []struct {
   336  		Input interface{}
   337  		Want  cty.Value
   338  	}{
   339  		{
   340  			nil,
   341  			cty.NullVal(cty.DynamicPseudoType),
   342  		},
   343  		{
   344  			UnknownVariableValue,
   345  			cty.DynamicVal,
   346  		},
   347  		{
   348  			true,
   349  			cty.True,
   350  		},
   351  		{
   352  			false,
   353  			cty.False,
   354  		},
   355  		{
   356  			int(12),
   357  			cty.NumberIntVal(12),
   358  		},
   359  		{
   360  			int(0),
   361  			cty.Zero,
   362  		},
   363  		{
   364  			float64(12.5),
   365  			cty.NumberFloatVal(12.5),
   366  		},
   367  		{
   368  			"hello world",
   369  			cty.StringVal("hello world"),
   370  		},
   371  		{
   372  			"O\u0308",               // decomposed letter + diacritic
   373  			cty.StringVal("\u00D6"), // NFC-normalized on entry into cty
   374  		},
   375  		{
   376  			[]interface{}{},
   377  			cty.EmptyTupleVal,
   378  		},
   379  		{
   380  			[]interface{}(nil),
   381  			cty.EmptyTupleVal,
   382  		},
   383  		{
   384  			[]interface{}{"hello", "world"},
   385  			cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("world")}),
   386  		},
   387  		{
   388  			map[string]interface{}{},
   389  			cty.EmptyObjectVal,
   390  		},
   391  		{
   392  			map[string]interface{}(nil),
   393  			cty.EmptyObjectVal,
   394  		},
   395  		{
   396  			map[string]interface{}{
   397  				"foo": "bar",
   398  				"bar": "baz",
   399  			},
   400  			cty.ObjectVal(map[string]cty.Value{
   401  				"foo": cty.StringVal("bar"),
   402  				"bar": cty.StringVal("baz"),
   403  			}),
   404  		},
   405  	}
   406  
   407  	for _, test := range tests {
   408  		t.Run(fmt.Sprintf("%#v", test.Input), func(t *testing.T) {
   409  			got := HCL2ValueFromConfigValue(test.Input)
   410  			if !got.RawEquals(test.Want) {
   411  				t.Errorf("wrong result\ninput: %#v\ngot:   %#v\nwant:  %#v", test.Input, got, test.Want)
   412  			}
   413  		})
   414  	}
   415  }