core: fix the tests in variables_test.go

This test required some adaptation for the new variable handling model in
the HCL2-oriented codepaths, where more of the handling is now done in the
"command" package.

The initial reorganization of this test was not correct, so this is a
further revision to adapt the original assertions to the new model as much
as possible, removing a few tests that no longer make sense in the new
world.
This commit is contained in:
Martin Atkins 2018-05-07 16:47:24 -07:00
parent 60ad24229f
commit c58bdc6390
2 changed files with 193 additions and 31 deletions

View File

@ -1,6 +1,8 @@
package terraform
import (
"fmt"
"github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/tfdiags"
"github.com/zclconf/go-cty/cty"
@ -57,6 +59,18 @@ const (
ValueFromCaller ValueSourceType = 'S'
)
func (v *InputValue) GoString() string {
if (v.SourceRange != tfdiags.SourceRange{}) {
return fmt.Sprintf("&terraform.InputValue{Value: %#v, SourceType: %#v, SourceRange: %#v}", v.Value, v.SourceType, v.SourceRange)
} else {
return fmt.Sprintf("&terraform.InputValue{Value: %#v, SourceType: %#v}", v.Value, v.SourceType)
}
}
func (v ValueSourceType) GoString() string {
return fmt.Sprintf("terraform.%s", v)
}
//go:generate stringer -type ValueSourceType
// InputValues is a map of InputValue instances.
@ -124,3 +138,84 @@ func DefaultVariableValues(configs map[string]*configs.Variable) InputValues {
}
return ret
}
// SameValues returns true if the given InputValues has the same values as
// the receiever, disregarding the source types and source ranges.
//
// Values are compared using the cty "RawEquals" method, which means that
// unknown values can be considered equal to one another if they are of the
// same type.
func (vv InputValues) SameValues(other InputValues) bool {
if len(vv) != len(other) {
return false
}
for k, v := range vv {
ov, exists := other[k]
if !exists {
return false
}
if !v.Value.RawEquals(ov.Value) {
return false
}
}
return true
}
// HasValues returns true if the reciever has the same values as in the given
// map, disregarding the source types and source ranges.
//
// Values are compared using the cty "RawEquals" method, which means that
// unknown values can be considered equal to one another if they are of the
// same type.
func (vv InputValues) HasValues(vals map[string]cty.Value) bool {
if len(vv) != len(vals) {
return false
}
for k, v := range vv {
oVal, exists := vals[k]
if !exists {
return false
}
if !v.Value.RawEquals(oVal) {
return false
}
}
return true
}
// Identical returns true if the given InputValues has the same values,
// source types, and source ranges as the receiver.
//
// Values are compared using the cty "RawEquals" method, which means that
// unknown values can be considered equal to one another if they are of the
// same type.
//
// This method is primarily for testing. For most practical purposes, it's
// better to use SameValues or HasValues.
func (vv InputValues) Identical(other InputValues) bool {
if len(vv) != len(other) {
return false
}
for k, v := range vv {
ov, exists := other[k]
if !exists {
return false
}
if !v.Value.RawEquals(ov.Value) {
return false
}
if v.SourceType != ov.SourceType {
return false
}
if v.SourceRange != ov.SourceRange {
return false
}
}
return true
}

View File

@ -1,25 +1,52 @@
package terraform
import (
"reflect"
"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) {
cases := map[string]struct {
tests := map[string]struct {
Module string
Override map[string]cty.Value
Expected map[string]cty.Value
Want InputValues
}{
"config only": {
"vars-basic",
nil,
map[string]cty.Value{
"a": cty.StringVal("foo"),
"b": cty.ListValEmpty(cty.String),
"c": cty.MapValEmpty(cty.String),
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},
},
},
},
},
@ -35,24 +62,49 @@ func TestVariables(t *testing.T) {
"foo": cty.StringVal("bar"),
}),
},
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,
map[string]cty.Value{
"a": cty.StringVal("1"),
"b": cty.StringVal("0"),
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},
},
},
},
},
@ -62,9 +114,15 @@ func TestVariables(t *testing.T) {
"a": cty.StringVal("foo"),
"b": cty.StringVal("bar"),
},
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,
},
},
},
@ -74,23 +132,32 @@ func TestVariables(t *testing.T) {
"a": cty.False,
"b": cty.True,
},
map[string]cty.Value{
"a": cty.StringVal("0"),
"b": cty.StringVal("1"),
InputValues{
"a": &InputValue{
Value: cty.False,
SourceType: ValueFromCaller,
},
"b": &InputValue{
Value: cty.True,
SourceType: ValueFromCaller,
},
},
},
}
for name, tc := range cases {
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, tc.Module)
m := testModule(t, test.Module)
fromConfig := DefaultVariableValues(m.Module.Variables)
overrides := InputValuesFromCaller(tc.Override)
actual := fromConfig.Override(overrides)
overrides := InputValuesFromCaller(test.Override)
got := fromConfig.Override(overrides)
if !reflect.DeepEqual(actual, tc.Expected) {
t.Fatalf("%s\n\nexpected: %#v\n\ngot: %#v", name, tc.Expected, actual)
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)
}
})
}