mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 18:01:01 -06:00
helper/schema: Add Set.HashEqual
Equality of schema.Sets gets tricky when dealing with nested sets - Set.Equal only superficially compares the underlying maps and hence any sets nested under the root sets cause issues. This adds a simple method, HashEqual, that does a top-level hash comparison, helping to work around this without any complex re-invention of things like reflect.DeepEqual. Of course, in order to make effective use of this function, the user needs to make sure they are properly hashing their nested sets, however this is trivial with things like HashResource.
This commit is contained in:
parent
bb00fd47c0
commit
ca42980e49
@ -153,6 +153,31 @@ func (s *Set) Equal(raw interface{}) bool {
|
||||
return reflect.DeepEqual(s.m, other.m)
|
||||
}
|
||||
|
||||
// HashEqual simply checks to the keys the top-level map to the keys in the
|
||||
// other set's top-level map to see if they are equal. This obviously assumes
|
||||
// you have a properly working hash function - use HashResource if in doubt.
|
||||
func (s *Set) HashEqual(raw interface{}) bool {
|
||||
other, ok := raw.(*Set)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
ks1 := make([]string, 0)
|
||||
ks2 := make([]string, 0)
|
||||
|
||||
for k := range s.m {
|
||||
ks1 = append(ks1, k)
|
||||
}
|
||||
for k := range other.m {
|
||||
ks2 = append(ks2, k)
|
||||
}
|
||||
|
||||
sort.Strings(ks1)
|
||||
sort.Strings(ks2)
|
||||
|
||||
return reflect.DeepEqual(ks1, ks2)
|
||||
}
|
||||
|
||||
func (s *Set) GoString() string {
|
||||
return fmt.Sprintf("*Set(%#v)", s.m)
|
||||
}
|
||||
|
@ -128,3 +128,68 @@ func TestHashResource_nil(t *testing.T) {
|
||||
t.Fatalf("Expected 0 when hashing nil, given: %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashEqual(t *testing.T) {
|
||||
nested := &Resource{
|
||||
Schema: map[string]*Schema{
|
||||
"foo": {
|
||||
Type: TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
root := &Resource{
|
||||
Schema: map[string]*Schema{
|
||||
"bar": {
|
||||
Type: TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
"nested": {
|
||||
Type: TypeSet,
|
||||
Optional: true,
|
||||
Elem: nested,
|
||||
},
|
||||
},
|
||||
}
|
||||
n1 := map[string]interface{}{"foo": "bar"}
|
||||
n2 := map[string]interface{}{"foo": "baz"}
|
||||
|
||||
r1 := map[string]interface{}{
|
||||
"bar": "baz",
|
||||
"nested": NewSet(HashResource(nested), []interface{}{n1}),
|
||||
}
|
||||
r2 := map[string]interface{}{
|
||||
"bar": "qux",
|
||||
"nested": NewSet(HashResource(nested), []interface{}{n2}),
|
||||
}
|
||||
s1 := NewSet(HashResource(root), []interface{}{r1})
|
||||
s2 := NewSet(HashResource(root), []interface{}{r2})
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
set *Set
|
||||
compare *Set
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "equal",
|
||||
set: s1,
|
||||
compare: s1,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "not equal",
|
||||
set: s1,
|
||||
compare: s2,
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
actual := tc.set.HashEqual(tc.compare)
|
||||
if tc.expected != actual {
|
||||
t.Fatalf("expected %t, got %t", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user