Files
opentf/internal/lang/eval/module_instance_test.go
Martin Atkins 72a32f726d lang/eval: Beginnings of a different way to handle config eval
In "package tofu" today we try to do everything using a generic acyclic
graph model and generic graph walk, which _works_ but tends to make every
other part of the problem very hard to follow because we rely a lot on
sidecar shared mutable data structures to propagate results between the
isolated operations.

This is the beginning of an experimental new way to do it where the "graph"
is implied by a model that more closely represents how the language itself
works, with explicit modelling of the relationships between different
types of objects and letting results flow directly from one object to
another without any big shared mutable state.

There's still a lot to do before this is actually complete enough to
evaluate whether it's a viable new design, but I'm considering this a good
starting checkpoint since there's enough here to run a simple test of
propagating data all the way from input variables to output values via
intermediate local values.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
2025-10-27 10:15:41 -07:00

57 lines
1.6 KiB
Go

// Copyright (c) The OpenTofu Authors
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2023 HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package eval
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/zclconf/go-cty-debug/ctydebug"
"github.com/zclconf/go-cty/cty"
"github.com/opentofu/opentofu/internal/addrs"
"github.com/opentofu/opentofu/internal/configs"
"github.com/opentofu/opentofu/internal/lang/grapheval"
)
func TestCompileModuleInstance_valuesOnly(t *testing.T) {
// This is a relatively straightforward test of compiling a module
// instance containing only inert values (no resources, etc) and
// then pulling values out of it to make sure that it's wired together
// correctly. This is far from exhaustive but covers some of
// the fundamentals that more complex situations rely on.
module := configs.ModuleFromStringForTesting(t, `
variable "a" {
type = string
}
locals {
b = "${var.a}:${var.a}"
}
output "c" {
value = "${local.b}/${local.b}"
}
`)
call := &moduleInstanceCall{
inputValues: InputValuesForTesting(map[string]cty.Value{
"a": cty.True,
}),
}
inst := compileModuleInstance(module, addrs.ModuleSourceLocal("."), call, nil)
ctx := grapheval.ContextWithNewWorker(t.Context())
got, diags := inst.Value(ctx)
if diags.HasErrors() {
t.Fatalf("unexpected errors: %s", diags.Err().Error())
}
want := cty.ObjectVal(map[string]cty.Value{
"c": cty.StringVal("true:true/true:true"),
})
if diff := cmp.Diff(want, got, ctydebug.CmpOptions); diff != "" {
t.Error("wrong result\n" + diff)
}
}