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