terraform/config/configschema/coerce_value_test.go

234 lines
4.5 KiB
Go

package configschema
import (
"testing"
"github.com/zclconf/go-cty/cty"
)
func TestCoerceValue(t *testing.T) {
tests := map[string]struct {
Schema *Block
Input cty.Value
WantValue cty.Value
WantErr string
}{
"empty schema and value": {
&Block{},
cty.EmptyObjectVal,
cty.EmptyObjectVal,
``,
},
"attribute present": {
&Block{
Attributes: map[string]*Attribute{
"foo": {
Type: cty.String,
Optional: true,
},
},
},
cty.ObjectVal(map[string]cty.Value{
"foo": cty.True,
}),
cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("true"),
}),
``,
},
"single block present": {
&Block{
BlockTypes: map[string]*NestedBlock{
"foo": {
Block: Block{},
Nesting: NestingSingle,
},
},
},
cty.ObjectVal(map[string]cty.Value{
"foo": cty.EmptyObjectVal,
}),
cty.ObjectVal(map[string]cty.Value{
"foo": cty.EmptyObjectVal,
}),
``,
},
"single block wrong type": {
&Block{
BlockTypes: map[string]*NestedBlock{
"foo": {
Block: Block{},
Nesting: NestingSingle,
},
},
},
cty.ObjectVal(map[string]cty.Value{
"foo": cty.True,
}),
cty.DynamicVal,
`an object is required`,
},
"missing optional attribute": {
&Block{
Attributes: map[string]*Attribute{
"foo": {
Type: cty.String,
Optional: true,
},
},
},
cty.EmptyObjectVal,
cty.ObjectVal(map[string]cty.Value{
"foo": cty.NullVal(cty.String),
}),
``,
},
"missing optional single block": {
&Block{
BlockTypes: map[string]*NestedBlock{
"foo": {
Block: Block{},
Nesting: NestingSingle,
},
},
},
cty.EmptyObjectVal,
cty.ObjectVal(map[string]cty.Value{
"foo": cty.NullVal(cty.EmptyObject),
}),
``,
},
"missing optional list block": {
&Block{
BlockTypes: map[string]*NestedBlock{
"foo": {
Block: Block{},
Nesting: NestingList,
},
},
},
cty.EmptyObjectVal,
cty.ObjectVal(map[string]cty.Value{
"foo": cty.ListValEmpty(cty.EmptyObject),
}),
``,
},
"missing optional set block": {
&Block{
BlockTypes: map[string]*NestedBlock{
"foo": {
Block: Block{},
Nesting: NestingSet,
},
},
},
cty.EmptyObjectVal,
cty.ObjectVal(map[string]cty.Value{
"foo": cty.SetValEmpty(cty.EmptyObject),
}),
``,
},
"missing optional map block": {
&Block{
BlockTypes: map[string]*NestedBlock{
"foo": {
Block: Block{},
Nesting: NestingMap,
},
},
},
cty.EmptyObjectVal,
cty.ObjectVal(map[string]cty.Value{
"foo": cty.MapValEmpty(cty.EmptyObject),
}),
``,
},
"missing required attribute": {
&Block{
Attributes: map[string]*Attribute{
"foo": {
Type: cty.String,
Required: true,
},
},
},
cty.EmptyObjectVal,
cty.DynamicVal,
`attribute "foo" is required`,
},
"missing required single block": {
&Block{
BlockTypes: map[string]*NestedBlock{
"foo": {
Block: Block{},
Nesting: NestingSingle,
MinItems: 1,
MaxItems: 1,
},
},
},
cty.EmptyObjectVal,
cty.DynamicVal,
`attribute "foo" is required`,
},
"missing required list block": {
&Block{
BlockTypes: map[string]*NestedBlock{
"foo": {
Block: Block{},
Nesting: NestingList,
MinItems: 1,
},
},
},
cty.EmptyObjectVal,
cty.DynamicVal,
`attribute "foo" is required`,
},
"missing required set block": {
&Block{
BlockTypes: map[string]*NestedBlock{
"foo": {
Block: Block{},
Nesting: NestingList,
MinItems: 1,
},
},
},
cty.EmptyObjectVal,
cty.DynamicVal,
`attribute "foo" is required`,
},
"extraneous attribute": {
&Block{},
cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("bar"),
}),
cty.DynamicVal,
`unexpected attribute "foo"`,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
gotValue, gotErrObj := test.Schema.CoerceValue(test.Input)
if gotErrObj == nil {
if test.WantErr != "" {
t.Fatalf("coersion succeeded; want error: %q", test.WantErr)
}
} else {
gotErr := gotErrObj.Error()
if gotErr != test.WantErr {
t.Fatalf("wrong error\ngot: %s\nwant: %s", gotErr, test.WantErr)
}
return
}
if !gotValue.RawEquals(test.WantValue) {
t.Errorf("wrong result\ninput: %#v\ngot: %#v\nwant: %#v", test.Input, gotValue, test.WantValue)
}
})
}
}