github.com/acm1/terraform@v0.6.2-0.20150729164239-1f314444f45c/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  
   215  		// Sets
   216  		"set": &Schema{
   217  			Type: TypeSet,
   218  			Elem: &Schema{Type: TypeInt},
   219  			Set: func(a interface{}) int {
   220  				return a.(int)
   221  			},
   222  		},
   223  		"setDeep": &Schema{
   224  			Type: TypeSet,
   225  			Elem: &Resource{
   226  				Schema: map[string]*Schema{
   227  					"index": &Schema{Type: TypeInt},
   228  					"value": &Schema{Type: TypeString},
   229  				},
   230  			},
   231  			Set: func(a interface{}) int {
   232  				return a.(map[string]interface{})["index"].(int)
   233  			},
   234  		},
   235  		"setEmpty": &Schema{
   236  			Type: TypeSet,
   237  			Elem: &Schema{Type: TypeInt},
   238  			Set: func(a interface{}) int {
   239  				return a.(int)
   240  			},
   241  		},
   242  	}
   243  
   244  	cases := map[string]struct {
   245  		Addr   []string
   246  		Result FieldReadResult
   247  		Err    bool
   248  	}{
   249  		"noexist": {
   250  			[]string{"boolNOPE"},
   251  			FieldReadResult{
   252  				Value:    nil,
   253  				Exists:   false,
   254  				Computed: false,
   255  			},
   256  			false,
   257  		},
   258  
   259  		"bool": {
   260  			[]string{"bool"},
   261  			FieldReadResult{
   262  				Value:    true,
   263  				Exists:   true,
   264  				Computed: false,
   265  			},
   266  			false,
   267  		},
   268  
   269  		"float": {
   270  			[]string{"float"},
   271  			FieldReadResult{
   272  				Value:    3.1415,
   273  				Exists:   true,
   274  				Computed: false,
   275  			},
   276  			false,
   277  		},
   278  
   279  		"int": {
   280  			[]string{"int"},
   281  			FieldReadResult{
   282  				Value:    42,
   283  				Exists:   true,
   284  				Computed: false,
   285  			},
   286  			false,
   287  		},
   288  
   289  		"string": {
   290  			[]string{"string"},
   291  			FieldReadResult{
   292  				Value:    "string",
   293  				Exists:   true,
   294  				Computed: false,
   295  			},
   296  			false,
   297  		},
   298  
   299  		"list": {
   300  			[]string{"list"},
   301  			FieldReadResult{
   302  				Value: []interface{}{
   303  					"foo",
   304  					"bar",
   305  				},
   306  				Exists:   true,
   307  				Computed: false,
   308  			},
   309  			false,
   310  		},
   311  
   312  		"listInt": {
   313  			[]string{"listInt"},
   314  			FieldReadResult{
   315  				Value: []interface{}{
   316  					21,
   317  					42,
   318  				},
   319  				Exists:   true,
   320  				Computed: false,
   321  			},
   322  			false,
   323  		},
   324  
   325  		"map": {
   326  			[]string{"map"},
   327  			FieldReadResult{
   328  				Value: map[string]interface{}{
   329  					"foo": "bar",
   330  					"bar": "baz",
   331  				},
   332  				Exists:   true,
   333  				Computed: false,
   334  			},
   335  			false,
   336  		},
   337  
   338  		"mapelem": {
   339  			[]string{"map", "foo"},
   340  			FieldReadResult{
   341  				Value:    "bar",
   342  				Exists:   true,
   343  				Computed: false,
   344  			},
   345  			false,
   346  		},
   347  
   348  		"set": {
   349  			[]string{"set"},
   350  			FieldReadResult{
   351  				Value:    []interface{}{10, 50},
   352  				Exists:   true,
   353  				Computed: false,
   354  			},
   355  			false,
   356  		},
   357  
   358  		"setDeep": {
   359  			[]string{"setDeep"},
   360  			FieldReadResult{
   361  				Value: []interface{}{
   362  					map[string]interface{}{
   363  						"index": 10,
   364  						"value": "foo",
   365  					},
   366  					map[string]interface{}{
   367  						"index": 50,
   368  						"value": "bar",
   369  					},
   370  				},
   371  				Exists:   true,
   372  				Computed: false,
   373  			},
   374  			false,
   375  		},
   376  
   377  		"setEmpty": {
   378  			[]string{"setEmpty"},
   379  			FieldReadResult{
   380  				Value:  []interface{}{},
   381  				Exists: false,
   382  			},
   383  			false,
   384  		},
   385  	}
   386  
   387  	for name, tc := range cases {
   388  		r := f(schema)
   389  		out, err := r.ReadField(tc.Addr)
   390  		if (err != nil) != tc.Err {
   391  			t.Fatalf("%s: err: %s", name, err)
   392  		}
   393  		if s, ok := out.Value.(*Set); ok {
   394  			// If it is a set, convert to a list so its more easily checked.
   395  			out.Value = s.List()
   396  		}
   397  		if !reflect.DeepEqual(tc.Result, out) {
   398  			t.Fatalf("%s: bad: %#v", name, out)
   399  		}
   400  	}
   401  }