bitset_test.gno
3.17 Kb · 137 lines
1package bitset
2
3import (
4 "strings"
5 "testing"
6
7 "gno.land/p/nt/uassert/v0"
8)
9
10func TestSetHasClear(t *testing.T) {
11 b := New(100)
12 uassert.False(t, b.Has(7))
13 uassert.True(t, b.Set(7))
14 uassert.True(t, b.Has(7))
15 uassert.True(t, b.Clear(7))
16 uassert.False(t, b.Has(7))
17}
18
19// Out of range is reported, never a panic — and Has is simply false.
20func TestOutOfRange(t *testing.T) {
21 b := New(64)
22 for _, i := range []int{-1, 64, 1000} {
23 uassert.False(t, b.Set(i))
24 uassert.False(t, b.Clear(i))
25 uassert.False(t, b.Flip(i))
26 uassert.False(t, b.Has(i))
27 }
28 uassert.Equal(t, 0, b.Count())
29}
30
31// Word boundaries are where an off-by-one lives: check either side of 64.
32func TestWordBoundaries(t *testing.T) {
33 b := New(200)
34 for _, i := range []int{0, 63, 64, 65, 127, 128, 199} {
35 uassert.True(t, b.Set(i))
36 }
37 uassert.Equal(t, 7, b.Count())
38 for _, i := range []int{0, 63, 64, 65, 127, 128, 199} {
39 uassert.True(t, b.Has(i))
40 }
41 uassert.False(t, b.Has(62))
42 uassert.False(t, b.Has(129))
43}
44
45func TestFlip(t *testing.T) {
46 b := New(10)
47 b.Flip(3)
48 uassert.True(t, b.Has(3))
49 b.Flip(3)
50 uassert.False(t, b.Has(3))
51}
52
53func TestCountAndSlice(t *testing.T) {
54 b := FromSlice(50, []int{1, 5, 9, 49})
55 uassert.Equal(t, 4, b.Count())
56 uassert.Equal(t, "1,5,9,49", join(b.Slice()))
57}
58
59func TestFromSliceIgnoresOutOfRange(t *testing.T) {
60 b := FromSlice(10, []int{1, -3, 10, 99, 4})
61 uassert.Equal(t, "1,4", join(b.Slice()))
62}
63
64func TestSetAlgebra(t *testing.T) {
65 a := FromSlice(20, []int{1, 2, 3})
66 b := FromSlice(20, []int{3, 4})
67 uassert.Equal(t, "1,2,3,4", join(Union(a, b).Slice()))
68 uassert.Equal(t, "3", join(Intersect(a, b).Slice()))
69 uassert.Equal(t, "1,2", join(Difference(a, b).Slice()))
70 uassert.Equal(t, "1,2,4", join(SymmetricDifference(a, b).Slice()))
71}
72
73// Combining different capacities is a caller error: nil, not a silent pad.
74func TestMismatchedCapacityIsNil(t *testing.T) {
75 a := New(10)
76 b := New(20)
77 uassert.True(t, Union(a, b) == nil)
78 uassert.True(t, Intersect(a, b) == nil)
79 uassert.True(t, Difference(a, b) == nil)
80 uassert.True(t, SymmetricDifference(a, b) == nil)
81 uassert.False(t, Equal(a, b))
82}
83
84func TestCloneIsIndependent(t *testing.T) {
85 a := FromSlice(30, []int{1, 2})
86 c := a.Clone()
87 c.Set(29)
88 uassert.False(t, a.Has(29))
89 uassert.True(t, Equal(a, FromSlice(30, []int{1, 2})))
90}
91
92func TestEqual(t *testing.T) {
93 uassert.True(t, Equal(FromSlice(8, []int{1, 3}), FromSlice(8, []int{3, 1})))
94 uassert.False(t, Equal(FromSlice(8, []int{1}), FromSlice(8, []int{2})))
95}
96
97func TestString(t *testing.T) {
98 uassert.Equal(t, "01010", FromSlice(5, []int{1, 3}).String())
99}
100
101func TestCapClamped(t *testing.T) {
102 uassert.Equal(t, 0, New(-5).Cap())
103 uassert.Equal(t, MaxBits, New(MaxBits+1000).Cap())
104}
105
106func TestPopcount(t *testing.T) {
107 uassert.Equal(t, 0, popcount(0))
108 uassert.Equal(t, 1, popcount(1))
109 uassert.Equal(t, 64, popcount(^uint64(0)))
110}
111
112func join(xs []int) string {
113 parts := []string{}
114 for _, x := range xs {
115 parts = append(parts, itoa(x))
116 }
117 return strings.Join(parts, ",")
118}
119
120func itoa(i int) string {
121 if i == 0 {
122 return "0"
123 }
124 neg := i < 0
125 if neg {
126 i = -i
127 }
128 var b []byte
129 for i > 0 {
130 b = append([]byte{byte('0' + i%10)}, b...)
131 i /= 10
132 }
133 if neg {
134 return "-" + string(b)
135 }
136 return string(b)
137}