package search import ( "fmt" "testing" "codeberg.org/snonux/algorithms/ds" "codeberg.org/snonux/algorithms/sort" ) const factor int = 10 const minLength int = 1 const maxLength int = 10000 // Store here so that Go isn't optimizing the benchmark away. var benchResult interface{} func TestElementary(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test[int,int](NewElementary[int,int](), i, t) } } func TestBST(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test[int,int](NewBST[int,int](), i, t) } } func TestRedBlackBST(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test[int,int](NewRedBlackBST[int,int](), i, t) } } func TestHash(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test[int,int](NewHash[int,int](i*2), i, t) } } func TestGoMap(t *testing.T) { for i := minLength; i <= maxLength; i *= factor { test[int,int](NewGoMap[int,int](), i, t) } } func test[K ds.Integer, V ds.Number](s Set[K,V], l int, t *testing.T) { keys := ds.NewRandomArrayList[K](l, l) randoms := ds.NewRandomArrayList[V](l, -1) mapping := make(map[K]V, l) get := func(key K, del bool) V { var val V var err error switch { case del: defer delete(mapping, key) val, err = s.Del(key) //t.Log("Del", key, val, err) default: val, err = s.Get(key) //t.Log("Get", key, val, err) } if mVal, ok := mapping[key]; ok { if err != nil { t.Error("Could not get element", key, val, mVal, err) } if mVal != val { t.Error("Got wrong value for element", key, val, mVal) } return val } if err == nil { t.Error("Got element but expected not to", key, val) } return val } testGet := func(key K) V { return get(key, false) } testDel := func(key K) V { return get(key, true) } testPut := func(key K, val V) { s.Put(key, val) mapping[key] = val //t.Log("Put", key, val) testGet(key) } //t.Log("Put random key-values", l) var prevKey K for _, key := range sort.Shuffle(keys) { testPut(key, randoms[key]) testGet(prevKey) prevKey = key } //t.Log("Del random key-values", l) for _, key := range sort.Shuffle(keys) { testDel(key) testGet(prevKey) prevKey = key } if !s.Empty() { t.Error("Expected set to be empty", l) } } func BenchmarkElementary(t *testing.B) { s := NewElementary[int,int]() for i := minLength; i <= maxLength; i *= factor { benchmark[int,int](s, i, t) } } func BenchmarkBST(t *testing.B) { s := NewBST[int,int]() for i := minLength; i <= maxLength; i *= factor { benchmark[int,int](s, i, t) } } func BenchmarkRedBlackBST(t *testing.B) { s := NewRedBlackBST[int,int]() for i := minLength; i <= maxLength; i *= factor { benchmark[int,int](s, i, t) } } func BenchmarkHash(t *testing.B) { s := NewHash[int,int](maxLength * 2) for i := minLength; i <= maxLength; i *= factor { benchmark[int,int](s, i, t) } } func BenchmarkGoMap(t *testing.B) { s := NewGoMap[int,int]() for i := minLength; i <= maxLength; i *= factor { benchmark[int,int](s, i, t) } } func benchmark[K ds.Integer, V ds.Number](s Set[K,V], l int, b *testing.B) { list := ds.NewRandomArrayList[K](l, -1) b.Run(fmt.Sprintf("random(%d)", l), func(b *testing.B) { b.ResetTimer() for i, a := range list { s.Put(a, V(i)) } for _, a := range list { benchResult, _ = s.Get(a) } }) }