| package hcldec |
| |
| import ( |
| "fmt" |
| "reflect" |
| "testing" |
| |
| "github.com/hashicorp/hcl/v2" |
| "github.com/hashicorp/hcl/v2/hclsyntax" |
| "github.com/zclconf/go-cty/cty" |
| ) |
| |
| func TestVariables(t *testing.T) { |
| tests := []struct { |
| config string |
| spec Spec |
| want []hcl.Traversal |
| }{ |
| { |
| ``, |
| &ObjectSpec{}, |
| nil, |
| }, |
| { |
| "a = foo\n", |
| &ObjectSpec{}, |
| nil, // "a" is not actually used, so "foo" is not required |
| }, |
| { |
| "a = foo\n", |
| &AttrSpec{ |
| Name: "a", |
| }, |
| []hcl.Traversal{ |
| { |
| hcl.TraverseRoot{ |
| Name: "foo", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| }, |
| }, |
| }, |
| { |
| "a = foo\nb = bar\n", |
| &DefaultSpec{ |
| Primary: &AttrSpec{ |
| Name: "a", |
| }, |
| Default: &AttrSpec{ |
| Name: "b", |
| }, |
| }, |
| []hcl.Traversal{ |
| { |
| hcl.TraverseRoot{ |
| Name: "foo", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| }, |
| { |
| hcl.TraverseRoot{ |
| Name: "bar", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 5, Byte: 12}, |
| End: hcl.Pos{Line: 2, Column: 8, Byte: 15}, |
| }, |
| }, |
| }, |
| }, |
| }, |
| { |
| "a = foo\n", |
| &ObjectSpec{ |
| "a": &AttrSpec{ |
| Name: "a", |
| }, |
| }, |
| []hcl.Traversal{ |
| { |
| hcl.TraverseRoot{ |
| Name: "foo", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| }, |
| }, |
| }, |
| { |
| ` |
| b { |
| a = foo |
| } |
| `, |
| &BlockSpec{ |
| TypeName: "b", |
| Nested: &AttrSpec{ |
| Name: "a", |
| }, |
| }, |
| []hcl.Traversal{ |
| { |
| hcl.TraverseRoot{ |
| Name: "foo", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 3, Column: 7, Byte: 11}, |
| End: hcl.Pos{Line: 3, Column: 10, Byte: 14}, |
| }, |
| }, |
| }, |
| }, |
| }, |
| { |
| ` |
| b { |
| a = foo |
| b = bar |
| } |
| `, |
| &BlockAttrsSpec{ |
| TypeName: "b", |
| ElementType: cty.String, |
| }, |
| []hcl.Traversal{ |
| { |
| hcl.TraverseRoot{ |
| Name: "foo", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 3, Column: 7, Byte: 11}, |
| End: hcl.Pos{Line: 3, Column: 10, Byte: 14}, |
| }, |
| }, |
| }, |
| { |
| hcl.TraverseRoot{ |
| Name: "bar", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 4, Column: 7, Byte: 21}, |
| End: hcl.Pos{Line: 4, Column: 10, Byte: 24}, |
| }, |
| }, |
| }, |
| }, |
| }, |
| { |
| ` |
| b { |
| a = foo |
| } |
| b { |
| a = bar |
| } |
| c { |
| a = baz |
| } |
| `, |
| &BlockListSpec{ |
| TypeName: "b", |
| Nested: &AttrSpec{ |
| Name: "a", |
| }, |
| }, |
| []hcl.Traversal{ |
| { |
| hcl.TraverseRoot{ |
| Name: "foo", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 3, Column: 7, Byte: 11}, |
| End: hcl.Pos{Line: 3, Column: 10, Byte: 14}, |
| }, |
| }, |
| }, |
| { |
| hcl.TraverseRoot{ |
| Name: "bar", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 6, Column: 7, Byte: 27}, |
| End: hcl.Pos{Line: 6, Column: 10, Byte: 30}, |
| }, |
| }, |
| }, |
| }, |
| }, |
| } |
| |
| for i, test := range tests { |
| t.Run(fmt.Sprintf("%02d-%s", i, test.config), func(t *testing.T) { |
| file, diags := hclsyntax.ParseConfig([]byte(test.config), "", hcl.Pos{Line: 1, Column: 1, Byte: 0}) |
| if len(diags) != 0 { |
| t.Errorf("wrong number of diagnostics from ParseConfig %d; want %d", len(diags), 0) |
| for _, diag := range diags { |
| t.Logf(" - %s", diag.Error()) |
| } |
| } |
| body := file.Body |
| |
| got := Variables(body, test.spec) |
| |
| if !reflect.DeepEqual(got, test.want) { |
| t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.want) |
| } |
| }) |
| } |
| |
| } |