opentofu/terraform/variables_test.go
Martin Atkins 1226e77999 core: Remove GraphSemanticChecker, etc
These overly-general interfaces are no longer used anywhere, and their
presence in the important-sounding semantics.go file was a distracting
red herring.

We'd previously replaced the one checker in here with a simple helper
function for checking input variables, and that's arguably more at home
with all of the other InputValue functionality in variables.go, and that
allows us to remove semantics.go (and its associated test file) altogether
and make room for some forthcoming new files for static validation.
2018-11-26 08:25:03 -08:00

208 lines
5.2 KiB
Go

package terraform
import (
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/hashicorp/terraform/tfdiags"
"github.com/go-test/deep"
"github.com/zclconf/go-cty/cty"
)
func TestVariables(t *testing.T) {
tests := map[string]struct {
Module string
Override map[string]cty.Value
Want InputValues
}{
"config only": {
"vars-basic",
nil,
InputValues{
"a": &InputValue{
Value: cty.StringVal("foo"),
SourceType: ValueFromConfig,
SourceRange: tfdiags.SourceRange{
Filename: "test-fixtures/vars-basic/main.tf",
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
End: tfdiags.SourcePos{Line: 1, Column: 13, Byte: 12},
},
},
"b": &InputValue{
Value: cty.ListValEmpty(cty.DynamicPseudoType),
SourceType: ValueFromConfig,
SourceRange: tfdiags.SourceRange{
Filename: "test-fixtures/vars-basic/main.tf",
Start: tfdiags.SourcePos{Line: 6, Column: 1, Byte: 58},
End: tfdiags.SourcePos{Line: 6, Column: 13, Byte: 70},
},
},
"c": &InputValue{
Value: cty.MapValEmpty(cty.DynamicPseudoType),
SourceType: ValueFromConfig,
SourceRange: tfdiags.SourceRange{
Filename: "test-fixtures/vars-basic/main.tf",
Start: tfdiags.SourcePos{Line: 11, Column: 1, Byte: 111},
End: tfdiags.SourcePos{Line: 11, Column: 13, Byte: 123},
},
},
},
},
"override": {
"vars-basic",
map[string]cty.Value{
"a": cty.StringVal("bar"),
"b": cty.ListVal([]cty.Value{
cty.StringVal("foo"),
cty.StringVal("bar"),
}),
"c": cty.MapVal(map[string]cty.Value{
"foo": cty.StringVal("bar"),
}),
},
InputValues{
"a": &InputValue{
Value: cty.StringVal("bar"),
SourceType: ValueFromCaller,
},
"b": &InputValue{
Value: cty.ListVal([]cty.Value{
cty.StringVal("foo"),
cty.StringVal("bar"),
}),
SourceType: ValueFromCaller,
},
"c": &InputValue{
Value: cty.MapVal(map[string]cty.Value{
"foo": cty.StringVal("bar"),
}),
SourceType: ValueFromCaller,
},
},
},
"bools: config only": {
"vars-basic-bool",
nil,
InputValues{
"a": &InputValue{
Value: cty.True,
SourceType: ValueFromConfig,
SourceRange: tfdiags.SourceRange{
Filename: "test-fixtures/vars-basic-bool/main.tf",
Start: tfdiags.SourcePos{Line: 4, Column: 1, Byte: 177},
End: tfdiags.SourcePos{Line: 4, Column: 13, Byte: 189},
},
},
"b": &InputValue{
Value: cty.False,
SourceType: ValueFromConfig,
SourceRange: tfdiags.SourceRange{
Filename: "test-fixtures/vars-basic-bool/main.tf",
Start: tfdiags.SourcePos{Line: 8, Column: 1, Byte: 214},
End: tfdiags.SourcePos{Line: 8, Column: 13, Byte: 226},
},
},
},
},
"bools: override with string": {
"vars-basic-bool",
map[string]cty.Value{
"a": cty.StringVal("foo"),
"b": cty.StringVal("bar"),
},
InputValues{
"a": &InputValue{
Value: cty.StringVal("foo"),
SourceType: ValueFromCaller,
},
"b": &InputValue{
Value: cty.StringVal("bar"),
SourceType: ValueFromCaller,
},
},
},
"bools: override with bool": {
"vars-basic-bool",
map[string]cty.Value{
"a": cty.False,
"b": cty.True,
},
InputValues{
"a": &InputValue{
Value: cty.False,
SourceType: ValueFromCaller,
},
"b": &InputValue{
Value: cty.True,
SourceType: ValueFromCaller,
},
},
},
}
for name, test := range tests {
// Wrapped in a func so we can get defers to work
t.Run(name, func(t *testing.T) {
m := testModule(t, test.Module)
fromConfig := DefaultVariableValues(m.Module.Variables)
overrides := InputValuesFromCaller(test.Override)
got := fromConfig.Override(overrides)
if !got.Identical(test.Want) {
t.Errorf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(test.Want))
}
for _, problem := range deep.Equal(got, test.Want) {
t.Errorf(problem)
}
})
}
}
func TestSMCUserVariables(t *testing.T) {
c := testModule(t, "smc-uservars")
// No variables set
diags := checkInputVariables(c.Module.Variables, nil)
if !diags.HasErrors() {
t.Fatal("check succeeded, but want errors")
}
// Required variables set, optional variables unset
// This is still an error at this layer, since it's the caller's
// responsibility to have already merged in any default values.
diags = checkInputVariables(c.Module.Variables, InputValues{
"foo": &InputValue{
Value: cty.StringVal("bar"),
SourceType: ValueFromCLIArg,
},
})
if !diags.HasErrors() {
t.Fatal("check succeeded, but want errors")
}
// All variables set
diags = checkInputVariables(c.Module.Variables, InputValues{
"foo": &InputValue{
Value: cty.StringVal("bar"),
SourceType: ValueFromCLIArg,
},
"bar": &InputValue{
Value: cty.StringVal("baz"),
SourceType: ValueFromCLIArg,
},
"map": &InputValue{
Value: cty.StringVal("baz"), // okay because config has no type constraint
SourceType: ValueFromCLIArg,
},
})
if diags.HasErrors() {
//t.Fatal("check succeeded, but want errors")
t.Fatalf("unexpected errors: %s", diags.Err())
}
}