Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions pkg/collections/maps/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package maps

import (
"reflect"

"k8s.io/utils/ptr"

"github.com/openmcp-project/controller-utils/pkg/collections/filters"
Expand Down Expand Up @@ -56,6 +58,36 @@ func Intersect[K comparable, V any](source map[K]V, maps ...map[K]V) map[K]V {
return res
}

// ContainsKeysWithValues checks if 'super' is a superset of 'sub', meaning that all keys of 'sub' are also present in 'super' with the same values.
// Uses reflect.DeepEqual to compare the values, use ContainsMapFunc if you want to use a custom equality function.
func ContainsKeysWithValues[K comparable, V any](super, sub map[K]V) bool {
return ContainsKeysWithValuesFunc(super, sub, func(a, b V) bool {
return reflect.DeepEqual(a, b)
})
}

// ContainsKeysWithValuesFunc checks if 'super' is a superset of 'sub', meaning that all keys of 'sub' are also present in 'super' with the same values.
// The values are compared using the provided equality function.
// If the equality function returns false for any key-value pair, it returns false.
func ContainsKeysWithValuesFunc[K comparable, V any](super, sub map[K]V, equal func(a, b V) bool) bool {
for k, bv := range sub {
if av, ok := super[k]; !ok || !equal(av, bv) {
return false
}
}
return true
}

// ContainsKeys returns true if all given keys are present in the map.
func ContainsKeys[K comparable, V any](super map[K]V, keys ...K) bool {
for _, k := range keys {
if _, ok := super[k]; !ok {
return false
}
}
return true
}

// GetAny returns an arbitrary key-value pair from the map as a pointer to a pairs.Pair.
// If the map is empty, it returns nil.
func GetAny[K comparable, V any](m map[K]V) *pairs.Pair[K, V] {
Expand Down
67 changes: 67 additions & 0 deletions pkg/collections/maps/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,71 @@ var _ = Describe("Map Utils Tests", func() {

})

Context("ContainsKeysWithValues", func() {

It("should return true if the second map is empty or nil", func() {
m1 := map[string]string{"foo": "bar", "bar": "baz"}
Expect(maps.ContainsKeysWithValues(m1, nil)).To(BeTrue())
Expect(maps.ContainsKeysWithValues(m1, map[string]string{})).To(BeTrue())
Expect(maps.ContainsKeysWithValues[string, string](nil, nil)).To(BeTrue())
})

It("should return true if both maps are identical", func() {
m1 := map[string]string{"foo": "bar", "bar": "baz"}
Expect(maps.ContainsKeysWithValues(m1, m1)).To(BeTrue())
})

It("should return true if the first map contains all keys and values of the second map", func() {
m1 := map[string]string{"foo": "bar", "bar": "baz", "baz": "asdf"}
m2 := map[string]string{"foo": "bar", "baz": "asdf"}
Expect(maps.ContainsKeysWithValues(m1, m2)).To(BeTrue())

m3 := map[string]string{"bar": "baz"}
Expect(maps.ContainsKeysWithValues(m1, m3)).To(BeTrue())
})

It("should return false if the first map contains all keys but has different values", func() {
m1 := map[string]string{"foo": "bar", "bar": "baz"}
m2 := map[string]string{"foo": "baz", "bar": "baz"}
Expect(maps.ContainsKeysWithValues(m1, m2)).To(BeFalse())
})

It("should return false if the first map does not contain all keys of the second map", func() {
m1 := map[string]string{"foo": "bar"}
m2 := map[string]string{"foo": "bar", "bar": "baz"}
Expect(maps.ContainsKeysWithValues(m1, m2)).To(BeFalse())
})

It("should work with a custom equality function", func() {
m1 := map[string]string{"foo": "bar", "bar": "baz"}
m2 := map[string]string{"foo": "xyz", "bar": "mno"}
cmp := func(a, b string) bool {
return len(a) == len(b)
}
Expect(maps.ContainsKeysWithValuesFunc(m1, m2, cmp)).To(BeTrue())
})

})

Context("ContainsKeys", func() {

It("should return true if all keys are present", func() {
m1 := map[string]string{"foo": "bar", "bar": "baz", "baz": "asdf"}
Expect(maps.ContainsKeys(m1, "foo", "bar")).To(BeTrue())
})

It("should return true if no keys are provided", func() {
m1 := map[string]string{"foo": "bar", "bar": "baz", "baz": "asdf"}
Expect(maps.ContainsKeys(m1)).To(BeTrue())
Expect(maps.ContainsKeys[string, string](nil)).To(BeTrue())
})

It("should return false if any key is missing", func() {
m1 := map[string]string{"foo": "bar", "bar": "baz", "baz": "asdf"}
Expect(maps.ContainsKeys(m1, "foo", "missing")).To(BeFalse())
Expect(maps.ContainsKeys(m1, "missing")).To(BeFalse())
})

})

})