Files
chain33-im/dtask/pkg/rbtree/stats_test.go
2022-03-17 15:55:27 +08:00

153 lines
3.1 KiB
Go

// Copyright 2015, Hu Keping. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rbtree
import (
"fmt"
"reflect"
"sync"
"testing"
"time"
)
func TestDeleteReturnValue(t *testing.T) {
rbt := New()
rbt.Insert(String("go"))
rbt.Insert(String("lang"))
if rbt.Len() != 2 {
t.Errorf("tree.Len() = %d, expect %d", rbt.Len(), 2)
}
// go should be in the rbtree
deletedGo := rbt.Delete(String("go"))
if deletedGo != String("go") {
t.Errorf("expect %v, got %v", "go", deletedGo)
}
// C should not be in the rbtree
deletedC := rbt.Delete(String("C"))
if deletedC != nil {
t.Errorf("expect %v, got %v", nil, deletedC)
}
}
func TestMin(t *testing.T) {
rbt := New()
m := 0
n := 1000
for m < n {
rbt.Insert(Int(m))
m++
}
if rbt.Len() != uint(n) {
t.Errorf("tree.Len() = %d, expect %d", rbt.Len(), n)
}
for m >= 0 {
rbt.Delete(rbt.Min())
m--
}
if rbt.Len() != 0 {
t.Errorf("tree.Len() = %d, expect %d", rbt.Len(), 0)
}
}
//
// This test will first add 1000 numbers into a tree and then delete some
// from it.
//
// All the adding and deleting are in goroutine so that the delete action
// will not always succeed for example `delete(400)` but `add(400)` has not
// been executed yet.
//
// Finally, we'll add back all the deleted nodes to see if there is
// anything wrong.
//
func TestWithGoroutine(t *testing.T) {
var Cache struct {
rbt *Rbtree
locker *sync.Mutex
}
var DeletedArray struct {
array []Item
locker *sync.Mutex
}
// Init the rbtree and the locker for later use
Cache.rbt = New()
Cache.locker = new(sync.Mutex)
// Init the locker for later use
DeletedArray.locker = new(sync.Mutex)
i, m := 0, 0
j, n := 1000, 1000
var expected []Item
// This loop will add intergers [m~n) to the rbtree.
for m < n {
expected = append(expected, Int(m))
go func(x Int) {
Cache.locker.Lock()
Cache.rbt.Insert(x)
Cache.locker.Unlock()
}(Int(m))
m++
}
// This loop will try to delete the even integers in [m~n),
// Be noticed that the delete will not always succeeds since we are
// in the goroutines.
// We will record which ones have been removed.
for i < j {
if i%2 == 0 {
go func(x Int) {
Cache.locker.Lock()
value := Cache.rbt.Delete(x)
Cache.locker.Unlock()
DeletedArray.locker.Lock()
DeletedArray.array = append(DeletedArray.array, value)
DeletedArray.locker.Unlock()
}(Int(i))
}
i++
}
// Let's give a little time to those goroutines to finish their job.
time.Sleep(time.Second * 1)
// Add deleted Items back
cnt := 0
DeletedArray.locker.Lock()
for _, v := range DeletedArray.array {
if v != nil {
Cache.locker.Lock()
Cache.rbt.Insert(v)
Cache.locker.Unlock()
cnt++
}
}
DeletedArray.locker.Unlock()
fmt.Printf("In TestWithGoroutine(), we have deleted [%v] nodes.\n", cnt)
var ret []Item
Cache.rbt.Ascend(Cache.rbt.Min(), func(item Item) bool {
ret = append(ret, item)
return true
})
if !reflect.DeepEqual(ret, expected) {
t.Errorf("expected %v but got %v", expected, ret)
}
}