github.com/terraform-linters/tflint-plugin-sdk@v0.22.0/terraform/lang/references_test.go (about)

     1  package lang
     2  
     3  import (
     4  	"sort"
     5  	"testing"
     6  
     7  	"github.com/go-test/deep"
     8  	"github.com/hashicorp/hcl/v2"
     9  	"github.com/hashicorp/hcl/v2/hclsyntax"
    10  	"github.com/terraform-linters/tflint-plugin-sdk/terraform/addrs"
    11  )
    12  
    13  func TestReferencesInExpr(t *testing.T) {
    14  	tests := []struct {
    15  		Name  string
    16  		Input string
    17  		Want  []*addrs.Reference
    18  	}{
    19  		{
    20  			Name:  "input variable",
    21  			Input: `var.foo`,
    22  			Want: []*addrs.Reference{
    23  				{
    24  					Subject: addrs.InputVariable{
    25  						Name: "foo",
    26  					},
    27  					SourceRange: hcl.Range{
    28  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
    29  						End:   hcl.Pos{Line: 1, Column: 8, Byte: 7},
    30  					},
    31  				},
    32  			},
    33  		},
    34  		{
    35  			Name:  "multiple input variables",
    36  			Input: `"${var.foo}-${var.bar}"`,
    37  			Want: []*addrs.Reference{
    38  				{
    39  					Subject: addrs.InputVariable{
    40  						Name: "foo",
    41  					},
    42  					SourceRange: hcl.Range{
    43  						Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
    44  						End:   hcl.Pos{Line: 1, Column: 11, Byte: 10},
    45  					},
    46  				},
    47  				{
    48  					Subject: addrs.InputVariable{
    49  						Name: "bar",
    50  					},
    51  					SourceRange: hcl.Range{
    52  						Start: hcl.Pos{Line: 1, Column: 15, Byte: 14},
    53  						End:   hcl.Pos{Line: 1, Column: 22, Byte: 21},
    54  					},
    55  				},
    56  			},
    57  		},
    58  		{
    59  			Name:  "input variable and resource",
    60  			Input: `"${boop_instance.foo}_${var.foo}"`,
    61  			Want: []*addrs.Reference{
    62  				{
    63  					Subject: addrs.Resource{
    64  						Mode: addrs.ManagedResourceMode,
    65  						Type: "boop_instance",
    66  						Name: "foo",
    67  					},
    68  					SourceRange: hcl.Range{
    69  						Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
    70  						End:   hcl.Pos{Line: 1, Column: 21, Byte: 20},
    71  					},
    72  				},
    73  				{
    74  					Subject: addrs.InputVariable{
    75  						Name: "foo",
    76  					},
    77  					SourceRange: hcl.Range{
    78  						Start: hcl.Pos{Line: 1, Column: 25, Byte: 24},
    79  						End:   hcl.Pos{Line: 1, Column: 32, Byte: 31},
    80  					},
    81  				},
    82  			},
    83  		},
    84  		{
    85  			Name:  "contains invalid references",
    86  			Input: `"${boop_instance}_${var.foo}"`, // A reference to a resource type must be followed by at least one attribute access, specifying the resource name.
    87  			Want: []*addrs.Reference{
    88  				{
    89  					Subject: addrs.InputVariable{
    90  						Name: "foo",
    91  					},
    92  					SourceRange: hcl.Range{
    93  						Start: hcl.Pos{Line: 1, Column: 21, Byte: 20},
    94  						End:   hcl.Pos{Line: 1, Column: 28, Byte: 27},
    95  					},
    96  				},
    97  			},
    98  		},
    99  	}
   100  
   101  	for _, test := range tests {
   102  		t.Run(test.Name, func(t *testing.T) {
   103  			expr, diags := hclsyntax.ParseExpression([]byte(test.Input), "", hcl.InitialPos)
   104  			if diags.HasErrors() {
   105  				t.Fatal(diags)
   106  			}
   107  
   108  			got := ReferencesInExpr(expr)
   109  			sort.Slice(got, func(i, j int) bool {
   110  				return got[i].SourceRange.String() > got[j].SourceRange.String()
   111  			})
   112  
   113  			for _, problem := range deep.Equal(got, test.Want) {
   114  				t.Errorf(problem)
   115  			}
   116  		})
   117  	}
   118  }