terraform/internal/lang/globalref/validate_test.go
2026-02-17 13:56:34 +00:00

338 lines
9.7 KiB
Go

// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1
package globalref
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/configs/configschema"
"github.com/hashicorp/terraform/internal/tfdiags"
)
func TestWalkBlock(t *testing.T) {
primitiveAttribute := &configschema.Attribute{
Type: cty.String,
}
nestedAttributes := map[string]*configschema.Attribute{
"primitive": primitiveAttribute,
"0": primitiveAttribute,
}
simpleBlock := configschema.Block{
Attributes: map[string]*configschema.Attribute{
"primitive": primitiveAttribute,
"0": primitiveAttribute,
"object": {
Type: cty.Object(map[string]cty.Type{
"primitive": cty.String,
"0": cty.String,
}),
},
"list": {
Type: cty.List(cty.String),
},
"set": {
Type: cty.Set(cty.String),
},
"map": {
Type: cty.Map(cty.String),
},
"nested_single": {
NestedType: &configschema.Object{
Attributes: nestedAttributes,
Nesting: configschema.NestingSingle,
},
},
"nested_list": {
NestedType: &configschema.Object{
Attributes: nestedAttributes,
Nesting: configschema.NestingList,
},
},
"nested_set": {
NestedType: &configschema.Object{
Attributes: nestedAttributes,
Nesting: configschema.NestingSet,
},
},
"nested_map": {
NestedType: &configschema.Object{
Attributes: nestedAttributes,
Nesting: configschema.NestingMap,
},
},
},
}
schema := &configschema.Block{
Attributes: simpleBlock.Attributes,
BlockTypes: map[string]*configschema.NestedBlock{
"nested_single_block": {
Block: simpleBlock,
Nesting: configschema.NestingSingle,
},
"nested_list_block": {
Block: simpleBlock,
Nesting: configschema.NestingList,
},
"nested_set_block": {
Block: simpleBlock,
Nesting: configschema.NestingSet,
},
"nested_map_block": {
Block: simpleBlock,
Nesting: configschema.NestingMap,
},
},
}
tcs := map[string]struct {
traversal string
want string
}{
"empty": {
traversal: "resource_type.resource_name",
},
// normal types
"primitive": {
traversal: "resource_type.resource_name.primitive",
want: ".primitive",
},
"primitive (wrong)": {
traversal: "resource_type.resource_name.primitive.extra",
want: ".primitive",
},
"object": {
traversal: "resource_type.resource_name.object.primitive",
want: ".object.primitive",
},
"object (missing)": {
traversal: "resource_type.resource_name.object.missing",
want: ".object",
},
"object (valid string index)": {
traversal: "resource_type.resource_name.object[\"primitive\"]",
want: ".object.primitive",
},
"object (invalid string index)": {
traversal: "resource_type.resource_name.object[\"missing\"]",
want: ".object",
},
"object (valid number index)": {
traversal: "resource_type.resource_name.object[0]",
want: ".object.0",
},
"object (invalid number index)": {
traversal: "resource_type.resource_name.object[1]",
want: ".object",
},
"list": {
traversal: "resource_type.resource_name.list[0]",
want: ".list[0]",
},
"list (string index)": {
traversal: "resource_type.resource_name.list[\"key\"]",
want: ".list",
},
"list (valid string index)": {
traversal: "resource_type.resource_name.list[\"0\"]",
want: ".list[0]",
},
"list (string attribute)": {
traversal: "resource_type.resource_name.list.primitive",
want: ".list",
},
"set (integer index)": {
traversal: "resource_type.resource_name.set[0]",
want: ".set",
},
"set (string index)": {
traversal: "resource_type.resource_name.set[\"key\"]",
want: ".set",
},
"set (string attribute)": {
traversal: "resource_type.resource_name.set.primitive",
want: ".set",
},
"map": {
traversal: "resource_type.resource_name.map[\"key\"]",
want: ".map[\"key\"]",
},
"map (integer index)": {
traversal: "resource_type.resource_name.map[0]",
want: ".map[\"0\"]",
},
"map (string attribute)": {
traversal: "resource_type.resource_name.map.key",
want: ".map[\"key\"]",
},
// nested types
"nested object": {
traversal: "resource_type.resource_name.nested_single.primitive",
want: ".nested_single.primitive",
},
"nested object (missing)": {
traversal: "resource_type.resource_name.nested_single.missing",
want: ".nested_single",
},
"nested object (valid string index)": {
traversal: "resource_type.resource_name.nested_single[\"primitive\"]",
want: ".nested_single.primitive",
},
"nested object (invalid string index)": {
traversal: "resource_type.resource_name.nested_single[\"missing\"]",
want: ".nested_single",
},
"nested object (valid number index)": {
traversal: "resource_type.resource_name.nested_single[0]",
want: ".nested_single.0",
},
"nested object (invalid number index)": {
traversal: "resource_type.resource_name.nested_single[1]",
want: ".nested_single",
},
"nested list": {
traversal: "resource_type.resource_name.nested_list[0]",
want: ".nested_list[0]",
},
"nested list (string index)": {
traversal: "resource_type.resource_name.nested_list[\"key\"]",
want: ".nested_list",
},
"nested list (valid string index)": {
traversal: "resource_type.resource_name.nested_list[\"0\"]",
want: ".nested_list[0]",
},
"nested list (string attribute)": {
traversal: "resource_type.resource_name.nested_list.primitive",
want: ".nested_list",
},
"nested set (integer index)": {
traversal: "resource_type.resource_name.nested_set[0]",
want: ".nested_set",
},
"nested set (string index)": {
traversal: "resource_type.resource_name.nested_set[\"key\"]",
want: ".nested_set",
},
"nested set (string attribute)": {
traversal: "resource_type.resource_name.nested_set.primitive",
want: ".nested_set",
},
"nested map": {
traversal: "resource_type.resource_name.nested_map[\"key\"]",
want: ".nested_map[\"key\"]",
},
"nested map (integer index)": {
traversal: "resource_type.resource_name.nested_map[0]",
want: ".nested_map[\"0\"]",
},
"nested map (string attribute)": {
traversal: "resource_type.resource_name.nested_map.key",
want: ".nested_map[\"key\"]",
},
// blocks
"nested object block": {
traversal: "resource_type.resource_name.nested_single_block.primitive",
want: ".nested_single_block.primitive",
},
"nested object block (missing)": {
traversal: "resource_type.resource_name.nested_single_block.missing",
want: ".nested_single_block",
},
"nested object block (valid string index)": {
traversal: "resource_type.resource_name.nested_single_block[\"primitive\"]",
want: ".nested_single_block.primitive",
},
"nested object block (invalid string index)": {
traversal: "resource_type.resource_name.nested_single_block[\"missing\"]",
want: ".nested_single_block",
},
"nested object block (valid number index)": {
traversal: "resource_type.resource_name.nested_single_block[0]",
want: ".nested_single_block.0",
},
"nested object block (invalid number index)": {
traversal: "resource_type.resource_name.nested_single_block[1]",
want: ".nested_single_block",
},
"nested list block": {
traversal: "resource_type.resource_name.nested_list_block[0].primitive",
want: ".nested_list_block[0].primitive",
},
"nested list block (invalid string index)": {
traversal: "resource_type.resource_name.nested_list_block[\"index\"].primitive",
want: ".nested_list_block",
},
"nested list block (valid string index)": {
traversal: "resource_type.resource_name.nested_list_block[\"0\"].primitive",
want: ".nested_list_block[0].primitive",
},
"nested list block (string attribute)": {
traversal: "resource_type.resource_name.nested_list_block.primitive",
want: ".nested_list_block",
},
"nested set block (integer index)": {
traversal: "resource_type.resource_name.nested_set_block[0].primitive",
want: ".nested_set_block",
},
"nested set block (string index)": {
traversal: "resource_type.resource_name.nested_set_block[\"index\"].primitive",
want: ".nested_set_block",
},
"nested set block (string attribute)": {
traversal: "resource_type.resource_name.nested_set_block.primitive",
want: ".nested_set_block",
},
"nested map block": {
traversal: "resource_type.resource_name.nested_map_block[\"key\"].primitive",
want: ".nested_map_block[\"key\"].primitive",
},
"nested map block (integer index)": {
traversal: "resource_type.resource_name.nested_map_block[0].primitive",
want: ".nested_map_block[\"0\"].primitive",
},
"nested map block (string attribute)": {
traversal: "resource_type.resource_name.nested_map_block.key.primitive",
want: ".nested_map_block[\"key\"].primitive",
},
// resource instances
"resource instance reference (count)": {
traversal: "resource_type.resource_name[0].primitive",
want: ".primitive",
},
"resource instance reference (for each)": {
traversal: "resource_type.resource_name[\"key\"].primitive",
want: ".primitive",
},
}
for name, tc := range tcs {
t.Run(name, func(t *testing.T) {
ref, diags := addrs.ParseRefStr(tc.traversal)
if diags.HasErrors() {
t.Fatal(diags.Err())
}
ret := walkBlock(schema, ref.Remaining)
got := tfdiags.TraversalStr(ret)
if diff := cmp.Diff(tc.want, got); diff != "" {
t.Fatal(diags, diff)
}
})
}
}