github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/addrs/target_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package addrs
     5  
     6  import (
     7  	"fmt"
     8  	"testing"
     9  )
    10  
    11  func TestTargetContains(t *testing.T) {
    12  	for _, test := range []struct {
    13  		addr, other Targetable
    14  		expect      bool
    15  	}{
    16  		{
    17  			mustParseTarget("module.foo"),
    18  			mustParseTarget("module.bar"),
    19  			false,
    20  		},
    21  		{
    22  			mustParseTarget("module.foo"),
    23  			mustParseTarget("module.foo"),
    24  			true,
    25  		},
    26  		{
    27  			RootModuleInstance,
    28  			mustParseTarget("module.foo"),
    29  			true,
    30  		},
    31  		{
    32  			mustParseTarget("module.foo"),
    33  			RootModuleInstance,
    34  			false,
    35  		},
    36  		{
    37  			mustParseTarget("module.foo"),
    38  			mustParseTarget("module.foo.module.bar[0]"),
    39  			true,
    40  		},
    41  		{
    42  			mustParseTarget("module.foo"),
    43  			mustParseTarget("module.foo.module.bar[0]"),
    44  			true,
    45  		},
    46  		{
    47  			mustParseTarget("module.foo[2]"),
    48  			mustParseTarget("module.foo[2].module.bar[0]"),
    49  			true,
    50  		},
    51  		{
    52  			mustParseTarget("module.foo"),
    53  			mustParseTarget("module.foo.test_resource.bar"),
    54  			true,
    55  		},
    56  		{
    57  			mustParseTarget("module.foo"),
    58  			mustParseTarget("module.foo.test_resource.bar[0]"),
    59  			true,
    60  		},
    61  
    62  		// Resources
    63  		{
    64  			mustParseTarget("test_resource.foo"),
    65  			mustParseTarget("test_resource.foo[\"bar\"]"),
    66  			true,
    67  		},
    68  		{
    69  			mustParseTarget(`test_resource.foo["bar"]`),
    70  			mustParseTarget(`test_resource.foo["bar"]`),
    71  			true,
    72  		},
    73  		{
    74  			mustParseTarget("test_resource.foo"),
    75  			mustParseTarget("test_resource.foo[2]"),
    76  			true,
    77  		},
    78  		{
    79  			mustParseTarget("test_resource.foo"),
    80  			mustParseTarget("module.bar.test_resource.foo[2]"),
    81  			false,
    82  		},
    83  		{
    84  			mustParseTarget("module.bar.test_resource.foo"),
    85  			mustParseTarget("module.bar.test_resource.foo[2]"),
    86  			true,
    87  		},
    88  		{
    89  			mustParseTarget("module.bar.test_resource.foo"),
    90  			mustParseTarget("module.bar[0].test_resource.foo[2]"),
    91  			false,
    92  		},
    93  		{
    94  			mustParseTarget("module.bar.test_resource.foo"),
    95  			mustParseTarget("module.bar.test_resource.foo[0]"),
    96  			true,
    97  		},
    98  		{
    99  			mustParseTarget("module.bax"),
   100  			mustParseTarget("module.bax[0].test_resource.foo[0]"),
   101  			true,
   102  		},
   103  
   104  		// Config paths, while never returned from parsing a target, must still
   105  		// be targetable
   106  		{
   107  			ConfigResource{
   108  				Module: []string{"bar"},
   109  				Resource: Resource{
   110  					Mode: ManagedResourceMode,
   111  					Type: "test_resource",
   112  					Name: "foo",
   113  				},
   114  			},
   115  			mustParseTarget("module.bar.test_resource.foo[2]"),
   116  			true,
   117  		},
   118  		{
   119  			mustParseTarget("module.bar"),
   120  			ConfigResource{
   121  				Module: []string{"bar"},
   122  				Resource: Resource{
   123  					Mode: ManagedResourceMode,
   124  					Type: "test_resource",
   125  					Name: "foo",
   126  				},
   127  			},
   128  			true,
   129  		},
   130  		{
   131  			mustParseTarget("module.bar.test_resource.foo"),
   132  			ConfigResource{
   133  				Module: []string{"bar"},
   134  				Resource: Resource{
   135  					Mode: ManagedResourceMode,
   136  					Type: "test_resource",
   137  					Name: "foo",
   138  				},
   139  			},
   140  			true,
   141  		},
   142  		{
   143  			ConfigResource{
   144  				Resource: Resource{
   145  					Mode: ManagedResourceMode,
   146  					Type: "test_resource",
   147  					Name: "foo",
   148  				},
   149  			},
   150  			mustParseTarget("module.bar.test_resource.foo[2]"),
   151  			false,
   152  		},
   153  		{
   154  			ConfigResource{
   155  				Module: []string{"bar"},
   156  				Resource: Resource{
   157  					Mode: ManagedResourceMode,
   158  					Type: "test_resource",
   159  					Name: "foo",
   160  				},
   161  			},
   162  			mustParseTarget("module.bar[0].test_resource.foo"),
   163  			true,
   164  		},
   165  
   166  		// Modules are also never the result of parsing a target, but also need
   167  		// to be targetable
   168  		{
   169  			Module{"bar"},
   170  			Module{"bar", "baz"},
   171  			true,
   172  		},
   173  		{
   174  			Module{"bar"},
   175  			mustParseTarget("module.bar[0]"),
   176  			true,
   177  		},
   178  		{
   179  			// Parsing an ambiguous module path needs to ensure the
   180  			// ModuleInstance could contain the Module. This is safe because if
   181  			// the module could be expanded, it must have an index, meaning no
   182  			// index indicates that the module instance and module are
   183  			// functionally equivalent.
   184  			mustParseTarget("module.bar"),
   185  			Module{"bar"},
   186  			true,
   187  		},
   188  		{
   189  			// A specific ModuleInstance cannot contain a module
   190  			mustParseTarget("module.bar[0]"),
   191  			Module{"bar"},
   192  			false,
   193  		},
   194  		{
   195  			Module{"bar", "baz"},
   196  			mustParseTarget("module.bar[0].module.baz.test_resource.foo[1]"),
   197  			true,
   198  		},
   199  		{
   200  			mustParseTarget("module.bar[0].module.baz"),
   201  			Module{"bar", "baz"},
   202  			false,
   203  		},
   204  	} {
   205  		t.Run(fmt.Sprintf("%s-in-%s", test.other, test.addr), func(t *testing.T) {
   206  			got := test.addr.TargetContains(test.other)
   207  			if got != test.expect {
   208  				t.Fatalf("expected %q.TargetContains(%q) == %t", test.addr, test.other, test.expect)
   209  			}
   210  		})
   211  	}
   212  }
   213  
   214  func TestResourceContains(t *testing.T) {
   215  	for _, test := range []struct {
   216  		in, other Targetable
   217  		expect    bool
   218  	}{} {
   219  		t.Run(fmt.Sprintf("%s-in-%s", test.other, test.in), func(t *testing.T) {
   220  			got := test.in.TargetContains(test.other)
   221  			if got != test.expect {
   222  				t.Fatalf("expected %q.TargetContains(%q) == %t", test.in, test.other, test.expect)
   223  			}
   224  		})
   225  	}
   226  }
   227  
   228  func mustParseTarget(str string) Targetable {
   229  	t, diags := ParseTargetStr(str)
   230  	if diags != nil {
   231  		panic(fmt.Sprintf("%s: %s", str, diags.ErrWithWarnings()))
   232  	}
   233  	return t.Subject
   234  }