github.com/arvindram03/terraform@v0.3.7-0.20150212015210-408f838db36d/helper/schema/resource_data_test.go (about)

     1  package schema
     2  
     3  import (
     4  	"math"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/terraform/terraform"
     9  )
    10  
    11  func TestResourceDataGet(t *testing.T) {
    12  	cases := []struct {
    13  		Schema map[string]*Schema
    14  		State  *terraform.InstanceState
    15  		Diff   *terraform.InstanceDiff
    16  		Key    string
    17  		Value  interface{}
    18  	}{
    19  		// #0
    20  		{
    21  			Schema: map[string]*Schema{
    22  				"availability_zone": &Schema{
    23  					Type:     TypeString,
    24  					Optional: true,
    25  					Computed: true,
    26  					ForceNew: true,
    27  				},
    28  			},
    29  
    30  			State: nil,
    31  
    32  			Diff: &terraform.InstanceDiff{
    33  				Attributes: map[string]*terraform.ResourceAttrDiff{
    34  					"availability_zone": &terraform.ResourceAttrDiff{
    35  						Old:         "foo",
    36  						New:         "bar",
    37  						NewComputed: true,
    38  					},
    39  				},
    40  			},
    41  
    42  			Key:   "availability_zone",
    43  			Value: "",
    44  		},
    45  
    46  		// #1
    47  		{
    48  			Schema: map[string]*Schema{
    49  				"availability_zone": &Schema{
    50  					Type:     TypeString,
    51  					Optional: true,
    52  					Computed: true,
    53  					ForceNew: true,
    54  				},
    55  			},
    56  
    57  			State: nil,
    58  
    59  			Diff: &terraform.InstanceDiff{
    60  				Attributes: map[string]*terraform.ResourceAttrDiff{
    61  					"availability_zone": &terraform.ResourceAttrDiff{
    62  						Old:         "",
    63  						New:         "foo",
    64  						RequiresNew: true,
    65  					},
    66  				},
    67  			},
    68  
    69  			Key: "availability_zone",
    70  
    71  			Value: "foo",
    72  		},
    73  
    74  		// #2
    75  		{
    76  			Schema: map[string]*Schema{
    77  				"availability_zone": &Schema{
    78  					Type:     TypeString,
    79  					Optional: true,
    80  					Computed: true,
    81  					ForceNew: true,
    82  				},
    83  			},
    84  
    85  			State: nil,
    86  
    87  			Diff: &terraform.InstanceDiff{
    88  				Attributes: map[string]*terraform.ResourceAttrDiff{
    89  					"availability_zone": &terraform.ResourceAttrDiff{
    90  						Old:      "",
    91  						New:      "foo!",
    92  						NewExtra: "foo",
    93  					},
    94  				},
    95  			},
    96  
    97  			Key:   "availability_zone",
    98  			Value: "foo",
    99  		},
   100  
   101  		// #3
   102  		{
   103  			Schema: map[string]*Schema{
   104  				"availability_zone": &Schema{
   105  					Type:     TypeString,
   106  					Optional: true,
   107  					Computed: true,
   108  					ForceNew: true,
   109  				},
   110  			},
   111  
   112  			State: &terraform.InstanceState{
   113  				Attributes: map[string]string{
   114  					"availability_zone": "bar",
   115  				},
   116  			},
   117  
   118  			Diff: nil,
   119  
   120  			Key: "availability_zone",
   121  
   122  			Value: "bar",
   123  		},
   124  
   125  		// #4
   126  		{
   127  			Schema: map[string]*Schema{
   128  				"availability_zone": &Schema{
   129  					Type:     TypeString,
   130  					Optional: true,
   131  					Computed: true,
   132  					ForceNew: true,
   133  				},
   134  			},
   135  
   136  			State: &terraform.InstanceState{
   137  				Attributes: map[string]string{
   138  					"availability_zone": "foo",
   139  				},
   140  			},
   141  
   142  			Diff: &terraform.InstanceDiff{
   143  				Attributes: map[string]*terraform.ResourceAttrDiff{
   144  					"availability_zone": &terraform.ResourceAttrDiff{
   145  						Old:         "foo",
   146  						New:         "bar",
   147  						NewComputed: true,
   148  					},
   149  				},
   150  			},
   151  
   152  			Key:   "availability_zone",
   153  			Value: "",
   154  		},
   155  
   156  		// #5
   157  		{
   158  			Schema: map[string]*Schema{
   159  				"port": &Schema{
   160  					Type:     TypeInt,
   161  					Optional: true,
   162  					Computed: true,
   163  					ForceNew: true,
   164  				},
   165  			},
   166  
   167  			State: &terraform.InstanceState{
   168  				Attributes: map[string]string{
   169  					"port": "80",
   170  				},
   171  			},
   172  
   173  			Diff: nil,
   174  
   175  			Key: "port",
   176  
   177  			Value: 80,
   178  		},
   179  
   180  		// #6
   181  		{
   182  			Schema: map[string]*Schema{
   183  				"ports": &Schema{
   184  					Type:     TypeList,
   185  					Required: true,
   186  					Elem:     &Schema{Type: TypeInt},
   187  				},
   188  			},
   189  
   190  			State: &terraform.InstanceState{
   191  				Attributes: map[string]string{
   192  					"ports.#": "3",
   193  					"ports.0": "1",
   194  					"ports.1": "2",
   195  					"ports.2": "5",
   196  				},
   197  			},
   198  
   199  			Key: "ports.1",
   200  
   201  			Value: 2,
   202  		},
   203  
   204  		// #7
   205  		{
   206  			Schema: map[string]*Schema{
   207  				"ports": &Schema{
   208  					Type:     TypeList,
   209  					Required: true,
   210  					Elem:     &Schema{Type: TypeInt},
   211  				},
   212  			},
   213  
   214  			State: &terraform.InstanceState{
   215  				Attributes: map[string]string{
   216  					"ports.#": "3",
   217  					"ports.0": "1",
   218  					"ports.1": "2",
   219  					"ports.2": "5",
   220  				},
   221  			},
   222  
   223  			Key: "ports.#",
   224  
   225  			Value: 3,
   226  		},
   227  
   228  		// #8
   229  		{
   230  			Schema: map[string]*Schema{
   231  				"ports": &Schema{
   232  					Type:     TypeList,
   233  					Required: true,
   234  					Elem:     &Schema{Type: TypeInt},
   235  				},
   236  			},
   237  
   238  			State: nil,
   239  
   240  			Key: "ports.#",
   241  
   242  			Value: 0,
   243  		},
   244  
   245  		// #9
   246  		{
   247  			Schema: map[string]*Schema{
   248  				"ports": &Schema{
   249  					Type:     TypeList,
   250  					Required: true,
   251  					Elem:     &Schema{Type: TypeInt},
   252  				},
   253  			},
   254  
   255  			State: &terraform.InstanceState{
   256  				Attributes: map[string]string{
   257  					"ports.#": "3",
   258  					"ports.0": "1",
   259  					"ports.1": "2",
   260  					"ports.2": "5",
   261  				},
   262  			},
   263  
   264  			Key: "ports",
   265  
   266  			Value: []interface{}{1, 2, 5},
   267  		},
   268  
   269  		// #10
   270  		{
   271  			Schema: map[string]*Schema{
   272  				"ingress": &Schema{
   273  					Type:     TypeList,
   274  					Required: true,
   275  					Elem: &Resource{
   276  						Schema: map[string]*Schema{
   277  							"from": &Schema{
   278  								Type:     TypeInt,
   279  								Required: true,
   280  							},
   281  						},
   282  					},
   283  				},
   284  			},
   285  
   286  			State: nil,
   287  
   288  			Diff: &terraform.InstanceDiff{
   289  				Attributes: map[string]*terraform.ResourceAttrDiff{
   290  					"ingress.#": &terraform.ResourceAttrDiff{
   291  						Old: "",
   292  						New: "1",
   293  					},
   294  					"ingress.0.from": &terraform.ResourceAttrDiff{
   295  						Old: "",
   296  						New: "8080",
   297  					},
   298  				},
   299  			},
   300  
   301  			Key: "ingress.0",
   302  
   303  			Value: map[string]interface{}{
   304  				"from": 8080,
   305  			},
   306  		},
   307  
   308  		// #11
   309  		{
   310  			Schema: map[string]*Schema{
   311  				"ingress": &Schema{
   312  					Type:     TypeList,
   313  					Required: true,
   314  					Elem: &Resource{
   315  						Schema: map[string]*Schema{
   316  							"from": &Schema{
   317  								Type:     TypeInt,
   318  								Required: true,
   319  							},
   320  						},
   321  					},
   322  				},
   323  			},
   324  
   325  			State: nil,
   326  
   327  			Diff: &terraform.InstanceDiff{
   328  				Attributes: map[string]*terraform.ResourceAttrDiff{
   329  					"ingress.#": &terraform.ResourceAttrDiff{
   330  						Old: "",
   331  						New: "1",
   332  					},
   333  					"ingress.0.from": &terraform.ResourceAttrDiff{
   334  						Old: "",
   335  						New: "8080",
   336  					},
   337  				},
   338  			},
   339  
   340  			Key: "ingress",
   341  
   342  			Value: []interface{}{
   343  				map[string]interface{}{
   344  					"from": 8080,
   345  				},
   346  			},
   347  		},
   348  
   349  		// #12 Computed get
   350  		{
   351  			Schema: map[string]*Schema{
   352  				"availability_zone": &Schema{
   353  					Type:     TypeString,
   354  					Computed: true,
   355  				},
   356  			},
   357  
   358  			State: &terraform.InstanceState{
   359  				Attributes: map[string]string{
   360  					"availability_zone": "foo",
   361  				},
   362  			},
   363  
   364  			Key: "availability_zone",
   365  
   366  			Value: "foo",
   367  		},
   368  
   369  		// #13 Full object
   370  		{
   371  			Schema: map[string]*Schema{
   372  				"availability_zone": &Schema{
   373  					Type:     TypeString,
   374  					Optional: true,
   375  					Computed: true,
   376  					ForceNew: true,
   377  				},
   378  			},
   379  
   380  			State: nil,
   381  
   382  			Diff: &terraform.InstanceDiff{
   383  				Attributes: map[string]*terraform.ResourceAttrDiff{
   384  					"availability_zone": &terraform.ResourceAttrDiff{
   385  						Old:         "",
   386  						New:         "foo",
   387  						RequiresNew: true,
   388  					},
   389  				},
   390  			},
   391  
   392  			Key: "",
   393  
   394  			Value: map[string]interface{}{
   395  				"availability_zone": "foo",
   396  			},
   397  		},
   398  
   399  		// #14 List of maps
   400  		{
   401  			Schema: map[string]*Schema{
   402  				"config_vars": &Schema{
   403  					Type:     TypeList,
   404  					Optional: true,
   405  					Computed: true,
   406  					Elem: &Schema{
   407  						Type: TypeMap,
   408  					},
   409  				},
   410  			},
   411  
   412  			State: nil,
   413  
   414  			Diff: &terraform.InstanceDiff{
   415  				Attributes: map[string]*terraform.ResourceAttrDiff{
   416  					"config_vars.#": &terraform.ResourceAttrDiff{
   417  						Old: "0",
   418  						New: "2",
   419  					},
   420  					"config_vars.0.foo": &terraform.ResourceAttrDiff{
   421  						Old: "",
   422  						New: "bar",
   423  					},
   424  					"config_vars.1.bar": &terraform.ResourceAttrDiff{
   425  						Old: "",
   426  						New: "baz",
   427  					},
   428  				},
   429  			},
   430  
   431  			Key: "config_vars",
   432  
   433  			Value: []interface{}{
   434  				map[string]interface{}{
   435  					"foo": "bar",
   436  				},
   437  				map[string]interface{}{
   438  					"bar": "baz",
   439  				},
   440  			},
   441  		},
   442  
   443  		// #15 List of maps in state
   444  		{
   445  			Schema: map[string]*Schema{
   446  				"config_vars": &Schema{
   447  					Type:     TypeList,
   448  					Optional: true,
   449  					Computed: true,
   450  					Elem: &Schema{
   451  						Type: TypeMap,
   452  					},
   453  				},
   454  			},
   455  
   456  			State: &terraform.InstanceState{
   457  				Attributes: map[string]string{
   458  					"config_vars.#":     "2",
   459  					"config_vars.0.foo": "baz",
   460  					"config_vars.1.bar": "bar",
   461  				},
   462  			},
   463  
   464  			Diff: nil,
   465  
   466  			Key: "config_vars",
   467  
   468  			Value: []interface{}{
   469  				map[string]interface{}{
   470  					"foo": "baz",
   471  				},
   472  				map[string]interface{}{
   473  					"bar": "bar",
   474  				},
   475  			},
   476  		},
   477  
   478  		// #16 List of maps with removal in diff
   479  		{
   480  			Schema: map[string]*Schema{
   481  				"config_vars": &Schema{
   482  					Type:     TypeList,
   483  					Optional: true,
   484  					Computed: true,
   485  					Elem: &Schema{
   486  						Type: TypeMap,
   487  					},
   488  				},
   489  			},
   490  
   491  			State: &terraform.InstanceState{
   492  				Attributes: map[string]string{
   493  					"config_vars.#":     "1",
   494  					"config_vars.0.FOO": "bar",
   495  				},
   496  			},
   497  
   498  			Diff: &terraform.InstanceDiff{
   499  				Attributes: map[string]*terraform.ResourceAttrDiff{
   500  					"config_vars.#": &terraform.ResourceAttrDiff{
   501  						Old: "1",
   502  						New: "0",
   503  					},
   504  					"config_vars.0.FOO": &terraform.ResourceAttrDiff{
   505  						Old:        "bar",
   506  						NewRemoved: true,
   507  					},
   508  				},
   509  			},
   510  
   511  			Key: "config_vars",
   512  
   513  			Value: []interface{}{},
   514  		},
   515  
   516  		// #17 Sets
   517  		{
   518  			Schema: map[string]*Schema{
   519  				"ports": &Schema{
   520  					Type:     TypeSet,
   521  					Optional: true,
   522  					Computed: true,
   523  					Elem:     &Schema{Type: TypeInt},
   524  					Set: func(a interface{}) int {
   525  						return a.(int)
   526  					},
   527  				},
   528  			},
   529  
   530  			State: &terraform.InstanceState{
   531  				Attributes: map[string]string{
   532  					"ports.#":  "1",
   533  					"ports.80": "80",
   534  				},
   535  			},
   536  
   537  			Diff: nil,
   538  
   539  			Key: "ports",
   540  
   541  			Value: []interface{}{80},
   542  		},
   543  
   544  		// #18
   545  		{
   546  			Schema: map[string]*Schema{
   547  				"data": &Schema{
   548  					Type:     TypeSet,
   549  					Optional: true,
   550  					Elem: &Resource{
   551  						Schema: map[string]*Schema{
   552  							"index": &Schema{
   553  								Type:     TypeInt,
   554  								Required: true,
   555  							},
   556  
   557  							"value": &Schema{
   558  								Type:     TypeString,
   559  								Required: true,
   560  							},
   561  						},
   562  					},
   563  					Set: func(a interface{}) int {
   564  						m := a.(map[string]interface{})
   565  						return m["index"].(int)
   566  					},
   567  				},
   568  			},
   569  
   570  			State: &terraform.InstanceState{
   571  				Attributes: map[string]string{
   572  					"data.#":        "1",
   573  					"data.10.index": "10",
   574  					"data.10.value": "50",
   575  				},
   576  			},
   577  
   578  			Diff: &terraform.InstanceDiff{
   579  				Attributes: map[string]*terraform.ResourceAttrDiff{
   580  					"data.10.value": &terraform.ResourceAttrDiff{
   581  						Old: "50",
   582  						New: "80",
   583  					},
   584  				},
   585  			},
   586  
   587  			Key: "data",
   588  
   589  			Value: []interface{}{
   590  				map[string]interface{}{
   591  					"index": 10,
   592  					"value": "80",
   593  				},
   594  			},
   595  		},
   596  
   597  		// #19 Empty Set
   598  		{
   599  			Schema: map[string]*Schema{
   600  				"ports": &Schema{
   601  					Type:     TypeSet,
   602  					Optional: true,
   603  					Computed: true,
   604  					Elem:     &Schema{Type: TypeInt},
   605  					Set: func(a interface{}) int {
   606  						return a.(int)
   607  					},
   608  				},
   609  			},
   610  
   611  			State: nil,
   612  
   613  			Diff: nil,
   614  
   615  			Key: "ports",
   616  
   617  			Value: []interface{}{},
   618  		},
   619  
   620  		// #20 Float zero
   621  		{
   622  			Schema: map[string]*Schema{
   623  				"ratio": &Schema{
   624  					Type:     TypeFloat,
   625  					Optional: true,
   626  					Computed: true,
   627  				},
   628  			},
   629  
   630  			State: nil,
   631  
   632  			Diff: nil,
   633  
   634  			Key: "ratio",
   635  
   636  			Value: 0.0,
   637  		},
   638  
   639  		// #21 Float given
   640  		{
   641  			Schema: map[string]*Schema{
   642  				"ratio": &Schema{
   643  					Type:     TypeFloat,
   644  					Optional: true,
   645  					Computed: true,
   646  				},
   647  			},
   648  
   649  			State: &terraform.InstanceState{
   650  				Attributes: map[string]string{
   651  					"ratio":        "0.5",
   652  				},
   653  			},
   654  
   655  
   656  			Diff: nil,
   657  
   658  			Key: "ratio",
   659  
   660  			Value: 0.5,
   661  		},
   662  
   663  		// #22 Float diff
   664  		{
   665  			Schema: map[string]*Schema{
   666  				"ratio": &Schema{
   667  					Type:     TypeFloat,
   668  					Optional: true,
   669  					Computed: true,
   670  				},
   671  			},
   672  
   673  			State: &terraform.InstanceState{
   674  				Attributes: map[string]string{
   675  					"ratio":        "-0.5",
   676  				},
   677  			},
   678  
   679  
   680  			Diff: &terraform.InstanceDiff{
   681  				Attributes: map[string]*terraform.ResourceAttrDiff{
   682  					"ratio": &terraform.ResourceAttrDiff{
   683  						Old: "-0.5",
   684  						New: "33.0",
   685  					},
   686  				},
   687  			},
   688  
   689  
   690  			Key: "ratio",
   691  
   692  			Value: 33.0,
   693  		},
   694  	}
   695  
   696  	for i, tc := range cases {
   697  		d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff)
   698  		if err != nil {
   699  			t.Fatalf("err: %s", err)
   700  		}
   701  
   702  		v := d.Get(tc.Key)
   703  		if s, ok := v.(*Set); ok {
   704  			v = s.List()
   705  		}
   706  
   707  		if !reflect.DeepEqual(v, tc.Value) {
   708  			t.Fatalf("Bad: %d\n\n%#v\n\nExpected: %#v", i, v, tc.Value)
   709  		}
   710  	}
   711  }
   712  
   713  func TestResourceDataGetChange(t *testing.T) {
   714  	cases := []struct {
   715  		Schema   map[string]*Schema
   716  		State    *terraform.InstanceState
   717  		Diff     *terraform.InstanceDiff
   718  		Key      string
   719  		OldValue interface{}
   720  		NewValue interface{}
   721  	}{
   722  		{
   723  			Schema: map[string]*Schema{
   724  				"availability_zone": &Schema{
   725  					Type:     TypeString,
   726  					Optional: true,
   727  					Computed: true,
   728  					ForceNew: true,
   729  				},
   730  			},
   731  
   732  			State: nil,
   733  
   734  			Diff: &terraform.InstanceDiff{
   735  				Attributes: map[string]*terraform.ResourceAttrDiff{
   736  					"availability_zone": &terraform.ResourceAttrDiff{
   737  						Old:         "",
   738  						New:         "foo",
   739  						RequiresNew: true,
   740  					},
   741  				},
   742  			},
   743  
   744  			Key: "availability_zone",
   745  
   746  			OldValue: "",
   747  			NewValue: "foo",
   748  		},
   749  
   750  		{
   751  			Schema: map[string]*Schema{
   752  				"availability_zone": &Schema{
   753  					Type:     TypeString,
   754  					Optional: true,
   755  					Computed: true,
   756  					ForceNew: true,
   757  				},
   758  			},
   759  
   760  			State: &terraform.InstanceState{
   761  				Attributes: map[string]string{
   762  					"availability_zone": "foo",
   763  				},
   764  			},
   765  
   766  			Diff: &terraform.InstanceDiff{
   767  				Attributes: map[string]*terraform.ResourceAttrDiff{
   768  					"availability_zone": &terraform.ResourceAttrDiff{
   769  						Old:         "",
   770  						New:         "foo",
   771  						RequiresNew: true,
   772  					},
   773  				},
   774  			},
   775  
   776  			Key: "availability_zone",
   777  
   778  			OldValue: "foo",
   779  			NewValue: "foo",
   780  		},
   781  	}
   782  
   783  	for i, tc := range cases {
   784  		d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff)
   785  		if err != nil {
   786  			t.Fatalf("err: %s", err)
   787  		}
   788  
   789  		o, n := d.GetChange(tc.Key)
   790  		if !reflect.DeepEqual(o, tc.OldValue) {
   791  			t.Fatalf("Old Bad: %d\n\n%#v", i, o)
   792  		}
   793  		if !reflect.DeepEqual(n, tc.NewValue) {
   794  			t.Fatalf("New Bad: %d\n\n%#v", i, n)
   795  		}
   796  	}
   797  }
   798  
   799  func TestResourceDataGetOk(t *testing.T) {
   800  	cases := []struct {
   801  		Schema map[string]*Schema
   802  		State  *terraform.InstanceState
   803  		Diff   *terraform.InstanceDiff
   804  		Key    string
   805  		Value  interface{}
   806  		Ok     bool
   807  	}{
   808  		/*
   809  		 * Primitives
   810  		 */
   811  		{
   812  			Schema: map[string]*Schema{
   813  				"availability_zone": &Schema{
   814  					Type:     TypeString,
   815  					Optional: true,
   816  					Computed: true,
   817  					ForceNew: true,
   818  				},
   819  			},
   820  
   821  			State: nil,
   822  
   823  			Diff: &terraform.InstanceDiff{
   824  				Attributes: map[string]*terraform.ResourceAttrDiff{
   825  					"availability_zone": &terraform.ResourceAttrDiff{
   826  						Old: "",
   827  						New: "",
   828  					},
   829  				},
   830  			},
   831  
   832  			Key:   "availability_zone",
   833  			Value: "",
   834  			Ok:    true,
   835  		},
   836  
   837  		{
   838  			Schema: map[string]*Schema{
   839  				"availability_zone": &Schema{
   840  					Type:     TypeString,
   841  					Optional: true,
   842  					Computed: true,
   843  					ForceNew: true,
   844  				},
   845  			},
   846  
   847  			State: nil,
   848  
   849  			Diff: &terraform.InstanceDiff{
   850  				Attributes: map[string]*terraform.ResourceAttrDiff{
   851  					"availability_zone": &terraform.ResourceAttrDiff{
   852  						Old:         "",
   853  						New:         "",
   854  						NewComputed: true,
   855  					},
   856  				},
   857  			},
   858  
   859  			Key:   "availability_zone",
   860  			Value: "",
   861  			Ok:    false,
   862  		},
   863  
   864  		{
   865  			Schema: map[string]*Schema{
   866  				"availability_zone": &Schema{
   867  					Type:     TypeString,
   868  					Optional: true,
   869  					Computed: true,
   870  					ForceNew: true,
   871  				},
   872  			},
   873  
   874  			State: nil,
   875  
   876  			Diff: nil,
   877  
   878  			Key:   "availability_zone",
   879  			Value: "",
   880  			Ok:    false,
   881  		},
   882  
   883  		/*
   884  		 * Lists
   885  		 */
   886  
   887  		{
   888  			Schema: map[string]*Schema{
   889  				"ports": &Schema{
   890  					Type:     TypeList,
   891  					Optional: true,
   892  					Elem:     &Schema{Type: TypeInt},
   893  				},
   894  			},
   895  
   896  			State: nil,
   897  
   898  			Diff: nil,
   899  
   900  			Key:   "ports",
   901  			Value: []interface{}{},
   902  			Ok:    false,
   903  		},
   904  
   905  		/*
   906  		 * Map
   907  		 */
   908  
   909  		{
   910  			Schema: map[string]*Schema{
   911  				"ports": &Schema{
   912  					Type:     TypeMap,
   913  					Optional: true,
   914  				},
   915  			},
   916  
   917  			State: nil,
   918  
   919  			Diff: nil,
   920  
   921  			Key:   "ports",
   922  			Value: map[string]interface{}{},
   923  			Ok:    false,
   924  		},
   925  
   926  		/*
   927  		 * Set
   928  		 */
   929  
   930  		{
   931  			Schema: map[string]*Schema{
   932  				"ports": &Schema{
   933  					Type:     TypeSet,
   934  					Optional: true,
   935  					Elem:     &Schema{Type: TypeInt},
   936  					Set:      func(a interface{}) int { return a.(int) },
   937  				},
   938  			},
   939  
   940  			State: nil,
   941  
   942  			Diff: nil,
   943  
   944  			Key:   "ports",
   945  			Value: []interface{}{},
   946  			Ok:    false,
   947  		},
   948  
   949  		{
   950  			Schema: map[string]*Schema{
   951  				"ports": &Schema{
   952  					Type:     TypeSet,
   953  					Optional: true,
   954  					Elem:     &Schema{Type: TypeInt},
   955  					Set:      func(a interface{}) int { return a.(int) },
   956  				},
   957  			},
   958  
   959  			State: nil,
   960  
   961  			Diff: nil,
   962  
   963  			Key:   "ports.0",
   964  			Value: 0,
   965  			Ok:    false,
   966  		},
   967  	}
   968  
   969  	for i, tc := range cases {
   970  		d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff)
   971  		if err != nil {
   972  			t.Fatalf("err: %s", err)
   973  		}
   974  
   975  		v, ok := d.GetOk(tc.Key)
   976  		if s, ok := v.(*Set); ok {
   977  			v = s.List()
   978  		}
   979  
   980  		if !reflect.DeepEqual(v, tc.Value) {
   981  			t.Fatalf("Bad: %d\n\n%#v", i, v)
   982  		}
   983  		if ok != tc.Ok {
   984  			t.Fatalf("Bad: %d\n\n%#v", i, ok)
   985  		}
   986  	}
   987  }
   988  
   989  func TestResourceDataHasChange(t *testing.T) {
   990  	cases := []struct {
   991  		Schema map[string]*Schema
   992  		State  *terraform.InstanceState
   993  		Diff   *terraform.InstanceDiff
   994  		Key    string
   995  		Change bool
   996  	}{
   997  		{
   998  			Schema: map[string]*Schema{
   999  				"availability_zone": &Schema{
  1000  					Type:     TypeString,
  1001  					Optional: true,
  1002  					Computed: true,
  1003  					ForceNew: true,
  1004  				},
  1005  			},
  1006  
  1007  			State: nil,
  1008  
  1009  			Diff: &terraform.InstanceDiff{
  1010  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1011  					"availability_zone": &terraform.ResourceAttrDiff{
  1012  						Old:         "",
  1013  						New:         "foo",
  1014  						RequiresNew: true,
  1015  					},
  1016  				},
  1017  			},
  1018  
  1019  			Key: "availability_zone",
  1020  
  1021  			Change: true,
  1022  		},
  1023  
  1024  		{
  1025  			Schema: map[string]*Schema{
  1026  				"availability_zone": &Schema{
  1027  					Type:     TypeString,
  1028  					Optional: true,
  1029  					Computed: true,
  1030  					ForceNew: true,
  1031  				},
  1032  			},
  1033  
  1034  			State: &terraform.InstanceState{
  1035  				Attributes: map[string]string{
  1036  					"availability_zone": "foo",
  1037  				},
  1038  			},
  1039  
  1040  			Diff: &terraform.InstanceDiff{
  1041  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1042  					"availability_zone": &terraform.ResourceAttrDiff{
  1043  						Old:         "",
  1044  						New:         "foo",
  1045  						RequiresNew: true,
  1046  					},
  1047  				},
  1048  			},
  1049  
  1050  			Key: "availability_zone",
  1051  
  1052  			Change: false,
  1053  		},
  1054  
  1055  		{
  1056  			Schema: map[string]*Schema{
  1057  				"tags": &Schema{
  1058  					Type:     TypeMap,
  1059  					Optional: true,
  1060  					Computed: true,
  1061  				},
  1062  			},
  1063  
  1064  			State: nil,
  1065  
  1066  			Diff: &terraform.InstanceDiff{
  1067  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1068  					"tags.Name": &terraform.ResourceAttrDiff{
  1069  						Old: "foo",
  1070  						New: "foo",
  1071  					},
  1072  				},
  1073  			},
  1074  
  1075  			Key: "tags",
  1076  
  1077  			Change: true,
  1078  		},
  1079  
  1080  		{
  1081  			Schema: map[string]*Schema{
  1082  				"ports": &Schema{
  1083  					Type:     TypeSet,
  1084  					Optional: true,
  1085  					Elem:     &Schema{Type: TypeInt},
  1086  					Set:      func(a interface{}) int { return a.(int) },
  1087  				},
  1088  			},
  1089  
  1090  			State: &terraform.InstanceState{
  1091  				Attributes: map[string]string{
  1092  					"ports.#":  "1",
  1093  					"ports.80": "80",
  1094  				},
  1095  			},
  1096  
  1097  			Diff: &terraform.InstanceDiff{
  1098  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1099  					"ports.#": &terraform.ResourceAttrDiff{
  1100  						Old: "1",
  1101  						New: "0",
  1102  					},
  1103  				},
  1104  			},
  1105  
  1106  			Key: "ports",
  1107  
  1108  			Change: true,
  1109  		},
  1110  	}
  1111  
  1112  	for i, tc := range cases {
  1113  		d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff)
  1114  		if err != nil {
  1115  			t.Fatalf("err: %s", err)
  1116  		}
  1117  
  1118  		actual := d.HasChange(tc.Key)
  1119  		if actual != tc.Change {
  1120  			t.Fatalf("Bad: %d %#v", i, actual)
  1121  		}
  1122  	}
  1123  }
  1124  
  1125  func TestResourceDataSet(t *testing.T) {
  1126  	cases := []struct {
  1127  		Schema   map[string]*Schema
  1128  		State    *terraform.InstanceState
  1129  		Diff     *terraform.InstanceDiff
  1130  		Key      string
  1131  		Value    interface{}
  1132  		Err      bool
  1133  		GetKey   string
  1134  		GetValue interface{}
  1135  
  1136  		// GetPreProcess can be set to munge the return value before being
  1137  		// compared to GetValue
  1138  		GetPreProcess func(interface{}) interface{}
  1139  	}{
  1140  		// #0: Basic good
  1141  		{
  1142  			Schema: map[string]*Schema{
  1143  				"availability_zone": &Schema{
  1144  					Type:     TypeString,
  1145  					Optional: true,
  1146  					Computed: true,
  1147  					ForceNew: true,
  1148  				},
  1149  			},
  1150  
  1151  			State: nil,
  1152  
  1153  			Diff: nil,
  1154  
  1155  			Key:   "availability_zone",
  1156  			Value: "foo",
  1157  
  1158  			GetKey:   "availability_zone",
  1159  			GetValue: "foo",
  1160  		},
  1161  
  1162  		// #1: Basic int
  1163  		{
  1164  			Schema: map[string]*Schema{
  1165  				"port": &Schema{
  1166  					Type:     TypeInt,
  1167  					Optional: true,
  1168  					Computed: true,
  1169  					ForceNew: true,
  1170  				},
  1171  			},
  1172  
  1173  			State: nil,
  1174  
  1175  			Diff: nil,
  1176  
  1177  			Key:   "port",
  1178  			Value: 80,
  1179  
  1180  			GetKey:   "port",
  1181  			GetValue: 80,
  1182  		},
  1183  
  1184  		// #2: Basic bool
  1185  		{
  1186  			Schema: map[string]*Schema{
  1187  				"vpc": &Schema{
  1188  					Type:     TypeBool,
  1189  					Optional: true,
  1190  				},
  1191  			},
  1192  
  1193  			State: nil,
  1194  
  1195  			Diff: nil,
  1196  
  1197  			Key:   "vpc",
  1198  			Value: true,
  1199  
  1200  			GetKey:   "vpc",
  1201  			GetValue: true,
  1202  		},
  1203  
  1204  		// #3
  1205  		{
  1206  			Schema: map[string]*Schema{
  1207  				"vpc": &Schema{
  1208  					Type:     TypeBool,
  1209  					Optional: true,
  1210  				},
  1211  			},
  1212  
  1213  			State: nil,
  1214  
  1215  			Diff: nil,
  1216  
  1217  			Key:   "vpc",
  1218  			Value: false,
  1219  
  1220  			GetKey:   "vpc",
  1221  			GetValue: false,
  1222  		},
  1223  
  1224  		// #4: Invalid type
  1225  		{
  1226  			Schema: map[string]*Schema{
  1227  				"availability_zone": &Schema{
  1228  					Type:     TypeString,
  1229  					Optional: true,
  1230  					Computed: true,
  1231  					ForceNew: true,
  1232  				},
  1233  			},
  1234  
  1235  			State: nil,
  1236  
  1237  			Diff: nil,
  1238  
  1239  			Key:   "availability_zone",
  1240  			Value: 80,
  1241  			Err:   true,
  1242  
  1243  			GetKey:   "availability_zone",
  1244  			GetValue: "",
  1245  		},
  1246  
  1247  		// #5: List of primitives, set list
  1248  		{
  1249  			Schema: map[string]*Schema{
  1250  				"ports": &Schema{
  1251  					Type:     TypeList,
  1252  					Computed: true,
  1253  					Elem:     &Schema{Type: TypeInt},
  1254  				},
  1255  			},
  1256  
  1257  			State: nil,
  1258  
  1259  			Diff: nil,
  1260  
  1261  			Key:   "ports",
  1262  			Value: []int{1, 2, 5},
  1263  
  1264  			GetKey:   "ports",
  1265  			GetValue: []interface{}{1, 2, 5},
  1266  		},
  1267  
  1268  		// #6: List of primitives, set list with error
  1269  		{
  1270  			Schema: map[string]*Schema{
  1271  				"ports": &Schema{
  1272  					Type:     TypeList,
  1273  					Computed: true,
  1274  					Elem:     &Schema{Type: TypeInt},
  1275  				},
  1276  			},
  1277  
  1278  			State: nil,
  1279  
  1280  			Diff: nil,
  1281  
  1282  			Key:   "ports",
  1283  			Value: []interface{}{1, "NOPE", 5},
  1284  			Err:   true,
  1285  
  1286  			GetKey:   "ports",
  1287  			GetValue: []interface{}{},
  1288  		},
  1289  
  1290  		// #7: Set a list of maps
  1291  		{
  1292  			Schema: map[string]*Schema{
  1293  				"config_vars": &Schema{
  1294  					Type:     TypeList,
  1295  					Optional: true,
  1296  					Computed: true,
  1297  					Elem: &Schema{
  1298  						Type: TypeMap,
  1299  					},
  1300  				},
  1301  			},
  1302  
  1303  			State: nil,
  1304  
  1305  			Diff: nil,
  1306  
  1307  			Key: "config_vars",
  1308  			Value: []interface{}{
  1309  				map[string]interface{}{
  1310  					"foo": "bar",
  1311  				},
  1312  				map[string]interface{}{
  1313  					"bar": "baz",
  1314  				},
  1315  			},
  1316  			Err: false,
  1317  
  1318  			GetKey: "config_vars",
  1319  			GetValue: []interface{}{
  1320  				map[string]interface{}{
  1321  					"foo": "bar",
  1322  				},
  1323  				map[string]interface{}{
  1324  					"bar": "baz",
  1325  				},
  1326  			},
  1327  		},
  1328  
  1329  		// #8: Set, with list
  1330  		{
  1331  			Schema: map[string]*Schema{
  1332  				"ports": &Schema{
  1333  					Type:     TypeSet,
  1334  					Optional: true,
  1335  					Computed: true,
  1336  					Elem:     &Schema{Type: TypeInt},
  1337  					Set: func(a interface{}) int {
  1338  						return a.(int)
  1339  					},
  1340  				},
  1341  			},
  1342  
  1343  			State: &terraform.InstanceState{
  1344  				Attributes: map[string]string{
  1345  					"ports.#": "3",
  1346  					"ports.0": "100",
  1347  					"ports.1": "80",
  1348  					"ports.2": "80",
  1349  				},
  1350  			},
  1351  
  1352  			Key:   "ports",
  1353  			Value: []interface{}{100, 125, 125},
  1354  
  1355  			GetKey:   "ports",
  1356  			GetValue: []interface{}{100, 125},
  1357  		},
  1358  
  1359  		// #9: Set, with Set
  1360  		{
  1361  			Schema: map[string]*Schema{
  1362  				"ports": &Schema{
  1363  					Type:     TypeSet,
  1364  					Optional: true,
  1365  					Computed: true,
  1366  					Elem:     &Schema{Type: TypeInt},
  1367  					Set: func(a interface{}) int {
  1368  						return a.(int)
  1369  					},
  1370  				},
  1371  			},
  1372  
  1373  			State: &terraform.InstanceState{
  1374  				Attributes: map[string]string{
  1375  					"ports.#":   "3",
  1376  					"ports.100": "100",
  1377  					"ports.80":  "80",
  1378  					"ports.81":  "81",
  1379  				},
  1380  			},
  1381  
  1382  			Key: "ports",
  1383  			Value: &Set{
  1384  				m: map[int]interface{}{
  1385  					1: 1,
  1386  					2: 2,
  1387  				},
  1388  			},
  1389  
  1390  			GetKey:   "ports",
  1391  			GetValue: []interface{}{1, 2},
  1392  		},
  1393  
  1394  		// #10: Set single item
  1395  		{
  1396  			Schema: map[string]*Schema{
  1397  				"ports": &Schema{
  1398  					Type:     TypeSet,
  1399  					Optional: true,
  1400  					Computed: true,
  1401  					Elem:     &Schema{Type: TypeInt},
  1402  					Set: func(a interface{}) int {
  1403  						return a.(int)
  1404  					},
  1405  				},
  1406  			},
  1407  
  1408  			State: &terraform.InstanceState{
  1409  				Attributes: map[string]string{
  1410  					"ports.#":   "2",
  1411  					"ports.100": "100",
  1412  					"ports.80":  "80",
  1413  				},
  1414  			},
  1415  
  1416  			Key:   "ports.100",
  1417  			Value: 256,
  1418  			Err:   true,
  1419  
  1420  			GetKey:   "ports",
  1421  			GetValue: []interface{}{80, 100},
  1422  		},
  1423  
  1424  		// #11: Set with nested set
  1425  		{
  1426  			Schema: map[string]*Schema{
  1427  				"ports": &Schema{
  1428  					Type: TypeSet,
  1429  					Elem: &Resource{
  1430  						Schema: map[string]*Schema{
  1431  							"port": &Schema{
  1432  								Type: TypeInt,
  1433  							},
  1434  
  1435  							"set": &Schema{
  1436  								Type: TypeSet,
  1437  								Elem: &Schema{Type: TypeInt},
  1438  								Set: func(a interface{}) int {
  1439  									return a.(int)
  1440  								},
  1441  							},
  1442  						},
  1443  					},
  1444  					Set: func(a interface{}) int {
  1445  						return a.(map[string]interface{})["port"].(int)
  1446  					},
  1447  				},
  1448  			},
  1449  
  1450  			State: nil,
  1451  
  1452  			Key: "ports",
  1453  			Value: []interface{}{
  1454  				map[string]interface{}{
  1455  					"port": 80,
  1456  				},
  1457  			},
  1458  
  1459  			GetKey: "ports",
  1460  			GetValue: []interface{}{
  1461  				map[string]interface{}{
  1462  					"port": 80,
  1463  					"set":  []interface{}{},
  1464  				},
  1465  			},
  1466  
  1467  			GetPreProcess: func(v interface{}) interface{} {
  1468  				if v == nil {
  1469  					return v
  1470  				}
  1471  				s, ok := v.([]interface{})
  1472  				if !ok {
  1473  					return v
  1474  				}
  1475  				for _, v := range s {
  1476  					m, ok := v.(map[string]interface{})
  1477  					if !ok {
  1478  						continue
  1479  					}
  1480  					if m["set"] == nil {
  1481  						continue
  1482  					}
  1483  					if s, ok := m["set"].(*Set); ok {
  1484  						m["set"] = s.List()
  1485  					}
  1486  				}
  1487  
  1488  				return v
  1489  			},
  1490  		},
  1491  
  1492  		// #12: List of floats, set list
  1493  		{
  1494  			Schema: map[string]*Schema{
  1495  				"ratios": &Schema{
  1496  					Type:     TypeList,
  1497  					Computed: true,
  1498  					Elem:     &Schema{Type: TypeFloat},
  1499  				},
  1500  			},
  1501  
  1502  			State: nil,
  1503  
  1504  			Diff: nil,
  1505  
  1506  			Key:   "ratios",
  1507  			Value: []float64{1.0, 2.2, 5.5},
  1508  
  1509  			GetKey:   "ratios",
  1510  			GetValue: []interface{}{1.0, 2.2, 5.5},
  1511  		},
  1512  
  1513  		// #12: Set of floats, set list
  1514  		{
  1515  			Schema: map[string]*Schema{
  1516  				"ratios": &Schema{
  1517  					Type:     TypeSet,
  1518  					Computed: true,
  1519  					Elem:     &Schema{Type: TypeFloat},
  1520  					Set: func(a interface{}) int {
  1521  						return int(math.Float64bits(a.(float64)))
  1522  					},
  1523  				},
  1524  			},
  1525  
  1526  			State: nil,
  1527  
  1528  			Diff: nil,
  1529  
  1530  			Key:   "ratios",
  1531  			Value: []float64{1.0, 2.2, 5.5},
  1532  
  1533  			GetKey:   "ratios",
  1534  			GetValue: []interface{}{1.0, 2.2, 5.5},
  1535  		},
  1536  
  1537  	}
  1538  
  1539  	for i, tc := range cases {
  1540  		d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff)
  1541  		if err != nil {
  1542  			t.Fatalf("err: %s", err)
  1543  		}
  1544  
  1545  		err = d.Set(tc.Key, tc.Value)
  1546  		if (err != nil) != tc.Err {
  1547  			t.Fatalf("%d err: %s", i, err)
  1548  		}
  1549  
  1550  		v := d.Get(tc.GetKey)
  1551  		if s, ok := v.(*Set); ok {
  1552  			v = s.List()
  1553  		}
  1554  
  1555  		if tc.GetPreProcess != nil {
  1556  			v = tc.GetPreProcess(v)
  1557  		}
  1558  
  1559  		if !reflect.DeepEqual(v, tc.GetValue) {
  1560  			t.Fatalf("Get Bad: %d\n\n%#v", i, v)
  1561  		}
  1562  	}
  1563  }
  1564  
  1565  func TestResourceDataState(t *testing.T) {
  1566  	cases := []struct {
  1567  		Schema  map[string]*Schema
  1568  		State   *terraform.InstanceState
  1569  		Diff    *terraform.InstanceDiff
  1570  		Set     map[string]interface{}
  1571  		Result  *terraform.InstanceState
  1572  		Partial []string
  1573  	}{
  1574  		// #0 Basic primitive in diff
  1575  		{
  1576  			Schema: map[string]*Schema{
  1577  				"availability_zone": &Schema{
  1578  					Type:     TypeString,
  1579  					Optional: true,
  1580  					Computed: true,
  1581  					ForceNew: true,
  1582  				},
  1583  			},
  1584  
  1585  			State: nil,
  1586  
  1587  			Diff: &terraform.InstanceDiff{
  1588  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1589  					"availability_zone": &terraform.ResourceAttrDiff{
  1590  						Old:         "",
  1591  						New:         "foo",
  1592  						RequiresNew: true,
  1593  					},
  1594  				},
  1595  			},
  1596  
  1597  			Result: &terraform.InstanceState{
  1598  				Attributes: map[string]string{
  1599  					"availability_zone": "foo",
  1600  				},
  1601  			},
  1602  		},
  1603  
  1604  		// #1 Basic primitive set override
  1605  		{
  1606  			Schema: map[string]*Schema{
  1607  				"availability_zone": &Schema{
  1608  					Type:     TypeString,
  1609  					Optional: true,
  1610  					Computed: true,
  1611  					ForceNew: true,
  1612  				},
  1613  			},
  1614  
  1615  			State: nil,
  1616  
  1617  			Diff: &terraform.InstanceDiff{
  1618  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1619  					"availability_zone": &terraform.ResourceAttrDiff{
  1620  						Old:         "",
  1621  						New:         "foo",
  1622  						RequiresNew: true,
  1623  					},
  1624  				},
  1625  			},
  1626  
  1627  			Set: map[string]interface{}{
  1628  				"availability_zone": "bar",
  1629  			},
  1630  
  1631  			Result: &terraform.InstanceState{
  1632  				Attributes: map[string]string{
  1633  					"availability_zone": "bar",
  1634  				},
  1635  			},
  1636  		},
  1637  
  1638  		// #2
  1639  		{
  1640  			Schema: map[string]*Schema{
  1641  				"vpc": &Schema{
  1642  					Type:     TypeBool,
  1643  					Optional: true,
  1644  				},
  1645  			},
  1646  
  1647  			State: nil,
  1648  
  1649  			Diff: nil,
  1650  
  1651  			Set: map[string]interface{}{
  1652  				"vpc": true,
  1653  			},
  1654  
  1655  			Result: &terraform.InstanceState{
  1656  				Attributes: map[string]string{
  1657  					"vpc": "true",
  1658  				},
  1659  			},
  1660  		},
  1661  
  1662  		// #3 Basic primitive with StateFunc set
  1663  		{
  1664  			Schema: map[string]*Schema{
  1665  				"availability_zone": &Schema{
  1666  					Type:      TypeString,
  1667  					Optional:  true,
  1668  					Computed:  true,
  1669  					StateFunc: func(interface{}) string { return "" },
  1670  				},
  1671  			},
  1672  
  1673  			State: nil,
  1674  
  1675  			Diff: &terraform.InstanceDiff{
  1676  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1677  					"availability_zone": &terraform.ResourceAttrDiff{
  1678  						Old:      "",
  1679  						New:      "foo",
  1680  						NewExtra: "foo!",
  1681  					},
  1682  				},
  1683  			},
  1684  
  1685  			Result: &terraform.InstanceState{
  1686  				Attributes: map[string]string{
  1687  					"availability_zone": "foo",
  1688  				},
  1689  			},
  1690  		},
  1691  
  1692  		// #4 List
  1693  		{
  1694  			Schema: map[string]*Schema{
  1695  				"ports": &Schema{
  1696  					Type:     TypeList,
  1697  					Required: true,
  1698  					Elem:     &Schema{Type: TypeInt},
  1699  				},
  1700  			},
  1701  
  1702  			State: &terraform.InstanceState{
  1703  				Attributes: map[string]string{
  1704  					"ports.#": "1",
  1705  					"ports.0": "80",
  1706  				},
  1707  			},
  1708  
  1709  			Diff: &terraform.InstanceDiff{
  1710  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1711  					"ports.#": &terraform.ResourceAttrDiff{
  1712  						Old: "1",
  1713  						New: "2",
  1714  					},
  1715  					"ports.1": &terraform.ResourceAttrDiff{
  1716  						Old: "",
  1717  						New: "100",
  1718  					},
  1719  				},
  1720  			},
  1721  
  1722  			Result: &terraform.InstanceState{
  1723  				Attributes: map[string]string{
  1724  					"ports.#": "2",
  1725  					"ports.0": "80",
  1726  					"ports.1": "100",
  1727  				},
  1728  			},
  1729  		},
  1730  
  1731  		// #5 List of resources
  1732  		{
  1733  			Schema: map[string]*Schema{
  1734  				"ingress": &Schema{
  1735  					Type:     TypeList,
  1736  					Required: true,
  1737  					Elem: &Resource{
  1738  						Schema: map[string]*Schema{
  1739  							"from": &Schema{
  1740  								Type:     TypeInt,
  1741  								Required: true,
  1742  							},
  1743  						},
  1744  					},
  1745  				},
  1746  			},
  1747  
  1748  			State: &terraform.InstanceState{
  1749  				Attributes: map[string]string{
  1750  					"ingress.#":      "1",
  1751  					"ingress.0.from": "80",
  1752  				},
  1753  			},
  1754  
  1755  			Diff: &terraform.InstanceDiff{
  1756  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1757  					"ingress.#": &terraform.ResourceAttrDiff{
  1758  						Old: "1",
  1759  						New: "2",
  1760  					},
  1761  					"ingress.0.from": &terraform.ResourceAttrDiff{
  1762  						Old: "80",
  1763  						New: "150",
  1764  					},
  1765  					"ingress.1.from": &terraform.ResourceAttrDiff{
  1766  						Old: "",
  1767  						New: "100",
  1768  					},
  1769  				},
  1770  			},
  1771  
  1772  			Result: &terraform.InstanceState{
  1773  				Attributes: map[string]string{
  1774  					"ingress.#":      "2",
  1775  					"ingress.0.from": "150",
  1776  					"ingress.1.from": "100",
  1777  				},
  1778  			},
  1779  		},
  1780  
  1781  		// #6 List of maps
  1782  		{
  1783  			Schema: map[string]*Schema{
  1784  				"config_vars": &Schema{
  1785  					Type:     TypeList,
  1786  					Optional: true,
  1787  					Computed: true,
  1788  					Elem: &Schema{
  1789  						Type: TypeMap,
  1790  					},
  1791  				},
  1792  			},
  1793  
  1794  			State: &terraform.InstanceState{
  1795  				Attributes: map[string]string{
  1796  					"config_vars.#":     "2",
  1797  					"config_vars.0.#":   "2",
  1798  					"config_vars.0.foo": "bar",
  1799  					"config_vars.0.bar": "bar",
  1800  					"config_vars.1.#":   "1",
  1801  					"config_vars.1.bar": "baz",
  1802  				},
  1803  			},
  1804  
  1805  			Diff: &terraform.InstanceDiff{
  1806  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1807  					"config_vars.0.bar": &terraform.ResourceAttrDiff{
  1808  						NewRemoved: true,
  1809  					},
  1810  				},
  1811  			},
  1812  
  1813  			Set: map[string]interface{}{
  1814  				"config_vars": []map[string]interface{}{
  1815  					map[string]interface{}{
  1816  						"foo": "bar",
  1817  					},
  1818  					map[string]interface{}{
  1819  						"baz": "bang",
  1820  					},
  1821  				},
  1822  			},
  1823  
  1824  			Result: &terraform.InstanceState{
  1825  				Attributes: map[string]string{
  1826  					"config_vars.#":     "2",
  1827  					"config_vars.0.#":   "1",
  1828  					"config_vars.0.foo": "bar",
  1829  					"config_vars.1.#":   "1",
  1830  					"config_vars.1.baz": "bang",
  1831  				},
  1832  			},
  1833  		},
  1834  
  1835  		// #7 List of maps with removal in diff
  1836  		{
  1837  			Schema: map[string]*Schema{
  1838  				"config_vars": &Schema{
  1839  					Type:     TypeList,
  1840  					Optional: true,
  1841  					Computed: true,
  1842  					Elem: &Schema{
  1843  						Type: TypeMap,
  1844  					},
  1845  				},
  1846  			},
  1847  
  1848  			State: &terraform.InstanceState{
  1849  				Attributes: map[string]string{
  1850  					"config_vars.#":     "1",
  1851  					"config_vars.0.FOO": "bar",
  1852  				},
  1853  			},
  1854  
  1855  			Diff: &terraform.InstanceDiff{
  1856  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1857  					"config_vars.#": &terraform.ResourceAttrDiff{
  1858  						Old: "1",
  1859  						New: "0",
  1860  					},
  1861  					"config_vars.0.FOO": &terraform.ResourceAttrDiff{
  1862  						Old:        "bar",
  1863  						NewRemoved: true,
  1864  					},
  1865  				},
  1866  			},
  1867  
  1868  			Result: &terraform.InstanceState{
  1869  				Attributes: map[string]string{
  1870  					"config_vars.#": "0",
  1871  				},
  1872  			},
  1873  		},
  1874  
  1875  		// #8 Basic state with other keys
  1876  		{
  1877  			Schema: map[string]*Schema{
  1878  				"availability_zone": &Schema{
  1879  					Type:     TypeString,
  1880  					Optional: true,
  1881  					Computed: true,
  1882  					ForceNew: true,
  1883  				},
  1884  			},
  1885  
  1886  			State: &terraform.InstanceState{
  1887  				ID: "bar",
  1888  				Attributes: map[string]string{
  1889  					"id": "bar",
  1890  				},
  1891  			},
  1892  
  1893  			Diff: &terraform.InstanceDiff{
  1894  				Attributes: map[string]*terraform.ResourceAttrDiff{
  1895  					"availability_zone": &terraform.ResourceAttrDiff{
  1896  						Old:         "",
  1897  						New:         "foo",
  1898  						RequiresNew: true,
  1899  					},
  1900  				},
  1901  			},
  1902  
  1903  			Result: &terraform.InstanceState{
  1904  				ID: "bar",
  1905  				Attributes: map[string]string{
  1906  					"id":                "bar",
  1907  					"availability_zone": "foo",
  1908  				},
  1909  			},
  1910  		},
  1911  
  1912  		// #9 Sets
  1913  		{
  1914  			Schema: map[string]*Schema{
  1915  				"ports": &Schema{
  1916  					Type:     TypeSet,
  1917  					Optional: true,
  1918  					Computed: true,
  1919  					Elem:     &Schema{Type: TypeInt},
  1920  					Set: func(a interface{}) int {
  1921  						return a.(int)
  1922  					},
  1923  				},
  1924  			},
  1925  
  1926  			State: &terraform.InstanceState{
  1927  				Attributes: map[string]string{
  1928  					"ports.#":   "3",
  1929  					"ports.100": "100",
  1930  					"ports.80":  "80",
  1931  					"ports.81":  "81",
  1932  				},
  1933  			},
  1934  
  1935  			Diff: nil,
  1936  
  1937  			Result: &terraform.InstanceState{
  1938  				Attributes: map[string]string{
  1939  					"ports.#":   "3",
  1940  					"ports.80":  "80",
  1941  					"ports.81":  "81",
  1942  					"ports.100": "100",
  1943  				},
  1944  			},
  1945  		},
  1946  
  1947  		// #10
  1948  		{
  1949  			Schema: map[string]*Schema{
  1950  				"ports": &Schema{
  1951  					Type:     TypeSet,
  1952  					Optional: true,
  1953  					Computed: true,
  1954  					Elem:     &Schema{Type: TypeInt},
  1955  					Set: func(a interface{}) int {
  1956  						return a.(int)
  1957  					},
  1958  				},
  1959  			},
  1960  
  1961  			State: nil,
  1962  
  1963  			Diff: nil,
  1964  
  1965  			Set: map[string]interface{}{
  1966  				"ports": []interface{}{100, 80},
  1967  			},
  1968  
  1969  			Result: &terraform.InstanceState{
  1970  				Attributes: map[string]string{
  1971  					"ports.#":   "2",
  1972  					"ports.80":  "80",
  1973  					"ports.100": "100",
  1974  				},
  1975  			},
  1976  		},
  1977  
  1978  		// #11
  1979  		{
  1980  			Schema: map[string]*Schema{
  1981  				"ports": &Schema{
  1982  					Type:     TypeSet,
  1983  					Optional: true,
  1984  					Computed: true,
  1985  					Elem: &Resource{
  1986  						Schema: map[string]*Schema{
  1987  							"order": &Schema{
  1988  								Type: TypeInt,
  1989  							},
  1990  
  1991  							"a": &Schema{
  1992  								Type: TypeList,
  1993  								Elem: &Schema{Type: TypeInt},
  1994  							},
  1995  
  1996  							"b": &Schema{
  1997  								Type: TypeList,
  1998  								Elem: &Schema{Type: TypeInt},
  1999  							},
  2000  						},
  2001  					},
  2002  					Set: func(a interface{}) int {
  2003  						m := a.(map[string]interface{})
  2004  						return m["order"].(int)
  2005  					},
  2006  				},
  2007  			},
  2008  
  2009  			State: &terraform.InstanceState{
  2010  				Attributes: map[string]string{
  2011  					"ports.#":        "2",
  2012  					"ports.10.order": "10",
  2013  					"ports.10.a.#":   "1",
  2014  					"ports.10.a.0":   "80",
  2015  					"ports.20.order": "20",
  2016  					"ports.20.b.#":   "1",
  2017  					"ports.20.b.0":   "100",
  2018  				},
  2019  			},
  2020  
  2021  			Set: map[string]interface{}{
  2022  				"ports": []interface{}{
  2023  					map[string]interface{}{
  2024  						"order": 20,
  2025  						"b":     []interface{}{100},
  2026  					},
  2027  					map[string]interface{}{
  2028  						"order": 10,
  2029  						"a":     []interface{}{80},
  2030  					},
  2031  				},
  2032  			},
  2033  
  2034  			Result: &terraform.InstanceState{
  2035  				Attributes: map[string]string{
  2036  					"ports.#":        "2",
  2037  					"ports.10.order": "10",
  2038  					"ports.10.a.#":   "1",
  2039  					"ports.10.a.0":   "80",
  2040  					"ports.10.b.#":   "0",
  2041  					"ports.20.order": "20",
  2042  					"ports.20.a.#":   "0",
  2043  					"ports.20.b.#":   "1",
  2044  					"ports.20.b.0":   "100",
  2045  				},
  2046  			},
  2047  		},
  2048  
  2049  		/*
  2050  		 * PARTIAL STATES
  2051  		 */
  2052  
  2053  		// #12 Basic primitive
  2054  		{
  2055  			Schema: map[string]*Schema{
  2056  				"availability_zone": &Schema{
  2057  					Type:     TypeString,
  2058  					Optional: true,
  2059  					Computed: true,
  2060  					ForceNew: true,
  2061  				},
  2062  			},
  2063  
  2064  			State: nil,
  2065  
  2066  			Diff: &terraform.InstanceDiff{
  2067  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2068  					"availability_zone": &terraform.ResourceAttrDiff{
  2069  						Old:         "",
  2070  						New:         "foo",
  2071  						RequiresNew: true,
  2072  					},
  2073  				},
  2074  			},
  2075  
  2076  			Partial: []string{},
  2077  
  2078  			Result: &terraform.InstanceState{
  2079  				Attributes: map[string]string{},
  2080  			},
  2081  		},
  2082  
  2083  		// #13 List
  2084  		{
  2085  			Schema: map[string]*Schema{
  2086  				"ports": &Schema{
  2087  					Type:     TypeList,
  2088  					Required: true,
  2089  					Elem:     &Schema{Type: TypeInt},
  2090  				},
  2091  			},
  2092  
  2093  			State: &terraform.InstanceState{
  2094  				Attributes: map[string]string{
  2095  					"ports.#": "1",
  2096  					"ports.0": "80",
  2097  				},
  2098  			},
  2099  
  2100  			Diff: &terraform.InstanceDiff{
  2101  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2102  					"ports.#": &terraform.ResourceAttrDiff{
  2103  						Old: "1",
  2104  						New: "2",
  2105  					},
  2106  					"ports.1": &terraform.ResourceAttrDiff{
  2107  						Old: "",
  2108  						New: "100",
  2109  					},
  2110  				},
  2111  			},
  2112  
  2113  			Partial: []string{},
  2114  
  2115  			Result: &terraform.InstanceState{
  2116  				Attributes: map[string]string{
  2117  					"ports.#": "1",
  2118  					"ports.0": "80",
  2119  				},
  2120  			},
  2121  		},
  2122  
  2123  		// #14
  2124  		{
  2125  			Schema: map[string]*Schema{
  2126  				"ports": &Schema{
  2127  					Type:     TypeList,
  2128  					Optional: true,
  2129  					Computed: true,
  2130  					Elem:     &Schema{Type: TypeInt},
  2131  				},
  2132  			},
  2133  
  2134  			State: nil,
  2135  
  2136  			Diff: &terraform.InstanceDiff{
  2137  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2138  					"ports.#": &terraform.ResourceAttrDiff{
  2139  						Old:         "",
  2140  						NewComputed: true,
  2141  					},
  2142  				},
  2143  			},
  2144  
  2145  			Partial: []string{},
  2146  
  2147  			Set: map[string]interface{}{
  2148  				"ports": []interface{}{},
  2149  			},
  2150  
  2151  			Result: &terraform.InstanceState{
  2152  				Attributes: map[string]string{},
  2153  			},
  2154  		},
  2155  
  2156  		// #15 List of resources
  2157  		{
  2158  			Schema: map[string]*Schema{
  2159  				"ingress": &Schema{
  2160  					Type:     TypeList,
  2161  					Required: true,
  2162  					Elem: &Resource{
  2163  						Schema: map[string]*Schema{
  2164  							"from": &Schema{
  2165  								Type:     TypeInt,
  2166  								Required: true,
  2167  							},
  2168  						},
  2169  					},
  2170  				},
  2171  			},
  2172  
  2173  			State: &terraform.InstanceState{
  2174  				Attributes: map[string]string{
  2175  					"ingress.#":      "1",
  2176  					"ingress.0.from": "80",
  2177  				},
  2178  			},
  2179  
  2180  			Diff: &terraform.InstanceDiff{
  2181  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2182  					"ingress.#": &terraform.ResourceAttrDiff{
  2183  						Old: "1",
  2184  						New: "2",
  2185  					},
  2186  					"ingress.0.from": &terraform.ResourceAttrDiff{
  2187  						Old: "80",
  2188  						New: "150",
  2189  					},
  2190  					"ingress.1.from": &terraform.ResourceAttrDiff{
  2191  						Old: "",
  2192  						New: "100",
  2193  					},
  2194  				},
  2195  			},
  2196  
  2197  			Partial: []string{},
  2198  
  2199  			Result: &terraform.InstanceState{
  2200  				Attributes: map[string]string{
  2201  					"ingress.#":      "1",
  2202  					"ingress.0.from": "80",
  2203  				},
  2204  			},
  2205  		},
  2206  
  2207  		// #16 List of maps
  2208  		{
  2209  			Schema: map[string]*Schema{
  2210  				"config_vars": &Schema{
  2211  					Type:     TypeList,
  2212  					Optional: true,
  2213  					Computed: true,
  2214  					Elem: &Schema{
  2215  						Type: TypeMap,
  2216  					},
  2217  				},
  2218  			},
  2219  
  2220  			State: &terraform.InstanceState{
  2221  				Attributes: map[string]string{
  2222  					"config_vars.#":     "2",
  2223  					"config_vars.0.foo": "bar",
  2224  					"config_vars.0.bar": "bar",
  2225  					"config_vars.1.bar": "baz",
  2226  				},
  2227  			},
  2228  
  2229  			Diff: &terraform.InstanceDiff{
  2230  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2231  					"config_vars.0.bar": &terraform.ResourceAttrDiff{
  2232  						NewRemoved: true,
  2233  					},
  2234  				},
  2235  			},
  2236  
  2237  			Set: map[string]interface{}{
  2238  				"config_vars": []map[string]interface{}{
  2239  					map[string]interface{}{
  2240  						"foo": "bar",
  2241  					},
  2242  					map[string]interface{}{
  2243  						"baz": "bang",
  2244  					},
  2245  				},
  2246  			},
  2247  
  2248  			Partial: []string{},
  2249  
  2250  			Result: &terraform.InstanceState{
  2251  				Attributes: map[string]string{
  2252  					// TODO: broken, shouldn't bar be removed?
  2253  					"config_vars.#":     "2",
  2254  					"config_vars.0.#":   "2",
  2255  					"config_vars.0.foo": "bar",
  2256  					"config_vars.0.bar": "bar",
  2257  					"config_vars.1.#":   "1",
  2258  					"config_vars.1.bar": "baz",
  2259  				},
  2260  			},
  2261  		},
  2262  
  2263  		// #17 Sets
  2264  		{
  2265  			Schema: map[string]*Schema{
  2266  				"ports": &Schema{
  2267  					Type:     TypeSet,
  2268  					Optional: true,
  2269  					Computed: true,
  2270  					Elem:     &Schema{Type: TypeInt},
  2271  					Set: func(a interface{}) int {
  2272  						return a.(int)
  2273  					},
  2274  				},
  2275  			},
  2276  
  2277  			State: &terraform.InstanceState{
  2278  				Attributes: map[string]string{
  2279  					"ports.#":   "3",
  2280  					"ports.100": "100",
  2281  					"ports.80":  "80",
  2282  					"ports.81":  "81",
  2283  				},
  2284  			},
  2285  
  2286  			Diff: &terraform.InstanceDiff{
  2287  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2288  					"ports.120": &terraform.ResourceAttrDiff{
  2289  						New: "120",
  2290  					},
  2291  				},
  2292  			},
  2293  
  2294  			Partial: []string{},
  2295  
  2296  			Result: &terraform.InstanceState{
  2297  				Attributes: map[string]string{
  2298  					"ports.#":   "3",
  2299  					"ports.80":  "80",
  2300  					"ports.81":  "81",
  2301  					"ports.100": "100",
  2302  				},
  2303  			},
  2304  		},
  2305  
  2306  		// #18
  2307  		{
  2308  			Schema: map[string]*Schema{
  2309  				"ports": &Schema{
  2310  					Type:     TypeSet,
  2311  					Optional: true,
  2312  					Computed: true,
  2313  					Elem:     &Schema{Type: TypeInt},
  2314  					Set: func(a interface{}) int {
  2315  						return a.(int)
  2316  					},
  2317  				},
  2318  			},
  2319  
  2320  			State: nil,
  2321  
  2322  			Diff: &terraform.InstanceDiff{
  2323  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2324  					"ports.#": &terraform.ResourceAttrDiff{
  2325  						Old:         "",
  2326  						NewComputed: true,
  2327  					},
  2328  				},
  2329  			},
  2330  
  2331  			Partial: []string{},
  2332  
  2333  			Result: &terraform.InstanceState{
  2334  				Attributes: map[string]string{},
  2335  			},
  2336  		},
  2337  
  2338  		// #19 Maps
  2339  		{
  2340  			Schema: map[string]*Schema{
  2341  				"tags": &Schema{
  2342  					Type:     TypeMap,
  2343  					Optional: true,
  2344  					Computed: true,
  2345  				},
  2346  			},
  2347  
  2348  			State: nil,
  2349  
  2350  			Diff: &terraform.InstanceDiff{
  2351  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2352  					"tags.Name": &terraform.ResourceAttrDiff{
  2353  						Old: "",
  2354  						New: "foo",
  2355  					},
  2356  				},
  2357  			},
  2358  
  2359  			Result: &terraform.InstanceState{
  2360  				Attributes: map[string]string{
  2361  					"tags.#":    "1",
  2362  					"tags.Name": "foo",
  2363  				},
  2364  			},
  2365  		},
  2366  
  2367  		// #20
  2368  		{
  2369  			Schema: map[string]*Schema{
  2370  				"tags": &Schema{
  2371  					Type:     TypeMap,
  2372  					Optional: true,
  2373  					Computed: true,
  2374  				},
  2375  			},
  2376  
  2377  			State: nil,
  2378  
  2379  			Diff: &terraform.InstanceDiff{
  2380  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2381  					"tags.Name": &terraform.ResourceAttrDiff{
  2382  						Old: "",
  2383  						New: "foo",
  2384  					},
  2385  				},
  2386  			},
  2387  
  2388  			Set: map[string]interface{}{
  2389  				"tags": map[string]string{},
  2390  			},
  2391  
  2392  			Result: &terraform.InstanceState{
  2393  				Attributes: map[string]string{},
  2394  			},
  2395  		},
  2396  
  2397  		// #21
  2398  		{
  2399  			Schema: map[string]*Schema{
  2400  				"foo": &Schema{
  2401  					Type:     TypeString,
  2402  					Optional: true,
  2403  					Computed: true,
  2404  				},
  2405  			},
  2406  
  2407  			State: nil,
  2408  
  2409  			Diff: &terraform.InstanceDiff{
  2410  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2411  					"foo": &terraform.ResourceAttrDiff{
  2412  						NewComputed: true,
  2413  					},
  2414  				},
  2415  			},
  2416  
  2417  			Result: &terraform.InstanceState{
  2418  				Attributes: map[string]string{},
  2419  			},
  2420  		},
  2421  
  2422  		// #22
  2423  		{
  2424  			Schema: map[string]*Schema{
  2425  				"foo": &Schema{
  2426  					Type:     TypeString,
  2427  					Optional: true,
  2428  					Computed: true,
  2429  				},
  2430  			},
  2431  
  2432  			State: nil,
  2433  
  2434  			Diff: &terraform.InstanceDiff{
  2435  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2436  					"foo": &terraform.ResourceAttrDiff{
  2437  						NewComputed: true,
  2438  					},
  2439  				},
  2440  			},
  2441  
  2442  			Set: map[string]interface{}{
  2443  				"foo": "bar",
  2444  			},
  2445  
  2446  			Result: &terraform.InstanceState{
  2447  				Attributes: map[string]string{
  2448  					"foo": "bar",
  2449  				},
  2450  			},
  2451  		},
  2452  
  2453  		// #23 Set of maps
  2454  		{
  2455  			Schema: map[string]*Schema{
  2456  				"ports": &Schema{
  2457  					Type:     TypeSet,
  2458  					Optional: true,
  2459  					Computed: true,
  2460  					Elem: &Resource{
  2461  						Schema: map[string]*Schema{
  2462  							"index": &Schema{Type: TypeInt},
  2463  							"uuids": &Schema{Type: TypeMap},
  2464  						},
  2465  					},
  2466  					Set: func(a interface{}) int {
  2467  						m := a.(map[string]interface{})
  2468  						return m["index"].(int)
  2469  					},
  2470  				},
  2471  			},
  2472  
  2473  			State: nil,
  2474  
  2475  			Diff: &terraform.InstanceDiff{
  2476  				Attributes: map[string]*terraform.ResourceAttrDiff{
  2477  					"ports.10.uuids.#": &terraform.ResourceAttrDiff{
  2478  						NewComputed: true,
  2479  					},
  2480  				},
  2481  			},
  2482  
  2483  			Set: map[string]interface{}{
  2484  				"ports": []interface{}{
  2485  					map[string]interface{}{
  2486  						"index": 10,
  2487  						"uuids": map[string]interface{}{
  2488  							"80": "value",
  2489  						},
  2490  					},
  2491  				},
  2492  			},
  2493  
  2494  			Result: &terraform.InstanceState{
  2495  				Attributes: map[string]string{
  2496  					"ports.#":           "1",
  2497  					"ports.10.index":    "10",
  2498  					"ports.10.uuids.#":  "1",
  2499  					"ports.10.uuids.80": "value",
  2500  				},
  2501  			},
  2502  		},
  2503  	}
  2504  
  2505  	for i, tc := range cases {
  2506  		d, err := schemaMap(tc.Schema).Data(tc.State, tc.Diff)
  2507  		if err != nil {
  2508  			t.Fatalf("err: %s", err)
  2509  		}
  2510  
  2511  		for k, v := range tc.Set {
  2512  			if err := d.Set(k, v); err != nil {
  2513  				t.Fatalf("%d err: %s", i, err)
  2514  			}
  2515  		}
  2516  
  2517  		// Set an ID so that the state returned is not nil
  2518  		idSet := false
  2519  		if d.Id() == "" {
  2520  			idSet = true
  2521  			d.SetId("foo")
  2522  		}
  2523  
  2524  		// If we have partial, then enable partial state mode.
  2525  		if tc.Partial != nil {
  2526  			d.Partial(true)
  2527  			for _, k := range tc.Partial {
  2528  				d.SetPartial(k)
  2529  			}
  2530  		}
  2531  
  2532  		actual := d.State()
  2533  
  2534  		// If we set an ID, then undo what we did so the comparison works
  2535  		if actual != nil && idSet {
  2536  			actual.ID = ""
  2537  			delete(actual.Attributes, "id")
  2538  		}
  2539  
  2540  		if !reflect.DeepEqual(actual, tc.Result) {
  2541  			t.Fatalf("Bad: %d\n\n%#v\n\nExpected:\n\n%#v", i, actual, tc.Result)
  2542  		}
  2543  	}
  2544  }
  2545  
  2546  func TestResourceDataSetConnInfo(t *testing.T) {
  2547  	d := &ResourceData{}
  2548  	d.SetId("foo")
  2549  	d.SetConnInfo(map[string]string{
  2550  		"foo": "bar",
  2551  	})
  2552  
  2553  	expected := map[string]string{
  2554  		"foo": "bar",
  2555  	}
  2556  
  2557  	actual := d.State()
  2558  	if !reflect.DeepEqual(actual.Ephemeral.ConnInfo, expected) {
  2559  		t.Fatalf("bad: %#v", actual)
  2560  	}
  2561  }
  2562  
  2563  func TestResourceDataSetId(t *testing.T) {
  2564  	d := &ResourceData{}
  2565  	d.SetId("foo")
  2566  
  2567  	actual := d.State()
  2568  	if actual.ID != "foo" {
  2569  		t.Fatalf("bad: %#v", actual)
  2570  	}
  2571  }
  2572  
  2573  func TestResourceDataSetId_clear(t *testing.T) {
  2574  	d := &ResourceData{
  2575  		state: &terraform.InstanceState{ID: "bar"},
  2576  	}
  2577  	d.SetId("")
  2578  
  2579  	actual := d.State()
  2580  	if actual != nil {
  2581  		t.Fatalf("bad: %#v", actual)
  2582  	}
  2583  }
  2584  
  2585  func TestResourceDataSetId_override(t *testing.T) {
  2586  	d := &ResourceData{
  2587  		state: &terraform.InstanceState{ID: "bar"},
  2588  	}
  2589  	d.SetId("foo")
  2590  
  2591  	actual := d.State()
  2592  	if actual.ID != "foo" {
  2593  		t.Fatalf("bad: %#v", actual)
  2594  	}
  2595  }