| 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)) |
| } |
| }) |
| } |