blob: ce998cf65e4be335f2fdbf25b7313c6af0f0b3e2 [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package terraform
import (
"reflect"
"testing"
"github.com/zclconf/go-cty/cty"
ctyjson "github.com/zclconf/go-cty/cty/json"
)
func TestStripRemovedStateAttributes(t *testing.T) {
cases := []struct {
name string
state map[string]interface{}
expect map[string]interface{}
ty cty.Type
modified bool
}{
{
"removed string",
map[string]interface{}{
"a": "ok",
"b": "gone",
},
map[string]interface{}{
"a": "ok",
},
cty.Object(map[string]cty.Type{
"a": cty.String,
}),
true,
},
{
"removed null",
map[string]interface{}{
"a": "ok",
"b": nil,
},
map[string]interface{}{
"a": "ok",
},
cty.Object(map[string]cty.Type{
"a": cty.String,
}),
true,
},
{
"has large number",
map[string]interface{}{
"a": "ok",
"b": nil,
},
map[string]interface{}{
"a": "ok",
},
cty.Object(map[string]cty.Type{
"a": cty.String,
}),
true,
},
{
"removed nested string",
map[string]interface{}{
"a": "ok",
"b": map[string]interface{}{
"a": "ok",
"b": "removed",
},
},
map[string]interface{}{
"a": "ok",
"b": map[string]interface{}{
"a": "ok",
},
},
cty.Object(map[string]cty.Type{
"a": cty.String,
"b": cty.Object(map[string]cty.Type{
"a": cty.String,
}),
}),
true,
},
{
"removed nested list",
map[string]interface{}{
"a": "ok",
"b": map[string]interface{}{
"a": "ok",
"b": []interface{}{"removed"},
},
},
map[string]interface{}{
"a": "ok",
"b": map[string]interface{}{
"a": "ok",
},
},
cty.Object(map[string]cty.Type{
"a": cty.String,
"b": cty.Object(map[string]cty.Type{
"a": cty.String,
}),
}),
true,
},
{
"removed keys in set of objs",
map[string]interface{}{
"a": "ok",
"b": map[string]interface{}{
"a": "ok",
"set": []interface{}{
map[string]interface{}{
"x": "ok",
"y": "removed",
},
map[string]interface{}{
"x": "ok",
"y": "removed",
},
},
},
},
map[string]interface{}{
"a": "ok",
"b": map[string]interface{}{
"a": "ok",
"set": []interface{}{
map[string]interface{}{
"x": "ok",
},
map[string]interface{}{
"x": "ok",
},
},
},
},
cty.Object(map[string]cty.Type{
"a": cty.String,
"b": cty.Object(map[string]cty.Type{
"a": cty.String,
"set": cty.Set(cty.Object(map[string]cty.Type{
"x": cty.String,
})),
}),
}),
true,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
modified := removeRemovedAttrs(tc.state, tc.ty)
if !reflect.DeepEqual(tc.state, tc.expect) {
t.Fatalf("expected: %#v\n got: %#v\n", tc.expect, tc.state)
}
if modified != tc.modified {
t.Fatal("incorrect return value")
}
})
}
}
func TestStripRemovedStateAttributesDecoder(t *testing.T) {
cases := []struct {
name string
state string
expect cty.Value
}{
{
"removed string",
`{"a": "ok","b": "gone"}`,
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("ok"),
}),
},
{
"removed null",
`{"a": "ok","b": "gone"}`,
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("ok"),
}),
},
{
"with large number",
`{"a": 123456789123456789.123456789,"b": "gone"}`,
cty.ObjectVal(map[string]cty.Value{
"a": cty.MustParseNumberVal("123456789123456789.123456789"),
}),
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
upgraded := stripRemovedStateAttributes([]byte(tc.state), tc.expect.Type())
got, err := ctyjson.Unmarshal(upgraded, tc.expect.Type())
if err != nil {
t.Fatal(err)
}
if !tc.expect.RawEquals(got) {
t.Fatalf("expected: %#v\n got: %#v\n", tc.expect, got)
}
})
}
}