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

     1  package hcl2shim
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  	"testing"
     7  
     8  	"github.com/zclconf/go-cty/cty"
     9  )
    10  
    11  func TestValuesSDKEquivalent(t *testing.T) {
    12  	piBig, _, err := big.ParseFloat("3.14159265358979323846264338327950288419716939937510582097494459", 10, 512, big.ToZero)
    13  	if err != nil {
    14  		t.Fatal(err)
    15  	}
    16  	pi64, _ := piBig.Float64()
    17  
    18  	tests := []struct {
    19  		A, B cty.Value
    20  		Want bool
    21  	}{
    22  		// Strings
    23  		{
    24  			cty.StringVal("hello"),
    25  			cty.StringVal("hello"),
    26  			true,
    27  		},
    28  		{
    29  			cty.StringVal("hello"),
    30  			cty.StringVal("world"),
    31  			false,
    32  		},
    33  		{
    34  			cty.StringVal("hello"),
    35  			cty.StringVal(""),
    36  			false,
    37  		},
    38  		{
    39  			cty.NullVal(cty.String),
    40  			cty.StringVal(""),
    41  			true,
    42  		},
    43  
    44  		// Numbers
    45  		{
    46  			cty.NumberIntVal(1),
    47  			cty.NumberIntVal(1),
    48  			true,
    49  		},
    50  		{
    51  			cty.NumberIntVal(1),
    52  			cty.NumberIntVal(2),
    53  			false,
    54  		},
    55  		{
    56  			cty.NumberIntVal(1),
    57  			cty.Zero,
    58  			false,
    59  		},
    60  		{
    61  			cty.NullVal(cty.Number),
    62  			cty.Zero,
    63  			true,
    64  		},
    65  		{
    66  			cty.NumberVal(piBig),
    67  			cty.Zero,
    68  			false,
    69  		},
    70  		{
    71  			cty.NumberFloatVal(pi64),
    72  			cty.Zero,
    73  			false,
    74  		},
    75  		{
    76  			cty.NumberFloatVal(pi64),
    77  			cty.NumberVal(piBig),
    78  			true,
    79  		},
    80  
    81  		// Bools
    82  		{
    83  			cty.True,
    84  			cty.True,
    85  			true,
    86  		},
    87  		{
    88  			cty.True,
    89  			cty.False,
    90  			false,
    91  		},
    92  		{
    93  			cty.NullVal(cty.Bool),
    94  			cty.False,
    95  			true,
    96  		},
    97  
    98  		// Mixed primitives
    99  		{
   100  			cty.StringVal("hello"),
   101  			cty.False,
   102  			false,
   103  		},
   104  		{
   105  			cty.StringVal(""),
   106  			cty.False,
   107  			true,
   108  		},
   109  		{
   110  			cty.NumberIntVal(0),
   111  			cty.False,
   112  			true,
   113  		},
   114  		{
   115  			cty.StringVal(""),
   116  			cty.NumberIntVal(0),
   117  			true,
   118  		},
   119  		{
   120  			cty.NullVal(cty.Bool),
   121  			cty.NullVal(cty.Number),
   122  			true,
   123  		},
   124  		{
   125  			cty.StringVal(""),
   126  			cty.NullVal(cty.Number),
   127  			true,
   128  		},
   129  
   130  		// Lists
   131  		{
   132  			cty.ListValEmpty(cty.String),
   133  			cty.ListValEmpty(cty.String),
   134  			true,
   135  		},
   136  		{
   137  			cty.ListValEmpty(cty.String),
   138  			cty.NullVal(cty.List(cty.String)),
   139  			true,
   140  		},
   141  		{
   142  			cty.ListVal([]cty.Value{cty.StringVal("hello")}),
   143  			cty.ListVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("hello")}),
   144  			false,
   145  		},
   146  		{
   147  			cty.ListVal([]cty.Value{cty.StringVal("hello")}),
   148  			cty.ListValEmpty(cty.String),
   149  			false,
   150  		},
   151  		{
   152  			cty.ListVal([]cty.Value{cty.StringVal("hello")}),
   153  			cty.ListVal([]cty.Value{cty.StringVal("hello")}),
   154  			true,
   155  		},
   156  		{
   157  			cty.ListVal([]cty.Value{cty.StringVal("hello")}),
   158  			cty.ListVal([]cty.Value{cty.StringVal("world")}),
   159  			false,
   160  		},
   161  		{
   162  			cty.ListVal([]cty.Value{cty.NullVal(cty.String)}),
   163  			cty.ListVal([]cty.Value{cty.StringVal("")}),
   164  			true,
   165  		},
   166  
   167  		// Tuples
   168  		{
   169  			cty.EmptyTupleVal,
   170  			cty.EmptyTupleVal,
   171  			true,
   172  		},
   173  		{
   174  			cty.EmptyTupleVal,
   175  			cty.NullVal(cty.EmptyTuple),
   176  			true,
   177  		},
   178  		{
   179  			cty.TupleVal([]cty.Value{cty.StringVal("hello")}),
   180  			cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("hello")}),
   181  			false,
   182  		},
   183  		{
   184  			cty.TupleVal([]cty.Value{cty.StringVal("hello")}),
   185  			cty.EmptyTupleVal,
   186  			false,
   187  		},
   188  		{
   189  			cty.TupleVal([]cty.Value{cty.StringVal("hello")}),
   190  			cty.TupleVal([]cty.Value{cty.StringVal("hello")}),
   191  			true,
   192  		},
   193  		{
   194  			cty.TupleVal([]cty.Value{cty.StringVal("hello")}),
   195  			cty.TupleVal([]cty.Value{cty.StringVal("world")}),
   196  			false,
   197  		},
   198  		{
   199  			cty.TupleVal([]cty.Value{cty.NullVal(cty.String)}),
   200  			cty.TupleVal([]cty.Value{cty.StringVal("")}),
   201  			true,
   202  		},
   203  
   204  		// Sets
   205  		{
   206  			cty.SetValEmpty(cty.String),
   207  			cty.SetValEmpty(cty.String),
   208  			true,
   209  		},
   210  		{
   211  			cty.SetValEmpty(cty.String),
   212  			cty.NullVal(cty.Set(cty.String)),
   213  			true,
   214  		},
   215  		{
   216  			cty.SetVal([]cty.Value{cty.StringVal("hello")}),
   217  			cty.SetValEmpty(cty.String),
   218  			false,
   219  		},
   220  		{
   221  			cty.SetVal([]cty.Value{cty.StringVal("hello")}),
   222  			cty.SetVal([]cty.Value{cty.StringVal("hello")}),
   223  			true,
   224  		},
   225  		{
   226  			cty.SetVal([]cty.Value{cty.StringVal("hello")}),
   227  			cty.SetVal([]cty.Value{cty.StringVal("world")}),
   228  			false,
   229  		},
   230  		{
   231  			cty.SetVal([]cty.Value{cty.NullVal(cty.String)}),
   232  			cty.SetVal([]cty.Value{cty.StringVal("")}),
   233  			true,
   234  		},
   235  		{
   236  			cty.SetVal([]cty.Value{
   237  				cty.NullVal(cty.String),
   238  				cty.StringVal(""),
   239  			}),
   240  			cty.SetVal([]cty.Value{
   241  				cty.NullVal(cty.String),
   242  			}),
   243  			false, // because the element count is different
   244  		},
   245  		{
   246  			cty.SetVal([]cty.Value{
   247  				cty.ObjectVal(map[string]cty.Value{
   248  					"a": cty.StringVal(""),
   249  					"b": cty.StringVal(""),
   250  				}),
   251  				cty.ObjectVal(map[string]cty.Value{
   252  					"a": cty.NullVal(cty.String),
   253  					"b": cty.StringVal(""),
   254  				}),
   255  			}),
   256  			cty.SetVal([]cty.Value{
   257  				cty.ObjectVal(map[string]cty.Value{
   258  					"a": cty.StringVal(""),
   259  					"b": cty.StringVal(""),
   260  				}),
   261  				cty.ObjectVal(map[string]cty.Value{
   262  					"a": cty.StringVal(""),
   263  					"b": cty.NullVal(cty.String),
   264  				}),
   265  			}),
   266  			true,
   267  		},
   268  		{
   269  			cty.SetVal([]cty.Value{
   270  				cty.ObjectVal(map[string]cty.Value{
   271  					"a": cty.StringVal("boop"),
   272  					"b": cty.StringVal(""),
   273  				}),
   274  				cty.ObjectVal(map[string]cty.Value{
   275  					"a": cty.NullVal(cty.String),
   276  					"b": cty.StringVal(""),
   277  				}),
   278  			}),
   279  			cty.SetVal([]cty.Value{
   280  				cty.ObjectVal(map[string]cty.Value{
   281  					"a": cty.StringVal("beep"),
   282  					"b": cty.StringVal(""),
   283  				}),
   284  				cty.ObjectVal(map[string]cty.Value{
   285  					"a": cty.StringVal(""),
   286  					"b": cty.NullVal(cty.String),
   287  				}),
   288  			}),
   289  			false,
   290  		},
   291  		{
   292  			cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{
   293  				"list": cty.ListValEmpty(cty.String),
   294  				"list_block": cty.ListVal([]cty.Value{
   295  					cty.ObjectVal(map[string]cty.Value{
   296  						"unused": cty.StringVal(""),
   297  					}),
   298  				}),
   299  			})}),
   300  			cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{
   301  				"list": cty.ListValEmpty(cty.String),
   302  				"list_block": cty.ListVal([]cty.Value{
   303  					cty.ObjectVal(map[string]cty.Value{
   304  						"unused": cty.NullVal(cty.String),
   305  					}),
   306  				}),
   307  			})}),
   308  			true,
   309  		},
   310  
   311  		// Maps
   312  		{
   313  			cty.MapValEmpty(cty.String),
   314  			cty.MapValEmpty(cty.String),
   315  			true,
   316  		},
   317  		{
   318  			cty.MapValEmpty(cty.String),
   319  			cty.NullVal(cty.Map(cty.String)),
   320  			true,
   321  		},
   322  		{
   323  			cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   324  			cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello"), "hey": cty.StringVal("hello")}),
   325  			false,
   326  		},
   327  		{
   328  			cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   329  			cty.MapValEmpty(cty.String),
   330  			false,
   331  		},
   332  		{
   333  			cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   334  			cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   335  			true,
   336  		},
   337  		{
   338  			cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   339  			cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("world")}),
   340  			false,
   341  		},
   342  		{
   343  			cty.MapVal(map[string]cty.Value{"hi": cty.NullVal(cty.String)}),
   344  			cty.MapVal(map[string]cty.Value{"hi": cty.StringVal("")}),
   345  			true,
   346  		},
   347  
   348  		// Objects
   349  		{
   350  			cty.EmptyObjectVal,
   351  			cty.EmptyObjectVal,
   352  			true,
   353  		},
   354  		{
   355  			cty.EmptyObjectVal,
   356  			cty.NullVal(cty.EmptyObject),
   357  			true,
   358  		},
   359  		{
   360  			cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   361  			cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello"), "hey": cty.StringVal("hello")}),
   362  			false,
   363  		},
   364  		{
   365  			cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   366  			cty.EmptyObjectVal,
   367  			false,
   368  		},
   369  		{
   370  			cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   371  			cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   372  			true,
   373  		},
   374  		{
   375  			cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("hello")}),
   376  			cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("world")}),
   377  			false,
   378  		},
   379  		{
   380  			cty.ObjectVal(map[string]cty.Value{"hi": cty.NullVal(cty.String)}),
   381  			cty.ObjectVal(map[string]cty.Value{"hi": cty.StringVal("")}),
   382  			true,
   383  		},
   384  
   385  		// Unknown values
   386  		{
   387  			cty.UnknownVal(cty.String),
   388  			cty.UnknownVal(cty.String),
   389  			true,
   390  		},
   391  		{
   392  			cty.StringVal("hello"),
   393  			cty.UnknownVal(cty.String),
   394  			false,
   395  		},
   396  		{
   397  			cty.StringVal(""),
   398  			cty.UnknownVal(cty.String),
   399  			false,
   400  		},
   401  		{
   402  			cty.NullVal(cty.String),
   403  			cty.UnknownVal(cty.String),
   404  			false,
   405  		},
   406  	}
   407  
   408  	run := func(t *testing.T, a, b cty.Value, want bool) {
   409  		got := ValuesSDKEquivalent(a, b)
   410  
   411  		if got != want {
   412  			t.Errorf("wrong result\nfor: %#v ≈ %#v\ngot %#v, but want %#v", a, b, got, want)
   413  		}
   414  	}
   415  
   416  	for _, test := range tests {
   417  		t.Run(fmt.Sprintf("%#v ≈ %#v", test.A, test.B), func(t *testing.T) {
   418  			run(t, test.A, test.B, test.Want)
   419  		})
   420  		// This function is symmetrical, so we'll also test in reverse so
   421  		// we don't need to manually copy all of the test cases. (But this does
   422  		// mean that one failure normally becomes two, of course!)
   423  		if !test.A.RawEquals(test.B) {
   424  			t.Run(fmt.Sprintf("%#v ≈ %#v", test.B, test.A), func(t *testing.T) {
   425  				run(t, test.B, test.A, test.Want)
   426  			})
   427  		}
   428  	}
   429  }