github.com/posener/terraform@v0.11.0-beta1.0.20171103235147-645df36af025/helper/schema/field_reader_test.go (about)

     1  package schema
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  )
     7  
     8  func TestAddrToSchema(t *testing.T) {
     9  	cases := map[string]struct {
    10  		Addr   []string
    11  		Schema map[string]*Schema
    12  		Result []ValueType
    13  	}{
    14  		"full object": {
    15  			[]string{},
    16  			map[string]*Schema{
    17  				"list": &Schema{
    18  					Type: TypeList,
    19  					Elem: &Schema{Type: TypeInt},
    20  				},
    21  			},
    22  			[]ValueType{typeObject},
    23  		},
    24  
    25  		"list": {
    26  			[]string{"list"},
    27  			map[string]*Schema{
    28  				"list": &Schema{
    29  					Type: TypeList,
    30  					Elem: &Schema{Type: TypeInt},
    31  				},
    32  			},
    33  			[]ValueType{TypeList},
    34  		},
    35  
    36  		"list.#": {
    37  			[]string{"list", "#"},
    38  			map[string]*Schema{
    39  				"list": &Schema{
    40  					Type: TypeList,
    41  					Elem: &Schema{Type: TypeInt},
    42  				},
    43  			},
    44  			[]ValueType{TypeList, TypeInt},
    45  		},
    46  
    47  		"list.0": {
    48  			[]string{"list", "0"},
    49  			map[string]*Schema{
    50  				"list": &Schema{
    51  					Type: TypeList,
    52  					Elem: &Schema{Type: TypeInt},
    53  				},
    54  			},
    55  			[]ValueType{TypeList, TypeInt},
    56  		},
    57  
    58  		"list.0 with resource": {
    59  			[]string{"list", "0"},
    60  			map[string]*Schema{
    61  				"list": &Schema{
    62  					Type: TypeList,
    63  					Elem: &Resource{
    64  						Schema: map[string]*Schema{
    65  							"field": &Schema{Type: TypeString},
    66  						},
    67  					},
    68  				},
    69  			},
    70  			[]ValueType{TypeList, typeObject},
    71  		},
    72  
    73  		"list.0.field": {
    74  			[]string{"list", "0", "field"},
    75  			map[string]*Schema{
    76  				"list": &Schema{
    77  					Type: TypeList,
    78  					Elem: &Resource{
    79  						Schema: map[string]*Schema{
    80  							"field": &Schema{Type: TypeString},
    81  						},
    82  					},
    83  				},
    84  			},
    85  			[]ValueType{TypeList, typeObject, TypeString},
    86  		},
    87  
    88  		"set": {
    89  			[]string{"set"},
    90  			map[string]*Schema{
    91  				"set": &Schema{
    92  					Type: TypeSet,
    93  					Elem: &Schema{Type: TypeInt},
    94  					Set: func(a interface{}) int {
    95  						return a.(int)
    96  					},
    97  				},
    98  			},
    99  			[]ValueType{TypeSet},
   100  		},
   101  
   102  		"set.#": {
   103  			[]string{"set", "#"},
   104  			map[string]*Schema{
   105  				"set": &Schema{
   106  					Type: TypeSet,
   107  					Elem: &Schema{Type: TypeInt},
   108  					Set: func(a interface{}) int {
   109  						return a.(int)
   110  					},
   111  				},
   112  			},
   113  			[]ValueType{TypeSet, TypeInt},
   114  		},
   115  
   116  		"set.0": {
   117  			[]string{"set", "0"},
   118  			map[string]*Schema{
   119  				"set": &Schema{
   120  					Type: TypeSet,
   121  					Elem: &Schema{Type: TypeInt},
   122  					Set: func(a interface{}) int {
   123  						return a.(int)
   124  					},
   125  				},
   126  			},
   127  			[]ValueType{TypeSet, TypeInt},
   128  		},
   129  
   130  		"set.0 with resource": {
   131  			[]string{"set", "0"},
   132  			map[string]*Schema{
   133  				"set": &Schema{
   134  					Type: TypeSet,
   135  					Elem: &Resource{
   136  						Schema: map[string]*Schema{
   137  							"field": &Schema{Type: TypeString},
   138  						},
   139  					},
   140  				},
   141  			},
   142  			[]ValueType{TypeSet, typeObject},
   143  		},
   144  
   145  		"mapElem": {
   146  			[]string{"map", "foo"},
   147  			map[string]*Schema{
   148  				"map": &Schema{Type: TypeMap},
   149  			},
   150  			[]ValueType{TypeMap, TypeString},
   151  		},
   152  
   153  		"setDeep": {
   154  			[]string{"set", "50", "index"},
   155  			map[string]*Schema{
   156  				"set": &Schema{
   157  					Type: TypeSet,
   158  					Elem: &Resource{
   159  						Schema: map[string]*Schema{
   160  							"index": &Schema{Type: TypeInt},
   161  							"value": &Schema{Type: TypeString},
   162  						},
   163  					},
   164  					Set: func(a interface{}) int {
   165  						return a.(map[string]interface{})["index"].(int)
   166  					},
   167  				},
   168  			},
   169  			[]ValueType{TypeSet, typeObject, TypeInt},
   170  		},
   171  	}
   172  
   173  	for name, tc := range cases {
   174  		result := addrToSchema(tc.Addr, tc.Schema)
   175  		types := make([]ValueType, len(result))
   176  		for i, v := range result {
   177  			types[i] = v.Type
   178  		}
   179  
   180  		if !reflect.DeepEqual(types, tc.Result) {
   181  			t.Fatalf("%s: %#v", name, types)
   182  		}
   183  	}
   184  }
   185  
   186  // testFieldReader is a helper that should be used to verify that
   187  // a FieldReader behaves properly in all the common cases.
   188  func testFieldReader(t *testing.T, f func(map[string]*Schema) FieldReader) {
   189  	schema := map[string]*Schema{
   190  		// Primitives
   191  		"bool":   &Schema{Type: TypeBool},
   192  		"float":  &Schema{Type: TypeFloat},
   193  		"int":    &Schema{Type: TypeInt},
   194  		"string": &Schema{Type: TypeString},
   195  
   196  		// Lists
   197  		"list": &Schema{
   198  			Type: TypeList,
   199  			Elem: &Schema{Type: TypeString},
   200  		},
   201  		"listInt": &Schema{
   202  			Type: TypeList,
   203  			Elem: &Schema{Type: TypeInt},
   204  		},
   205  		"listMap": &Schema{
   206  			Type: TypeList,
   207  			Elem: &Schema{
   208  				Type: TypeMap,
   209  			},
   210  		},
   211  
   212  		// Maps
   213  		"map": &Schema{Type: TypeMap},
   214  		"mapInt": &Schema{
   215  			Type: TypeMap,
   216  			Elem: TypeInt,
   217  		},
   218  		"mapFloat": &Schema{
   219  			Type: TypeMap,
   220  			Elem: TypeFloat,
   221  		},
   222  		"mapBool": &Schema{
   223  			Type: TypeMap,
   224  			Elem: TypeBool,
   225  		},
   226  
   227  		// Sets
   228  		"set": &Schema{
   229  			Type: TypeSet,
   230  			Elem: &Schema{Type: TypeInt},
   231  			Set: func(a interface{}) int {
   232  				return a.(int)
   233  			},
   234  		},
   235  		"setDeep": &Schema{
   236  			Type: TypeSet,
   237  			Elem: &Resource{
   238  				Schema: map[string]*Schema{
   239  					"index": &Schema{Type: TypeInt},
   240  					"value": &Schema{Type: TypeString},
   241  				},
   242  			},
   243  			Set: func(a interface{}) int {
   244  				return a.(map[string]interface{})["index"].(int)
   245  			},
   246  		},
   247  		"setEmpty": &Schema{
   248  			Type: TypeSet,
   249  			Elem: &Schema{Type: TypeInt},
   250  			Set: func(a interface{}) int {
   251  				return a.(int)
   252  			},
   253  		},
   254  	}
   255  
   256  	cases := map[string]struct {
   257  		Addr   []string
   258  		Result FieldReadResult
   259  		Err    bool
   260  	}{
   261  		"noexist": {
   262  			[]string{"boolNOPE"},
   263  			FieldReadResult{
   264  				Value:    nil,
   265  				Exists:   false,
   266  				Computed: false,
   267  			},
   268  			false,
   269  		},
   270  
   271  		"bool": {
   272  			[]string{"bool"},
   273  			FieldReadResult{
   274  				Value:    true,
   275  				Exists:   true,
   276  				Computed: false,
   277  			},
   278  			false,
   279  		},
   280  
   281  		"float": {
   282  			[]string{"float"},
   283  			FieldReadResult{
   284  				Value:    3.1415,
   285  				Exists:   true,
   286  				Computed: false,
   287  			},
   288  			false,
   289  		},
   290  
   291  		"int": {
   292  			[]string{"int"},
   293  			FieldReadResult{
   294  				Value:    42,
   295  				Exists:   true,
   296  				Computed: false,
   297  			},
   298  			false,
   299  		},
   300  
   301  		"string": {
   302  			[]string{"string"},
   303  			FieldReadResult{
   304  				Value:    "string",
   305  				Exists:   true,
   306  				Computed: false,
   307  			},
   308  			false,
   309  		},
   310  
   311  		"list": {
   312  			[]string{"list"},
   313  			FieldReadResult{
   314  				Value: []interface{}{
   315  					"foo",
   316  					"bar",
   317  				},
   318  				Exists:   true,
   319  				Computed: false,
   320  			},
   321  			false,
   322  		},
   323  
   324  		"listInt": {
   325  			[]string{"listInt"},
   326  			FieldReadResult{
   327  				Value: []interface{}{
   328  					21,
   329  					42,
   330  				},
   331  				Exists:   true,
   332  				Computed: false,
   333  			},
   334  			false,
   335  		},
   336  
   337  		"map": {
   338  			[]string{"map"},
   339  			FieldReadResult{
   340  				Value: map[string]interface{}{
   341  					"foo": "bar",
   342  					"bar": "baz",
   343  				},
   344  				Exists:   true,
   345  				Computed: false,
   346  			},
   347  			false,
   348  		},
   349  
   350  		"mapInt": {
   351  			[]string{"mapInt"},
   352  			FieldReadResult{
   353  				Value: map[string]interface{}{
   354  					"one": 1,
   355  					"two": 2,
   356  				},
   357  				Exists:   true,
   358  				Computed: false,
   359  			},
   360  			false,
   361  		},
   362  
   363  		"mapFloat": {
   364  			[]string{"mapFloat"},
   365  			FieldReadResult{
   366  				Value: map[string]interface{}{
   367  					"oneDotTwo": 1.2,
   368  				},
   369  				Exists:   true,
   370  				Computed: false,
   371  			},
   372  			false,
   373  		},
   374  
   375  		"mapBool": {
   376  			[]string{"mapBool"},
   377  			FieldReadResult{
   378  				Value: map[string]interface{}{
   379  					"True":  true,
   380  					"False": false,
   381  				},
   382  				Exists:   true,
   383  				Computed: false,
   384  			},
   385  			false,
   386  		},
   387  
   388  		"mapelem": {
   389  			[]string{"map", "foo"},
   390  			FieldReadResult{
   391  				Value:    "bar",
   392  				Exists:   true,
   393  				Computed: false,
   394  			},
   395  			false,
   396  		},
   397  
   398  		"set": {
   399  			[]string{"set"},
   400  			FieldReadResult{
   401  				Value:    []interface{}{10, 50},
   402  				Exists:   true,
   403  				Computed: false,
   404  			},
   405  			false,
   406  		},
   407  
   408  		"setDeep": {
   409  			[]string{"setDeep"},
   410  			FieldReadResult{
   411  				Value: []interface{}{
   412  					map[string]interface{}{
   413  						"index": 10,
   414  						"value": "foo",
   415  					},
   416  					map[string]interface{}{
   417  						"index": 50,
   418  						"value": "bar",
   419  					},
   420  				},
   421  				Exists:   true,
   422  				Computed: false,
   423  			},
   424  			false,
   425  		},
   426  
   427  		"setEmpty": {
   428  			[]string{"setEmpty"},
   429  			FieldReadResult{
   430  				Value:  []interface{}{},
   431  				Exists: false,
   432  			},
   433  			false,
   434  		},
   435  	}
   436  
   437  	for name, tc := range cases {
   438  		r := f(schema)
   439  		out, err := r.ReadField(tc.Addr)
   440  		if err != nil != tc.Err {
   441  			t.Fatalf("%s: err: %s", name, err)
   442  		}
   443  		if s, ok := out.Value.(*Set); ok {
   444  			// If it is a set, convert to a list so its more easily checked.
   445  			out.Value = s.List()
   446  		}
   447  		if !reflect.DeepEqual(tc.Result, out) {
   448  			t.Fatalf("%s: bad: %#v", name, out)
   449  		}
   450  	}
   451  }