hclsyntax: Some tests for Walk
These tests are not yet comprehensive, but at least cover some normal cases and some cases that have some trickier behavior.
This commit is contained in:
parent
e1e97716f5
commit
983c83c156
179
hcl/hclsyntax/walk_test.go
Normal file
179
hcl/hclsyntax/walk_test.go
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
package hclsyntax
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/go-test/deep"
|
||||||
|
|
||||||
|
"github.com/hashicorp/hcl2/hcl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWalk(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
src string
|
||||||
|
want []testWalkCall
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
`1`,
|
||||||
|
[]testWalkCall{
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`foo`,
|
||||||
|
[]testWalkCall{
|
||||||
|
{testWalkEnter, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`1 + 1`,
|
||||||
|
[]testWalkCall{
|
||||||
|
{testWalkEnter, "*hclsyntax.BinaryOpExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.BinaryOpExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`(1 + 1)`,
|
||||||
|
[]testWalkCall{
|
||||||
|
{testWalkEnter, "*hclsyntax.BinaryOpExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.BinaryOpExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`a[0]`,
|
||||||
|
[]testWalkCall{
|
||||||
|
// because the index is constant here, the index is absorbed into the traversal
|
||||||
|
{testWalkEnter, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`0[foo]`, // semantically incorrect, but should still parse and be walkable
|
||||||
|
[]testWalkCall{
|
||||||
|
{testWalkEnter, "*hclsyntax.IndexExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.IndexExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`bar()`,
|
||||||
|
[]testWalkCall{
|
||||||
|
{testWalkEnter, "*hclsyntax.FunctionCallExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.FunctionCallExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`bar(1, a)`,
|
||||||
|
[]testWalkCall{
|
||||||
|
{testWalkEnter, "*hclsyntax.FunctionCallExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.FunctionCallExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`bar(1, a)[0]`,
|
||||||
|
[]testWalkCall{
|
||||||
|
{testWalkEnter, "*hclsyntax.RelativeTraversalExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.FunctionCallExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.FunctionCallExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.RelativeTraversalExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`[for x in foo: x + 1 if x < 10]`,
|
||||||
|
[]testWalkCall{
|
||||||
|
{testWalkEnter, "*hclsyntax.ForExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkEnter, "hclsyntax.ChildScope"},
|
||||||
|
{testWalkEnter, "*hclsyntax.BinaryOpExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.BinaryOpExpr"},
|
||||||
|
{testWalkExit, "hclsyntax.ChildScope"},
|
||||||
|
{testWalkEnter, "hclsyntax.ChildScope"},
|
||||||
|
{testWalkEnter, "*hclsyntax.BinaryOpExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.ScopeTraversalExpr"},
|
||||||
|
{testWalkEnter, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.LiteralValueExpr"},
|
||||||
|
{testWalkExit, "*hclsyntax.BinaryOpExpr"},
|
||||||
|
{testWalkExit, "hclsyntax.ChildScope"},
|
||||||
|
{testWalkExit, "*hclsyntax.ForExpr"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.src, func(t *testing.T) {
|
||||||
|
expr, diags := ParseExpression([]byte(test.src), "", hcl.Pos{Line: 1, Column: 1})
|
||||||
|
if diags.HasErrors() {
|
||||||
|
t.Fatalf("failed to parse expression: %s", diags.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
w := testWalker{}
|
||||||
|
diags = Walk(expr, &w)
|
||||||
|
if diags.HasErrors() {
|
||||||
|
t.Fatalf("failed to walk: %s", diags.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
got := w.Calls
|
||||||
|
if !reflect.DeepEqual(got, test.want) {
|
||||||
|
t.Errorf("wrong calls\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(test.want))
|
||||||
|
for _, problem := range deep.Equal(got, test.want) {
|
||||||
|
t.Errorf(problem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type testWalkMethod int
|
||||||
|
|
||||||
|
const testWalkEnter testWalkMethod = 1
|
||||||
|
const testWalkExit testWalkMethod = 2
|
||||||
|
|
||||||
|
type testWalkCall struct {
|
||||||
|
Method testWalkMethod
|
||||||
|
NodeType string
|
||||||
|
}
|
||||||
|
|
||||||
|
type testWalker struct {
|
||||||
|
Calls []testWalkCall
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *testWalker) Enter(node Node) hcl.Diagnostics {
|
||||||
|
w.Calls = append(w.Calls, testWalkCall{testWalkEnter, fmt.Sprintf("%T", node)})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *testWalker) Exit(node Node) hcl.Diagnostics {
|
||||||
|
w.Calls = append(w.Calls, testWalkCall{testWalkExit, fmt.Sprintf("%T", node)})
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user