github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/terraform/resource_address_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/terraform/config"
     9  	"github.com/hashicorp/terraform/config/module"
    10  )
    11  
    12  func TestParseResourceAddressInternal(t *testing.T) {
    13  	cases := map[string]struct {
    14  		Input    string
    15  		Expected *ResourceAddress
    16  		Output   string
    17  	}{
    18  		"basic resource": {
    19  			"aws_instance.foo",
    20  			&ResourceAddress{
    21  				Mode:         config.ManagedResourceMode,
    22  				Type:         "aws_instance",
    23  				Name:         "foo",
    24  				InstanceType: TypePrimary,
    25  				Index:        -1,
    26  			},
    27  			"aws_instance.foo",
    28  		},
    29  
    30  		"basic resource with count": {
    31  			"aws_instance.foo.1",
    32  			&ResourceAddress{
    33  				Mode:         config.ManagedResourceMode,
    34  				Type:         "aws_instance",
    35  				Name:         "foo",
    36  				InstanceType: TypePrimary,
    37  				Index:        1,
    38  			},
    39  			"aws_instance.foo[1]",
    40  		},
    41  
    42  		"data resource": {
    43  			"data.aws_ami.foo",
    44  			&ResourceAddress{
    45  				Mode:         config.DataResourceMode,
    46  				Type:         "aws_ami",
    47  				Name:         "foo",
    48  				InstanceType: TypePrimary,
    49  				Index:        -1,
    50  			},
    51  			"data.aws_ami.foo",
    52  		},
    53  
    54  		"data resource with count": {
    55  			"data.aws_ami.foo.1",
    56  			&ResourceAddress{
    57  				Mode:         config.DataResourceMode,
    58  				Type:         "aws_ami",
    59  				Name:         "foo",
    60  				InstanceType: TypePrimary,
    61  				Index:        1,
    62  			},
    63  			"data.aws_ami.foo[1]",
    64  		},
    65  
    66  		"non-data resource with 4 elements": {
    67  			"aws_instance.foo.bar.1",
    68  			nil,
    69  			"",
    70  		},
    71  	}
    72  
    73  	for tn, tc := range cases {
    74  		t.Run(tc.Input, func(t *testing.T) {
    75  			out, err := parseResourceAddressInternal(tc.Input)
    76  			if (err != nil) != (tc.Expected == nil) {
    77  				t.Fatalf("%s: unexpected err: %#v", tn, err)
    78  			}
    79  			if err != nil {
    80  				return
    81  			}
    82  
    83  			if !reflect.DeepEqual(out, tc.Expected) {
    84  				t.Fatalf("bad: %q\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Expected, out)
    85  			}
    86  
    87  			// Compare outputs if those exist
    88  			expected := tc.Input
    89  			if tc.Output != "" {
    90  				expected = tc.Output
    91  			}
    92  			if out.String() != expected {
    93  				t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, expected, out)
    94  			}
    95  
    96  			// Compare equality because the internal parse is used
    97  			// to compare equality to equal inputs.
    98  			if !out.Equals(tc.Expected) {
    99  				t.Fatalf("expected equality:\n\n%#v\n\n%#v", out, tc.Expected)
   100  			}
   101  		})
   102  	}
   103  }
   104  
   105  func TestParseResourceAddress(t *testing.T) {
   106  	cases := map[string]struct {
   107  		Input    string
   108  		Expected *ResourceAddress
   109  		Output   string
   110  		Err      bool
   111  	}{
   112  		"implicit primary managed instance, no specific index": {
   113  			"aws_instance.foo",
   114  			&ResourceAddress{
   115  				Mode:         config.ManagedResourceMode,
   116  				Type:         "aws_instance",
   117  				Name:         "foo",
   118  				InstanceType: TypePrimary,
   119  				Index:        -1,
   120  			},
   121  			"",
   122  			false,
   123  		},
   124  		"implicit primary data instance, no specific index": {
   125  			"data.aws_instance.foo",
   126  			&ResourceAddress{
   127  				Mode:         config.DataResourceMode,
   128  				Type:         "aws_instance",
   129  				Name:         "foo",
   130  				InstanceType: TypePrimary,
   131  				Index:        -1,
   132  			},
   133  			"",
   134  			false,
   135  		},
   136  		"implicit primary, explicit index": {
   137  			"aws_instance.foo[2]",
   138  			&ResourceAddress{
   139  				Mode:         config.ManagedResourceMode,
   140  				Type:         "aws_instance",
   141  				Name:         "foo",
   142  				InstanceType: TypePrimary,
   143  				Index:        2,
   144  			},
   145  			"",
   146  			false,
   147  		},
   148  		"implicit primary, explicit index over ten": {
   149  			"aws_instance.foo[12]",
   150  			&ResourceAddress{
   151  				Mode:         config.ManagedResourceMode,
   152  				Type:         "aws_instance",
   153  				Name:         "foo",
   154  				InstanceType: TypePrimary,
   155  				Index:        12,
   156  			},
   157  			"",
   158  			false,
   159  		},
   160  		"explicit primary, explicit index": {
   161  			"aws_instance.foo.primary[2]",
   162  			&ResourceAddress{
   163  				Mode:            config.ManagedResourceMode,
   164  				Type:            "aws_instance",
   165  				Name:            "foo",
   166  				InstanceType:    TypePrimary,
   167  				InstanceTypeSet: true,
   168  				Index:           2,
   169  			},
   170  			"",
   171  			false,
   172  		},
   173  		"tainted": {
   174  			"aws_instance.foo.tainted",
   175  			&ResourceAddress{
   176  				Mode:            config.ManagedResourceMode,
   177  				Type:            "aws_instance",
   178  				Name:            "foo",
   179  				InstanceType:    TypeTainted,
   180  				InstanceTypeSet: true,
   181  				Index:           -1,
   182  			},
   183  			"",
   184  			false,
   185  		},
   186  		"deposed": {
   187  			"aws_instance.foo.deposed",
   188  			&ResourceAddress{
   189  				Mode:            config.ManagedResourceMode,
   190  				Type:            "aws_instance",
   191  				Name:            "foo",
   192  				InstanceType:    TypeDeposed,
   193  				InstanceTypeSet: true,
   194  				Index:           -1,
   195  			},
   196  			"",
   197  			false,
   198  		},
   199  		"with a hyphen": {
   200  			"aws_instance.foo-bar",
   201  			&ResourceAddress{
   202  				Mode:         config.ManagedResourceMode,
   203  				Type:         "aws_instance",
   204  				Name:         "foo-bar",
   205  				InstanceType: TypePrimary,
   206  				Index:        -1,
   207  			},
   208  			"",
   209  			false,
   210  		},
   211  		"managed in a module": {
   212  			"module.child.aws_instance.foo",
   213  			&ResourceAddress{
   214  				Path:         []string{"child"},
   215  				Mode:         config.ManagedResourceMode,
   216  				Type:         "aws_instance",
   217  				Name:         "foo",
   218  				InstanceType: TypePrimary,
   219  				Index:        -1,
   220  			},
   221  			"",
   222  			false,
   223  		},
   224  		"data in a module": {
   225  			"module.child.data.aws_instance.foo",
   226  			&ResourceAddress{
   227  				Path:         []string{"child"},
   228  				Mode:         config.DataResourceMode,
   229  				Type:         "aws_instance",
   230  				Name:         "foo",
   231  				InstanceType: TypePrimary,
   232  				Index:        -1,
   233  			},
   234  			"",
   235  			false,
   236  		},
   237  		"nested modules": {
   238  			"module.a.module.b.module.forever.aws_instance.foo",
   239  			&ResourceAddress{
   240  				Path:         []string{"a", "b", "forever"},
   241  				Mode:         config.ManagedResourceMode,
   242  				Type:         "aws_instance",
   243  				Name:         "foo",
   244  				InstanceType: TypePrimary,
   245  				Index:        -1,
   246  			},
   247  			"",
   248  			false,
   249  		},
   250  		"just a module": {
   251  			"module.a",
   252  			&ResourceAddress{
   253  				Path:         []string{"a"},
   254  				Type:         "",
   255  				Name:         "",
   256  				InstanceType: TypePrimary,
   257  				Index:        -1,
   258  			},
   259  			"",
   260  			false,
   261  		},
   262  		"just a nested module": {
   263  			"module.a.module.b",
   264  			&ResourceAddress{
   265  				Path:         []string{"a", "b"},
   266  				Type:         "",
   267  				Name:         "",
   268  				InstanceType: TypePrimary,
   269  				Index:        -1,
   270  			},
   271  			"",
   272  			false,
   273  		},
   274  		"module missing resource type": {
   275  			"module.name.foo",
   276  			nil,
   277  			"",
   278  			true,
   279  		},
   280  	}
   281  
   282  	for tn, tc := range cases {
   283  		t.Run(tn, func(t *testing.T) {
   284  			out, err := ParseResourceAddress(tc.Input)
   285  			if (err != nil) != tc.Err {
   286  				t.Fatalf("%s: unexpected err: %#v", tn, err)
   287  			}
   288  			if tc.Err {
   289  				return
   290  			}
   291  
   292  			if !reflect.DeepEqual(out, tc.Expected) {
   293  				t.Fatalf("bad: %q\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Expected, out)
   294  			}
   295  
   296  			expected := tc.Input
   297  			if tc.Output != "" {
   298  				expected = tc.Output
   299  			}
   300  			if out.String() != expected {
   301  				t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, expected, out)
   302  			}
   303  		})
   304  	}
   305  }
   306  
   307  func TestResourceAddressEquals(t *testing.T) {
   308  	cases := map[string]struct {
   309  		Address *ResourceAddress
   310  		Other   interface{}
   311  		Expect  bool
   312  	}{
   313  		"basic match": {
   314  			Address: &ResourceAddress{
   315  				Mode:         config.ManagedResourceMode,
   316  				Type:         "aws_instance",
   317  				Name:         "foo",
   318  				InstanceType: TypePrimary,
   319  				Index:        0,
   320  			},
   321  			Other: &ResourceAddress{
   322  				Mode:         config.ManagedResourceMode,
   323  				Type:         "aws_instance",
   324  				Name:         "foo",
   325  				InstanceType: TypePrimary,
   326  				Index:        0,
   327  			},
   328  			Expect: true,
   329  		},
   330  		"address does not set index": {
   331  			Address: &ResourceAddress{
   332  				Mode:         config.ManagedResourceMode,
   333  				Type:         "aws_instance",
   334  				Name:         "foo",
   335  				InstanceType: TypePrimary,
   336  				Index:        -1,
   337  			},
   338  			Other: &ResourceAddress{
   339  				Mode:         config.ManagedResourceMode,
   340  				Type:         "aws_instance",
   341  				Name:         "foo",
   342  				InstanceType: TypePrimary,
   343  				Index:        3,
   344  			},
   345  			Expect: true,
   346  		},
   347  		"other does not set index": {
   348  			Address: &ResourceAddress{
   349  				Mode:         config.ManagedResourceMode,
   350  				Type:         "aws_instance",
   351  				Name:         "foo",
   352  				InstanceType: TypePrimary,
   353  				Index:        3,
   354  			},
   355  			Other: &ResourceAddress{
   356  				Mode:         config.ManagedResourceMode,
   357  				Type:         "aws_instance",
   358  				Name:         "foo",
   359  				InstanceType: TypePrimary,
   360  				Index:        -1,
   361  			},
   362  			Expect: true,
   363  		},
   364  		"neither sets index": {
   365  			Address: &ResourceAddress{
   366  				Mode:         config.ManagedResourceMode,
   367  				Type:         "aws_instance",
   368  				Name:         "foo",
   369  				InstanceType: TypePrimary,
   370  				Index:        -1,
   371  			},
   372  			Other: &ResourceAddress{
   373  				Mode:         config.ManagedResourceMode,
   374  				Type:         "aws_instance",
   375  				Name:         "foo",
   376  				InstanceType: TypePrimary,
   377  				Index:        -1,
   378  			},
   379  			Expect: true,
   380  		},
   381  		"index over ten": {
   382  			Address: &ResourceAddress{
   383  				Mode:         config.ManagedResourceMode,
   384  				Type:         "aws_instance",
   385  				Name:         "foo",
   386  				InstanceType: TypePrimary,
   387  				Index:        1,
   388  			},
   389  			Other: &ResourceAddress{
   390  				Mode:         config.ManagedResourceMode,
   391  				Type:         "aws_instance",
   392  				Name:         "foo",
   393  				InstanceType: TypePrimary,
   394  				Index:        13,
   395  			},
   396  			Expect: false,
   397  		},
   398  		"different type": {
   399  			Address: &ResourceAddress{
   400  				Mode:         config.ManagedResourceMode,
   401  				Type:         "aws_instance",
   402  				Name:         "foo",
   403  				InstanceType: TypePrimary,
   404  				Index:        0,
   405  			},
   406  			Other: &ResourceAddress{
   407  				Mode:         config.ManagedResourceMode,
   408  				Type:         "aws_vpc",
   409  				Name:         "foo",
   410  				InstanceType: TypePrimary,
   411  				Index:        0,
   412  			},
   413  			Expect: false,
   414  		},
   415  		"different mode": {
   416  			Address: &ResourceAddress{
   417  				Mode:         config.ManagedResourceMode,
   418  				Type:         "aws_instance",
   419  				Name:         "foo",
   420  				InstanceType: TypePrimary,
   421  				Index:        0,
   422  			},
   423  			Other: &ResourceAddress{
   424  				Mode:         config.DataResourceMode,
   425  				Type:         "aws_instance",
   426  				Name:         "foo",
   427  				InstanceType: TypePrimary,
   428  				Index:        0,
   429  			},
   430  			Expect: false,
   431  		},
   432  		"different name": {
   433  			Address: &ResourceAddress{
   434  				Mode:         config.ManagedResourceMode,
   435  				Type:         "aws_instance",
   436  				Name:         "foo",
   437  				InstanceType: TypePrimary,
   438  				Index:        0,
   439  			},
   440  			Other: &ResourceAddress{
   441  				Mode:         config.ManagedResourceMode,
   442  				Type:         "aws_instance",
   443  				Name:         "bar",
   444  				InstanceType: TypePrimary,
   445  				Index:        0,
   446  			},
   447  			Expect: false,
   448  		},
   449  		"different instance type": {
   450  			Address: &ResourceAddress{
   451  				Mode:         config.ManagedResourceMode,
   452  				Type:         "aws_instance",
   453  				Name:         "foo",
   454  				InstanceType: TypePrimary,
   455  				Index:        0,
   456  			},
   457  			Other: &ResourceAddress{
   458  				Mode:         config.ManagedResourceMode,
   459  				Type:         "aws_instance",
   460  				Name:         "foo",
   461  				InstanceType: TypeTainted,
   462  				Index:        0,
   463  			},
   464  			Expect: false,
   465  		},
   466  		"different index": {
   467  			Address: &ResourceAddress{
   468  				Mode:         config.ManagedResourceMode,
   469  				Type:         "aws_instance",
   470  				Name:         "foo",
   471  				InstanceType: TypePrimary,
   472  				Index:        0,
   473  			},
   474  			Other: &ResourceAddress{
   475  				Mode:         config.ManagedResourceMode,
   476  				Type:         "aws_instance",
   477  				Name:         "foo",
   478  				InstanceType: TypePrimary,
   479  				Index:        1,
   480  			},
   481  			Expect: false,
   482  		},
   483  		"module address matches address of managed resource inside module": {
   484  			Address: &ResourceAddress{
   485  				Path:         []string{"a", "b"},
   486  				Type:         "",
   487  				Name:         "",
   488  				InstanceType: TypePrimary,
   489  				Index:        -1,
   490  			},
   491  			Other: &ResourceAddress{
   492  				Path:         []string{"a", "b"},
   493  				Mode:         config.ManagedResourceMode,
   494  				Type:         "aws_instance",
   495  				Name:         "foo",
   496  				InstanceType: TypePrimary,
   497  				Index:        0,
   498  			},
   499  			Expect: true,
   500  		},
   501  		"module address matches address of data resource inside module": {
   502  			Address: &ResourceAddress{
   503  				Path:         []string{"a", "b"},
   504  				Type:         "",
   505  				Name:         "",
   506  				InstanceType: TypePrimary,
   507  				Index:        -1,
   508  			},
   509  			Other: &ResourceAddress{
   510  				Path:         []string{"a", "b"},
   511  				Mode:         config.DataResourceMode,
   512  				Type:         "aws_instance",
   513  				Name:         "foo",
   514  				InstanceType: TypePrimary,
   515  				Index:        0,
   516  			},
   517  			Expect: true,
   518  		},
   519  		"module address doesn't match managed resource outside module": {
   520  			Address: &ResourceAddress{
   521  				Path:         []string{"a", "b"},
   522  				Type:         "",
   523  				Name:         "",
   524  				InstanceType: TypePrimary,
   525  				Index:        -1,
   526  			},
   527  			Other: &ResourceAddress{
   528  				Path:         []string{"a"},
   529  				Mode:         config.ManagedResourceMode,
   530  				Type:         "aws_instance",
   531  				Name:         "foo",
   532  				InstanceType: TypePrimary,
   533  				Index:        0,
   534  			},
   535  			Expect: false,
   536  		},
   537  		"module address doesn't match data resource outside module": {
   538  			Address: &ResourceAddress{
   539  				Path:         []string{"a", "b"},
   540  				Type:         "",
   541  				Name:         "",
   542  				InstanceType: TypePrimary,
   543  				Index:        -1,
   544  			},
   545  			Other: &ResourceAddress{
   546  				Path:         []string{"a"},
   547  				Mode:         config.DataResourceMode,
   548  				Type:         "aws_instance",
   549  				Name:         "foo",
   550  				InstanceType: TypePrimary,
   551  				Index:        0,
   552  			},
   553  			Expect: false,
   554  		},
   555  		"nil path vs empty path should match": {
   556  			Address: &ResourceAddress{
   557  				Path:         []string{},
   558  				Mode:         config.ManagedResourceMode,
   559  				Type:         "aws_instance",
   560  				Name:         "foo",
   561  				InstanceType: TypePrimary,
   562  				Index:        -1,
   563  			},
   564  			Other: &ResourceAddress{
   565  				Path:         nil,
   566  				Mode:         config.ManagedResourceMode,
   567  				Type:         "aws_instance",
   568  				Name:         "foo",
   569  				InstanceType: TypePrimary,
   570  				Index:        0,
   571  			},
   572  			Expect: true,
   573  		},
   574  	}
   575  
   576  	for tn, tc := range cases {
   577  		actual := tc.Address.Equals(tc.Other)
   578  		if actual != tc.Expect {
   579  			t.Fatalf("%q: expected equals: %t, got %t for:\n%#v\n%#v",
   580  				tn, tc.Expect, actual, tc.Address, tc.Other)
   581  		}
   582  	}
   583  }
   584  
   585  func TestResourceAddressStateId(t *testing.T) {
   586  	cases := map[string]struct {
   587  		Input    *ResourceAddress
   588  		Expected string
   589  	}{
   590  		"basic resource": {
   591  			&ResourceAddress{
   592  				Mode:         config.ManagedResourceMode,
   593  				Type:         "aws_instance",
   594  				Name:         "foo",
   595  				InstanceType: TypePrimary,
   596  				Index:        -1,
   597  			},
   598  			"aws_instance.foo",
   599  		},
   600  
   601  		"basic resource with index": {
   602  			&ResourceAddress{
   603  				Mode:         config.ManagedResourceMode,
   604  				Type:         "aws_instance",
   605  				Name:         "foo",
   606  				InstanceType: TypePrimary,
   607  				Index:        2,
   608  			},
   609  			"aws_instance.foo.2",
   610  		},
   611  
   612  		"data resource": {
   613  			&ResourceAddress{
   614  				Mode:         config.DataResourceMode,
   615  				Type:         "aws_instance",
   616  				Name:         "foo",
   617  				InstanceType: TypePrimary,
   618  				Index:        -1,
   619  			},
   620  			"data.aws_instance.foo",
   621  		},
   622  	}
   623  
   624  	for tn, tc := range cases {
   625  		t.Run(tn, func(t *testing.T) {
   626  			actual := tc.Input.stateId()
   627  			if actual != tc.Expected {
   628  				t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, tc.Expected, actual)
   629  			}
   630  		})
   631  	}
   632  }
   633  
   634  func TestResourceAddressHasResourceSpec(t *testing.T) {
   635  	cases := []struct {
   636  		Input string
   637  		Want  bool
   638  	}{
   639  		{
   640  			"module.foo",
   641  			false,
   642  		},
   643  		{
   644  			"module.foo.module.bar",
   645  			false,
   646  		},
   647  		{
   648  			"null_resource.baz",
   649  			true,
   650  		},
   651  		{
   652  			"null_resource.baz[0]",
   653  			true,
   654  		},
   655  		{
   656  			"data.null_data_source.baz",
   657  			true,
   658  		},
   659  		{
   660  			"data.null_data_source.baz[0]",
   661  			true,
   662  		},
   663  		{
   664  			"module.foo.null_resource.baz",
   665  			true,
   666  		},
   667  		{
   668  			"module.foo.data.null_data_source.baz",
   669  			true,
   670  		},
   671  		{
   672  			"module.foo.module.bar.null_resource.baz",
   673  			true,
   674  		},
   675  	}
   676  
   677  	for _, test := range cases {
   678  		t.Run(test.Input, func(t *testing.T) {
   679  			addr, err := ParseResourceAddress(test.Input)
   680  			if err != nil {
   681  				t.Fatalf("error parsing address: %s", err)
   682  			}
   683  			got := addr.HasResourceSpec()
   684  			if got != test.Want {
   685  				t.Fatalf("%q: wrong result %#v; want %#v", test.Input, got, test.Want)
   686  			}
   687  		})
   688  	}
   689  }
   690  
   691  func TestResourceAddressWholeModuleAddress(t *testing.T) {
   692  	cases := []struct {
   693  		Input string
   694  		Want  string
   695  	}{
   696  		{
   697  			"module.foo",
   698  			"module.foo",
   699  		},
   700  		{
   701  			"module.foo.module.bar",
   702  			"module.foo.module.bar",
   703  		},
   704  		{
   705  			"null_resource.baz",
   706  			"",
   707  		},
   708  		{
   709  			"null_resource.baz[0]",
   710  			"",
   711  		},
   712  		{
   713  			"data.null_data_source.baz",
   714  			"",
   715  		},
   716  		{
   717  			"data.null_data_source.baz[0]",
   718  			"",
   719  		},
   720  		{
   721  			"module.foo.null_resource.baz",
   722  			"module.foo",
   723  		},
   724  		{
   725  			"module.foo.data.null_data_source.baz",
   726  			"module.foo",
   727  		},
   728  		{
   729  			"module.foo.module.bar.null_resource.baz",
   730  			"module.foo.module.bar",
   731  		},
   732  	}
   733  
   734  	for _, test := range cases {
   735  		t.Run(test.Input, func(t *testing.T) {
   736  			addr, err := ParseResourceAddress(test.Input)
   737  			if err != nil {
   738  				t.Fatalf("error parsing address: %s", err)
   739  			}
   740  			gotAddr := addr.WholeModuleAddress()
   741  			got := gotAddr.String()
   742  			if got != test.Want {
   743  				t.Fatalf("%q: wrong result %#v; want %#v", test.Input, got, test.Want)
   744  			}
   745  		})
   746  	}
   747  }
   748  
   749  func TestResourceAddressMatchesConfig(t *testing.T) {
   750  	root := testModule(t, "empty-with-child-module")
   751  	child := root.Child([]string{"child"})
   752  	grandchild := root.Child([]string{"child", "grandchild"})
   753  
   754  	tests := []struct {
   755  		Addr     *ResourceAddress
   756  		Module   *module.Tree
   757  		Resource *config.Resource
   758  		Want     bool
   759  	}{
   760  		{
   761  			&ResourceAddress{
   762  				Mode:  config.ManagedResourceMode,
   763  				Type:  "null_resource",
   764  				Name:  "baz",
   765  				Index: -1,
   766  			},
   767  			root,
   768  			&config.Resource{
   769  				Mode: config.ManagedResourceMode,
   770  				Type: "null_resource",
   771  				Name: "baz",
   772  			},
   773  			true,
   774  		},
   775  		{
   776  			&ResourceAddress{
   777  				Path:  []string{"child"},
   778  				Mode:  config.ManagedResourceMode,
   779  				Type:  "null_resource",
   780  				Name:  "baz",
   781  				Index: -1,
   782  			},
   783  			child,
   784  			&config.Resource{
   785  				Mode: config.ManagedResourceMode,
   786  				Type: "null_resource",
   787  				Name: "baz",
   788  			},
   789  			true,
   790  		},
   791  		{
   792  			&ResourceAddress{
   793  				Path:  []string{"child", "grandchild"},
   794  				Mode:  config.ManagedResourceMode,
   795  				Type:  "null_resource",
   796  				Name:  "baz",
   797  				Index: -1,
   798  			},
   799  			grandchild,
   800  			&config.Resource{
   801  				Mode: config.ManagedResourceMode,
   802  				Type: "null_resource",
   803  				Name: "baz",
   804  			},
   805  			true,
   806  		},
   807  		{
   808  			&ResourceAddress{
   809  				Path:  []string{"child"},
   810  				Index: -1,
   811  			},
   812  			child,
   813  			&config.Resource{
   814  				Mode: config.ManagedResourceMode,
   815  				Type: "null_resource",
   816  				Name: "baz",
   817  			},
   818  			true,
   819  		},
   820  		{
   821  			&ResourceAddress{
   822  				Path:  []string{"child", "grandchild"},
   823  				Index: -1,
   824  			},
   825  			grandchild,
   826  			&config.Resource{
   827  				Mode: config.ManagedResourceMode,
   828  				Type: "null_resource",
   829  				Name: "baz",
   830  			},
   831  			true,
   832  		},
   833  		{
   834  			&ResourceAddress{
   835  				Mode:  config.DataResourceMode,
   836  				Type:  "null_resource",
   837  				Name:  "baz",
   838  				Index: -1,
   839  			},
   840  			module.NewEmptyTree(),
   841  			&config.Resource{
   842  				Mode: config.ManagedResourceMode,
   843  				Type: "null_resource",
   844  				Name: "baz",
   845  			},
   846  			false,
   847  		},
   848  		{
   849  			&ResourceAddress{
   850  				Mode:  config.ManagedResourceMode,
   851  				Type:  "null_resource",
   852  				Name:  "baz",
   853  				Index: -1,
   854  			},
   855  			module.NewEmptyTree(),
   856  			&config.Resource{
   857  				Mode: config.ManagedResourceMode,
   858  				Type: "null_resource",
   859  				Name: "pizza",
   860  			},
   861  			false,
   862  		},
   863  		{
   864  			&ResourceAddress{
   865  				Mode:  config.ManagedResourceMode,
   866  				Type:  "null_resource",
   867  				Name:  "baz",
   868  				Index: -1,
   869  			},
   870  			module.NewEmptyTree(),
   871  			&config.Resource{
   872  				Mode: config.ManagedResourceMode,
   873  				Type: "aws_instance",
   874  				Name: "baz",
   875  			},
   876  			false,
   877  		},
   878  		{
   879  			&ResourceAddress{
   880  				Path:  []string{"child", "grandchild"},
   881  				Mode:  config.ManagedResourceMode,
   882  				Type:  "null_resource",
   883  				Name:  "baz",
   884  				Index: -1,
   885  			},
   886  			child,
   887  			&config.Resource{
   888  				Mode: config.ManagedResourceMode,
   889  				Type: "null_resource",
   890  				Name: "baz",
   891  			},
   892  			false,
   893  		},
   894  		{
   895  			&ResourceAddress{
   896  				Path:  []string{"child"},
   897  				Mode:  config.ManagedResourceMode,
   898  				Type:  "null_resource",
   899  				Name:  "baz",
   900  				Index: -1,
   901  			},
   902  			grandchild,
   903  			&config.Resource{
   904  				Mode: config.ManagedResourceMode,
   905  				Type: "null_resource",
   906  				Name: "baz",
   907  			},
   908  			false,
   909  		},
   910  	}
   911  
   912  	for i, test := range tests {
   913  		t.Run(fmt.Sprintf("%02d-%s", i, test.Addr), func(t *testing.T) {
   914  			got := test.Addr.MatchesConfig(test.Module, test.Resource)
   915  			if got != test.Want {
   916  				t.Errorf(
   917  					"wrong result\naddr: %s\nmod:  %#v\nrsrc: %#v\ngot:  %#v\nwant: %#v",
   918  					test.Addr, test.Module.Path(), test.Resource, got, test.Want,
   919  				)
   920  			}
   921  		})
   922  	}
   923  }