terraform/internal/namedvals/values_test.go
2026-02-17 13:56:34 +00:00

91 lines
5.3 KiB
Go

// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1
package namedvals
import (
"testing"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/zclconf/go-cty/cty"
)
func TestValues(t *testing.T) {
// The behavior of [values] is the same for all named value address types,
// and so we'll just use local values here as a placeholder and assume
// that input variables and output values would also work.
// The following addresses are taking some liberties with which combinations
// would actually be possible in practice with a real Terraform
// configuration -- unknowns and knowns cannot typically mix at the same
// known-expansion module prefix -- but the abstraction in this package
// doesn't aim to enforce those rules, and so we can expect it to be a
// little more flexible here than it really needs to be, as a way to
// reduce the amount of test setup we need.
childInst0 := addrs.ModuleInstance{{Name: "child", InstanceKey: addrs.IntKey(0)}}
childInst1 := addrs.ModuleInstance{{Name: "child", InstanceKey: addrs.IntKey(1)}}
childInst2 := addrs.ModuleInstance{{Name: "child", InstanceKey: addrs.IntKey(2)}}
childInstUnk := addrs.RootModuleInstance.UnexpandedChild(addrs.ModuleCall{Name: "child"})
grandchildInst0_0 := childInst0.Child("grandchild", addrs.IntKey(0))
grandchildInst1_unk := childInst1.UnexpandedChild(addrs.ModuleCall{Name: "grandchild"})
grandchildInst2_unk := childInst2.UnexpandedChild(addrs.ModuleCall{Name: "grandchild"})
grandchildInstUnk_unk := childInstUnk.Child(addrs.ModuleCall{Name: "grandchild"})
inRoot := addrs.LocalValue{Name: "in_root"}.Absolute(addrs.RootModuleInstance)
inChild0 := addrs.LocalValue{Name: "in_child"}.Absolute(childInst0)
inChildUnk := addrs.ObjectInPartialExpandedModule(childInstUnk, addrs.LocalValue{Name: "in_child"})
inGrandchild0_0 := addrs.LocalValue{Name: "in_grandchild"}.Absolute(grandchildInst0_0)
inGrandchild1_unk := addrs.ObjectInPartialExpandedModule(grandchildInst1_unk, addrs.LocalValue{Name: "in_grandchild"})
inGrandchild2_unk := addrs.ObjectInPartialExpandedModule(grandchildInst2_unk, addrs.LocalValue{Name: "in_grandchild"})
inGrandchildUnk_unk := addrs.ObjectInPartialExpandedModule(grandchildInstUnk_unk, addrs.LocalValue{Name: "in_grandchild"})
vals := newValues[addrs.LocalValue, addrs.AbsLocalValue]()
vals.SetExactResult(inRoot, cty.StringVal("in root"))
vals.SetExactResult(inChild0, cty.StringVal("in child 0"))
vals.SetExactResult(inGrandchild0_0, cty.StringVal("in grandchild 0, 0"))
vals.SetPlaceholderResult(inChildUnk, cty.StringVal("placeholder for all unknown instances of child"))
vals.SetPlaceholderResult(inGrandchild1_unk, cty.StringVal("placeholder for all unknown instances of child 1 grandchild"))
vals.SetPlaceholderResult(inGrandchildUnk_unk, cty.StringVal("placeholder for all unknown instances of child unknown grandchild"))
t.Run("exact values", func(t *testing.T) {
// Exact values require the given address to exactly match something
// that was registered.
if got, want := vals.GetExactResult(inRoot), cty.StringVal("in root"); !want.RawEquals(got) {
t.Errorf("wrong exact value for %s\ngot: %#v\nwant: %#v", inRoot, got, want)
}
if got, want := vals.GetExactResult(inChild0), cty.StringVal("in child 0"); !want.RawEquals(got) {
t.Errorf("wrong exact value for %s\ngot: %#v\nwant: %#v", inChild0, got, want)
}
if got, want := vals.GetExactResult(inGrandchild0_0), cty.StringVal("in grandchild 0, 0"); !want.RawEquals(got) {
t.Errorf("wrong exact value for %s\ngot: %#v\nwant: %#v", inGrandchild0_0, got, want)
}
})
t.Run("placeholder values", func(t *testing.T) {
// Placeholder values are selected by longest-prefix pattern matching,
// and so we can ask both for specific prefixes we registered above
// and for more specific prefixes that we didn't register but yet
// still match a less-specific address.
if got, want := vals.GetPlaceholderResult(inChildUnk), cty.StringVal("placeholder for all unknown instances of child"); !want.RawEquals(got) {
// This one exactly matches one of the address patterns we registered.
t.Errorf("wrong exact value for %s\ngot: %#v\nwant: %#v", inChildUnk, got, want)
}
if got, want := vals.GetPlaceholderResult(inGrandchild1_unk), cty.StringVal("placeholder for all unknown instances of child 1 grandchild"); !want.RawEquals(got) {
// This one exactly matches one of the address patterns we registered.
t.Errorf("wrong exact value for %s\ngot: %#v\nwant: %#v", inGrandchild1_unk, got, want)
}
if got, want := vals.GetPlaceholderResult(inGrandchild2_unk), cty.StringVal("placeholder for all unknown instances of child unknown grandchild"); !want.RawEquals(got) {
// This one falls back to the placeholder for when the child
// instance key isn't known, because there isn't a more specific
// placeholder available.
t.Errorf("wrong exact value for %s\ngot: %#v\nwant: %#v", inGrandchild2_unk, got, want)
}
if got, want := vals.GetPlaceholderResult(inGrandchildUnk_unk), cty.StringVal("placeholder for all unknown instances of child unknown grandchild"); !want.RawEquals(got) {
// This one falls back to the placeholder for when the child
// instance key isn't known, because we can't know which of
// the more specific placeholders to select.
t.Errorf("wrong exact value for %s\ngot: %#v\nwant: %#v", inGrandchildUnk_unk, got, want)
}
})
}