From 9586e3c00a3994386e7b3d7e254eeeaaf5db4a4a Mon Sep 17 00:00:00 2001 From: Seth Hoenig Date: Sat, 13 Aug 2022 09:13:54 -0500 Subject: [PATCH] cleanup: helper funcs for comparing slices of references --- helper/funcs.go | 24 ++++++++++++++++++++++++ helper/funcs_test.go | 39 +++++++++++++++++++++++++++++++++++++++ nomad/structs/services.go | 15 +-------------- 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/helper/funcs.go b/helper/funcs.go index ec3842f4c..8b5137cad 100644 --- a/helper/funcs.go +++ b/helper/funcs.go @@ -735,3 +735,27 @@ func IsMethodHTTP(s string) bool { } return true } + +// EqualsFunc represents a type implementing the Equals method. +type EqualsFunc[A any] interface { + Equals(A) bool +} + +// ElementsEquals returns true if slices a and b contain the same elements (in +// no particular order) using the Equals function defined on their type for +// comparison. +func ElementsEquals[T EqualsFunc[T]](a, b []T) bool { + if len(a) != len(b) { + return false + } +OUTER: + for _, item := range a { + for _, other := range b { + if item.Equals(other) { + continue OUTER + } + } + return false + } + return true +} diff --git a/helper/funcs_test.go b/helper/funcs_test.go index 79fd90026..977454bcd 100644 --- a/helper/funcs_test.go +++ b/helper/funcs_test.go @@ -574,3 +574,42 @@ func Test_IsMethodHTTP(t *testing.T) { } }) } + +type employee struct { + id int + name string +} + +func (e *employee) Equals(o *employee) bool { + return e.id == o.id // name can be different +} + +func Test_ElementsEquals(t *testing.T) { + t.Run("empty", func(t *testing.T) { + a := []*employee(nil) + var b []*employee + must.True(t, ElementsEquals(a, b)) + must.True(t, ElementsEquals(b, a)) + }) + + t.Run("different sizes", func(t *testing.T) { + a := []*employee{{1, "mitchell"}, {2, "armon"}, {3, "jack"}} + b := []*employee{{1, "mitchell"}, {2, "armon"}} + must.False(t, ElementsEquals(a, b)) + must.False(t, ElementsEquals(b, a)) + }) + + t.Run("equal", func(t *testing.T) { + a := []*employee{{1, "mitchell"}, {2, "armon"}, {3, "jack"}} + b := []*employee{{1, "M.H."}, {2, "A.D."}, {3, "J.P."}} + must.True(t, ElementsEquals(a, b)) + must.True(t, ElementsEquals(b, a)) + }) + + t.Run("different", func(t *testing.T) { + a := []*employee{{1, "mitchell"}, {2, "armon"}, {3, "jack"}} + b := []*employee{{0, "mitchell."}, {2, "armon"}, {3, "jack"}} + must.False(t, ElementsEquals(a, b)) + must.False(t, ElementsEquals(b, a)) + }) +} diff --git a/nomad/structs/services.go b/nomad/structs/services.go index 229023340..822414cc2 100644 --- a/nomad/structs/services.go +++ b/nomad/structs/services.go @@ -905,20 +905,7 @@ func (s *Service) Equals(o *Service) bool { return false } - if len(s.Checks) != len(o.Checks) { - return false - } - -OUTER: - for i := range s.Checks { - for ii := range o.Checks { - if s.Checks[i].Equals(o.Checks[ii]) { - // Found match; continue with next check - continue OUTER - } - } - - // No match + if !helper.ElementsEquals(s.Checks, o.Checks) { return false }