opentofu/terraform/eval_local_test.go
Martin Atkins 176ae6e95f core: Detect and reject self-referencing local values
We already catch indirect cycles through the normal cycle detector, but
we never create self-edges in the graph so we need to handle a direct
self-reference separately here.

The prior behavior was simply to produce an incorrect result (since the
local value wasn't assigned a new value yet).

This fixes #18503.
2018-12-19 13:46:01 -08:00

87 lines
1.7 KiB
Go

package terraform
import (
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/config/hcl2shim"
"github.com/hashicorp/terraform/states"
)
func TestEvalLocal_impl(t *testing.T) {
var _ EvalNode = new(EvalLocal)
}
func TestEvalLocal(t *testing.T) {
tests := []struct {
Value string
Want interface{}
Err bool
}{
{
"hello!",
"hello!",
false,
},
{
"",
"",
false,
},
{
"Hello, ${local.foo}",
nil,
true, // self-referencing
},
}
for _, test := range tests {
t.Run(test.Value, func(t *testing.T) {
expr, diags := hclsyntax.ParseTemplate([]byte(test.Value), "", hcl.Pos{Line: 1, Column: 1})
if diags.HasErrors() {
t.Fatal(diags.Error())
}
n := &EvalLocal{
Addr: addrs.LocalValue{Name: "foo"},
Expr: expr,
}
ctx := &MockEvalContext{
StateState: states.NewState().SyncWrapper(),
EvaluateExprResult: hcl2shim.HCL2ValueFromConfigValue(test.Want),
}
_, err := n.Eval(ctx)
if (err != nil) != test.Err {
if err != nil {
t.Errorf("unexpected error: %s", err)
} else {
t.Errorf("successful Eval; want error")
}
}
ms := ctx.StateState.Module(addrs.RootModuleInstance)
gotLocals := ms.LocalValues
wantLocals := map[string]cty.Value{}
if test.Want != nil {
wantLocals["foo"] = hcl2shim.HCL2ValueFromConfigValue(test.Want)
}
if !reflect.DeepEqual(gotLocals, wantLocals) {
t.Errorf(
"wrong locals after Eval\ngot: %swant: %s",
spew.Sdump(gotLocals), spew.Sdump(wantLocals),
)
}
})
}
}