mirror of
https://github.com/tailscale/tailscale.git
synced 2026-05-05 04:06:35 +02:00
util/set: add ContainsSet and ContainsAll
These are trivial methods, but useful and generally applicable operations for a set type. Updates #cleanup Change-Id: I94610b901cd10fe66dd15c38b8601f29ead71811 Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
This commit is contained in:
parent
a7d8aeb8ae
commit
5de7033a82
@ -6,6 +6,7 @@ package set
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"iter"
|
||||
"maps"
|
||||
"reflect"
|
||||
"sort"
|
||||
@ -111,6 +112,23 @@ func (s Set[T]) Contains(e T) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// ContainsSet reports whether s is a superset of e. Returns true if e is nil,
|
||||
// empty, or equal to s.
|
||||
func (s Set[T]) ContainsSet(e Set[T]) bool {
|
||||
return s.ContainsAll(maps.Keys(e))
|
||||
}
|
||||
|
||||
// ContainsAll reports whether s contains all elements of e. Returns true if e
|
||||
// has 0 elements.
|
||||
func (s Set[T]) ContainsAll(e iter.Seq[T]) bool {
|
||||
for k := range e {
|
||||
if !s.Contains(k) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Len reports the number of items in s.
|
||||
func (s Set[T]) Len() int { return len(s) }
|
||||
|
||||
|
||||
@ -5,6 +5,8 @@ package set
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"iter"
|
||||
"maps"
|
||||
"slices"
|
||||
"testing"
|
||||
)
|
||||
@ -200,3 +202,69 @@ func TestMake(t *testing.T) {
|
||||
t.Error("missing 1")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainsCollection(t *testing.T) {
|
||||
s := Of(1, 2, 3)
|
||||
for name, tc := range map[string]struct {
|
||||
e []int
|
||||
expected bool
|
||||
}{
|
||||
"equal": {
|
||||
e: []int{1, 2, 3},
|
||||
expected: true,
|
||||
},
|
||||
"superset": {
|
||||
e: []int{2, 3},
|
||||
expected: true,
|
||||
},
|
||||
"disjoint": {
|
||||
e: []int{4, 5},
|
||||
expected: false,
|
||||
},
|
||||
"partial": {
|
||||
e: []int{2, 4},
|
||||
expected: false,
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if s.ContainsSet(Of(tc.e...)) != tc.expected {
|
||||
t.Errorf("ContainsSet(%v) = %v; want %v", tc.e, !tc.expected, tc.expected)
|
||||
}
|
||||
if s.ContainsAll(slices.Values(tc.e)) != tc.expected {
|
||||
t.Errorf("ContainsSet(%v) = %v; want %v", tc.e, !tc.expected, tc.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test ContainsSet always return true for empty collections.
|
||||
func TestContainsSetEmpty(t *testing.T) {
|
||||
var emptySets = []Set[int]{
|
||||
nil,
|
||||
make(Set[int]),
|
||||
Of[int](),
|
||||
}
|
||||
for _, s := range []Set[int]{nil, make(Set[int]), Of[int](), Of(1, 2, 3)} {
|
||||
for _, empty := range emptySets {
|
||||
if !s.ContainsSet(empty) {
|
||||
t.Errorf("set %v should contain empty set %v", s, empty)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test ContainsAll always return true for empty collections.
|
||||
func TestContainsAllEmpty(t *testing.T) {
|
||||
var emptyIters = []iter.Seq[int]{
|
||||
func(yield func(int) bool) {},
|
||||
slices.Values([]int{}),
|
||||
maps.Keys(map[int]struct{}{}),
|
||||
}
|
||||
for _, s := range []Set[int]{nil, make(Set[int]), Of[int](), Of(1, 2, 3)} {
|
||||
for _, empty := range emptyIters {
|
||||
if !s.ContainsAll(empty) {
|
||||
t.Errorf("set %v should contain empty iterator %v", s, empty)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user