mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-21 17:01:35 +00:00
merge go-clist
This commit is contained in:
218
clist/clist_test.go
Normal file
218
clist/clist_test.go
Normal file
@ -0,0 +1,218 @@
|
||||
package clist
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSmall(t *testing.T) {
|
||||
l := New()
|
||||
el1 := l.PushBack(1)
|
||||
el2 := l.PushBack(2)
|
||||
el3 := l.PushBack(3)
|
||||
if l.Len() != 3 {
|
||||
t.Error("Expected len 3, got ", l.Len())
|
||||
}
|
||||
|
||||
//fmt.Printf("%p %v\n", el1, el1)
|
||||
//fmt.Printf("%p %v\n", el2, el2)
|
||||
//fmt.Printf("%p %v\n", el3, el3)
|
||||
|
||||
r1 := l.Remove(el1)
|
||||
|
||||
//fmt.Printf("%p %v\n", el1, el1)
|
||||
//fmt.Printf("%p %v\n", el2, el2)
|
||||
//fmt.Printf("%p %v\n", el3, el3)
|
||||
|
||||
r2 := l.Remove(el2)
|
||||
|
||||
//fmt.Printf("%p %v\n", el1, el1)
|
||||
//fmt.Printf("%p %v\n", el2, el2)
|
||||
//fmt.Printf("%p %v\n", el3, el3)
|
||||
|
||||
r3 := l.Remove(el3)
|
||||
|
||||
if r1 != 1 {
|
||||
t.Error("Expected 1, got ", r1)
|
||||
}
|
||||
if r2 != 2 {
|
||||
t.Error("Expected 2, got ", r2)
|
||||
}
|
||||
if r3 != 3 {
|
||||
t.Error("Expected 3, got ", r3)
|
||||
}
|
||||
if l.Len() != 0 {
|
||||
t.Error("Expected len 0, got ", l.Len())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
This test is quite hacky because it relies on SetFinalizer
|
||||
which isn't guaranteed to run at all.
|
||||
*/
|
||||
func _TestGCFifo(t *testing.T) {
|
||||
|
||||
const numElements = 1000000
|
||||
l := New()
|
||||
gcCount := new(uint64)
|
||||
|
||||
// SetFinalizer doesn't work well with circular structures,
|
||||
// so we construct a trivial non-circular structure to
|
||||
// track.
|
||||
type value struct {
|
||||
Int int
|
||||
}
|
||||
done := make(chan struct{})
|
||||
|
||||
for i := 0; i < numElements; i++ {
|
||||
v := new(value)
|
||||
v.Int = i
|
||||
l.PushBack(v)
|
||||
runtime.SetFinalizer(v, func(v *value) {
|
||||
atomic.AddUint64(gcCount, 1)
|
||||
})
|
||||
}
|
||||
|
||||
for el := l.Front(); el != nil; {
|
||||
l.Remove(el)
|
||||
//oldEl := el
|
||||
el = el.Next()
|
||||
//oldEl.DetachPrev()
|
||||
//oldEl.DetachNext()
|
||||
}
|
||||
|
||||
runtime.GC()
|
||||
time.Sleep(time.Second * 3)
|
||||
runtime.GC()
|
||||
time.Sleep(time.Second * 3)
|
||||
_ = done
|
||||
|
||||
if *gcCount != numElements {
|
||||
t.Errorf("Expected gcCount to be %v, got %v", numElements,
|
||||
*gcCount)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This test is quite hacky because it relies on SetFinalizer
|
||||
which isn't guaranteed to run at all.
|
||||
*/
|
||||
func _TestGCRandom(t *testing.T) {
|
||||
|
||||
const numElements = 1000000
|
||||
l := New()
|
||||
gcCount := 0
|
||||
|
||||
// SetFinalizer doesn't work well with circular structures,
|
||||
// so we construct a trivial non-circular structure to
|
||||
// track.
|
||||
type value struct {
|
||||
Int int
|
||||
}
|
||||
|
||||
for i := 0; i < numElements; i++ {
|
||||
v := new(value)
|
||||
v.Int = i
|
||||
l.PushBack(v)
|
||||
runtime.SetFinalizer(v, func(v *value) {
|
||||
gcCount += 1
|
||||
})
|
||||
}
|
||||
|
||||
els := make([]*CElement, 0, numElements)
|
||||
for el := l.Front(); el != nil; el = el.Next() {
|
||||
els = append(els, el)
|
||||
}
|
||||
|
||||
for _, i := range rand.Perm(numElements) {
|
||||
el := els[i]
|
||||
l.Remove(el)
|
||||
el = el.Next()
|
||||
}
|
||||
|
||||
runtime.GC()
|
||||
time.Sleep(time.Second * 3)
|
||||
|
||||
if gcCount != numElements {
|
||||
t.Errorf("Expected gcCount to be %v, got %v", numElements,
|
||||
gcCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanRightDeleteRandom(t *testing.T) {
|
||||
|
||||
const numElements = 10000
|
||||
const numTimes = 100000
|
||||
const numScanners = 10
|
||||
|
||||
l := New()
|
||||
stop := make(chan struct{})
|
||||
|
||||
els := make([]*CElement, numElements, numElements)
|
||||
for i := 0; i < numElements; i++ {
|
||||
el := l.PushBack(i)
|
||||
els[i] = el
|
||||
}
|
||||
|
||||
// Launch scanner routines that will rapidly iterate over elements.
|
||||
for i := 0; i < numScanners; i++ {
|
||||
go func(scannerID int) {
|
||||
var el *CElement
|
||||
restartCounter := 0
|
||||
counter := 0
|
||||
FOR_LOOP:
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
fmt.Println("stopped")
|
||||
break FOR_LOOP
|
||||
default:
|
||||
}
|
||||
if el == nil {
|
||||
el = l.FrontWait()
|
||||
restartCounter += 1
|
||||
}
|
||||
el = el.Next()
|
||||
counter += 1
|
||||
}
|
||||
fmt.Printf("Scanner %v restartCounter: %v counter: %v\n", scannerID, restartCounter, counter)
|
||||
}(i)
|
||||
}
|
||||
|
||||
// Remove an element, push back an element.
|
||||
for i := 0; i < numTimes; i++ {
|
||||
// Pick an element to remove
|
||||
rmElIdx := rand.Intn(len(els))
|
||||
rmEl := els[rmElIdx]
|
||||
|
||||
// Remove it
|
||||
l.Remove(rmEl)
|
||||
//fmt.Print(".")
|
||||
|
||||
// Insert a new element
|
||||
newEl := l.PushBack(-1*i - 1)
|
||||
els[rmElIdx] = newEl
|
||||
|
||||
if i%100000 == 0 {
|
||||
fmt.Printf("Pushed %vK elements so far...\n", i/1000)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Stop scanners
|
||||
close(stop)
|
||||
time.Sleep(time.Second * 1)
|
||||
|
||||
// And remove all the elements.
|
||||
for el := l.Front(); el != nil; el = el.Next() {
|
||||
l.Remove(el)
|
||||
}
|
||||
if l.Len() != 0 {
|
||||
t.Fatal("Failed to remove all elements from CList")
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user