hcl/ext/dynblock/variables_test.go

156 lines
4.2 KiB
Go

package dynblock
import (
"reflect"
"testing"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
"github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)
func TestVariables(t *testing.T) {
const src = `
# We have some references to things inside the "val" attribute inside each
# of our "b" blocks, which should be included in the result of WalkVariables
# but not WalkExpandVariables.
a {
dynamic "b" {
for_each = [for i, v in some_list_0: "${i}=${v},${baz}"]
labels = ["${b.value} ${something_else_0}"]
content {
val = "${b.value} ${something_else_1}"
}
}
}
dynamic "a" {
for_each = some_list_1
content {
b "foo" {
val = "${a.value} ${something_else_2}"
}
dynamic "b" {
for_each = some_list_2
iterator = dyn_b
labels = ["${a.value} ${dyn_b.value} ${b} ${something_else_3}"]
content {
val = "${a.value} ${dyn_b.value} ${something_else_4}"
}
}
}
}
dynamic "a" {
for_each = some_list_3
iterator = dyn_a
content {
b "foo" {
val = "${dyn_a.value} ${something_else_5}"
}
dynamic "b" {
for_each = some_list_4
labels = ["${dyn_a.value} ${b.value} ${a} ${something_else_6}"]
content {
val = "${dyn_a.value} ${b.value} ${something_else_7}"
}
}
}
}
`
f, diags := hclsyntax.ParseConfig([]byte(src), "", hcl.Pos{})
if len(diags) != 0 {
t.Errorf("unexpected diagnostics during parse")
for _, diag := range diags {
t.Logf("- %s", diag)
}
return
}
spec := &hcldec.BlockListSpec{
TypeName: "a",
Nested: &hcldec.BlockMapSpec{
TypeName: "b",
LabelNames: []string{"key"},
Nested: &hcldec.AttrSpec{
Name: "val",
Type: cty.String,
},
},
}
t.Run("WalkVariables", func(t *testing.T) {
traversals := VariablesHCLDec(f.Body, spec)
got := make([]string, len(traversals))
for i, traversal := range traversals {
got[i] = traversal.RootName()
}
// The block structure is traversed one level at a time, so the ordering
// here is reflecting first a pass of the root, then the first child
// under the root, then the first child under that, etc.
want := []string{
"some_list_1",
"some_list_3",
"some_list_0",
"baz",
"something_else_0",
"something_else_1", // Would not be included for WalkExpandVariables because it only appears in content
"some_list_2",
"b", // This is correct because it is referenced in a context where the iterator is overridden to be dyn_b
"something_else_3",
"something_else_2", // Would not be included for WalkExpandVariables because it only appears in content
"something_else_4", // Would not be included for WalkExpandVariables because it only appears in content
"some_list_4",
"a", // This is correct because it is referenced in a context where the iterator is overridden to be dyn_a
"something_else_6",
"something_else_5", // Would not be included for WalkExpandVariables because it only appears in content
"something_else_7", // Would not be included for WalkExpandVariables because it only appears in content
}
if !reflect.DeepEqual(got, want) {
t.Errorf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want))
}
})
t.Run("WalkExpandVariables", func(t *testing.T) {
traversals := ExpandVariablesHCLDec(f.Body, spec)
got := make([]string, len(traversals))
for i, traversal := range traversals {
got[i] = traversal.RootName()
}
// The block structure is traversed one level at a time, so the ordering
// here is reflecting first a pass of the root, then the first child
// under the root, then the first child under that, etc.
want := []string{
"some_list_1",
"some_list_3",
"some_list_0",
"baz",
"something_else_0",
"some_list_2",
"b", // This is correct because it is referenced in a context where the iterator is overridden to be dyn_b
"something_else_3",
"some_list_4",
"a", // This is correct because it is referenced in a context where the iterator is overridden to be dyn_a
"something_else_6",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want))
}
})
}