github.com/hashicorp/hcl/v2@v2.20.0/hclsyntax/parse_traversal_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package hclsyntax
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/go-test/deep"
    10  	"github.com/hashicorp/hcl/v2"
    11  	"github.com/zclconf/go-cty/cty"
    12  )
    13  
    14  func TestParseTraversalAbs(t *testing.T) {
    15  	tests := []struct {
    16  		src       string
    17  		want      hcl.Traversal
    18  		diagCount int
    19  	}{
    20  		{
    21  			"",
    22  			nil,
    23  			1, // variable name required
    24  		},
    25  		{
    26  			"foo",
    27  			hcl.Traversal{
    28  				hcl.TraverseRoot{
    29  					Name: "foo",
    30  					SrcRange: hcl.Range{
    31  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
    32  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
    33  					},
    34  				},
    35  			},
    36  			0,
    37  		},
    38  		{
    39  			"foo.bar.baz",
    40  			hcl.Traversal{
    41  				hcl.TraverseRoot{
    42  					Name: "foo",
    43  					SrcRange: hcl.Range{
    44  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
    45  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
    46  					},
    47  				},
    48  				hcl.TraverseAttr{
    49  					Name: "bar",
    50  					SrcRange: hcl.Range{
    51  						Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
    52  						End:   hcl.Pos{Line: 1, Column: 8, Byte: 7},
    53  					},
    54  				},
    55  				hcl.TraverseAttr{
    56  					Name: "baz",
    57  					SrcRange: hcl.Range{
    58  						Start: hcl.Pos{Line: 1, Column: 8, Byte: 7},
    59  						End:   hcl.Pos{Line: 1, Column: 12, Byte: 11},
    60  					},
    61  				},
    62  			},
    63  			0,
    64  		},
    65  		{
    66  			"foo[1]",
    67  			hcl.Traversal{
    68  				hcl.TraverseRoot{
    69  					Name: "foo",
    70  					SrcRange: hcl.Range{
    71  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
    72  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
    73  					},
    74  				},
    75  				hcl.TraverseIndex{
    76  					Key: cty.NumberIntVal(1),
    77  					SrcRange: hcl.Range{
    78  						Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
    79  						End:   hcl.Pos{Line: 1, Column: 7, Byte: 6},
    80  					},
    81  				},
    82  			},
    83  			0,
    84  		},
    85  		{
    86  			"foo[1][2]",
    87  			hcl.Traversal{
    88  				hcl.TraverseRoot{
    89  					Name: "foo",
    90  					SrcRange: hcl.Range{
    91  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
    92  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
    93  					},
    94  				},
    95  				hcl.TraverseIndex{
    96  					Key: cty.NumberIntVal(1),
    97  					SrcRange: hcl.Range{
    98  						Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
    99  						End:   hcl.Pos{Line: 1, Column: 7, Byte: 6},
   100  					},
   101  				},
   102  				hcl.TraverseIndex{
   103  					Key: cty.NumberIntVal(2),
   104  					SrcRange: hcl.Range{
   105  						Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
   106  						End:   hcl.Pos{Line: 1, Column: 10, Byte: 9},
   107  					},
   108  				},
   109  			},
   110  			0,
   111  		},
   112  		{
   113  			"foo[1].bar",
   114  			hcl.Traversal{
   115  				hcl.TraverseRoot{
   116  					Name: "foo",
   117  					SrcRange: hcl.Range{
   118  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
   119  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
   120  					},
   121  				},
   122  				hcl.TraverseIndex{
   123  					Key: cty.NumberIntVal(1),
   124  					SrcRange: hcl.Range{
   125  						Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
   126  						End:   hcl.Pos{Line: 1, Column: 7, Byte: 6},
   127  					},
   128  				},
   129  				hcl.TraverseAttr{
   130  					Name: "bar",
   131  					SrcRange: hcl.Range{
   132  						Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
   133  						End:   hcl.Pos{Line: 1, Column: 11, Byte: 10},
   134  					},
   135  				},
   136  			},
   137  			0,
   138  		},
   139  		{
   140  			"foo.",
   141  			hcl.Traversal{
   142  				hcl.TraverseRoot{
   143  					Name: "foo",
   144  					SrcRange: hcl.Range{
   145  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
   146  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
   147  					},
   148  				},
   149  			},
   150  			1, // attribute name required
   151  		},
   152  		{
   153  			"foo[",
   154  			hcl.Traversal{
   155  				hcl.TraverseRoot{
   156  					Name: "foo",
   157  					SrcRange: hcl.Range{
   158  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
   159  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
   160  					},
   161  				},
   162  			},
   163  			1, // index required
   164  		},
   165  		{
   166  			"foo[index]",
   167  			hcl.Traversal{
   168  				hcl.TraverseRoot{
   169  					Name: "foo",
   170  					SrcRange: hcl.Range{
   171  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
   172  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
   173  					},
   174  				},
   175  			},
   176  			1, // index must be literal
   177  		},
   178  		{
   179  			"foo[0",
   180  			hcl.Traversal{
   181  				hcl.TraverseRoot{
   182  					Name: "foo",
   183  					SrcRange: hcl.Range{
   184  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
   185  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
   186  					},
   187  				},
   188  				hcl.TraverseIndex{
   189  					Key: cty.NumberIntVal(0),
   190  					SrcRange: hcl.Range{
   191  						Start: hcl.Pos{Line: 1, Column: 4, Byte: 3},
   192  						End:   hcl.Pos{Line: 1, Column: 6, Byte: 5},
   193  					},
   194  				},
   195  			},
   196  			1, // missing close bracket
   197  		},
   198  		{
   199  			"foo 0",
   200  			hcl.Traversal{
   201  				hcl.TraverseRoot{
   202  					Name: "foo",
   203  					SrcRange: hcl.Range{
   204  						Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
   205  						End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},
   206  					},
   207  				},
   208  			},
   209  			1, // extra junk after traversal
   210  		},
   211  	}
   212  
   213  	for _, test := range tests {
   214  		t.Run(test.src, func(t *testing.T) {
   215  			got, diags := ParseTraversalAbs([]byte(test.src), "", hcl.Pos{Line: 1, Column: 1})
   216  			if len(diags) != test.diagCount {
   217  				for _, diag := range diags {
   218  					t.Logf(" - %s", diag.Error())
   219  				}
   220  				t.Errorf("wrong number of diagnostics %d; want %d", len(diags), test.diagCount)
   221  			}
   222  
   223  			if diff := deep.Equal(got, test.want); diff != nil {
   224  				for _, problem := range diff {
   225  					t.Error(problem)
   226  				}
   227  			}
   228  		})
   229  	}
   230  }