package hbrdd import ( "testing" ) // === Unit Tests === func TestBitmap_Basic(t *testing.T) { bm := NewBitmapFilter(100) bm.Set(1); bm.Set(50); bm.Set(100) if !bm.Test(1) || !bm.Test(50) || !bm.Test(100) { t.Error("Set bits should test true") } if bm.Test(2) || bm.Test(99) { t.Error("Unset bits should test false") } if bm.Count() != 3 { t.Errorf("Count = %d, want 3", bm.Count()) } } func TestBitmap_NextSet(t *testing.T) { bm := NewBitmapFilter(1000) bm.Set(10); bm.Set(100); bm.Set(500); bm.Set(999) if n := bm.NextSet(1); n != 10 { t.Errorf("NextSet(1) = %d, want 10", n) } if n := bm.NextSet(11); n != 100 { t.Errorf("NextSet(11) = %d, want 100", n) } if n := bm.NextSet(501); n != 999 { t.Errorf("NextSet(501) = %d, want 999", n) } if n := bm.NextSet(1000); n != 0 { t.Errorf("NextSet(1000) = %d, want 0", n) } } func TestBitmap_PrevSet(t *testing.T) { bm := NewBitmapFilter(1000) bm.Set(10); bm.Set(100); bm.Set(500); bm.Set(999) if n := bm.PrevSet(1000); n != 999 { t.Errorf("PrevSet(1000) = %d, want 999", n) } if n := bm.PrevSet(998); n != 500 { t.Errorf("PrevSet(998) = %d, want 500", n) } if n := bm.PrevSet(99); n != 10 { t.Errorf("PrevSet(99) = %d, want 10", n) } if n := bm.PrevSet(9); n != 0 { t.Errorf("PrevSet(9) = %d, want 0", n) } } func TestBitmap_Full(t *testing.T) { bm := NewBitmapFilterFull(100) if bm.Count() != 100 { t.Errorf("Full count = %d, want 100", bm.Count()) } bm.Clear(50) if bm.Count() != 99 { t.Errorf("After clear = %d, want 99", bm.Count()) } if bm.Test(50) { t.Error("Cleared bit should be false") } // Verify no excess bits if bm.Test(101) { t.Error("Bit 101 should be false (past maxRec)") } } func TestBitmap_FullEdge(t *testing.T) { // Test exact 64-bit boundary bm := NewBitmapFilterFull(64) if bm.Count() != 64 { t.Errorf("Full(64) = %d", bm.Count()) } bm2 := NewBitmapFilterFull(65) if bm2.Count() != 65 { t.Errorf("Full(65) = %d", bm2.Count()) } bm3 := NewBitmapFilterFull(128) if bm3.Count() != 128 { t.Errorf("Full(128) = %d", bm3.Count()) } } func TestBitmap_And(t *testing.T) { a := NewBitmapFilter(100) b := NewBitmapFilter(100) a.Set(1); a.Set(2); a.Set(3) b.Set(2); b.Set(3); b.Set(4) result := a.And(b) if result.Count() != 2 { t.Errorf("AND count = %d, want 2", result.Count()) } if !result.Test(2) || !result.Test(3) { t.Error("AND should have 2,3") } } func TestBitmap_Or(t *testing.T) { a := NewBitmapFilter(100) b := NewBitmapFilter(100) a.Set(1); a.Set(2) b.Set(3); b.Set(4) result := a.Or(b) if result.Count() != 4 { t.Errorf("OR count = %d, want 4", result.Count()) } } func TestBitmap_AndNot(t *testing.T) { a := NewBitmapFilterFull(100) b := NewBitmapFilter(100) b.Set(1); b.Set(50); b.Set(100) result := a.AndNot(b) if result.Count() != 97 { t.Errorf("ANDNOT count = %d, want 97", result.Count()) } if result.Test(1) || result.Test(50) || result.Test(100) { t.Error("ANDNOT should exclude 1,50,100") } if !result.Test(2) { t.Error("ANDNOT should include 2") } } func TestBitmap_Not(t *testing.T) { bm := NewBitmapFilter(64) bm.Set(1) inv := bm.Not() if inv.Test(1) { t.Error("NOT should clear bit 1") } if !inv.Test(2) { t.Error("NOT should set bit 2") } if inv.Count() != 63 { t.Errorf("NOT count = %d, want 63", inv.Count()) } } func TestBitmap_InPlace(t *testing.T) { a := NewBitmapFilterFull(100) b := NewBitmapFilter(100) b.Set(10); b.Set(20); b.Set(30) a.AndInPlace(b) if a.Count() != 3 { t.Errorf("AndInPlace count = %d, want 3", a.Count()) } c := NewBitmapFilter(100) c.Set(40); c.Set(50) a.OrInPlace(c) if a.Count() != 5 { t.Errorf("OrInPlace count = %d, want 5", a.Count()) } } func TestBitmap_Parallel(t *testing.T) { bm := BuildParallel(10000, func(r uint32) bool { return r%10 == 0 // every 10th record }) if bm.Count() != 1000 { t.Errorf("Parallel count = %d, want 1000", bm.Count()) } if !bm.Test(10) { t.Error("Record 10 should match") } if bm.Test(11) { t.Error("Record 11 should not match") } } // === Benchmarks === func BenchmarkBitmap_NextSet_Sparse(b *testing.B) { bm := NewBitmapFilter(1000000) for i := uint32(1); i <= 1000000; i += 100 { bm.Set(i) } b.ResetTimer() for i := 0; i < b.N; i++ { rec := uint32(1) for rec != 0 { rec = bm.NextSet(rec + 1) } } } func BenchmarkBitmap_PrevSet_Sparse(b *testing.B) { bm := NewBitmapFilter(1000000) for i := uint32(1); i <= 1000000; i += 100 { bm.Set(i) } b.ResetTimer() for i := 0; i < b.N; i++ { rec := bm.maxRec for rec != 0 { rec = bm.PrevSet(rec - 1) } } } func BenchmarkBitmap_NextSet_Dense(b *testing.B) { bm := NewBitmapFilterFull(1000000) for i := uint32(1); i <= 1000000; i += 100 { bm.Clear(i) } b.ResetTimer() for i := 0; i < b.N; i++ { count := 0 rec := uint32(1) for rec != 0 { count++ rec = bm.NextSet(rec + 1) if count > 1000000 { break } } } } func BenchmarkBitmap_SequentialScan(b *testing.B) { records := make([]bool, 1000000) for i := 0; i < len(records); i += 100 { records[i] = true } b.ResetTimer() for i := 0; i < b.N; i++ { count := 0 for _, match := range records { if match { count++ } } } } func BenchmarkBitmap_And_1M(b *testing.B) { a := NewBitmapFilterFull(1000000) bm := NewBitmapFilterFull(1000000) for i := uint32(1); i <= 1000000; i += 2 { a.Clear(i) } b.ResetTimer() for i := 0; i < b.N; i++ { a.And(bm) } } func BenchmarkBitmap_AndInPlace_1M(b *testing.B) { template := NewBitmapFilterFull(1000000) other := NewBitmapFilterFull(1000000) for i := uint32(1); i <= 1000000; i += 2 { other.Clear(i) } b.ResetTimer() for i := 0; i < b.N; i++ { bm := NewBitmapFilterFull(1000000) copy(bm.bits, template.bits) bm.count = template.count bm.AndInPlace(other) } } func BenchmarkBitmap_Or_1M(b *testing.B) { a := NewBitmapFilter(1000000) bm := NewBitmapFilter(1000000) for i := uint32(1); i <= 1000000; i += 3 { a.Set(i) } for i := uint32(1); i <= 1000000; i += 5 { bm.Set(i) } b.ResetTimer() for i := 0; i < b.N; i++ { a.Or(bm) } } func BenchmarkBitmap_AndNot_1M(b *testing.B) { a := NewBitmapFilterFull(1000000) bm := NewBitmapFilter(1000000) for i := uint32(1); i <= 1000000; i += 3 { bm.Set(i) } b.ResetTimer() for i := 0; i < b.N; i++ { a.AndNot(bm) } } func BenchmarkBitmap_Parallel_1M(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { BuildParallel(1000000, func(r uint32) bool { return r%100 == 0 }) } } func BenchmarkBitmap_Sequential_1M(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { bm := NewBitmapFilter(1000000) for r := uint32(1); r <= 1000000; r++ { if r%100 == 0 { bm.Set(r) } } } }