github.com/trawler/terraform@v0.10.8-0.20171106022149-4b1c7a1d9b48/terraform/state_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"os"
     8  	"reflect"
     9  	"sort"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/hashicorp/terraform/config"
    14  )
    15  
    16  func TestStateValidate(t *testing.T) {
    17  	cases := map[string]struct {
    18  		In  *State
    19  		Err bool
    20  	}{
    21  		"empty state": {
    22  			&State{},
    23  			false,
    24  		},
    25  
    26  		"multiple modules": {
    27  			&State{
    28  				Modules: []*ModuleState{
    29  					&ModuleState{
    30  						Path: []string{"root", "foo"},
    31  					},
    32  					&ModuleState{
    33  						Path: []string{"root", "foo"},
    34  					},
    35  				},
    36  			},
    37  			true,
    38  		},
    39  	}
    40  
    41  	for name, tc := range cases {
    42  		// Init the state
    43  		tc.In.init()
    44  
    45  		err := tc.In.Validate()
    46  		if (err != nil) != tc.Err {
    47  			t.Fatalf("%s: err: %s", name, err)
    48  		}
    49  	}
    50  }
    51  
    52  func TestStateAddModule(t *testing.T) {
    53  	cases := []struct {
    54  		In  [][]string
    55  		Out [][]string
    56  	}{
    57  		{
    58  			[][]string{
    59  				[]string{"root"},
    60  				[]string{"root", "child"},
    61  			},
    62  			[][]string{
    63  				[]string{"root"},
    64  				[]string{"root", "child"},
    65  			},
    66  		},
    67  
    68  		{
    69  			[][]string{
    70  				[]string{"root", "foo", "bar"},
    71  				[]string{"root", "foo"},
    72  				[]string{"root"},
    73  				[]string{"root", "bar"},
    74  			},
    75  			[][]string{
    76  				[]string{"root"},
    77  				[]string{"root", "bar"},
    78  				[]string{"root", "foo"},
    79  				[]string{"root", "foo", "bar"},
    80  			},
    81  		},
    82  		// Same last element, different middle element
    83  		{
    84  			[][]string{
    85  				[]string{"root", "foo", "bar"}, // This one should sort after...
    86  				[]string{"root", "foo"},
    87  				[]string{"root"},
    88  				[]string{"root", "bar", "bar"}, // ...this one.
    89  				[]string{"root", "bar"},
    90  			},
    91  			[][]string{
    92  				[]string{"root"},
    93  				[]string{"root", "bar"},
    94  				[]string{"root", "foo"},
    95  				[]string{"root", "bar", "bar"},
    96  				[]string{"root", "foo", "bar"},
    97  			},
    98  		},
    99  	}
   100  
   101  	for _, tc := range cases {
   102  		s := new(State)
   103  		for _, p := range tc.In {
   104  			s.AddModule(p)
   105  		}
   106  
   107  		actual := make([][]string, 0, len(tc.In))
   108  		for _, m := range s.Modules {
   109  			actual = append(actual, m.Path)
   110  		}
   111  
   112  		if !reflect.DeepEqual(actual, tc.Out) {
   113  			t.Fatalf("In: %#v\n\nOut: %#v", tc.In, actual)
   114  		}
   115  	}
   116  }
   117  
   118  func TestStateOutputTypeRoundTrip(t *testing.T) {
   119  	state := &State{
   120  		Modules: []*ModuleState{
   121  			&ModuleState{
   122  				Path: RootModulePath,
   123  				Outputs: map[string]*OutputState{
   124  					"string_output": &OutputState{
   125  						Value: "String Value",
   126  						Type:  "string",
   127  					},
   128  				},
   129  			},
   130  		},
   131  	}
   132  	state.init()
   133  
   134  	buf := new(bytes.Buffer)
   135  	if err := WriteState(state, buf); err != nil {
   136  		t.Fatalf("err: %s", err)
   137  	}
   138  
   139  	roundTripped, err := ReadState(buf)
   140  	if err != nil {
   141  		t.Fatalf("err: %s", err)
   142  	}
   143  
   144  	if !reflect.DeepEqual(state, roundTripped) {
   145  		t.Logf("expected:\n%#v", state)
   146  		t.Fatalf("got:\n%#v", roundTripped)
   147  	}
   148  }
   149  
   150  func TestStateModuleOrphans(t *testing.T) {
   151  	state := &State{
   152  		Modules: []*ModuleState{
   153  			&ModuleState{
   154  				Path: RootModulePath,
   155  			},
   156  			&ModuleState{
   157  				Path: []string{RootModuleName, "foo"},
   158  			},
   159  			&ModuleState{
   160  				Path: []string{RootModuleName, "bar"},
   161  			},
   162  		},
   163  	}
   164  
   165  	state.init()
   166  
   167  	config := testModule(t, "state-module-orphans").Config()
   168  	actual := state.ModuleOrphans(RootModulePath, config)
   169  	expected := [][]string{
   170  		[]string{RootModuleName, "foo"},
   171  	}
   172  
   173  	if !reflect.DeepEqual(actual, expected) {
   174  		t.Fatalf("bad: %#v", actual)
   175  	}
   176  }
   177  
   178  func TestStateModuleOrphans_nested(t *testing.T) {
   179  	state := &State{
   180  		Modules: []*ModuleState{
   181  			&ModuleState{
   182  				Path: RootModulePath,
   183  			},
   184  			&ModuleState{
   185  				Path: []string{RootModuleName, "foo", "bar"},
   186  			},
   187  		},
   188  	}
   189  
   190  	state.init()
   191  
   192  	actual := state.ModuleOrphans(RootModulePath, nil)
   193  	expected := [][]string{
   194  		[]string{RootModuleName, "foo"},
   195  	}
   196  
   197  	if !reflect.DeepEqual(actual, expected) {
   198  		t.Fatalf("bad: %#v", actual)
   199  	}
   200  }
   201  
   202  func TestStateModuleOrphans_nilConfig(t *testing.T) {
   203  	state := &State{
   204  		Modules: []*ModuleState{
   205  			&ModuleState{
   206  				Path: RootModulePath,
   207  			},
   208  			&ModuleState{
   209  				Path: []string{RootModuleName, "foo"},
   210  			},
   211  			&ModuleState{
   212  				Path: []string{RootModuleName, "bar"},
   213  			},
   214  		},
   215  	}
   216  
   217  	state.init()
   218  
   219  	actual := state.ModuleOrphans(RootModulePath, nil)
   220  	expected := [][]string{
   221  		[]string{RootModuleName, "foo"},
   222  		[]string{RootModuleName, "bar"},
   223  	}
   224  
   225  	if !reflect.DeepEqual(actual, expected) {
   226  		t.Fatalf("bad: %#v", actual)
   227  	}
   228  }
   229  
   230  func TestStateModuleOrphans_deepNestedNilConfig(t *testing.T) {
   231  	state := &State{
   232  		Modules: []*ModuleState{
   233  			&ModuleState{
   234  				Path: RootModulePath,
   235  			},
   236  			&ModuleState{
   237  				Path: []string{RootModuleName, "parent", "childfoo"},
   238  			},
   239  			&ModuleState{
   240  				Path: []string{RootModuleName, "parent", "childbar"},
   241  			},
   242  		},
   243  	}
   244  
   245  	state.init()
   246  
   247  	actual := state.ModuleOrphans(RootModulePath, nil)
   248  	expected := [][]string{
   249  		[]string{RootModuleName, "parent"},
   250  	}
   251  
   252  	if !reflect.DeepEqual(actual, expected) {
   253  		t.Fatalf("bad: %#v", actual)
   254  	}
   255  }
   256  
   257  func TestStateDeepCopy(t *testing.T) {
   258  	cases := []struct {
   259  		State *State
   260  	}{
   261  		// Nil
   262  		{nil},
   263  
   264  		// Version
   265  		{
   266  			&State{Version: 5},
   267  		},
   268  		// TFVersion
   269  		{
   270  			&State{TFVersion: "5"},
   271  		},
   272  		// Modules
   273  		{
   274  			&State{
   275  				Version: 6,
   276  				Modules: []*ModuleState{
   277  					&ModuleState{
   278  						Path: rootModulePath,
   279  						Resources: map[string]*ResourceState{
   280  							"test_instance.foo": &ResourceState{
   281  								Primary: &InstanceState{
   282  									Meta: map[string]interface{}{},
   283  								},
   284  							},
   285  						},
   286  					},
   287  				},
   288  			},
   289  		},
   290  		// Deposed
   291  		// The nil values shouldn't be there if the State was properly init'ed,
   292  		// but the Copy should still work anyway.
   293  		{
   294  			&State{
   295  				Version: 6,
   296  				Modules: []*ModuleState{
   297  					&ModuleState{
   298  						Path: rootModulePath,
   299  						Resources: map[string]*ResourceState{
   300  							"test_instance.foo": &ResourceState{
   301  								Primary: &InstanceState{
   302  									Meta: map[string]interface{}{},
   303  								},
   304  								Deposed: []*InstanceState{
   305  									{ID: "test"},
   306  									nil,
   307  								},
   308  							},
   309  						},
   310  					},
   311  				},
   312  			},
   313  		},
   314  	}
   315  
   316  	for i, tc := range cases {
   317  		t.Run(fmt.Sprintf("copy-%d", i), func(t *testing.T) {
   318  			actual := tc.State.DeepCopy()
   319  			expected := tc.State
   320  			if !reflect.DeepEqual(actual, expected) {
   321  				t.Fatalf("Expected: %#v\nRecevied: %#v\n", expected, actual)
   322  			}
   323  		})
   324  	}
   325  }
   326  
   327  func TestStateEqual(t *testing.T) {
   328  	cases := []struct {
   329  		Name     string
   330  		Result   bool
   331  		One, Two *State
   332  	}{
   333  		// Nils
   334  		{
   335  			"one nil",
   336  			false,
   337  			nil,
   338  			&State{Version: 2},
   339  		},
   340  
   341  		{
   342  			"both nil",
   343  			true,
   344  			nil,
   345  			nil,
   346  		},
   347  
   348  		// Different versions
   349  		{
   350  			"different state versions",
   351  			false,
   352  			&State{Version: 5},
   353  			&State{Version: 2},
   354  		},
   355  
   356  		// Different modules
   357  		{
   358  			"different module states",
   359  			false,
   360  			&State{
   361  				Modules: []*ModuleState{
   362  					&ModuleState{
   363  						Path: RootModulePath,
   364  					},
   365  				},
   366  			},
   367  			&State{},
   368  		},
   369  
   370  		{
   371  			"same module states",
   372  			true,
   373  			&State{
   374  				Modules: []*ModuleState{
   375  					&ModuleState{
   376  						Path: RootModulePath,
   377  					},
   378  				},
   379  			},
   380  			&State{
   381  				Modules: []*ModuleState{
   382  					&ModuleState{
   383  						Path: RootModulePath,
   384  					},
   385  				},
   386  			},
   387  		},
   388  
   389  		// Meta differs
   390  		{
   391  			"differing meta values with primitives",
   392  			false,
   393  			&State{
   394  				Modules: []*ModuleState{
   395  					&ModuleState{
   396  						Path: rootModulePath,
   397  						Resources: map[string]*ResourceState{
   398  							"test_instance.foo": &ResourceState{
   399  								Primary: &InstanceState{
   400  									Meta: map[string]interface{}{
   401  										"schema_version": "1",
   402  									},
   403  								},
   404  							},
   405  						},
   406  					},
   407  				},
   408  			},
   409  			&State{
   410  				Modules: []*ModuleState{
   411  					&ModuleState{
   412  						Path: rootModulePath,
   413  						Resources: map[string]*ResourceState{
   414  							"test_instance.foo": &ResourceState{
   415  								Primary: &InstanceState{
   416  									Meta: map[string]interface{}{
   417  										"schema_version": "2",
   418  									},
   419  								},
   420  							},
   421  						},
   422  					},
   423  				},
   424  			},
   425  		},
   426  
   427  		// Meta with complex types
   428  		{
   429  			"same meta with complex types",
   430  			true,
   431  			&State{
   432  				Modules: []*ModuleState{
   433  					&ModuleState{
   434  						Path: rootModulePath,
   435  						Resources: map[string]*ResourceState{
   436  							"test_instance.foo": &ResourceState{
   437  								Primary: &InstanceState{
   438  									Meta: map[string]interface{}{
   439  										"timeouts": map[string]interface{}{
   440  											"create": 42,
   441  											"read":   "27",
   442  										},
   443  									},
   444  								},
   445  							},
   446  						},
   447  					},
   448  				},
   449  			},
   450  			&State{
   451  				Modules: []*ModuleState{
   452  					&ModuleState{
   453  						Path: rootModulePath,
   454  						Resources: map[string]*ResourceState{
   455  							"test_instance.foo": &ResourceState{
   456  								Primary: &InstanceState{
   457  									Meta: map[string]interface{}{
   458  										"timeouts": map[string]interface{}{
   459  											"create": 42,
   460  											"read":   "27",
   461  										},
   462  									},
   463  								},
   464  							},
   465  						},
   466  					},
   467  				},
   468  			},
   469  		},
   470  
   471  		// Meta with complex types that have been altered during serialization
   472  		{
   473  			"same meta with complex types that have been json-ified",
   474  			true,
   475  			&State{
   476  				Modules: []*ModuleState{
   477  					&ModuleState{
   478  						Path: rootModulePath,
   479  						Resources: map[string]*ResourceState{
   480  							"test_instance.foo": &ResourceState{
   481  								Primary: &InstanceState{
   482  									Meta: map[string]interface{}{
   483  										"timeouts": map[string]interface{}{
   484  											"create": int(42),
   485  											"read":   "27",
   486  										},
   487  									},
   488  								},
   489  							},
   490  						},
   491  					},
   492  				},
   493  			},
   494  			&State{
   495  				Modules: []*ModuleState{
   496  					&ModuleState{
   497  						Path: rootModulePath,
   498  						Resources: map[string]*ResourceState{
   499  							"test_instance.foo": &ResourceState{
   500  								Primary: &InstanceState{
   501  									Meta: map[string]interface{}{
   502  										"timeouts": map[string]interface{}{
   503  											"create": float64(42),
   504  											"read":   "27",
   505  										},
   506  									},
   507  								},
   508  							},
   509  						},
   510  					},
   511  				},
   512  			},
   513  		},
   514  	}
   515  
   516  	for i, tc := range cases {
   517  		t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
   518  			if tc.One.Equal(tc.Two) != tc.Result {
   519  				t.Fatalf("Bad: %d\n\n%s\n\n%s", i, tc.One.String(), tc.Two.String())
   520  			}
   521  			if tc.Two.Equal(tc.One) != tc.Result {
   522  				t.Fatalf("Bad: %d\n\n%s\n\n%s", i, tc.One.String(), tc.Two.String())
   523  			}
   524  		})
   525  	}
   526  }
   527  
   528  func TestStateCompareAges(t *testing.T) {
   529  	cases := []struct {
   530  		Result   StateAgeComparison
   531  		Err      bool
   532  		One, Two *State
   533  	}{
   534  		{
   535  			StateAgeEqual, false,
   536  			&State{
   537  				Lineage: "1",
   538  				Serial:  2,
   539  			},
   540  			&State{
   541  				Lineage: "1",
   542  				Serial:  2,
   543  			},
   544  		},
   545  		{
   546  			StateAgeReceiverOlder, false,
   547  			&State{
   548  				Lineage: "1",
   549  				Serial:  2,
   550  			},
   551  			&State{
   552  				Lineage: "1",
   553  				Serial:  3,
   554  			},
   555  		},
   556  		{
   557  			StateAgeReceiverNewer, false,
   558  			&State{
   559  				Lineage: "1",
   560  				Serial:  3,
   561  			},
   562  			&State{
   563  				Lineage: "1",
   564  				Serial:  2,
   565  			},
   566  		},
   567  		{
   568  			StateAgeEqual, true,
   569  			&State{
   570  				Lineage: "1",
   571  				Serial:  2,
   572  			},
   573  			&State{
   574  				Lineage: "2",
   575  				Serial:  2,
   576  			},
   577  		},
   578  		{
   579  			StateAgeEqual, true,
   580  			&State{
   581  				Lineage: "1",
   582  				Serial:  3,
   583  			},
   584  			&State{
   585  				Lineage: "2",
   586  				Serial:  2,
   587  			},
   588  		},
   589  	}
   590  
   591  	for i, tc := range cases {
   592  		result, err := tc.One.CompareAges(tc.Two)
   593  
   594  		if err != nil && !tc.Err {
   595  			t.Errorf(
   596  				"%d: got error, but want success\n\n%s\n\n%s",
   597  				i, tc.One, tc.Two,
   598  			)
   599  			continue
   600  		}
   601  
   602  		if err == nil && tc.Err {
   603  			t.Errorf(
   604  				"%d: got success, but want error\n\n%s\n\n%s",
   605  				i, tc.One, tc.Two,
   606  			)
   607  			continue
   608  		}
   609  
   610  		if result != tc.Result {
   611  			t.Errorf(
   612  				"%d: got result %d, but want %d\n\n%s\n\n%s",
   613  				i, result, tc.Result, tc.One, tc.Two,
   614  			)
   615  			continue
   616  		}
   617  	}
   618  }
   619  
   620  func TestStateSameLineage(t *testing.T) {
   621  	cases := []struct {
   622  		Result   bool
   623  		One, Two *State
   624  	}{
   625  		{
   626  			true,
   627  			&State{
   628  				Lineage: "1",
   629  			},
   630  			&State{
   631  				Lineage: "1",
   632  			},
   633  		},
   634  		{
   635  			// Empty lineage is compatible with all
   636  			true,
   637  			&State{
   638  				Lineage: "",
   639  			},
   640  			&State{
   641  				Lineage: "1",
   642  			},
   643  		},
   644  		{
   645  			// Empty lineage is compatible with all
   646  			true,
   647  			&State{
   648  				Lineage: "1",
   649  			},
   650  			&State{
   651  				Lineage: "",
   652  			},
   653  		},
   654  		{
   655  			false,
   656  			&State{
   657  				Lineage: "1",
   658  			},
   659  			&State{
   660  				Lineage: "2",
   661  			},
   662  		},
   663  	}
   664  
   665  	for i, tc := range cases {
   666  		result := tc.One.SameLineage(tc.Two)
   667  
   668  		if result != tc.Result {
   669  			t.Errorf(
   670  				"%d: got %v, but want %v\n\n%s\n\n%s",
   671  				i, result, tc.Result, tc.One, tc.Two,
   672  			)
   673  			continue
   674  		}
   675  	}
   676  }
   677  
   678  func TestStateMarshalEqual(t *testing.T) {
   679  	tests := map[string]struct {
   680  		S1, S2 *State
   681  		Want   bool
   682  	}{
   683  		"both nil": {
   684  			nil,
   685  			nil,
   686  			true,
   687  		},
   688  		"first zero, second nil": {
   689  			&State{},
   690  			nil,
   691  			false,
   692  		},
   693  		"first nil, second zero": {
   694  			nil,
   695  			&State{},
   696  			false,
   697  		},
   698  		"both zero": {
   699  			// These are not equal because they both implicitly init with
   700  			// different lineage.
   701  			&State{},
   702  			&State{},
   703  			false,
   704  		},
   705  		"both set, same lineage": {
   706  			&State{
   707  				Lineage: "abc123",
   708  			},
   709  			&State{
   710  				Lineage: "abc123",
   711  			},
   712  			true,
   713  		},
   714  		"both set, same lineage, different serial": {
   715  			&State{
   716  				Lineage: "abc123",
   717  				Serial:  1,
   718  			},
   719  			&State{
   720  				Lineage: "abc123",
   721  				Serial:  2,
   722  			},
   723  			false,
   724  		},
   725  		"both set, same lineage, same serial, same resources": {
   726  			&State{
   727  				Lineage: "abc123",
   728  				Serial:  1,
   729  				Modules: []*ModuleState{
   730  					{
   731  						Path: []string{"root"},
   732  						Resources: map[string]*ResourceState{
   733  							"foo_bar.baz": {},
   734  						},
   735  					},
   736  				},
   737  			},
   738  			&State{
   739  				Lineage: "abc123",
   740  				Serial:  1,
   741  				Modules: []*ModuleState{
   742  					{
   743  						Path: []string{"root"},
   744  						Resources: map[string]*ResourceState{
   745  							"foo_bar.baz": {},
   746  						},
   747  					},
   748  				},
   749  			},
   750  			true,
   751  		},
   752  		"both set, same lineage, same serial, different resources": {
   753  			&State{
   754  				Lineage: "abc123",
   755  				Serial:  1,
   756  				Modules: []*ModuleState{
   757  					{
   758  						Path: []string{"root"},
   759  						Resources: map[string]*ResourceState{
   760  							"foo_bar.baz": {},
   761  						},
   762  					},
   763  				},
   764  			},
   765  			&State{
   766  				Lineage: "abc123",
   767  				Serial:  1,
   768  				Modules: []*ModuleState{
   769  					{
   770  						Path: []string{"root"},
   771  						Resources: map[string]*ResourceState{
   772  							"pizza_crust.tasty": {},
   773  						},
   774  					},
   775  				},
   776  			},
   777  			false,
   778  		},
   779  	}
   780  
   781  	for name, test := range tests {
   782  		t.Run(name, func(t *testing.T) {
   783  			got := test.S1.MarshalEqual(test.S2)
   784  			if got != test.Want {
   785  				t.Errorf("wrong result %#v; want %#v", got, test.Want)
   786  				s1Buf := &bytes.Buffer{}
   787  				s2Buf := &bytes.Buffer{}
   788  				_ = WriteState(test.S1, s1Buf)
   789  				_ = WriteState(test.S2, s2Buf)
   790  				t.Logf("\nState 1: %s\nState 2: %s", s1Buf.Bytes(), s2Buf.Bytes())
   791  			}
   792  		})
   793  	}
   794  }
   795  
   796  func TestStateRemove(t *testing.T) {
   797  	cases := map[string]struct {
   798  		Address  string
   799  		One, Two *State
   800  	}{
   801  		"simple resource": {
   802  			"test_instance.foo",
   803  			&State{
   804  				Modules: []*ModuleState{
   805  					&ModuleState{
   806  						Path: rootModulePath,
   807  						Resources: map[string]*ResourceState{
   808  							"test_instance.foo": &ResourceState{
   809  								Type: "test_instance",
   810  								Primary: &InstanceState{
   811  									ID: "foo",
   812  								},
   813  							},
   814  
   815  							"test_instance.bar": &ResourceState{
   816  								Type: "test_instance",
   817  								Primary: &InstanceState{
   818  									ID: "foo",
   819  								},
   820  							},
   821  						},
   822  					},
   823  				},
   824  			},
   825  			&State{
   826  				Modules: []*ModuleState{
   827  					&ModuleState{
   828  						Path: rootModulePath,
   829  						Resources: map[string]*ResourceState{
   830  							"test_instance.bar": &ResourceState{
   831  								Type: "test_instance",
   832  								Primary: &InstanceState{
   833  									ID: "foo",
   834  								},
   835  							},
   836  						},
   837  					},
   838  				},
   839  			},
   840  		},
   841  
   842  		"single instance": {
   843  			"test_instance.foo.primary",
   844  			&State{
   845  				Modules: []*ModuleState{
   846  					&ModuleState{
   847  						Path: rootModulePath,
   848  						Resources: map[string]*ResourceState{
   849  							"test_instance.foo": &ResourceState{
   850  								Type: "test_instance",
   851  								Primary: &InstanceState{
   852  									ID: "foo",
   853  								},
   854  							},
   855  						},
   856  					},
   857  				},
   858  			},
   859  			&State{
   860  				Modules: []*ModuleState{
   861  					&ModuleState{
   862  						Path:      rootModulePath,
   863  						Resources: map[string]*ResourceState{},
   864  					},
   865  				},
   866  			},
   867  		},
   868  
   869  		"single instance in multi-count": {
   870  			"test_instance.foo[0]",
   871  			&State{
   872  				Modules: []*ModuleState{
   873  					&ModuleState{
   874  						Path: rootModulePath,
   875  						Resources: map[string]*ResourceState{
   876  							"test_instance.foo.0": &ResourceState{
   877  								Type: "test_instance",
   878  								Primary: &InstanceState{
   879  									ID: "foo",
   880  								},
   881  							},
   882  
   883  							"test_instance.foo.1": &ResourceState{
   884  								Type: "test_instance",
   885  								Primary: &InstanceState{
   886  									ID: "foo",
   887  								},
   888  							},
   889  						},
   890  					},
   891  				},
   892  			},
   893  			&State{
   894  				Modules: []*ModuleState{
   895  					&ModuleState{
   896  						Path: rootModulePath,
   897  						Resources: map[string]*ResourceState{
   898  							"test_instance.foo.1": &ResourceState{
   899  								Type: "test_instance",
   900  								Primary: &InstanceState{
   901  									ID: "foo",
   902  								},
   903  							},
   904  						},
   905  					},
   906  				},
   907  			},
   908  		},
   909  
   910  		"single resource, multi-count": {
   911  			"test_instance.foo",
   912  			&State{
   913  				Modules: []*ModuleState{
   914  					&ModuleState{
   915  						Path: rootModulePath,
   916  						Resources: map[string]*ResourceState{
   917  							"test_instance.foo.0": &ResourceState{
   918  								Type: "test_instance",
   919  								Primary: &InstanceState{
   920  									ID: "foo",
   921  								},
   922  							},
   923  
   924  							"test_instance.foo.1": &ResourceState{
   925  								Type: "test_instance",
   926  								Primary: &InstanceState{
   927  									ID: "foo",
   928  								},
   929  							},
   930  						},
   931  					},
   932  				},
   933  			},
   934  			&State{
   935  				Modules: []*ModuleState{
   936  					&ModuleState{
   937  						Path:      rootModulePath,
   938  						Resources: map[string]*ResourceState{},
   939  					},
   940  				},
   941  			},
   942  		},
   943  
   944  		"full module": {
   945  			"module.foo",
   946  			&State{
   947  				Modules: []*ModuleState{
   948  					&ModuleState{
   949  						Path: rootModulePath,
   950  						Resources: map[string]*ResourceState{
   951  							"test_instance.foo": &ResourceState{
   952  								Type: "test_instance",
   953  								Primary: &InstanceState{
   954  									ID: "foo",
   955  								},
   956  							},
   957  						},
   958  					},
   959  
   960  					&ModuleState{
   961  						Path: []string{"root", "foo"},
   962  						Resources: map[string]*ResourceState{
   963  							"test_instance.foo": &ResourceState{
   964  								Type: "test_instance",
   965  								Primary: &InstanceState{
   966  									ID: "foo",
   967  								},
   968  							},
   969  
   970  							"test_instance.bar": &ResourceState{
   971  								Type: "test_instance",
   972  								Primary: &InstanceState{
   973  									ID: "foo",
   974  								},
   975  							},
   976  						},
   977  					},
   978  				},
   979  			},
   980  			&State{
   981  				Modules: []*ModuleState{
   982  					&ModuleState{
   983  						Path: rootModulePath,
   984  						Resources: map[string]*ResourceState{
   985  							"test_instance.foo": &ResourceState{
   986  								Type: "test_instance",
   987  								Primary: &InstanceState{
   988  									ID: "foo",
   989  								},
   990  							},
   991  						},
   992  					},
   993  				},
   994  			},
   995  		},
   996  
   997  		"module and children": {
   998  			"module.foo",
   999  			&State{
  1000  				Modules: []*ModuleState{
  1001  					&ModuleState{
  1002  						Path: rootModulePath,
  1003  						Resources: map[string]*ResourceState{
  1004  							"test_instance.foo": &ResourceState{
  1005  								Type: "test_instance",
  1006  								Primary: &InstanceState{
  1007  									ID: "foo",
  1008  								},
  1009  							},
  1010  						},
  1011  					},
  1012  
  1013  					&ModuleState{
  1014  						Path: []string{"root", "foo"},
  1015  						Resources: map[string]*ResourceState{
  1016  							"test_instance.foo": &ResourceState{
  1017  								Type: "test_instance",
  1018  								Primary: &InstanceState{
  1019  									ID: "foo",
  1020  								},
  1021  							},
  1022  
  1023  							"test_instance.bar": &ResourceState{
  1024  								Type: "test_instance",
  1025  								Primary: &InstanceState{
  1026  									ID: "foo",
  1027  								},
  1028  							},
  1029  						},
  1030  					},
  1031  
  1032  					&ModuleState{
  1033  						Path: []string{"root", "foo", "bar"},
  1034  						Resources: map[string]*ResourceState{
  1035  							"test_instance.foo": &ResourceState{
  1036  								Type: "test_instance",
  1037  								Primary: &InstanceState{
  1038  									ID: "foo",
  1039  								},
  1040  							},
  1041  
  1042  							"test_instance.bar": &ResourceState{
  1043  								Type: "test_instance",
  1044  								Primary: &InstanceState{
  1045  									ID: "foo",
  1046  								},
  1047  							},
  1048  						},
  1049  					},
  1050  				},
  1051  			},
  1052  			&State{
  1053  				Modules: []*ModuleState{
  1054  					&ModuleState{
  1055  						Path: rootModulePath,
  1056  						Resources: map[string]*ResourceState{
  1057  							"test_instance.foo": &ResourceState{
  1058  								Type: "test_instance",
  1059  								Primary: &InstanceState{
  1060  									ID: "foo",
  1061  								},
  1062  							},
  1063  						},
  1064  					},
  1065  				},
  1066  			},
  1067  		},
  1068  	}
  1069  
  1070  	for k, tc := range cases {
  1071  		if err := tc.One.Remove(tc.Address); err != nil {
  1072  			t.Fatalf("bad: %s\n\n%s", k, err)
  1073  		}
  1074  
  1075  		if !tc.One.Equal(tc.Two) {
  1076  			t.Fatalf("Bad: %s\n\n%s\n\n%s", k, tc.One.String(), tc.Two.String())
  1077  		}
  1078  	}
  1079  }
  1080  
  1081  func TestResourceStateEqual(t *testing.T) {
  1082  	cases := []struct {
  1083  		Result   bool
  1084  		One, Two *ResourceState
  1085  	}{
  1086  		// Different types
  1087  		{
  1088  			false,
  1089  			&ResourceState{Type: "foo"},
  1090  			&ResourceState{Type: "bar"},
  1091  		},
  1092  
  1093  		// Different dependencies
  1094  		{
  1095  			false,
  1096  			&ResourceState{Dependencies: []string{"foo"}},
  1097  			&ResourceState{Dependencies: []string{"bar"}},
  1098  		},
  1099  
  1100  		{
  1101  			false,
  1102  			&ResourceState{Dependencies: []string{"foo", "bar"}},
  1103  			&ResourceState{Dependencies: []string{"foo"}},
  1104  		},
  1105  
  1106  		{
  1107  			true,
  1108  			&ResourceState{Dependencies: []string{"bar", "foo"}},
  1109  			&ResourceState{Dependencies: []string{"foo", "bar"}},
  1110  		},
  1111  
  1112  		// Different primaries
  1113  		{
  1114  			false,
  1115  			&ResourceState{Primary: nil},
  1116  			&ResourceState{Primary: &InstanceState{ID: "foo"}},
  1117  		},
  1118  
  1119  		{
  1120  			true,
  1121  			&ResourceState{Primary: &InstanceState{ID: "foo"}},
  1122  			&ResourceState{Primary: &InstanceState{ID: "foo"}},
  1123  		},
  1124  
  1125  		// Different tainted
  1126  		{
  1127  			false,
  1128  			&ResourceState{
  1129  				Primary: &InstanceState{
  1130  					ID: "foo",
  1131  				},
  1132  			},
  1133  			&ResourceState{
  1134  				Primary: &InstanceState{
  1135  					ID:      "foo",
  1136  					Tainted: true,
  1137  				},
  1138  			},
  1139  		},
  1140  
  1141  		{
  1142  			true,
  1143  			&ResourceState{
  1144  				Primary: &InstanceState{
  1145  					ID:      "foo",
  1146  					Tainted: true,
  1147  				},
  1148  			},
  1149  			&ResourceState{
  1150  				Primary: &InstanceState{
  1151  					ID:      "foo",
  1152  					Tainted: true,
  1153  				},
  1154  			},
  1155  		},
  1156  	}
  1157  
  1158  	for i, tc := range cases {
  1159  		if tc.One.Equal(tc.Two) != tc.Result {
  1160  			t.Fatalf("Bad: %d\n\n%s\n\n%s", i, tc.One.String(), tc.Two.String())
  1161  		}
  1162  		if tc.Two.Equal(tc.One) != tc.Result {
  1163  			t.Fatalf("Bad: %d\n\n%s\n\n%s", i, tc.One.String(), tc.Two.String())
  1164  		}
  1165  	}
  1166  }
  1167  
  1168  func TestResourceStateTaint(t *testing.T) {
  1169  	cases := map[string]struct {
  1170  		Input  *ResourceState
  1171  		Output *ResourceState
  1172  	}{
  1173  		"no primary": {
  1174  			&ResourceState{},
  1175  			&ResourceState{},
  1176  		},
  1177  
  1178  		"primary, not tainted": {
  1179  			&ResourceState{
  1180  				Primary: &InstanceState{ID: "foo"},
  1181  			},
  1182  			&ResourceState{
  1183  				Primary: &InstanceState{
  1184  					ID:      "foo",
  1185  					Tainted: true,
  1186  				},
  1187  			},
  1188  		},
  1189  
  1190  		"primary, tainted": {
  1191  			&ResourceState{
  1192  				Primary: &InstanceState{
  1193  					ID:      "foo",
  1194  					Tainted: true,
  1195  				},
  1196  			},
  1197  			&ResourceState{
  1198  				Primary: &InstanceState{
  1199  					ID:      "foo",
  1200  					Tainted: true,
  1201  				},
  1202  			},
  1203  		},
  1204  	}
  1205  
  1206  	for k, tc := range cases {
  1207  		tc.Input.Taint()
  1208  		if !reflect.DeepEqual(tc.Input, tc.Output) {
  1209  			t.Fatalf(
  1210  				"Failure: %s\n\nExpected: %#v\n\nGot: %#v",
  1211  				k, tc.Output, tc.Input)
  1212  		}
  1213  	}
  1214  }
  1215  
  1216  func TestResourceStateUntaint(t *testing.T) {
  1217  	cases := map[string]struct {
  1218  		Input          *ResourceState
  1219  		ExpectedOutput *ResourceState
  1220  	}{
  1221  		"no primary, err": {
  1222  			Input:          &ResourceState{},
  1223  			ExpectedOutput: &ResourceState{},
  1224  		},
  1225  
  1226  		"primary, not tainted": {
  1227  			Input: &ResourceState{
  1228  				Primary: &InstanceState{ID: "foo"},
  1229  			},
  1230  			ExpectedOutput: &ResourceState{
  1231  				Primary: &InstanceState{ID: "foo"},
  1232  			},
  1233  		},
  1234  		"primary, tainted": {
  1235  			Input: &ResourceState{
  1236  				Primary: &InstanceState{
  1237  					ID:      "foo",
  1238  					Tainted: true,
  1239  				},
  1240  			},
  1241  			ExpectedOutput: &ResourceState{
  1242  				Primary: &InstanceState{ID: "foo"},
  1243  			},
  1244  		},
  1245  	}
  1246  
  1247  	for k, tc := range cases {
  1248  		tc.Input.Untaint()
  1249  		if !reflect.DeepEqual(tc.Input, tc.ExpectedOutput) {
  1250  			t.Fatalf(
  1251  				"Failure: %s\n\nExpected: %#v\n\nGot: %#v",
  1252  				k, tc.ExpectedOutput, tc.Input)
  1253  		}
  1254  	}
  1255  }
  1256  
  1257  func TestInstanceStateEmpty(t *testing.T) {
  1258  	cases := map[string]struct {
  1259  		In     *InstanceState
  1260  		Result bool
  1261  	}{
  1262  		"nil is empty": {
  1263  			nil,
  1264  			true,
  1265  		},
  1266  		"non-nil but without ID is empty": {
  1267  			&InstanceState{},
  1268  			true,
  1269  		},
  1270  		"with ID is not empty": {
  1271  			&InstanceState{
  1272  				ID: "i-abc123",
  1273  			},
  1274  			false,
  1275  		},
  1276  	}
  1277  
  1278  	for tn, tc := range cases {
  1279  		if tc.In.Empty() != tc.Result {
  1280  			t.Fatalf("%q expected %#v to be empty: %#v", tn, tc.In, tc.Result)
  1281  		}
  1282  	}
  1283  }
  1284  
  1285  func TestInstanceStateEqual(t *testing.T) {
  1286  	cases := []struct {
  1287  		Result   bool
  1288  		One, Two *InstanceState
  1289  	}{
  1290  		// Nils
  1291  		{
  1292  			false,
  1293  			nil,
  1294  			&InstanceState{},
  1295  		},
  1296  
  1297  		{
  1298  			false,
  1299  			&InstanceState{},
  1300  			nil,
  1301  		},
  1302  
  1303  		// Different IDs
  1304  		{
  1305  			false,
  1306  			&InstanceState{ID: "foo"},
  1307  			&InstanceState{ID: "bar"},
  1308  		},
  1309  
  1310  		// Different Attributes
  1311  		{
  1312  			false,
  1313  			&InstanceState{Attributes: map[string]string{"foo": "bar"}},
  1314  			&InstanceState{Attributes: map[string]string{"foo": "baz"}},
  1315  		},
  1316  
  1317  		// Different Attribute keys
  1318  		{
  1319  			false,
  1320  			&InstanceState{Attributes: map[string]string{"foo": "bar"}},
  1321  			&InstanceState{Attributes: map[string]string{"bar": "baz"}},
  1322  		},
  1323  
  1324  		{
  1325  			false,
  1326  			&InstanceState{Attributes: map[string]string{"bar": "baz"}},
  1327  			&InstanceState{Attributes: map[string]string{"foo": "bar"}},
  1328  		},
  1329  	}
  1330  
  1331  	for i, tc := range cases {
  1332  		if tc.One.Equal(tc.Two) != tc.Result {
  1333  			t.Fatalf("Bad: %d\n\n%s\n\n%s", i, tc.One.String(), tc.Two.String())
  1334  		}
  1335  	}
  1336  }
  1337  
  1338  func TestStateEmpty(t *testing.T) {
  1339  	cases := []struct {
  1340  		In     *State
  1341  		Result bool
  1342  	}{
  1343  		{
  1344  			nil,
  1345  			true,
  1346  		},
  1347  		{
  1348  			&State{},
  1349  			true,
  1350  		},
  1351  		{
  1352  			&State{
  1353  				Remote: &RemoteState{Type: "foo"},
  1354  			},
  1355  			true,
  1356  		},
  1357  		{
  1358  			&State{
  1359  				Modules: []*ModuleState{
  1360  					&ModuleState{},
  1361  				},
  1362  			},
  1363  			false,
  1364  		},
  1365  	}
  1366  
  1367  	for i, tc := range cases {
  1368  		if tc.In.Empty() != tc.Result {
  1369  			t.Fatalf("bad %d %#v:\n\n%#v", i, tc.Result, tc.In)
  1370  		}
  1371  	}
  1372  }
  1373  
  1374  func TestStateHasResources(t *testing.T) {
  1375  	cases := []struct {
  1376  		In     *State
  1377  		Result bool
  1378  	}{
  1379  		{
  1380  			nil,
  1381  			false,
  1382  		},
  1383  		{
  1384  			&State{},
  1385  			false,
  1386  		},
  1387  		{
  1388  			&State{
  1389  				Remote: &RemoteState{Type: "foo"},
  1390  			},
  1391  			false,
  1392  		},
  1393  		{
  1394  			&State{
  1395  				Modules: []*ModuleState{
  1396  					&ModuleState{},
  1397  				},
  1398  			},
  1399  			false,
  1400  		},
  1401  		{
  1402  			&State{
  1403  				Modules: []*ModuleState{
  1404  					&ModuleState{},
  1405  					&ModuleState{},
  1406  				},
  1407  			},
  1408  			false,
  1409  		},
  1410  		{
  1411  			&State{
  1412  				Modules: []*ModuleState{
  1413  					&ModuleState{},
  1414  					&ModuleState{
  1415  						Resources: map[string]*ResourceState{
  1416  							"foo.foo": &ResourceState{},
  1417  						},
  1418  					},
  1419  				},
  1420  			},
  1421  			true,
  1422  		},
  1423  	}
  1424  
  1425  	for i, tc := range cases {
  1426  		if tc.In.HasResources() != tc.Result {
  1427  			t.Fatalf("bad %d %#v:\n\n%#v", i, tc.Result, tc.In)
  1428  		}
  1429  	}
  1430  }
  1431  
  1432  func TestStateFromFutureTerraform(t *testing.T) {
  1433  	cases := []struct {
  1434  		In     string
  1435  		Result bool
  1436  	}{
  1437  		{
  1438  			"",
  1439  			false,
  1440  		},
  1441  		{
  1442  			"0.1",
  1443  			false,
  1444  		},
  1445  		{
  1446  			"999.15.1",
  1447  			true,
  1448  		},
  1449  	}
  1450  
  1451  	for _, tc := range cases {
  1452  		state := &State{TFVersion: tc.In}
  1453  		actual := state.FromFutureTerraform()
  1454  		if actual != tc.Result {
  1455  			t.Fatalf("%s: bad: %v", tc.In, actual)
  1456  		}
  1457  	}
  1458  }
  1459  
  1460  func TestStateIsRemote(t *testing.T) {
  1461  	cases := []struct {
  1462  		In     *State
  1463  		Result bool
  1464  	}{
  1465  		{
  1466  			nil,
  1467  			false,
  1468  		},
  1469  		{
  1470  			&State{},
  1471  			false,
  1472  		},
  1473  		{
  1474  			&State{
  1475  				Remote: &RemoteState{Type: "foo"},
  1476  			},
  1477  			true,
  1478  		},
  1479  	}
  1480  
  1481  	for i, tc := range cases {
  1482  		if tc.In.IsRemote() != tc.Result {
  1483  			t.Fatalf("bad %d %#v:\n\n%#v", i, tc.Result, tc.In)
  1484  		}
  1485  	}
  1486  }
  1487  
  1488  func TestInstanceState_MergeDiff(t *testing.T) {
  1489  	is := InstanceState{
  1490  		ID: "foo",
  1491  		Attributes: map[string]string{
  1492  			"foo":  "bar",
  1493  			"port": "8000",
  1494  		},
  1495  	}
  1496  
  1497  	diff := &InstanceDiff{
  1498  		Attributes: map[string]*ResourceAttrDiff{
  1499  			"foo": &ResourceAttrDiff{
  1500  				Old: "bar",
  1501  				New: "baz",
  1502  			},
  1503  			"bar": &ResourceAttrDiff{
  1504  				Old: "",
  1505  				New: "foo",
  1506  			},
  1507  			"baz": &ResourceAttrDiff{
  1508  				Old:         "",
  1509  				New:         "foo",
  1510  				NewComputed: true,
  1511  			},
  1512  			"port": &ResourceAttrDiff{
  1513  				NewRemoved: true,
  1514  			},
  1515  		},
  1516  	}
  1517  
  1518  	is2 := is.MergeDiff(diff)
  1519  
  1520  	expected := map[string]string{
  1521  		"foo": "baz",
  1522  		"bar": "foo",
  1523  		"baz": config.UnknownVariableValue,
  1524  	}
  1525  
  1526  	if !reflect.DeepEqual(expected, is2.Attributes) {
  1527  		t.Fatalf("bad: %#v", is2.Attributes)
  1528  	}
  1529  }
  1530  
  1531  // GH-12183. This tests that a list with a computed set generates the
  1532  // right partial state. This never failed but is put here for completion
  1533  // of the test case for GH-12183.
  1534  func TestInstanceState_MergeDiff_computedSet(t *testing.T) {
  1535  	is := InstanceState{}
  1536  
  1537  	diff := &InstanceDiff{
  1538  		Attributes: map[string]*ResourceAttrDiff{
  1539  			"config.#": &ResourceAttrDiff{
  1540  				Old:         "0",
  1541  				New:         "1",
  1542  				RequiresNew: true,
  1543  			},
  1544  
  1545  			"config.0.name": &ResourceAttrDiff{
  1546  				Old: "",
  1547  				New: "hello",
  1548  			},
  1549  
  1550  			"config.0.rules.#": &ResourceAttrDiff{
  1551  				Old:         "",
  1552  				NewComputed: true,
  1553  			},
  1554  		},
  1555  	}
  1556  
  1557  	is2 := is.MergeDiff(diff)
  1558  
  1559  	expected := map[string]string{
  1560  		"config.#":         "1",
  1561  		"config.0.name":    "hello",
  1562  		"config.0.rules.#": config.UnknownVariableValue,
  1563  	}
  1564  
  1565  	if !reflect.DeepEqual(expected, is2.Attributes) {
  1566  		t.Fatalf("bad: %#v", is2.Attributes)
  1567  	}
  1568  }
  1569  
  1570  func TestInstanceState_MergeDiff_nil(t *testing.T) {
  1571  	var is *InstanceState
  1572  
  1573  	diff := &InstanceDiff{
  1574  		Attributes: map[string]*ResourceAttrDiff{
  1575  			"foo": &ResourceAttrDiff{
  1576  				Old: "",
  1577  				New: "baz",
  1578  			},
  1579  		},
  1580  	}
  1581  
  1582  	is2 := is.MergeDiff(diff)
  1583  
  1584  	expected := map[string]string{
  1585  		"foo": "baz",
  1586  	}
  1587  
  1588  	if !reflect.DeepEqual(expected, is2.Attributes) {
  1589  		t.Fatalf("bad: %#v", is2.Attributes)
  1590  	}
  1591  }
  1592  
  1593  func TestInstanceState_MergeDiff_nilDiff(t *testing.T) {
  1594  	is := InstanceState{
  1595  		ID: "foo",
  1596  		Attributes: map[string]string{
  1597  			"foo": "bar",
  1598  		},
  1599  	}
  1600  
  1601  	is2 := is.MergeDiff(nil)
  1602  
  1603  	expected := map[string]string{
  1604  		"foo": "bar",
  1605  	}
  1606  
  1607  	if !reflect.DeepEqual(expected, is2.Attributes) {
  1608  		t.Fatalf("bad: %#v", is2.Attributes)
  1609  	}
  1610  }
  1611  
  1612  func TestReadWriteState(t *testing.T) {
  1613  	state := &State{
  1614  		Serial:  9,
  1615  		Lineage: "5d1ad1a1-4027-4665-a908-dbe6adff11d8",
  1616  		Remote: &RemoteState{
  1617  			Type: "http",
  1618  			Config: map[string]string{
  1619  				"url": "http://my-cool-server.com/",
  1620  			},
  1621  		},
  1622  		Modules: []*ModuleState{
  1623  			&ModuleState{
  1624  				Path: rootModulePath,
  1625  				Dependencies: []string{
  1626  					"aws_instance.bar",
  1627  				},
  1628  				Resources: map[string]*ResourceState{
  1629  					"foo": &ResourceState{
  1630  						Primary: &InstanceState{
  1631  							ID: "bar",
  1632  							Ephemeral: EphemeralState{
  1633  								ConnInfo: map[string]string{
  1634  									"type":     "ssh",
  1635  									"user":     "root",
  1636  									"password": "supersecret",
  1637  								},
  1638  							},
  1639  						},
  1640  					},
  1641  				},
  1642  			},
  1643  		},
  1644  	}
  1645  	state.init()
  1646  
  1647  	buf := new(bytes.Buffer)
  1648  	if err := WriteState(state, buf); err != nil {
  1649  		t.Fatalf("err: %s", err)
  1650  	}
  1651  
  1652  	// Verify that the version and serial are set
  1653  	if state.Version != StateVersion {
  1654  		t.Fatalf("bad version number: %d", state.Version)
  1655  	}
  1656  
  1657  	actual, err := ReadState(buf)
  1658  	if err != nil {
  1659  		t.Fatalf("err: %s", err)
  1660  	}
  1661  
  1662  	// ReadState should not restore sensitive information!
  1663  	mod := state.RootModule()
  1664  	mod.Resources["foo"].Primary.Ephemeral = EphemeralState{}
  1665  	mod.Resources["foo"].Primary.Ephemeral.init()
  1666  
  1667  	if !reflect.DeepEqual(actual, state) {
  1668  		t.Logf("expected:\n%#v", state)
  1669  		t.Fatalf("got:\n%#v", actual)
  1670  	}
  1671  }
  1672  
  1673  func TestReadStateNewVersion(t *testing.T) {
  1674  	type out struct {
  1675  		Version int
  1676  	}
  1677  
  1678  	buf, err := json.Marshal(&out{StateVersion + 1})
  1679  	if err != nil {
  1680  		t.Fatalf("err: %v", err)
  1681  	}
  1682  
  1683  	s, err := ReadState(bytes.NewReader(buf))
  1684  	if s != nil {
  1685  		t.Fatalf("unexpected: %#v", s)
  1686  	}
  1687  	if !strings.Contains(err.Error(), "does not support state version") {
  1688  		t.Fatalf("err: %v", err)
  1689  	}
  1690  }
  1691  
  1692  func TestReadStateEmptyOrNilFile(t *testing.T) {
  1693  	var emptyState bytes.Buffer
  1694  	_, err := ReadState(&emptyState)
  1695  	if err != ErrNoState {
  1696  		t.Fatal("expected ErrNostate, got", err)
  1697  	}
  1698  
  1699  	var nilFile *os.File
  1700  	_, err = ReadState(nilFile)
  1701  	if err != ErrNoState {
  1702  		t.Fatal("expected ErrNostate, got", err)
  1703  	}
  1704  }
  1705  
  1706  func TestReadStateTFVersion(t *testing.T) {
  1707  	type tfVersion struct {
  1708  		Version   int    `json:"version"`
  1709  		TFVersion string `json:"terraform_version"`
  1710  	}
  1711  
  1712  	cases := []struct {
  1713  		Written string
  1714  		Read    string
  1715  		Err     bool
  1716  	}{
  1717  		{
  1718  			"0.0.0",
  1719  			"0.0.0",
  1720  			false,
  1721  		},
  1722  		{
  1723  			"",
  1724  			"",
  1725  			false,
  1726  		},
  1727  		{
  1728  			"bad",
  1729  			"",
  1730  			true,
  1731  		},
  1732  	}
  1733  
  1734  	for _, tc := range cases {
  1735  		buf, err := json.Marshal(&tfVersion{
  1736  			Version:   2,
  1737  			TFVersion: tc.Written,
  1738  		})
  1739  		if err != nil {
  1740  			t.Fatalf("err: %v", err)
  1741  		}
  1742  
  1743  		s, err := ReadState(bytes.NewReader(buf))
  1744  		if (err != nil) != tc.Err {
  1745  			t.Fatalf("%s: err: %s", tc.Written, err)
  1746  		}
  1747  		if err != nil {
  1748  			continue
  1749  		}
  1750  
  1751  		if s.TFVersion != tc.Read {
  1752  			t.Fatalf("%s: bad: %s", tc.Written, s.TFVersion)
  1753  		}
  1754  	}
  1755  }
  1756  
  1757  func TestWriteStateTFVersion(t *testing.T) {
  1758  	cases := []struct {
  1759  		Write string
  1760  		Read  string
  1761  		Err   bool
  1762  	}{
  1763  		{
  1764  			"0.0.0",
  1765  			"0.0.0",
  1766  			false,
  1767  		},
  1768  		{
  1769  			"",
  1770  			"",
  1771  			false,
  1772  		},
  1773  		{
  1774  			"bad",
  1775  			"",
  1776  			true,
  1777  		},
  1778  	}
  1779  
  1780  	for _, tc := range cases {
  1781  		var buf bytes.Buffer
  1782  		err := WriteState(&State{TFVersion: tc.Write}, &buf)
  1783  		if (err != nil) != tc.Err {
  1784  			t.Fatalf("%s: err: %s", tc.Write, err)
  1785  		}
  1786  		if err != nil {
  1787  			continue
  1788  		}
  1789  
  1790  		s, err := ReadState(&buf)
  1791  		if err != nil {
  1792  			t.Fatalf("%s: err: %s", tc.Write, err)
  1793  		}
  1794  
  1795  		if s.TFVersion != tc.Read {
  1796  			t.Fatalf("%s: bad: %s", tc.Write, s.TFVersion)
  1797  		}
  1798  	}
  1799  }
  1800  
  1801  func TestParseResourceStateKey(t *testing.T) {
  1802  	cases := []struct {
  1803  		Input       string
  1804  		Expected    *ResourceStateKey
  1805  		ExpectedErr bool
  1806  	}{
  1807  		{
  1808  			Input: "aws_instance.foo.3",
  1809  			Expected: &ResourceStateKey{
  1810  				Mode:  config.ManagedResourceMode,
  1811  				Type:  "aws_instance",
  1812  				Name:  "foo",
  1813  				Index: 3,
  1814  			},
  1815  		},
  1816  		{
  1817  			Input: "aws_instance.foo.0",
  1818  			Expected: &ResourceStateKey{
  1819  				Mode:  config.ManagedResourceMode,
  1820  				Type:  "aws_instance",
  1821  				Name:  "foo",
  1822  				Index: 0,
  1823  			},
  1824  		},
  1825  		{
  1826  			Input: "aws_instance.foo",
  1827  			Expected: &ResourceStateKey{
  1828  				Mode:  config.ManagedResourceMode,
  1829  				Type:  "aws_instance",
  1830  				Name:  "foo",
  1831  				Index: -1,
  1832  			},
  1833  		},
  1834  		{
  1835  			Input: "data.aws_ami.foo",
  1836  			Expected: &ResourceStateKey{
  1837  				Mode:  config.DataResourceMode,
  1838  				Type:  "aws_ami",
  1839  				Name:  "foo",
  1840  				Index: -1,
  1841  			},
  1842  		},
  1843  		{
  1844  			Input:       "aws_instance.foo.malformed",
  1845  			ExpectedErr: true,
  1846  		},
  1847  		{
  1848  			Input:       "aws_instance.foo.malformedwithnumber.123",
  1849  			ExpectedErr: true,
  1850  		},
  1851  		{
  1852  			Input:       "malformed",
  1853  			ExpectedErr: true,
  1854  		},
  1855  	}
  1856  	for _, tc := range cases {
  1857  		rsk, err := ParseResourceStateKey(tc.Input)
  1858  		if rsk != nil && tc.Expected != nil && !rsk.Equal(tc.Expected) {
  1859  			t.Fatalf("%s: expected %s, got %s", tc.Input, tc.Expected, rsk)
  1860  		}
  1861  		if (err != nil) != tc.ExpectedErr {
  1862  			t.Fatalf("%s: expected err: %t, got %s", tc.Input, tc.ExpectedErr, err)
  1863  		}
  1864  	}
  1865  }
  1866  
  1867  func TestStateModuleOrphans_empty(t *testing.T) {
  1868  	state := &State{
  1869  		Modules: []*ModuleState{
  1870  			&ModuleState{
  1871  				Path: RootModulePath,
  1872  			},
  1873  			&ModuleState{
  1874  				Path: []string{RootModuleName, "foo", "bar"},
  1875  			},
  1876  			&ModuleState{
  1877  				Path: []string{},
  1878  			},
  1879  			nil,
  1880  		},
  1881  	}
  1882  
  1883  	state.init()
  1884  
  1885  	// just calling this to check for panic
  1886  	state.ModuleOrphans(RootModulePath, nil)
  1887  }
  1888  
  1889  func TestReadState_prune(t *testing.T) {
  1890  	state := &State{
  1891  		Modules: []*ModuleState{
  1892  			&ModuleState{Path: rootModulePath},
  1893  			nil,
  1894  		},
  1895  	}
  1896  	state.init()
  1897  
  1898  	buf := new(bytes.Buffer)
  1899  	if err := WriteState(state, buf); err != nil {
  1900  		t.Fatalf("err: %s", err)
  1901  	}
  1902  
  1903  	actual, err := ReadState(buf)
  1904  	if err != nil {
  1905  		t.Fatalf("err: %s", err)
  1906  	}
  1907  
  1908  	expected := &State{
  1909  		Version: state.Version,
  1910  		Lineage: state.Lineage,
  1911  	}
  1912  	expected.init()
  1913  
  1914  	if !reflect.DeepEqual(actual, expected) {
  1915  		t.Fatalf("got:\n%#v", actual)
  1916  	}
  1917  }
  1918  
  1919  func TestReadState_pruneDependencies(t *testing.T) {
  1920  	state := &State{
  1921  		Serial:  9,
  1922  		Lineage: "5d1ad1a1-4027-4665-a908-dbe6adff11d8",
  1923  		Remote: &RemoteState{
  1924  			Type: "http",
  1925  			Config: map[string]string{
  1926  				"url": "http://my-cool-server.com/",
  1927  			},
  1928  		},
  1929  		Modules: []*ModuleState{
  1930  			&ModuleState{
  1931  				Path: rootModulePath,
  1932  				Dependencies: []string{
  1933  					"aws_instance.bar",
  1934  					"aws_instance.bar",
  1935  				},
  1936  				Resources: map[string]*ResourceState{
  1937  					"foo": &ResourceState{
  1938  						Dependencies: []string{
  1939  							"aws_instance.baz",
  1940  							"aws_instance.baz",
  1941  						},
  1942  						Primary: &InstanceState{
  1943  							ID: "bar",
  1944  						},
  1945  					},
  1946  				},
  1947  			},
  1948  		},
  1949  	}
  1950  	state.init()
  1951  
  1952  	buf := new(bytes.Buffer)
  1953  	if err := WriteState(state, buf); err != nil {
  1954  		t.Fatalf("err: %s", err)
  1955  	}
  1956  
  1957  	actual, err := ReadState(buf)
  1958  	if err != nil {
  1959  		t.Fatalf("err: %s", err)
  1960  	}
  1961  
  1962  	// make sure the duplicate Dependencies are filtered
  1963  	modDeps := actual.Modules[0].Dependencies
  1964  	resourceDeps := actual.Modules[0].Resources["foo"].Dependencies
  1965  
  1966  	if len(modDeps) > 1 || modDeps[0] != "aws_instance.bar" {
  1967  		t.Fatalf("expected 1 module depends_on entry, got %q", modDeps)
  1968  	}
  1969  
  1970  	if len(resourceDeps) > 1 || resourceDeps[0] != "aws_instance.baz" {
  1971  		t.Fatalf("expected 1 resource depends_on entry, got  %q", resourceDeps)
  1972  	}
  1973  }
  1974  
  1975  func TestResourceNameSort(t *testing.T) {
  1976  	names := []string{
  1977  		"a",
  1978  		"b",
  1979  		"a.0",
  1980  		"a.c",
  1981  		"a.d",
  1982  		"c",
  1983  		"a.b.0",
  1984  		"a.b.1",
  1985  		"a.b.10",
  1986  		"a.b.2",
  1987  	}
  1988  
  1989  	sort.Sort(resourceNameSort(names))
  1990  
  1991  	expected := []string{
  1992  		"a",
  1993  		"a.0",
  1994  		"a.b.0",
  1995  		"a.b.1",
  1996  		"a.b.2",
  1997  		"a.b.10",
  1998  		"a.c",
  1999  		"a.d",
  2000  		"b",
  2001  		"c",
  2002  	}
  2003  
  2004  	if !reflect.DeepEqual(names, expected) {
  2005  		t.Fatalf("got: %q\nexpected: %q\n", names, expected)
  2006  	}
  2007  }