Skip to content

Commit 6d45157

Browse files
terraform: lang.Data fake for use in unit tests
Our real implementation of the lang.Data interface depends on just about everything else in the modules runtime to implement its behavior, and so it's not really appropriate to use in unit tests. This new implementation is considerably simpler, just returning values predefined in a set of fixed tables. This is appropriate for unit tests of features that perform expression evaluation as a side-effect of their work but that don't contribute their own values to the real evaluation data implementation.
1 parent c61201d commit 6d45157

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

internal/terraform/evaluate_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package terraform
55

66
import (
7+
"fmt"
78
"testing"
89

910
"github.com/davecgh/go-spew/spew"
@@ -617,3 +618,102 @@ func evaluatorForModule(stateSync *states.SyncState, changesSync *plans.ChangesS
617618
NamedValues: namedvals.NewState(),
618619
}
619620
}
621+
622+
// fakeEvaluationData is an implementation of [lang.Data] that answers most
623+
// questions just by returning data directly from the maps stored inside it.
624+
type fakeEvaluationData struct {
625+
checkBlocks map[addrs.Check]cty.Value
626+
countAttrs map[addrs.CountAttr]cty.Value
627+
forEachAttrs map[addrs.ForEachAttr]cty.Value
628+
inputVariables map[addrs.InputVariable]cty.Value
629+
localValues map[addrs.LocalValue]cty.Value
630+
modules map[addrs.ModuleCall]cty.Value
631+
outputValues map[addrs.OutputValue]cty.Value
632+
pathAttrs map[addrs.PathAttr]cty.Value
633+
resources map[addrs.Resource]cty.Value
634+
runBlocks map[addrs.Run]cty.Value
635+
terraformAttrs map[addrs.TerraformAttr]cty.Value
636+
637+
// staticValidateRefs optionally implements [lang.Data.StaticValidateReferences],
638+
// but can be left as nil to just skip static validation altogether.
639+
staticValidateRefs func(refs []*addrs.Reference, self addrs.Referenceable, source addrs.Referenceable) tfdiags.Diagnostics
640+
}
641+
642+
var _ lang.Data = (*fakeEvaluationData)(nil)
643+
644+
func fakeEvaluationDataLookup[Addr interface {
645+
comparable
646+
addrs.Referenceable
647+
}](addr Addr, _ tfdiags.SourceRange, table map[Addr]cty.Value) (cty.Value, tfdiags.Diagnostics) {
648+
ret, ok := table[addr]
649+
if !ok {
650+
var diags tfdiags.Diagnostics
651+
diags = diags.Append(fmt.Errorf("fakeEvaluationData does not know about %s", addr))
652+
return cty.DynamicVal, diags
653+
}
654+
return ret, nil
655+
}
656+
657+
// GetCheckBlock implements lang.Data.
658+
func (d *fakeEvaluationData) GetCheckBlock(addr addrs.Check, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
659+
return fakeEvaluationDataLookup(addr, rng, d.checkBlocks)
660+
}
661+
662+
// GetCountAttr implements lang.Data.
663+
func (d *fakeEvaluationData) GetCountAttr(addr addrs.CountAttr, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
664+
return fakeEvaluationDataLookup(addr, rng, d.countAttrs)
665+
}
666+
667+
// GetForEachAttr implements lang.Data.
668+
func (d *fakeEvaluationData) GetForEachAttr(addr addrs.ForEachAttr, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
669+
return fakeEvaluationDataLookup(addr, rng, d.forEachAttrs)
670+
}
671+
672+
// GetInputVariable implements lang.Data.
673+
func (d *fakeEvaluationData) GetInputVariable(addr addrs.InputVariable, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
674+
return fakeEvaluationDataLookup(addr, rng, d.inputVariables)
675+
}
676+
677+
// GetLocalValue implements lang.Data.
678+
func (d *fakeEvaluationData) GetLocalValue(addr addrs.LocalValue, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
679+
return fakeEvaluationDataLookup(addr, rng, d.localValues)
680+
}
681+
682+
// GetModule implements lang.Data.
683+
func (d *fakeEvaluationData) GetModule(addr addrs.ModuleCall, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
684+
return fakeEvaluationDataLookup(addr, rng, d.modules)
685+
}
686+
687+
// GetOutput implements lang.Data.
688+
func (d *fakeEvaluationData) GetOutput(addr addrs.OutputValue, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
689+
return fakeEvaluationDataLookup(addr, rng, d.outputValues)
690+
}
691+
692+
// GetPathAttr implements lang.Data.
693+
func (d *fakeEvaluationData) GetPathAttr(addr addrs.PathAttr, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
694+
return fakeEvaluationDataLookup(addr, rng, d.pathAttrs)
695+
}
696+
697+
// GetResource implements lang.Data.
698+
func (d *fakeEvaluationData) GetResource(addr addrs.Resource, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
699+
return fakeEvaluationDataLookup(addr, rng, d.resources)
700+
}
701+
702+
// GetRunBlock implements lang.Data.
703+
func (d *fakeEvaluationData) GetRunBlock(addr addrs.Run, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
704+
return fakeEvaluationDataLookup(addr, rng, d.runBlocks)
705+
}
706+
707+
// GetTerraformAttr implements lang.Data.
708+
func (d *fakeEvaluationData) GetTerraformAttr(addr addrs.TerraformAttr, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
709+
return fakeEvaluationDataLookup(addr, rng, d.terraformAttrs)
710+
}
711+
712+
// StaticValidateReferences implements lang.Data.
713+
func (d *fakeEvaluationData) StaticValidateReferences(refs []*addrs.Reference, self addrs.Referenceable, source addrs.Referenceable) tfdiags.Diagnostics {
714+
if d.staticValidateRefs == nil {
715+
// By default we just skip static validation
716+
return nil
717+
}
718+
return d.staticValidateRefs(refs, self, source)
719+
}

0 commit comments

Comments
 (0)