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) } } }) }