// Copyright 2010 Petar Maymounkov. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package llrb import ( "math" "math/rand" "testing" ) func TestCases(t *testing.T) { tree := New() tree.ReplaceOrInsert(Int(1)) tree.ReplaceOrInsert(Int(1)) if tree.Len() != 1 { t.Errorf("expecting len 1") } if !tree.Has(Int(1)) { t.Errorf("expecting to find key=1") } tree.Delete(Int(1)) if tree.Len() != 0 { t.Errorf("expecting len 0") } if tree.Has(Int(1)) { t.Errorf("not expecting to find key=1") } tree.Delete(Int(1)) if tree.Len() != 0 { t.Errorf("expecting len 0") } if tree.Has(Int(1)) { t.Errorf("not expecting to find key=1") } } func TestReverseInsertOrder(t *testing.T) { tree := New() n := 100 for i := 0; i < n; i++ { tree.ReplaceOrInsert(Int(n - i)) } i := 0 tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { i++ if item.(Int) != Int(i) { t.Errorf("bad order: got %d, expect %d", item.(Int), i) } return true }) } func TestRange(t *testing.T) { tree := New() order := []String{ "ab", "aba", "abc", "a", "aa", "aaa", "b", "a-", "a!", } for _, i := range order { tree.ReplaceOrInsert(i) } k := 0 tree.AscendRange(String("ab"), String("ac"), func(item Item) bool { if k > 3 { t.Fatalf("returned more items than expected") } i1 := order[k] i2 := item.(String) if i1 != i2 { t.Errorf("expecting %s, got %s", i1, i2) } k++ return true }) } func TestRandomInsertOrder(t *testing.T) { tree := New() n := 1000 perm := rand.Perm(n) for i := 0; i < n; i++ { tree.ReplaceOrInsert(Int(perm[i])) } j := 0 tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { if item.(Int) != Int(j) { t.Fatalf("bad order") } j++ return true }) } func TestRandomReplace(t *testing.T) { tree := New() n := 100 perm := rand.Perm(n) for i := 0; i < n; i++ { tree.ReplaceOrInsert(Int(perm[i])) } perm = rand.Perm(n) for i := 0; i < n; i++ { if replaced := tree.ReplaceOrInsert(Int(perm[i])); replaced == nil || replaced.(Int) != Int(perm[i]) { t.Errorf("error replacing") } } } func TestRandomInsertSequentialDelete(t *testing.T) { tree := New() n := 1000 perm := rand.Perm(n) for i := 0; i < n; i++ { tree.ReplaceOrInsert(Int(perm[i])) } for i := 0; i < n; i++ { tree.Delete(Int(i)) } } func TestRandomInsertDeleteNonExistent(t *testing.T) { tree := New() n := 100 perm := rand.Perm(n) for i := 0; i < n; i++ { tree.ReplaceOrInsert(Int(perm[i])) } if tree.Delete(Int(200)) != nil { t.Errorf("deleted non-existent item") } if tree.Delete(Int(-2)) != nil { t.Errorf("deleted non-existent item") } for i := 0; i < n; i++ { if u := tree.Delete(Int(i)); u == nil || u.(Int) != Int(i) { t.Errorf("delete failed") } } if tree.Delete(Int(200)) != nil { t.Errorf("deleted non-existent item") } if tree.Delete(Int(-2)) != nil { t.Errorf("deleted non-existent item") } } func TestRandomInsertPartialDeleteOrder(t *testing.T) { tree := New() n := 100 perm := rand.Perm(n) for i := 0; i < n; i++ { tree.ReplaceOrInsert(Int(perm[i])) } for i := 1; i < n-1; i++ { tree.Delete(Int(i)) } j := 0 tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { switch j { case 0: if item.(Int) != Int(0) { t.Errorf("expecting 0") } case 1: if item.(Int) != Int(n-1) { t.Errorf("expecting %d", n-1) } } j++ return true }) } func TestRandomInsertStats(t *testing.T) { tree := New() n := 100000 perm := rand.Perm(n) for i := 0; i < n; i++ { tree.ReplaceOrInsert(Int(perm[i])) } avg, _ := tree.HeightStats() expAvg := math.Log2(float64(n)) - 1.5 if math.Abs(avg-expAvg) >= 2.0 { t.Errorf("too much deviation from expected average height") } } func BenchmarkInsert(b *testing.B) { tree := New() for i := 0; i < b.N; i++ { tree.ReplaceOrInsert(Int(b.N - i)) } } func BenchmarkDelete(b *testing.B) { b.StopTimer() tree := New() for i := 0; i < b.N; i++ { tree.ReplaceOrInsert(Int(b.N - i)) } b.StartTimer() for i := 0; i < b.N; i++ { tree.Delete(Int(i)) } } func BenchmarkDeleteMin(b *testing.B) { b.StopTimer() tree := New() for i := 0; i < b.N; i++ { tree.ReplaceOrInsert(Int(b.N - i)) } b.StartTimer() for i := 0; i < b.N; i++ { tree.DeleteMin() } } func TestInsertNoReplace(t *testing.T) { tree := New() n := 1000 for q := 0; q < 2; q++ { perm := rand.Perm(n) for i := 0; i < n; i++ { tree.InsertNoReplace(Int(perm[i])) } } j := 0 tree.AscendGreaterOrEqual(Int(0), func(item Item) bool { if item.(Int) != Int(j/2) { t.Fatalf("bad order") } j++ return true }) }