func TestKeys(t *testing.T) {
	f, err := NewFilter(1000, 4, 0.01)
	if err != nil {
		t.Error("unable to create a filter")
	}
	if f.HasKey("a") {
		t.Error("filter shouldn't contain key a")
	}
	if f.AddKey("a"); !f.HasKey("a") {
		t.Error("filter should contain key a")
	}
	if f.HasKey("b") {
		t.Error("filter should contain key b")
	}
	if f.RemoveKey("a"); f.HasKey("a") {
		t.Error("filter shouldn't contain key a after removal")
	}
	f.AddKey("a")
	f.AddKey("a")
	f.RemoveKey("a")
	if !f.HasKey("a") {
		t.Error("filter should still contain key a")
	}
}
TestKeys adds keys, tests existence, and removes keys.
package cbfilter
import (
	"fmt"
	"math"
	"testing"
)
func TestProbFalsePositive(t *testing.T) {
	if probFalsePositive(0, 1, 1) != 0 {
		t.Error("P(FP) with no insertions != 0")
	}
	if probFalsePositive(1, 1, 1) != 1 {
		t.Error("P(FP) with full filter != 1")
	}
	if probFalsePositive(1, 1, 10) > probFalsePositive(10, 1, 10) {
		t.Error("P(FP) should increase with insertions")
	}
	if probFalsePositive(10, 1, 10) < probFalsePositive(10, 1, 100) {
		t.Error("P(FP) should decrease with space")
	}
}
func TestOptimalValues(t *testing.T) {
	M10, _ := computeOptimalValues(1000, 0.10)
	M05, _ := computeOptimalValues(1000, 0.05)
	M01, _ := computeOptimalValues(1000, 0.01)
	if M10 > M05 || M05 > M01 {
		t.Error("space efficiency should decrease with lower P(FP)", M10, M05, M01)
	}
}
func TestNewFilter(t *testing.T) {
	if _, err := NewFilter(0, 3, 0.10); err == nil {
		t.Error("NewFilter should not accept N == 0")
	}
	if _, err := NewFilter(1, 0, 0.10); err == nil {
		t.Error("NewFilter should not accept 0 bits")
	}
	if _, err := NewFilter(1, 9, 0.10); err == nil {
		t.Error("NewFilter should not accept more than 8 bits")
	}
	if _, err := NewFilter(1, 16, 0.10); err == nil {
		t.Error("NewFilter should not accept bits B which are > 8")
	}
	f, err := NewFilter(1000, 8, 0.01)
	if err != nil {
		t.Error("unable to create a filter")
	}
	M, K := computeOptimalValues(1000, 0.01)
	if M != f.M || K != f.K {
		t.Error("optimal values not used", M, K, f)
	}
	if len(f.Data) != int(M) {
		t.Error("slots data should require M bytes")
	}
	for B := uint32(1); B <= 8; B++ {
		f, err := NewFilter(1000, B, 0.01)
		if err != nil {
			t.Error("unable to create a filter")
		}
		expSize := int((M*B + 7) / 8)
		if len(f.Data) != expSize {
			t.Error("slot sizes don't match", len(f.Data), expSize)
		}
		if f.MaxCount != 1<<B-1 {
			t.Error("max count incorrect", f.MaxCount, 1<<B-1)
		}
	}
}
func TestSlots(t *testing.T) {
	for b := 1; b <= 8; b++ {
		f, err := NewFilter(10, uint32(b), 0.10)
		if err != nil {
			t.Error("unable to create a filter")
		}
		for i := 0; i < len(f.Data); i++ {
			if f.Data[i] != 0 {
				t.Errorf("slot %d not empty", i)
			}
		}
		for s := uint32(0); s < f.M; s++ {
			f.incrementSlot(s, 1)
			if f.getSlot(s) != 1 {
				t.Errorf("slot value %d != 1", f.getSlot(s))
			}
			f.incrementSlot(s, int32(f.MaxCount))
			if f.getSlot(s) != f.MaxCount {
				t.Errorf("slot value should be max %d != %d", f.getSlot(s), f.MaxCount)
			}
			f.incrementSlot(s, -1)
			if f.getSlot(s) != f.MaxCount-1 {
				t.Errorf("slot value should be max-1 %d != %d", f.getSlot(s), f.MaxCount-1)
			}
			f.incrementSlot(s, -int32(f.MaxCount))
			if f.getSlot(s) != 0 {
				t.Errorf("slot value should be 0 %d != 0", f.getSlot(s))
			}
			for i := uint32(0); i < f.MaxCount; i++ {
				f.incrementSlot(s, 1)
				if f.getSlot(s) != i+1 {
					t.Errorf("slot value should be %d != %d", i+1, f.getSlot(s))
				}
			}
		}
	}
}