github.com/weaviate/sroar@v0.0.0-20230210105426-26108af5465d/bitmap_test.go (about)

     1  package sroar
     2  
     3  import (
     4  	"math"
     5  	"math/rand"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  func fill(c []uint16, b uint16) {
    13  	for i := range c[startIdx:] {
    14  		c[i+int(startIdx)] = b
    15  	}
    16  }
    17  
    18  func TestModify(t *testing.T) {
    19  	data := make([]uint16, 16)
    20  	s := toUint64Slice(data)
    21  	for i := 0; i < len(s); i++ {
    22  		s[i] = uint64(i)
    23  	}
    24  
    25  	o := toUint64Slice(data)
    26  	for i := 0; i < len(o); i++ {
    27  		require.Equal(t, uint64(i), o[i])
    28  	}
    29  }
    30  
    31  func TestContainer(t *testing.T) {
    32  	ra := NewBitmap()
    33  
    34  	// We're creating a container of size 64 words. 4 of these would be used for
    35  	// the header. So, the data can only live in 60 words.
    36  	offset := ra.newContainer(64)
    37  	c := ra.getContainer(offset)
    38  	require.Equal(t, uint16(64), ra.data[offset])
    39  	require.Equal(t, uint16(0), c[indexCardinality])
    40  
    41  	fill(c, 0xFF)
    42  	for i, u := range c[startIdx:] {
    43  		if i < 60 {
    44  			require.Equalf(t, uint16(0xFF), u, "at index: %d", i)
    45  		} else {
    46  			require.Equalf(t, uint16(0x00), u, "at index: %d", i)
    47  		}
    48  	}
    49  
    50  	offset2 := ra.newContainer(32) // Add a second container.
    51  	c2 := ra.getContainer(offset2)
    52  	require.Equal(t, uint16(32), ra.data[offset2])
    53  	fill(c2, 0xEE)
    54  
    55  	// Expand the first container. This would push out the second container, so update its offset.
    56  	ra.expandContainer(offset)
    57  	offset2 += 64
    58  
    59  	// Check if the second container is correct.
    60  	c2 = ra.getContainer(offset2)
    61  	require.Equal(t, uint16(32), ra.data[offset2])
    62  	require.Equal(t, 32, len(c2))
    63  	for _, val := range c2[startIdx:] {
    64  		require.Equal(t, uint16(0xEE), val)
    65  	}
    66  
    67  	// Check if the first container is correct.
    68  	c = ra.getContainer(offset)
    69  	require.Equal(t, uint16(128), ra.data[offset])
    70  	require.Equal(t, 128, len(c))
    71  	for i, u := range c[startIdx:] {
    72  		if i < 60 {
    73  			require.Equalf(t, uint16(0xFF), u, "at index: %d", i)
    74  		} else {
    75  			require.Equalf(t, uint16(0x00), u, "at index: %d", i)
    76  		}
    77  	}
    78  }
    79  
    80  func TestKey(t *testing.T) {
    81  	ra := NewBitmap()
    82  	for i := 1; i <= 10; i++ {
    83  		ra.Set(uint64(i))
    84  	}
    85  
    86  	off, has := ra.keys.getValue(0)
    87  	require.True(t, has)
    88  	c := ra.getContainer(off)
    89  	require.Equal(t, uint16(10), c[indexCardinality])
    90  
    91  	// Create 10 containers
    92  	for i := 0; i < 10; i++ {
    93  		t.Logf("Creating a new container: %d\n", i)
    94  		ra.Set(uint64(i)<<16 + 1)
    95  	}
    96  
    97  	for i := 0; i < 10; i++ {
    98  		ra.Set(uint64(i)<<16 + 2)
    99  	}
   100  
   101  	for i := 1; i < 10; i++ {
   102  		offset, has := ra.keys.getValue(uint64(i) << 16)
   103  		require.True(t, has)
   104  		c = ra.getContainer(offset)
   105  		require.Equal(t, uint16(2), c[indexCardinality])
   106  	}
   107  
   108  	// Do add in the reverse order.
   109  	for i := 19; i >= 10; i-- {
   110  		ra.Set(uint64(i)<<16 + 2)
   111  	}
   112  
   113  	for i := 10; i < 20; i++ {
   114  		offset, has := ra.keys.getValue(uint64(i) << 16)
   115  		require.True(t, has)
   116  		c = ra.getContainer(offset)
   117  		require.Equal(t, uint16(1), c[indexCardinality])
   118  	}
   119  }
   120  
   121  func TestEdgeCase(t *testing.T) {
   122  	ra := NewBitmap()
   123  
   124  	require.True(t, ra.Set(65536))
   125  	require.True(t, ra.Contains(65536))
   126  }
   127  
   128  func TestBulkAdd(t *testing.T) {
   129  	ra := NewBitmap()
   130  	m := make(map[uint64]struct{})
   131  	max := int64(64 << 16)
   132  	start := time.Now()
   133  
   134  	var cnt int
   135  	for i := 0; ; i++ {
   136  		if i%100 == 0 && time.Since(start) > time.Second {
   137  			cnt++
   138  			start = time.Now()
   139  			// t.Logf("Bitmap:\n%s\n", ra)
   140  			if cnt == 3 {
   141  				t.Logf("Breaking out of the loop\n")
   142  				break
   143  			}
   144  		}
   145  		x := uint64(rand.Int63n(max))
   146  
   147  		if _, has := m[x]; has {
   148  			if !ra.Contains(x) {
   149  				t.Logf("x should be present: %d %#x. Bitmap: %s\n", x, x, ra)
   150  				off, found := ra.keys.getValue(x & mask)
   151  				assert(found)
   152  				c := ra.getContainer(off)
   153  				lo := uint16(x)
   154  				t.Logf("x: %#x lo: %#x. offset: %d\n", x, lo, off)
   155  				switch c[indexType] {
   156  				case typeArray:
   157  				case typeBitmap:
   158  					idx := lo / 16
   159  					pos := lo % 16
   160  					t.Logf("At idx: %d. Pos: %d val: %#b\n", idx, pos, c[startIdx+idx])
   161  				}
   162  
   163  				t.Logf("Added: %d %#x. Added: %v\n", x, x, ra.Set(x))
   164  				t.Logf("After add. has: %v\n", ra.Contains(x))
   165  
   166  				// 				t.Logf("Hex dump of container at offset: %d\n%s\n", off, hex.Dump(toByteSlice(c)))
   167  				t.FailNow()
   168  			}
   169  			continue
   170  		}
   171  		m[x] = struct{}{}
   172  		// fmt.Printf("Setting x: %#x\n", x)
   173  		if added := ra.Set(x); !added {
   174  			t.Logf("Unable to set: %d %#x\n", x, x)
   175  			t.Logf("ra.Has(x): %v\n", ra.Contains(x))
   176  			t.FailNow()
   177  		}
   178  		// for x := range m {
   179  		// 	if !ra.Has(x) {
   180  		// 		t.Logf("has(x) failed: %#x\n", x)
   181  		// 		t.Logf("Debug: %s\n", ra.Debug(x))
   182  		// 		t.FailNow()
   183  		// 	}
   184  		// }
   185  		// require.Truef(t, ra.Set(x), "Unable to set x: %d %#x\n", x, x)
   186  	}
   187  	t.Logf("Card: %d\n", len(m))
   188  	require.Equalf(t, len(m), ra.GetCardinality(), "Bitmap:\n%s\n", ra)
   189  	for x := range m {
   190  		require.True(t, ra.Contains(x))
   191  	}
   192  
   193  	// _, has := ra.keys.getValue(0)
   194  	// require.True(t, has)
   195  	// for i := uint64(1); i <= max; i++ {
   196  	// 	require.Truef(t, ra.Has(i), "i=%d", i)
   197  	// }
   198  	// t.Logf("Data size: %d\n", len(ra.data))
   199  
   200  	t.Logf("Copying data. Size: %d\n", len(ra.data))
   201  	dup := make([]uint16, len(ra.data))
   202  	copy(dup, ra.data)
   203  
   204  	ra2 := FromBuffer(toByteSlice(dup))
   205  	require.Equal(t, len(m), ra2.GetCardinality())
   206  	for x := range m {
   207  		require.True(t, ra2.Contains(x))
   208  	}
   209  }
   210  
   211  func TestBitmapUint64Max(t *testing.T) {
   212  	bm := NewBitmap()
   213  
   214  	edges := []uint64{0, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64}
   215  	for _, e := range edges {
   216  		bm.Set(e)
   217  	}
   218  	for _, e := range edges {
   219  		require.True(t, bm.Contains(e))
   220  	}
   221  }
   222  
   223  func TestBitmapZero(t *testing.T) {
   224  	bm1 := NewBitmap()
   225  	bm1.Set(1)
   226  	uids := bm1.ToArray()
   227  	require.Equal(t, 1, len(uids))
   228  	for _, u := range uids {
   229  		require.Equal(t, uint64(1), u)
   230  	}
   231  
   232  	bm2 := NewBitmap()
   233  	bm2.Set(2)
   234  
   235  	bm3 := Or(bm1, bm2)
   236  	require.False(t, bm3.Contains(0))
   237  	require.True(t, bm3.Contains(1))
   238  	require.True(t, bm3.Contains(2))
   239  	require.Equal(t, 2, bm3.GetCardinality())
   240  }
   241  
   242  func TestBitmapOps(t *testing.T) {
   243  	M := int64(10000)
   244  	// smaller bitmap would always operate with [0, M) range.
   245  	// max for each bitmap = M * F
   246  	F := []int64{1, 10, 100, 1000}
   247  	N := 10000
   248  
   249  	for _, f := range F {
   250  		t.Logf("Using N: %d M: %d F: %d\n", N, M, f)
   251  		small, big := NewBitmap(), NewBitmap()
   252  		occ := make(map[uint64]int)
   253  		smallMap := make(map[uint64]struct{})
   254  		bigMap := make(map[uint64]struct{})
   255  
   256  		for i := 0; i < N; i++ {
   257  			smallx := uint64(rand.Int63n(M))
   258  
   259  			_, has := smallMap[smallx]
   260  			added := small.Set(smallx)
   261  			if has {
   262  				require.False(t, added, "Can't readd already present x: %d", smallx)
   263  			}
   264  			smallMap[smallx] = struct{}{}
   265  
   266  			bigx := uint64(rand.Int63n(M * f))
   267  			_, has = bigMap[bigx]
   268  			added = big.Set(bigx)
   269  			if has {
   270  				require.False(t, added, "Can't readd already present x: %d", bigx)
   271  			}
   272  			bigMap[bigx] = struct{}{}
   273  
   274  			occ[smallx] |= 0x01 // binary 0001
   275  			occ[bigx] |= 0x02   // binary 0010
   276  		}
   277  		require.Equal(t, len(smallMap), small.GetCardinality())
   278  		require.Equal(t, len(bigMap), big.GetCardinality())
   279  
   280  		bitOr := Or(small, big)
   281  		bitAnd := And(small, big)
   282  
   283  		t.Logf("Sizes. small: %d big: %d, bitOr: %d bitAnd: %d\n",
   284  			small.GetCardinality(), big.GetCardinality(),
   285  			bitOr.GetCardinality(), bitAnd.GetCardinality())
   286  
   287  		cntOr, cntAnd := 0, 0
   288  		for x, freq := range occ {
   289  			if freq == 0x00 {
   290  				require.Failf(t, "Failed", "Value of freq can't be zero. Found: %#x\n", freq)
   291  			} else if freq == 0x01 {
   292  				_, has := smallMap[x]
   293  				require.True(t, has)
   294  				require.True(t, small.Contains(x))
   295  				require.Truef(t, bitOr.Contains(x), "Expected %d %#x. But, not found. freq: %#x\n",
   296  					x, x, freq)
   297  				cntOr++
   298  
   299  			} else if freq == 0x02 {
   300  				// one of them has it.
   301  				_, has := bigMap[x]
   302  				require.True(t, has)
   303  				require.True(t, big.Contains(x))
   304  				require.Truef(t, bitOr.Contains(x), "Expected %d %#x. But, not found. freq: %#x\n",
   305  					x, x, freq)
   306  				cntOr++
   307  
   308  			} else if freq == 0x03 {
   309  				require.True(t, small.Contains(x))
   310  				require.True(t, big.Contains(x))
   311  				require.Truef(t, bitAnd.Contains(x), "x: %#x\n", x)
   312  				cntOr++
   313  				cntAnd++
   314  			} else {
   315  				require.Failf(t, "Failed", "Value of freq can't exceed 0x03. Found: %#x\n", freq)
   316  			}
   317  		}
   318  		if cntAnd != bitAnd.GetCardinality() {
   319  			uids := bitAnd.ToArray()
   320  			t.Logf("Len Uids: %d Card: %d cntAnd: %d. Occ: %d\n", len(uids), bitAnd.GetCardinality(), cntAnd, len(occ))
   321  
   322  			uidMap := make(map[uint64]struct{})
   323  			for _, u := range uids {
   324  				uidMap[u] = struct{}{}
   325  			}
   326  			for u := range occ {
   327  				delete(uidMap, u)
   328  			}
   329  			for x := range uidMap {
   330  				t.Logf("Remaining uids in UidMap: %d %#b\n", x, x)
   331  			}
   332  			require.FailNow(t, "Cardinality isn't matching")
   333  		}
   334  		require.Equal(t, cntOr, bitOr.GetCardinality())
   335  		require.Equal(t, cntAnd, bitAnd.GetCardinality())
   336  	}
   337  }
   338  
   339  func TestUint16(t *testing.T) {
   340  	a := uint16(0xfeff)
   341  	b := uint16(0x100)
   342  	t.Logf("a & b: %#x", a&b)
   343  	var x uint16
   344  	for i := 0; i < 100000; i++ {
   345  		prev := x
   346  		x++
   347  		if x <= prev {
   348  			// This triggers when prev = 0xFFFF.
   349  			// require.Failf(t, "x<=prev", "x %d <= prev %d", x, prev)
   350  		}
   351  	}
   352  }
   353  
   354  func TestSetGet(t *testing.T) {
   355  	bm := NewBitmap()
   356  	N := int(1e6)
   357  	for i := 0; i < N; i++ {
   358  		bm.Set(uint64(i))
   359  	}
   360  	for i := 0; i < N; i++ {
   361  		has := bm.Contains(uint64(i))
   362  		require.True(t, has)
   363  	}
   364  }
   365  
   366  func TestSetSorted(t *testing.T) {
   367  	check := func(n int) {
   368  		var arr []uint64
   369  		for i := 0; i < n; i++ {
   370  			arr = append(arr, uint64(i))
   371  		}
   372  		r := FromSortedList(arr)
   373  		require.Equal(t, len(arr), r.GetCardinality())
   374  
   375  		rarr := r.ToArray()
   376  		for i := 0; i < n; i++ {
   377  			require.Equal(t, uint64(i), rarr[i])
   378  		}
   379  
   380  		r.Set(uint64(n))
   381  		require.True(t, r.Contains(uint64(n)))
   382  	}
   383  	check(10)
   384  	check(1e6)
   385  }
   386  
   387  func TestAnd(t *testing.T) {
   388  	a := NewBitmap()
   389  	b := NewBitmap()
   390  
   391  	N := int(1e7)
   392  	for i := 0; i < N; i++ {
   393  		if i%2 == 0 {
   394  			a.Set(uint64(i))
   395  		} else {
   396  			b.Set(uint64(i))
   397  		}
   398  	}
   399  	require.Equal(t, N/2, a.GetCardinality())
   400  	require.Equal(t, N/2, b.GetCardinality())
   401  	res := And(a, b)
   402  	require.Equal(t, 0, res.GetCardinality())
   403  	a.And(b)
   404  	require.Equal(t, 0, a.GetCardinality())
   405  }
   406  
   407  func TestAnd2(t *testing.T) {
   408  	a := NewBitmap()
   409  	n := int(1e7)
   410  
   411  	for i := 0; i < n; i++ {
   412  		a.Set(uint64(i))
   413  	}
   414  	require.Equal(t, n, a.GetCardinality())
   415  	a.RemoveRange(0, uint64(n/2))
   416  
   417  	for i := 0; i < n; i++ {
   418  		a.Set(uint64(i))
   419  	}
   420  	require.Equal(t, n, a.GetCardinality())
   421  }
   422  
   423  func TestAndNot(t *testing.T) {
   424  	a := NewBitmap()
   425  	b := NewBitmap()
   426  
   427  	N := int(1e7)
   428  	for i := 0; i < N; i++ {
   429  		a.Set(uint64(i))
   430  		if i < N/2 {
   431  			b.Set(uint64(i))
   432  		}
   433  	}
   434  	require.Equal(t, N, a.GetCardinality())
   435  	require.Equal(t, N/2, b.GetCardinality())
   436  
   437  	a.AndNot(b)
   438  	require.Equal(t, N/2, a.GetCardinality())
   439  
   440  	// Test for case when array container will be generated.
   441  	a = NewBitmap()
   442  	b = NewBitmap()
   443  
   444  	a.SetMany([]uint64{1, 2, 3, 4})
   445  	b.SetMany([]uint64{3, 4, 5, 6})
   446  
   447  	a.AndNot(b)
   448  	require.Equal(t, []uint64{1, 2}, a.ToArray())
   449  
   450  	// Test for case when bitmap container will be generated.
   451  	a = NewBitmap()
   452  	b = NewBitmap()
   453  	for i := 0; i < 10000; i++ {
   454  		a.Set(uint64(i))
   455  		if i < 7000 {
   456  			b.Set(uint64(i))
   457  		}
   458  	}
   459  	a.AndNot(b)
   460  	require.Equal(t, 3000, a.GetCardinality())
   461  	for i := 0; i < 10000; i++ {
   462  		if i < 7000 {
   463  			require.False(t, a.Contains(uint64(i)))
   464  		} else {
   465  			require.True(t, a.Contains(uint64(i)))
   466  		}
   467  	}
   468  }
   469  
   470  func TestAndNot2(t *testing.T) {
   471  	a := NewBitmap()
   472  	b := NewBitmap()
   473  	n := int(1e6)
   474  
   475  	for i := 0; i < n/2; i++ {
   476  		a.Set(uint64(i))
   477  	}
   478  	for i := n / 2; i < n; i++ {
   479  		b.Set(uint64(i))
   480  	}
   481  	require.Equal(t, n/2, a.GetCardinality())
   482  	a.AndNot(b)
   483  	require.Equal(t, n/2, a.GetCardinality())
   484  
   485  }
   486  
   487  func TestOr(t *testing.T) {
   488  	a := NewBitmap()
   489  	b := NewBitmap()
   490  
   491  	N := int(1e7)
   492  	for i := 0; i < N; i++ {
   493  		if i%2 == 0 {
   494  			a.Set(uint64(i))
   495  		} else {
   496  			b.Set(uint64(i))
   497  		}
   498  	}
   499  	require.Equal(t, N/2, a.GetCardinality())
   500  	require.Equal(t, N/2, b.GetCardinality())
   501  	res := Or(a, b)
   502  	require.Equal(t, N, res.GetCardinality())
   503  	a.or(b, 0)
   504  	require.Equal(t, N, a.GetCardinality())
   505  }
   506  
   507  func TestCardinality(t *testing.T) {
   508  	a := NewBitmap()
   509  	n := 1 << 20
   510  	for i := 0; i < n; i++ {
   511  		a.Set(uint64(i))
   512  	}
   513  	require.Equal(t, n, a.GetCardinality())
   514  }
   515  
   516  func TestRemove(t *testing.T) {
   517  	a := NewBitmap()
   518  	N := int(1e7)
   519  	for i := 0; i < N; i++ {
   520  		a.Set(uint64(i))
   521  	}
   522  	require.Equal(t, N, a.GetCardinality())
   523  	for i := 0; i < N/2; i++ {
   524  		require.True(t, a.Remove(uint64(i)))
   525  	}
   526  	require.Equal(t, N/2, a.GetCardinality())
   527  
   528  	// Remove elelemts which doesn't exist should be no-op
   529  	for i := 0; i < N/2; i++ {
   530  		require.False(t, a.Remove(uint64(i)))
   531  	}
   532  	require.Equal(t, N/2, a.GetCardinality())
   533  
   534  	for i := 0; i < N/2; i++ {
   535  		require.True(t, a.Remove(uint64(i+N/2)))
   536  	}
   537  	require.Equal(t, 0, a.GetCardinality())
   538  }
   539  
   540  func TestContainerRemoveRange(t *testing.T) {
   541  	ra := NewBitmap()
   542  
   543  	type cases struct {
   544  		lo       uint16
   545  		hi       uint16
   546  		expected []uint16
   547  	}
   548  
   549  	testBitmap := func(tc cases) {
   550  		offset := ra.newContainer(maxContainerSize)
   551  		c := ra.getContainer(offset)
   552  		c[indexType] = typeBitmap
   553  		a := bitmap(c)
   554  
   555  		for i := 1; i <= 5; i++ {
   556  			a.add(uint16(5 * i))
   557  		}
   558  		a.removeRange(tc.lo, tc.hi)
   559  		result := a.all()
   560  		require.Equalf(t, len(tc.expected), getCardinality(a), "case: %+v, actual:%v\n", tc, result)
   561  		require.Equalf(t, tc.expected, result, "case: %+v actual: %v\n", tc, result)
   562  	}
   563  
   564  	testArray := func(tc cases) {
   565  		offset := ra.newContainer(maxContainerSize)
   566  		c := ra.getContainer(offset)
   567  		c[indexType] = typeArray
   568  		a := array(c)
   569  
   570  		for i := 1; i <= 5; i++ {
   571  			a.add(uint16(5 * i))
   572  		}
   573  		a.removeRange(tc.lo, tc.hi)
   574  		result := a.all()
   575  		require.Equalf(t, len(tc.expected), getCardinality(a), "case: %+v, actual:%v\n", tc, result)
   576  		require.Equalf(t, tc.expected, result, "case: %+v actual: %v\n", tc, result)
   577  	}
   578  
   579  	tests := []cases{
   580  		{8, 22, []uint16{5, 25}},
   581  		{8, 20, []uint16{5, 25}},
   582  		{10, 22, []uint16{5, 25}},
   583  		{10, 20, []uint16{5, 25}},
   584  		{7, 11, []uint16{5, 15, 20, 25}},
   585  		{7, 10, []uint16{5, 15, 20, 25}},
   586  		{10, 11, []uint16{5, 15, 20, 25}},
   587  		{0, 0, []uint16{5, 10, 15, 20, 25}},
   588  		{30, 30, []uint16{5, 10, 15, 20, 25}},
   589  	}
   590  
   591  	for _, tc := range tests {
   592  		testBitmap(tc)
   593  		testArray(tc)
   594  	}
   595  }
   596  
   597  func TestRemoveRange(t *testing.T) {
   598  	a := NewBitmap()
   599  	N := int(1e7)
   600  	for i := 0; i < N; i++ {
   601  		a.Set(uint64(i))
   602  	}
   603  	a.RemoveRange(0, 0)
   604  	require.Equal(t, N, a.GetCardinality())
   605  
   606  	require.Equal(t, N, a.GetCardinality())
   607  	a.RemoveRange(uint64(N/4), uint64(N/2))
   608  	require.Equal(t, 3*N/4, a.GetCardinality())
   609  
   610  	a.RemoveRange(0, uint64(N/2))
   611  	require.Equal(t, N/2, a.GetCardinality())
   612  
   613  	a.RemoveRange(uint64(N/2), uint64(N))
   614  	require.Equal(t, 0, a.GetCardinality())
   615  	a.Set(uint64(N / 4))
   616  	a.Set(uint64(N / 2))
   617  	a.Set(uint64(3 * N / 4))
   618  	require.Equal(t, 3, a.GetCardinality())
   619  
   620  	var arr []uint64
   621  	for i := 0; i < 123; i++ {
   622  		arr = append(arr, uint64(i))
   623  	}
   624  	b := FromSortedList(arr)
   625  	b.RemoveRange(50, math.MaxUint64)
   626  	require.Equal(t, 50, b.GetCardinality())
   627  }
   628  
   629  func TestRemoveRange2(t *testing.T) {
   630  	// High from the last container should not be removed.
   631  	a := NewBitmap()
   632  	for i := 1; i < 10; i++ {
   633  		a.Set(uint64(i * (1 << 16)))
   634  		a.Set(uint64(i*(1<<16)) - 1)
   635  	}
   636  	a.RemoveRange(1<<16, (4<<16)-1)
   637  	require.True(t, a.Contains((4<<16)-1))
   638  }
   639  
   640  func TestSelect(t *testing.T) {
   641  	a := NewBitmap()
   642  	N := int(1e4)
   643  	for i := 0; i < N; i++ {
   644  		a.Set(uint64(i))
   645  	}
   646  	for i := 0; i < N; i++ {
   647  		val, err := a.Select(uint64(i))
   648  		require.NoError(t, err)
   649  		require.Equal(t, uint64(i), val)
   650  	}
   651  }
   652  
   653  func TestClone(t *testing.T) {
   654  	a := NewBitmap()
   655  	N := int(1e5)
   656  
   657  	for i := 0; i < N; i++ {
   658  		a.Set(uint64(rand.Int63n(math.MaxInt64)))
   659  	}
   660  	b := a.Clone()
   661  	require.Equal(t, a.GetCardinality(), b.GetCardinality())
   662  	require.Equal(t, a.ToArray(), b.ToArray())
   663  }
   664  
   665  func TestContainerFull(t *testing.T) {
   666  	c := make([]uint16, maxContainerSize)
   667  	b := bitmap(c)
   668  	b[indexType] = typeBitmap
   669  	b[indexSize] = maxContainerSize
   670  	for i := 0; i < 1<<16; i++ {
   671  		b.add(uint16(i))
   672  	}
   673  	require.Equal(t, math.MaxUint16+1, getCardinality(b))
   674  
   675  	c2 := make([]uint16, maxContainerSize)
   676  	copy(c2, c)
   677  	b2 := bitmap(c2)
   678  
   679  	b.orBitmap(b2, nil, runInline)
   680  	require.Equal(t, math.MaxUint16+1, getCardinality(b))
   681  
   682  	setCardinality(b, invalidCardinality)
   683  	b.orBitmap(b2, nil, runInline)
   684  	require.Equal(t, invalidCardinality, getCardinality(b))
   685  
   686  	setCardinality(b, b.cardinality())
   687  	require.Equal(t, maxCardinality, getCardinality(b))
   688  }
   689  
   690  func TestExtremes(t *testing.T) {
   691  	a := NewBitmap()
   692  	require.Equal(t, uint64(0), a.Minimum())
   693  	require.Equal(t, uint64(0), a.Maximum())
   694  
   695  	a.Set(1)
   696  	require.Equal(t, uint64(1), a.Minimum())
   697  	require.Equal(t, uint64(1), a.Maximum())
   698  
   699  	a.Set(100000)
   700  	require.Equal(t, uint64(1), a.Minimum())
   701  	require.Equal(t, uint64(100000), a.Maximum())
   702  
   703  	a.Remove(100000)
   704  	require.Equal(t, uint64(1), a.Minimum())
   705  	require.Equal(t, uint64(1), a.Maximum())
   706  
   707  	a.Remove(1)
   708  	require.Equal(t, uint64(0), a.Minimum())
   709  	require.Equal(t, uint64(0), a.Maximum())
   710  
   711  	a.Set(100000)
   712  	require.Equal(t, uint64(100000), a.Minimum())
   713  	require.Equal(t, uint64(100000), a.Maximum())
   714  }
   715  
   716  func TestCleanup(t *testing.T) {
   717  	a := NewBitmap()
   718  	n := 10
   719  
   720  	for i := 0; i < n; i++ {
   721  		a.Set(uint64((i * (1 << 16))))
   722  	}
   723  	abuf := a.ToBufferWithCopy()
   724  
   725  	require.Equal(t, 10, a.keys.numKeys())
   726  	a.RemoveRange(1<<16, 2*(1<<16))
   727  	require.Equal(t, 9, a.keys.numKeys())
   728  
   729  	a.RemoveRange(6*(1<<16), 8*(1<<16))
   730  	require.Equal(t, 7, a.keys.numKeys())
   731  
   732  	a = FromBufferWithCopy(abuf)
   733  	require.Equal(t, 10, a.keys.numKeys())
   734  	a.Remove(6 * (1 << 16))
   735  	a.RemoveRange(7*(1<<16), 9*(1<<16))
   736  	require.Equal(t, 7, a.keys.numKeys())
   737  
   738  	n = int(1e6)
   739  	b := NewBitmap()
   740  	for i := 0; i < n; i++ {
   741  		b.Set(uint64(i))
   742  	}
   743  	b.RemoveRange(0, uint64(n/2))
   744  	require.Equal(t, n/2, b.GetCardinality())
   745  	buf := b.ToBuffer()
   746  	b = FromBuffer(buf)
   747  	require.Equal(t, n/2, b.GetCardinality())
   748  }
   749  
   750  func TestCleanup2(t *testing.T) {
   751  	a := NewBitmap()
   752  	n := 10
   753  	for i := 0; i < n; i++ {
   754  		a.Set(uint64(i * (1 << 16)))
   755  	}
   756  	require.Equal(t, n, a.GetCardinality())
   757  	require.Equal(t, n, a.keys.numKeys())
   758  
   759  	for i := 0; i < n; i++ {
   760  		if i%2 == 1 {
   761  			a.Remove(uint64(i * (1 << 16)))
   762  		}
   763  	}
   764  	require.Equal(t, n/2, a.GetCardinality())
   765  	require.Equal(t, n, a.keys.numKeys())
   766  
   767  	a.Cleanup()
   768  	require.Equal(t, n/2, a.GetCardinality())
   769  	require.Equal(t, n/2, a.keys.numKeys())
   770  }
   771  
   772  func TestCleanupSplit(t *testing.T) {
   773  	a := NewBitmap()
   774  	n := int(1e8)
   775  
   776  	for i := 0; i < n; i++ {
   777  		a.Set(uint64(i))
   778  	}
   779  
   780  	split := func() {
   781  		n := a.GetCardinality()
   782  		mid, err := a.Select(uint64(n / 2))
   783  		require.NoError(t, err)
   784  
   785  		b := a.Clone()
   786  		a.RemoveRange(0, mid)
   787  		b.RemoveRange(mid, math.MaxUint64)
   788  
   789  		require.Equal(t, n, a.GetCardinality()+b.GetCardinality())
   790  	}
   791  	for a.GetCardinality() > 1 {
   792  		split()
   793  	}
   794  }
   795  
   796  func TestIsEmpty(t *testing.T) {
   797  	a := NewBitmap()
   798  	require.True(t, a.IsEmpty())
   799  
   800  	n := int(1e6)
   801  	for i := 0; i < n; i++ {
   802  		a.Set(uint64(i))
   803  	}
   804  	require.False(t, a.IsEmpty())
   805  	a.RemoveRange(0, math.MaxUint64)
   806  	require.True(t, a.IsEmpty())
   807  }
   808  
   809  func TestRank(t *testing.T) {
   810  	a := NewBitmap()
   811  	n := int(1e6)
   812  	for i := uint64(0); i < uint64(n); i++ {
   813  		a.Set(i)
   814  	}
   815  	for i := 0; i < n; i++ {
   816  		require.Equal(t, i, a.Rank(uint64(i)))
   817  	}
   818  	require.Equal(t, -1, a.Rank(uint64(n)))
   819  
   820  	// Check ranks after removing an element.
   821  	a.Remove(100)
   822  	for i := 0; i < n; i++ {
   823  		if i < 100 {
   824  			require.Equal(t, i, a.Rank(uint64(i)))
   825  		} else if i == 100 {
   826  			require.Equal(t, -1, a.Rank(uint64(i)))
   827  		} else {
   828  			require.Equal(t, i-1, a.Rank(uint64(i)))
   829  		}
   830  	}
   831  
   832  	// Check ranks after removing a range of elements.
   833  	a.RemoveRange(0, uint64(1e4))
   834  	for i := 0; i < n; i++ {
   835  		if i < 1e4 {
   836  			require.Equal(t, -1, a.Rank(uint64(n)))
   837  		} else {
   838  			require.Equal(t, i-1e4, a.Rank(uint64(i)))
   839  		}
   840  	}
   841  }
   842  
   843  func TestSplit(t *testing.T) {
   844  	run := func(n int) {
   845  		r := NewBitmap()
   846  		for i := 1; i <= n; i++ {
   847  			r.Set(uint64(i))
   848  		}
   849  		f := func(start, end uint64) uint64 { return 0 }
   850  
   851  		// Split the bitmaps.
   852  		bms := r.Split(f, 1<<10)
   853  		var csum int
   854  		for _, bm := range bms {
   855  			csum += bm.GetCardinality()
   856  		}
   857  		require.Equal(t, n, csum)
   858  
   859  		id := uint64(1)
   860  		for _, bm := range bms {
   861  			itr := bm.NewIterator()
   862  			for cur := itr.Next(); cur != 0; cur = itr.Next() {
   863  				require.Equal(t, id, cur)
   864  				id++
   865  			}
   866  		}
   867  	}
   868  
   869  	run(2)
   870  	run(11)
   871  	run(1e3)
   872  	run(1e6)
   873  }
   874  
   875  // Test making sure out of range panic does not occur anymore
   876  // https://github.com/weaviate/sroar/issues/1
   877  //
   878  // panic: runtime error: slice bounds out of range [:204] with capacity 64
   879  func Test_Issue_1(t *testing.T) {
   880  
   881  	genBitmap := func(fromInc, toExc uint64) *Bitmap {
   882  		bm := NewBitmap()
   883  		for i := fromInc; i < toExc; i++ {
   884  			bm.Set(i)
   885  		}
   886  		return bm
   887  	}
   888  
   889  	genSlice := func(fromInc, toExc uint64) []uint64 {
   890  		slice := []uint64{}
   891  		for i := fromInc; i < toExc; i++ {
   892  			slice = append(slice, i)
   893  		}
   894  		return slice
   895  	}
   896  
   897  	type testCase struct {
   898  		name             string
   899  		leftBm           *Bitmap
   900  		rightBm          *Bitmap
   901  		nextLeftBm       *Bitmap
   902  		expectedElements []uint64
   903  	}
   904  
   905  	testCases := []testCase{
   906  		{
   907  			// returns 30x 65536 instead of 71970..71999
   908  			name:       "array of 60 elements in left bitmap, 2 internal containers (numbers > 2^16), empty bitmap on left Or",
   909  			leftBm:     genBitmap(71_970, 72_030),
   910  			rightBm:    genBitmap(72_000, 75_000),
   911  			nextLeftBm: NewBitmap(),
   912  
   913  			expectedElements: genSlice(71_970, 72_000),
   914  		},
   915  		{
   916  			// working (sanity check)
   917  			name:       "array of 60 elements in left bitmap, 1 internal container (numbers < 2^16), empty bitmap on left Or",
   918  			leftBm:     genBitmap(970, 1_030),
   919  			rightBm:    genBitmap(1_000, 4_000),
   920  			nextLeftBm: NewBitmap(),
   921  
   922  			expectedElements: genSlice(970, 1_000),
   923  		},
   924  		{
   925  			// panic: runtime error: slice bounds out of range [:204] with capacity 64
   926  			name:       "array of 300 elements in left bitmap, 2 internal containers (numbers > 2^16), empty bitmap on left Or",
   927  			leftBm:     genBitmap(71_800, 72_100),
   928  			rightBm:    genBitmap(72_000, 75_000),
   929  			nextLeftBm: NewBitmap(),
   930  
   931  			expectedElements: genSlice(71_800, 72_000),
   932  		},
   933  		{
   934  			// working (sanity check)
   935  			name:       "array of 300 elements in left bitmap, 1 internal container (numbers < 2^16), empty bitmap on left Or",
   936  			leftBm:     genBitmap(800, 1_100),
   937  			rightBm:    genBitmap(1_000, 4_000),
   938  			nextLeftBm: NewBitmap(),
   939  
   940  			expectedElements: genSlice(800, 1_000),
   941  		},
   942  		{
   943  			// working (sanity check)
   944  			name:       "array of 60 elements in left bitmap, 2 internal containers (numbers > 2^16), non-empty bitmap on left Or",
   945  			leftBm:     genBitmap(71_970, 72_030),
   946  			rightBm:    genBitmap(72_000, 75_000),
   947  			nextLeftBm: genBitmap(71_980, 72_000),
   948  
   949  			expectedElements: genSlice(71_970, 72_000),
   950  		},
   951  		{
   952  			// working (sanity check)
   953  			name:       "array of 60 elements in left bitmap, 1 internal container (numbers < 2^16), non-empty bitmap on left Or",
   954  			leftBm:     genBitmap(970, 1_030),
   955  			rightBm:    genBitmap(1_000, 4_000),
   956  			nextLeftBm: genBitmap(980, 1_000),
   957  
   958  			expectedElements: genSlice(970, 1_000),
   959  		},
   960  		{
   961  			// working (sanity check)
   962  			name:       "array of 300 elements in left bitmap, 2 internal containers (numbers > 2^16), non-empty bitmap on left Or",
   963  			leftBm:     genBitmap(71_800, 72_100),
   964  			rightBm:    genBitmap(72_000, 75_000),
   965  			nextLeftBm: genBitmap(71_900, 72_000),
   966  
   967  			expectedElements: genSlice(71_800, 72_000),
   968  		},
   969  		{
   970  			// working (sanity check)
   971  			name:       "array of 300 elements in left bitmap, 1 internal container (numbers < 2^16), non-empty bitmap on left Or",
   972  			leftBm:     genBitmap(800, 1_100),
   973  			rightBm:    genBitmap(1_000, 4_000),
   974  			nextLeftBm: genBitmap(900, 1_000),
   975  
   976  			expectedElements: genSlice(800, 1_000),
   977  		},
   978  		{
   979  			// returns 30x 65536 instead of 71970..71999
   980  			name:       "array of 60 elements in left bitmap, 2 internal containers (numbers > 2^16), non-empty (other container) bitmap on left Or",
   981  			leftBm:     genBitmap(71_970, 72_030),
   982  			rightBm:    genBitmap(72_000, 75_000),
   983  			nextLeftBm: genBitmap(970, 1_000),
   984  
   985  			expectedElements: append(genSlice(970, 1_000), genSlice(71_970, 72_000)...),
   986  		},
   987  		{
   988  			// working (sanity check)
   989  			name:       "array of 60 elements in left bitmap, 1 internal container (numbers < 2^16), non-empty bitmap (other container) on left Or",
   990  			leftBm:     genBitmap(970, 1_030),
   991  			rightBm:    genBitmap(1_000, 4_000),
   992  			nextLeftBm: genBitmap(71_970, 72_000),
   993  
   994  			expectedElements: append(genSlice(970, 1_000), genSlice(71_970, 72_000)...),
   995  		},
   996  		{
   997  			// returns 200x 65536 instead of 71800..71999
   998  			name:       "array of 300 elements in left bitmap, 2 internal containers (numbers > 2^16), non-empty (other container) bitmap on left Or",
   999  			leftBm:     genBitmap(71_800, 72_100),
  1000  			rightBm:    genBitmap(72_000, 75_000),
  1001  			nextLeftBm: genBitmap(800, 1_000),
  1002  
  1003  			expectedElements: append(genSlice(800, 1_000), genSlice(71_800, 72_000)...),
  1004  		},
  1005  		{
  1006  			// working (sanity check)
  1007  			name:       "array of 300 elements in left bitmap, 1 internal container (numbers < 2^16), non-empty (other container) bitmap on left Or",
  1008  			leftBm:     genBitmap(800, 1_100),
  1009  			rightBm:    genBitmap(1_000, 4_000),
  1010  			nextLeftBm: genBitmap(71_800, 72_000),
  1011  
  1012  			expectedElements: append(genSlice(800, 1_000), genSlice(71_800, 72_000)...),
  1013  		},
  1014  	}
  1015  
  1016  	for _, tc := range testCases {
  1017  		t.Run(tc.name, func(t *testing.T) {
  1018  			broken := tc.leftBm.Clone()
  1019  			broken.AndNot(tc.rightBm)
  1020  
  1021  			failing := tc.nextLeftBm.Clone()
  1022  			failing.Or(broken)
  1023  
  1024  			elements := failing.ToArray()
  1025  
  1026  			require.Len(t, elements, len(tc.expectedElements))
  1027  			require.ElementsMatch(t, elements, tc.expectedElements)
  1028  		})
  1029  	}
  1030  }