kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/configs/configschema/empty_value_test.go (about)

     1  package configschema
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/apparentlymart/go-dump/dump"
     8  	"github.com/davecgh/go-spew/spew"
     9  	"github.com/zclconf/go-cty/cty"
    10  )
    11  
    12  func TestBlockEmptyValue(t *testing.T) {
    13  	tests := []struct {
    14  		Schema *Block
    15  		Want   cty.Value
    16  	}{
    17  		{
    18  			&Block{},
    19  			cty.EmptyObjectVal,
    20  		},
    21  		{
    22  			&Block{
    23  				Attributes: map[string]*Attribute{
    24  					"str": {Type: cty.String, Required: true},
    25  				},
    26  			},
    27  			cty.ObjectVal(map[string]cty.Value{
    28  				"str": cty.NullVal(cty.String),
    29  			}),
    30  		},
    31  		{
    32  			&Block{
    33  				BlockTypes: map[string]*NestedBlock{
    34  					"single": {
    35  						Nesting: NestingSingle,
    36  						Block: Block{
    37  							Attributes: map[string]*Attribute{
    38  								"str": {Type: cty.String, Required: true},
    39  							},
    40  						},
    41  					},
    42  				},
    43  			},
    44  			cty.ObjectVal(map[string]cty.Value{
    45  				"single": cty.NullVal(cty.Object(map[string]cty.Type{
    46  					"str": cty.String,
    47  				})),
    48  			}),
    49  		},
    50  		{
    51  			&Block{
    52  				BlockTypes: map[string]*NestedBlock{
    53  					"group": {
    54  						Nesting: NestingGroup,
    55  						Block: Block{
    56  							Attributes: map[string]*Attribute{
    57  								"str": {Type: cty.String, Required: true},
    58  							},
    59  						},
    60  					},
    61  				},
    62  			},
    63  			cty.ObjectVal(map[string]cty.Value{
    64  				"group": cty.ObjectVal(map[string]cty.Value{
    65  					"str": cty.NullVal(cty.String),
    66  				}),
    67  			}),
    68  		},
    69  		{
    70  			&Block{
    71  				BlockTypes: map[string]*NestedBlock{
    72  					"list": {
    73  						Nesting: NestingList,
    74  						Block: Block{
    75  							Attributes: map[string]*Attribute{
    76  								"str": {Type: cty.String, Required: true},
    77  							},
    78  						},
    79  					},
    80  				},
    81  			},
    82  			cty.ObjectVal(map[string]cty.Value{
    83  				"list": cty.ListValEmpty(cty.Object(map[string]cty.Type{
    84  					"str": cty.String,
    85  				})),
    86  			}),
    87  		},
    88  		{
    89  			&Block{
    90  				BlockTypes: map[string]*NestedBlock{
    91  					"list_dynamic": {
    92  						Nesting: NestingList,
    93  						Block: Block{
    94  							Attributes: map[string]*Attribute{
    95  								"str": {Type: cty.DynamicPseudoType, Required: true},
    96  							},
    97  						},
    98  					},
    99  				},
   100  			},
   101  			cty.ObjectVal(map[string]cty.Value{
   102  				"list_dynamic": cty.EmptyTupleVal,
   103  			}),
   104  		},
   105  		{
   106  			&Block{
   107  				BlockTypes: map[string]*NestedBlock{
   108  					"map": {
   109  						Nesting: NestingMap,
   110  						Block: Block{
   111  							Attributes: map[string]*Attribute{
   112  								"str": {Type: cty.String, Required: true},
   113  							},
   114  						},
   115  					},
   116  				},
   117  			},
   118  			cty.ObjectVal(map[string]cty.Value{
   119  				"map": cty.MapValEmpty(cty.Object(map[string]cty.Type{
   120  					"str": cty.String,
   121  				})),
   122  			}),
   123  		},
   124  		{
   125  			&Block{
   126  				BlockTypes: map[string]*NestedBlock{
   127  					"map_dynamic": {
   128  						Nesting: NestingMap,
   129  						Block: Block{
   130  							Attributes: map[string]*Attribute{
   131  								"str": {Type: cty.DynamicPseudoType, Required: true},
   132  							},
   133  						},
   134  					},
   135  				},
   136  			},
   137  			cty.ObjectVal(map[string]cty.Value{
   138  				"map_dynamic": cty.EmptyObjectVal,
   139  			}),
   140  		},
   141  		{
   142  			&Block{
   143  				BlockTypes: map[string]*NestedBlock{
   144  					"set": {
   145  						Nesting: NestingSet,
   146  						Block: Block{
   147  							Attributes: map[string]*Attribute{
   148  								"str": {Type: cty.String, Required: true},
   149  							},
   150  						},
   151  					},
   152  				},
   153  			},
   154  			cty.ObjectVal(map[string]cty.Value{
   155  				"set": cty.SetValEmpty(cty.Object(map[string]cty.Type{
   156  					"str": cty.String,
   157  				})),
   158  			}),
   159  		},
   160  	}
   161  
   162  	for _, test := range tests {
   163  		t.Run(fmt.Sprintf("%#v", test.Schema), func(t *testing.T) {
   164  			got := test.Schema.EmptyValue()
   165  			if !test.Want.RawEquals(got) {
   166  				t.Errorf("wrong result\nschema: %s\ngot: %s\nwant: %s", spew.Sdump(test.Schema), dump.Value(got), dump.Value(test.Want))
   167  			}
   168  		})
   169  	}
   170  }
   171  
   172  // Attribute EmptyValue() is well covered by the Block tests above; these tests
   173  // focus on the behavior with NestedType field inside an Attribute
   174  func TestAttributeEmptyValue(t *testing.T) {
   175  	tests := []struct {
   176  		Schema *Attribute
   177  		Want   cty.Value
   178  	}{
   179  		{
   180  			&Attribute{},
   181  			cty.NilVal,
   182  		},
   183  		{
   184  			&Attribute{
   185  				Type: cty.String,
   186  			},
   187  			cty.NullVal(cty.String),
   188  		},
   189  		{
   190  			&Attribute{
   191  				NestedType: &Object{
   192  					Nesting: NestingSingle,
   193  					Attributes: map[string]*Attribute{
   194  						"str": {Type: cty.String, Required: true},
   195  					},
   196  				},
   197  			},
   198  			cty.NullVal(cty.Object(map[string]cty.Type{
   199  				"str": cty.String,
   200  			})),
   201  		},
   202  		{
   203  			&Attribute{
   204  				NestedType: &Object{
   205  					Nesting: NestingList,
   206  					Attributes: map[string]*Attribute{
   207  						"str": {Type: cty.String, Required: true},
   208  					},
   209  				},
   210  			},
   211  			cty.NullVal(cty.List(
   212  				cty.Object(map[string]cty.Type{
   213  					"str": cty.String,
   214  				}),
   215  			)),
   216  		},
   217  		{
   218  			&Attribute{
   219  				NestedType: &Object{
   220  					Nesting: NestingMap,
   221  					Attributes: map[string]*Attribute{
   222  						"str": {Type: cty.String, Required: true},
   223  					},
   224  				},
   225  			},
   226  			cty.NullVal(cty.Map(
   227  				cty.Object(map[string]cty.Type{
   228  					"str": cty.String,
   229  				}),
   230  			)),
   231  		},
   232  		{
   233  			&Attribute{
   234  				NestedType: &Object{
   235  					Nesting: NestingSet,
   236  					Attributes: map[string]*Attribute{
   237  						"str": {Type: cty.String, Required: true},
   238  					},
   239  				},
   240  			},
   241  			cty.NullVal(cty.Set(
   242  				cty.Object(map[string]cty.Type{
   243  					"str": cty.String,
   244  				}),
   245  			)),
   246  		},
   247  	}
   248  
   249  	for _, test := range tests {
   250  		t.Run(fmt.Sprintf("%#v", test.Schema), func(t *testing.T) {
   251  			got := test.Schema.EmptyValue()
   252  			if !test.Want.RawEquals(got) {
   253  				t.Errorf("wrong result\nschema: %s\ngot: %s\nwant: %s", spew.Sdump(test.Schema), dump.Value(got), dump.Value(test.Want))
   254  			}
   255  		})
   256  	}
   257  }