You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
524 lines
11 KiB
Go
524 lines
11 KiB
Go
2 years ago
|
package mapset_test
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"sort"
|
||
|
"testing"
|
||
|
|
||
|
"git.blauwelle.com/go/crate/mapset"
|
||
|
)
|
||
|
|
||
|
func TestNewEmpty(t *testing.T) {
|
||
|
s := mapset.New[int]()
|
||
|
if size := s.Cardinality(); size != 0 {
|
||
|
t.Fatalf("got %d, want cardinality 0", size)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestNew(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3, 4, 5)
|
||
|
if size := s.Cardinality(); size != 5 {
|
||
|
t.Fatalf("got %d, want cardinality 5", size)
|
||
|
}
|
||
|
keys := make([]int, 0, 10)
|
||
|
for i := 1; i < 6; i++ {
|
||
|
keys = append(keys, i)
|
||
|
if ok := s.ContainsOne(i); !ok {
|
||
|
t.Fatalf("got false, want contains %d", i)
|
||
|
}
|
||
|
}
|
||
|
if ok := s.ContainsAll(keys...); !ok {
|
||
|
t.Fatalf("want contains all of %v", keys)
|
||
|
}
|
||
|
for i := 6; i < 11; i++ {
|
||
|
keys = append(keys, i)
|
||
|
if ok := s.ContainsOne(i); ok {
|
||
|
t.Fatalf("want do not contain %d", i)
|
||
|
}
|
||
|
}
|
||
|
if ok := s.ContainsAll(keys...); ok {
|
||
|
t.Fatalf("want do not contain all of %v", keys)
|
||
|
}
|
||
|
if ok := s.ContainsAny(keys...); !ok {
|
||
|
t.Fatalf("want contains any of %v", keys)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestAddOne(t *testing.T) {
|
||
|
s := mapset.New[int]()
|
||
|
s.AddOne(1)
|
||
|
if size := s.Cardinality(); size != 1 {
|
||
|
t.Fatalf("got %d, want cardinality 1", size)
|
||
|
}
|
||
|
if ok := s.ContainsOne(1); !ok {
|
||
|
t.Fatalf("want contains 1")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestAddOneOk(t *testing.T) {
|
||
|
t.Run("ok", func(t *testing.T) {
|
||
|
s := mapset.New[int]()
|
||
|
ok := s.AddOneOk(1)
|
||
|
if size := s.Cardinality(); size != 1 {
|
||
|
t.Fatalf("got %d, want cardinality 1", size)
|
||
|
}
|
||
|
if !ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
if ok := s.ContainsOne(1); !ok {
|
||
|
t.Fatalf("want contains 1")
|
||
|
}
|
||
|
})
|
||
|
t.Run("exists", func(t *testing.T) {
|
||
|
s := mapset.New[int](1)
|
||
|
ok := s.AddOneOk(1)
|
||
|
if size := s.Cardinality(); size != 1 {
|
||
|
t.Fatalf("got %d, want cardinality 1", size)
|
||
|
}
|
||
|
if ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
if ok := s.ContainsOne(1); !ok {
|
||
|
t.Fatalf("want contains 1")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestAddManyOk(t *testing.T) {
|
||
|
t.Run("ok", func(t *testing.T) {
|
||
|
s := mapset.New[int]()
|
||
|
n := s.AddManyOk(1, 2, 3)
|
||
|
if n != 3 {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("exists", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2)
|
||
|
n := s.AddManyOk(1, 2, 3, 4)
|
||
|
if n != 2 {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestDeleteOneOk(t *testing.T) {
|
||
|
t.Run("ok", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
ok := s.DeleteOneOk(1)
|
||
|
if !ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("not_exists", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
ok := s.DeleteOneOk(4)
|
||
|
if ok {
|
||
|
t.Fatalf("faila")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestDeleteManyOk(t *testing.T) {
|
||
|
t.Run("ok", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
n := s.DeleteManyOk(1, 2, 3)
|
||
|
if n != 3 {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("delete_more", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
n := s.DeleteManyOk(1, 2, 3, 4)
|
||
|
if n != 3 {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("delete_partial", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
n := s.DeleteManyOk(1, 2, 4)
|
||
|
if n != 2 {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestDelete(t *testing.T) {
|
||
|
s := mapset.New(1)
|
||
|
s.DeleteOne(1)
|
||
|
if size := s.Cardinality(); size != 0 {
|
||
|
t.Fatalf("got %d, want cardinality 0", size)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDeleteMany(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
s.DeleteMany(1, 3)
|
||
|
if size := s.Cardinality(); size != 1 {
|
||
|
t.Fatalf("got %d, want cardinality 1", size)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestContainsAny(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
if ok := s.ContainsAny(); ok {
|
||
|
t.Fatalf("got true, should not contains empty")
|
||
|
}
|
||
|
if ok := s.ContainsAny(-1, -2); ok {
|
||
|
t.Fatalf("got true, should not contains any of -1, -2")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestPopOne(t *testing.T) {
|
||
|
s := mapset.New[int]()
|
||
|
if _, ok := s.PopOne(); ok {
|
||
|
t.Fatalf("should not pop any key")
|
||
|
}
|
||
|
s.AddMany(1, 2, 3)
|
||
|
if key, ok := s.PopOne(); !ok {
|
||
|
t.Fatalf("should pop 1 key")
|
||
|
} else if key < 1 || key > 3 {
|
||
|
t.Fatalf("wrong key")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestClear(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
s.Clear()
|
||
|
if size := s.Cardinality(); size != 0 {
|
||
|
t.Fatalf("got %d, want 0 cardinality after clean", size)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestClone(t *testing.T) {
|
||
|
s := mapset.New(1, 2)
|
||
|
c := s.Clone()
|
||
|
if ok := s.Equal(c); !ok {
|
||
|
t.Fatalf("got false, want equal")
|
||
|
}
|
||
|
s.AddOne(3)
|
||
|
if size := c.Cardinality(); size != 2 {
|
||
|
t.Fatalf("got %d, want 2", size)
|
||
|
}
|
||
|
if ok := s.Equal(c); ok {
|
||
|
t.Fatalf("got true, want not equal")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestIsEmpty(t *testing.T) {
|
||
|
t.Run("empty", func(t *testing.T) {
|
||
|
s := mapset.New[int]()
|
||
|
if ok := s.IsEmpty(); !ok {
|
||
|
t.Fatalf("got false, want empty")
|
||
|
}
|
||
|
})
|
||
|
t.Run("not_empty", func(t *testing.T) {
|
||
|
s := mapset.New(1)
|
||
|
if ok := s.IsEmpty(); ok {
|
||
|
t.Fatalf("got true, want not empty")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestEqual(t *testing.T) {
|
||
|
s := mapset.New(1, 2)
|
||
|
c := mapset.New(1, 2)
|
||
|
v := mapset.New(1, 2, 3)
|
||
|
p := mapset.New(2, 3)
|
||
|
t.Run("equal", func(t *testing.T) {
|
||
|
if ok := s.Equal(c); !ok {
|
||
|
t.Fatalf("got false, want equal")
|
||
|
}
|
||
|
})
|
||
|
t.Run("not_equal_1", func(t *testing.T) {
|
||
|
if ok := s.Equal(v); ok {
|
||
|
t.Fatalf("got true, want not equal")
|
||
|
}
|
||
|
})
|
||
|
t.Run("not_equal_2", func(t *testing.T) {
|
||
|
if ok := s.Equal(p); ok {
|
||
|
t.Fatalf("got true, want not equal")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestIsSubsetOf(t *testing.T) {
|
||
|
s := mapset.New(1, 2)
|
||
|
c := mapset.New(1, 2, 3)
|
||
|
v := mapset.New(2, 3)
|
||
|
e := mapset.New[int]()
|
||
|
t.Run("is_subset_of_self", func(t *testing.T) {
|
||
|
if ok := s.IsSubsetOf(s); !ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("is_subset", func(t *testing.T) {
|
||
|
if ok := s.IsSubsetOf(c); !ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("not_subset_1", func(t *testing.T) {
|
||
|
if ok := s.IsSubsetOf(v); ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("not_subset_2", func(t *testing.T) {
|
||
|
if ok := c.IsSubsetOf(s); ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("empty_is_subset_of_empty", func(t *testing.T) {
|
||
|
if ok := e.IsSubsetOf(e); !ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("empty_is_subset_of_other", func(t *testing.T) {
|
||
|
if ok := e.IsSubsetOf(s); !ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestIsProperSubsetOf(t *testing.T) {
|
||
|
s := mapset.New(1, 2)
|
||
|
c := mapset.New(1, 2, 3)
|
||
|
v := mapset.New(2, 3)
|
||
|
p := mapset.New(1, 3, 5, 7)
|
||
|
t.Run("not_proper_subset_of_self", func(t *testing.T) {
|
||
|
if ok := s.IsProperSubsetOf(s); ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("is_proper_subset", func(t *testing.T) {
|
||
|
if ok := s.IsProperSubsetOf(c); !ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("not_proper_subset_1", func(t *testing.T) {
|
||
|
if ok := s.IsProperSubsetOf(v); ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("not_proper_subset_2", func(t *testing.T) {
|
||
|
if ok := c.IsProperSubsetOf(s); ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("not_proper_subset_3", func(t *testing.T) {
|
||
|
if ok := s.IsProperSubsetOf(p); ok {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestUnion(t *testing.T) {
|
||
|
t.Run("union_1", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2)
|
||
|
c := mapset.New(2, 3)
|
||
|
u := mapset.New(1, 2, 3)
|
||
|
if g := s.Union(c); !g.Equal(u) {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("union_2", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 5, 7)
|
||
|
c := mapset.New(2, 3)
|
||
|
u := mapset.New(1, 2, 3, 5, 7)
|
||
|
if g := s.Union(c); !g.Equal(u) {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestIntersection(t *testing.T) {
|
||
|
t.Run("intersection_1", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2)
|
||
|
c := mapset.New(2, 3)
|
||
|
u := mapset.New(2)
|
||
|
if g := s.Intersection(c); !g.Equal(u) {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("intersection_2", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 4)
|
||
|
c := mapset.New(2, 3)
|
||
|
u := mapset.New(2)
|
||
|
if g := s.Intersection(c); !g.Equal(u) {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestDifference(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
c := mapset.New(1, 2)
|
||
|
t.Run("diff_1", func(t *testing.T) {
|
||
|
o := s.Difference(c)
|
||
|
if !o.Equal(mapset.New(3)) {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestSymmetricDifference(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
c := mapset.New(1, 2, 4)
|
||
|
t.Run("diff_1", func(t *testing.T) {
|
||
|
o := s.SymmetricDifference(c)
|
||
|
if !o.Equal(mapset.New(3, 4)) {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestToSlice(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
r := s.ToSlice()
|
||
|
sort.Ints(r)
|
||
|
if size := len(r); size != 3 {
|
||
|
t.Fatalf("got %d, want 3", size)
|
||
|
}
|
||
|
if !([3]int(r) == [3]int{1, 2, 3}) {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestToAnySlice(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
r := s.ToAnySlice()
|
||
|
if size := len(r); size != 3 {
|
||
|
t.Fatalf("got %d, want 3", size)
|
||
|
}
|
||
|
sort.Slice(r, func(i, j int) bool {
|
||
|
return r[i].(int) < r[j].(int)
|
||
|
})
|
||
|
if !([3]any(r) == [3]any{1, 2, 3}) {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestString(t *testing.T) {
|
||
|
t.Run("int", func(t *testing.T) {
|
||
|
s := mapset.New(1, 2, 3)
|
||
|
str := s.String()
|
||
|
t.Log(str)
|
||
|
})
|
||
|
t.Run("int_large", func(t *testing.T) {
|
||
|
s := mapset.New[int]()
|
||
|
for i := 0; i < 80; i++ {
|
||
|
s.AddOne(i)
|
||
|
}
|
||
|
str := s.String()
|
||
|
t.Log(str)
|
||
|
})
|
||
|
t.Run("string", func(t *testing.T) {
|
||
|
s := mapset.New("a", "aa,bb", `"cc"`)
|
||
|
t.Log(s.String())
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestMarshalUnmarshal(t *testing.T) {
|
||
|
t.Run("marshal", func(t *testing.T) {
|
||
|
s := mapset.New(1)
|
||
|
b, err := json.Marshal(s)
|
||
|
if err != nil {
|
||
|
t.Fatalf("err: %v", err)
|
||
|
}
|
||
|
if string(b) != "[1]" {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
t.Run("unmarshal", func(t *testing.T) {
|
||
|
b := []byte(`[1, 2]`)
|
||
|
var s mapset.MapSet[int]
|
||
|
if err := json.Unmarshal(b, &s); err != nil {
|
||
|
t.Fatalf("err: %v", err)
|
||
|
}
|
||
|
if !s.Equal(mapset.New(1, 2)) {
|
||
|
t.Fatalf("failed")
|
||
|
}
|
||
|
})
|
||
|
t.Run("unmarshal_error", func(t *testing.T) {
|
||
|
b := []byte(`1`)
|
||
|
var s mapset.MapSet[int]
|
||
|
if err := json.Unmarshal(b, &s); err == nil {
|
||
|
t.Fatalf("fail")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func BenchmarkAdd(b *testing.B) {
|
||
|
size := 1024 * 1
|
||
|
s := mapset.New[int]()
|
||
|
keys := make([]int, size)
|
||
|
for i := 0; i < size; i++ {
|
||
|
s.AddOne(i)
|
||
|
keys[i] = i
|
||
|
}
|
||
|
b.Run("addOne", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
for i := 0; i < size; i++ {
|
||
|
s.AddOne(i)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
b.Run("addMany", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
for i := 0; i < size; i++ {
|
||
|
keys[i] = i
|
||
|
}
|
||
|
s.AddMany(keys...)
|
||
|
}
|
||
|
})
|
||
|
b.Run("addManyPrepared", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
s.AddMany(keys...)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func BenchmarkContains(b *testing.B) {
|
||
|
s := mapset.New[int]()
|
||
|
for i := 0; i < 1024; i++ {
|
||
|
s.AddOne(i)
|
||
|
}
|
||
|
b.Run("containsAll_keyExists", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
s.ContainsAll(1)
|
||
|
}
|
||
|
})
|
||
|
b.Run("containsAll_keyNotExists", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
s.ContainsAll(-1)
|
||
|
}
|
||
|
})
|
||
|
b.Run("containsOne_keyExists", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
s.ContainsOne(1)
|
||
|
}
|
||
|
})
|
||
|
b.Run("containsOne_keyNotExists", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
s.ContainsOne(-1)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func BenchmarkRaw(b *testing.B) {
|
||
|
b.Run("raw-64", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
m := map[int]struct{}{}
|
||
|
for j := 0; j < 64; j++ {
|
||
|
m[j] = struct{}{}
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
b.Run("mapset-64", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
s := mapset.New[int]()
|
||
|
for j := 0; j < 64; j++ {
|
||
|
s.AddOne(j)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|