github.com/Hashicorp/terraform@v0.11.12-beta1/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  
   219  		// This is used to verify that the type of a Map can be specified using the
   220  		// same syntax as for lists (as a nested *Schema passed to Elem)
   221  		"mapIntNestedSchema": &Schema{
   222  			Type: TypeMap,
   223  			Elem: &Schema{Type: TypeInt},
   224  		},
   225  		"mapFloat": &Schema{
   226  			Type: TypeMap,
   227  			Elem: TypeFloat,
   228  		},
   229  		"mapBool": &Schema{
   230  			Type: TypeMap,
   231  			Elem: TypeBool,
   232  		},
   233  
   234  		// Sets
   235  		"set": &Schema{
   236  			Type: TypeSet,
   237  			Elem: &Schema{Type: TypeInt},
   238  			Set: func(a interface{}) int {
   239  				return a.(int)
   240  			},
   241  		},
   242  		"setDeep": &Schema{
   243  			Type: TypeSet,
   244  			Elem: &Resource{
   245  				Schema: map[string]*Schema{
   246  					"index": &Schema{Type: TypeInt},
   247  					"value": &Schema{Type: TypeString},
   248  				},
   249  			},
   250  			Set: func(a interface{}) int {
   251  				return a.(map[string]interface{})["index"].(int)
   252  			},
   253  		},
   254  		"setEmpty": &Schema{
   255  			Type: TypeSet,
   256  			Elem: &Schema{Type: TypeInt},
   257  			Set: func(a interface{}) int {
   258  				return a.(int)
   259  			},
   260  		},
   261  	}
   262  
   263  	cases := map[string]struct {
   264  		Addr   []string
   265  		Result FieldReadResult
   266  		Err    bool
   267  	}{
   268  		"noexist": {
   269  			[]string{"boolNOPE"},
   270  			FieldReadResult{
   271  				Value:    nil,
   272  				Exists:   false,
   273  				Computed: false,
   274  			},
   275  			false,
   276  		},
   277  
   278  		"bool": {
   279  			[]string{"bool"},
   280  			FieldReadResult{
   281  				Value:    true,
   282  				Exists:   true,
   283  				Computed: false,
   284  			},
   285  			false,
   286  		},
   287  
   288  		"float": {
   289  			[]string{"float"},
   290  			FieldReadResult{
   291  				Value:    3.1415,
   292  				Exists:   true,
   293  				Computed: false,
   294  			},
   295  			false,
   296  		},
   297  
   298  		"int": {
   299  			[]string{"int"},
   300  			FieldReadResult{
   301  				Value:    42,
   302  				Exists:   true,
   303  				Computed: false,
   304  			},
   305  			false,
   306  		},
   307  
   308  		"string": {
   309  			[]string{"string"},
   310  			FieldReadResult{
   311  				Value:    "string",
   312  				Exists:   true,
   313  				Computed: false,
   314  			},
   315  			false,
   316  		},
   317  
   318  		"list": {
   319  			[]string{"list"},
   320  			FieldReadResult{
   321  				Value: []interface{}{
   322  					"foo",
   323  					"bar",
   324  				},
   325  				Exists:   true,
   326  				Computed: false,
   327  			},
   328  			false,
   329  		},
   330  
   331  		"listInt": {
   332  			[]string{"listInt"},
   333  			FieldReadResult{
   334  				Value: []interface{}{
   335  					21,
   336  					42,
   337  				},
   338  				Exists:   true,
   339  				Computed: false,
   340  			},
   341  			false,
   342  		},
   343  
   344  		"map": {
   345  			[]string{"map"},
   346  			FieldReadResult{
   347  				Value: map[string]interface{}{
   348  					"foo": "bar",
   349  					"bar": "baz",
   350  				},
   351  				Exists:   true,
   352  				Computed: false,
   353  			},
   354  			false,
   355  		},
   356  
   357  		"mapInt": {
   358  			[]string{"mapInt"},
   359  			FieldReadResult{
   360  				Value: map[string]interface{}{
   361  					"one": 1,
   362  					"two": 2,
   363  				},
   364  				Exists:   true,
   365  				Computed: false,
   366  			},
   367  			false,
   368  		},
   369  
   370  		"mapIntNestedSchema": {
   371  			[]string{"mapIntNestedSchema"},
   372  			FieldReadResult{
   373  				Value: map[string]interface{}{
   374  					"one": 1,
   375  					"two": 2,
   376  				},
   377  				Exists:   true,
   378  				Computed: false,
   379  			},
   380  			false,
   381  		},
   382  
   383  		"mapFloat": {
   384  			[]string{"mapFloat"},
   385  			FieldReadResult{
   386  				Value: map[string]interface{}{
   387  					"oneDotTwo": 1.2,
   388  				},
   389  				Exists:   true,
   390  				Computed: false,
   391  			},
   392  			false,
   393  		},
   394  
   395  		"mapBool": {
   396  			[]string{"mapBool"},
   397  			FieldReadResult{
   398  				Value: map[string]interface{}{
   399  					"True":  true,
   400  					"False": false,
   401  				},
   402  				Exists:   true,
   403  				Computed: false,
   404  			},
   405  			false,
   406  		},
   407  
   408  		"mapelem": {
   409  			[]string{"map", "foo"},
   410  			FieldReadResult{
   411  				Value:    "bar",
   412  				Exists:   true,
   413  				Computed: false,
   414  			},
   415  			false,
   416  		},
   417  
   418  		"set": {
   419  			[]string{"set"},
   420  			FieldReadResult{
   421  				Value:    []interface{}{10, 50},
   422  				Exists:   true,
   423  				Computed: false,
   424  			},
   425  			false,
   426  		},
   427  
   428  		"setDeep": {
   429  			[]string{"setDeep"},
   430  			FieldReadResult{
   431  				Value: []interface{}{
   432  					map[string]interface{}{
   433  						"index": 10,
   434  						"value": "foo",
   435  					},
   436  					map[string]interface{}{
   437  						"index": 50,
   438  						"value": "bar",
   439  					},
   440  				},
   441  				Exists:   true,
   442  				Computed: false,
   443  			},
   444  			false,
   445  		},
   446  
   447  		"setEmpty": {
   448  			[]string{"setEmpty"},
   449  			FieldReadResult{
   450  				Value:  []interface{}{},
   451  				Exists: false,
   452  			},
   453  			false,
   454  		},
   455  	}
   456  
   457  	for name, tc := range cases {
   458  		r := f(schema)
   459  		out, err := r.ReadField(tc.Addr)
   460  		if err != nil != tc.Err {
   461  			t.Fatalf("%s: err: %s", name, err)
   462  		}
   463  		if s, ok := out.Value.(*Set); ok {
   464  			// If it is a set, convert to a list so its more easily checked.
   465  			out.Value = s.List()
   466  		}
   467  		if !reflect.DeepEqual(tc.Result, out) {
   468  			t.Fatalf("%s: bad: %#v", name, out)
   469  		}
   470  	}
   471  }