terraform: State.Equal needs to use reflect for rich types
Due to the change to `interface{}` we need to use `reflect.DeepEqual` here. With the restriction of primitive types this should always be safe. We'll never get functions, channels, etc.
This commit is contained in:
parent
9fc577547c
commit
41d2c145b2
|
@ -1633,13 +1633,11 @@ func (s *InstanceState) Equal(other *InstanceState) bool {
|
|||
if len(s.Meta) != len(other.Meta) {
|
||||
return false
|
||||
}
|
||||
for k, v := range s.Meta {
|
||||
otherV, ok := other.Meta[k]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if v != otherV {
|
||||
if s.Meta != nil && other.Meta != nil {
|
||||
// We only do the deep check if both are non-nil. If one is nil
|
||||
// we treat it as equal since their lengths are both zero (check
|
||||
// above).
|
||||
if !reflect.DeepEqual(s.Meta, other.Meta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -325,17 +325,20 @@ func TestStateDeepCopy(t *testing.T) {
|
|||
|
||||
func TestStateEqual(t *testing.T) {
|
||||
cases := []struct {
|
||||
Name string
|
||||
Result bool
|
||||
One, Two *State
|
||||
}{
|
||||
// Nils
|
||||
{
|
||||
"one nil",
|
||||
false,
|
||||
nil,
|
||||
&State{Version: 2},
|
||||
},
|
||||
|
||||
{
|
||||
"both nil",
|
||||
true,
|
||||
nil,
|
||||
nil,
|
||||
|
@ -343,6 +346,7 @@ func TestStateEqual(t *testing.T) {
|
|||
|
||||
// Different versions
|
||||
{
|
||||
"different state versions",
|
||||
false,
|
||||
&State{Version: 5},
|
||||
&State{Version: 2},
|
||||
|
@ -350,6 +354,7 @@ func TestStateEqual(t *testing.T) {
|
|||
|
||||
// Different modules
|
||||
{
|
||||
"different module states",
|
||||
false,
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
|
@ -362,6 +367,7 @@ func TestStateEqual(t *testing.T) {
|
|||
},
|
||||
|
||||
{
|
||||
"same module states",
|
||||
true,
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
|
@ -381,6 +387,7 @@ func TestStateEqual(t *testing.T) {
|
|||
|
||||
// Meta differs
|
||||
{
|
||||
"differing meta values with primitives",
|
||||
false,
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
|
@ -415,15 +422,61 @@ func TestStateEqual(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Meta with complex types
|
||||
{
|
||||
"same meta with complex types",
|
||||
true,
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Primary: &InstanceState{
|
||||
Meta: map[string]interface{}{
|
||||
"timeouts": map[string]interface{}{
|
||||
"create": 42,
|
||||
"read": "27",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Primary: &InstanceState{
|
||||
Meta: map[string]interface{}{
|
||||
"timeouts": map[string]interface{}{
|
||||
"create": 42,
|
||||
"read": "27",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
if tc.One.Equal(tc.Two) != tc.Result {
|
||||
t.Fatalf("Bad: %d\n\n%s\n\n%s", i, tc.One.String(), tc.Two.String())
|
||||
}
|
||||
if tc.Two.Equal(tc.One) != tc.Result {
|
||||
t.Fatalf("Bad: %d\n\n%s\n\n%s", i, tc.One.String(), tc.Two.String())
|
||||
}
|
||||
t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
|
||||
if tc.One.Equal(tc.Two) != tc.Result {
|
||||
t.Fatalf("Bad: %d\n\n%s\n\n%s", i, tc.One.String(), tc.Two.String())
|
||||
}
|
||||
if tc.Two.Equal(tc.One) != tc.Result {
|
||||
t.Fatalf("Bad: %d\n\n%s\n\n%s", i, tc.One.String(), tc.Two.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue