Files
bl/common/utils/timer/timer_test.go

220 lines
4.0 KiB
Go

// Copyright 2020-2024 guonaihong, antlabs. All rights reserved.
//
// mit license
package timer
import (
"log"
"sync"
"sync/atomic"
"testing"
"time"
)
func Test_ScheduleFunc(t *testing.T) {
tm := NewTimer()
log.SetFlags(log.Ldate | log.Lmicroseconds)
count := uint32(0)
log.Printf("start\n")
tm.ScheduleFunc(time.Millisecond*100, func() {
log.Printf("schedule\n")
atomic.AddUint32(&count, 1)
})
go func() {
time.Sleep(570 * time.Millisecond)
log.Printf("stop\n")
tm.Stop()
}()
tm.Run()
if count != 5 {
t.Errorf("count:%d != 5\n", count)
}
}
func Test_AfterFunc(t *testing.T) {
tm := NewTimer()
go tm.Run()
log.Printf("start\n")
count := uint32(0)
tm.AfterFunc(time.Millisecond*20, func() {
log.Printf("after Millisecond * 20")
atomic.AddUint32(&count, 1)
})
tm.AfterFunc(time.Second, func() {
log.Printf("after second")
atomic.AddUint32(&count, 1)
})
/*
tm.AfterFunc(time.Minute, func() {
log.Printf("after Minute")
})
*/
/*
tm.AfterFunc(time.Hour, nil)
tm.AfterFunc(time.Hour*24, nil)
tm.AfterFunc(time.Hour*24*365, nil)
tm.AfterFunc(time.Hour*24*365*12, nil)
*/
time.Sleep(time.Second + time.Millisecond*100)
tm.Stop()
if count != 2 {
t.Errorf("count:%d != 2\n", count)
}
}
func Test_Node_Stop_1(t *testing.T) {
tm := NewTimer()
count := uint32(0)
node := tm.AfterFunc(time.Millisecond*10, func() {
atomic.AddUint32(&count, 1)
})
go func() {
time.Sleep(time.Millisecond * 30)
node.Stop()
tm.Stop()
}()
tm.Run()
if count != 1 {
t.Errorf("count:%d == 1\n", count)
}
}
func Test_Node_Stop(t *testing.T) {
tm := NewTimer()
count := uint32(0)
node := tm.AfterFunc(time.Millisecond*100, func() {
atomic.AddUint32(&count, 1)
})
node.Stop()
go func() {
time.Sleep(time.Millisecond * 200)
tm.Stop()
}()
tm.Run()
if count == 1 {
t.Errorf("count:%d == 1\n", count)
}
}
// 测试重置定时器
func Test_Reset(t *testing.T) {
t.Run("min heap reset", func(t *testing.T) {
tm := NewTimer(WithMinHeap())
go tm.Run()
count := int32(0)
tc := make(chan time.Duration, 2)
var mu sync.Mutex
isClose := false
now := time.Now()
node1 := tm.AfterFunc(time.Millisecond*100, func() {
mu.Lock()
atomic.AddInt32(&count, 1)
if atomic.LoadInt32(&count) <= 2 && !isClose {
tc <- time.Since(now)
}
mu.Unlock()
})
node2 := tm.AfterFunc(time.Millisecond*100, func() {
mu.Lock()
atomic.AddInt32(&count, 1)
if atomic.LoadInt32(&count) <= 2 && !isClose {
tc <- time.Since(now)
}
mu.Unlock()
})
node1.Reset(time.Millisecond)
node2.Reset(time.Millisecond)
time.Sleep(time.Millisecond * 3)
mu.Lock()
isClose = true
close(tc)
node1.Stop()
node2.Stop()
mu.Unlock()
for tv := range tc {
if tv < time.Millisecond || tv > 2*time.Millisecond {
t.Errorf("tc < time.Millisecond tc > 2*time.Millisecond")
}
}
if atomic.LoadInt32(&count) != 2 {
t.Errorf("count:%d != 2", atomic.LoadInt32(&count))
}
})
t.Run("time wheel reset", func(t *testing.T) {
tm := NewTimer()
go func() {
tm.Run()
}()
count := int32(0)
tc := make(chan time.Duration, 2)
var mu sync.Mutex
isClose := false
now := time.Now()
node1 := tm.AfterFunc(time.Millisecond*10, func() {
mu.Lock()
atomic.AddInt32(&count, 1)
if atomic.LoadInt32(&count) <= 2 && !isClose {
tc <- time.Since(now)
}
mu.Unlock()
})
node2 := tm.AfterFunc(time.Millisecond*10, func() {
mu.Lock()
atomic.AddInt32(&count, 1)
if atomic.LoadInt32(&count) <= 2 && !isClose {
tc <- time.Since(now)
}
mu.Unlock()
})
node1.Reset(time.Millisecond * 20)
node2.Reset(time.Millisecond * 20)
time.Sleep(time.Millisecond * 40)
mu.Lock()
isClose = true
close(tc)
node1.Stop()
node2.Stop()
mu.Unlock()
for tv := range tc {
if tv < time.Millisecond*20 || tv > 2*time.Millisecond*20 {
t.Errorf("tc < time.Millisecond tc > 2*time.Millisecond")
}
}
if atomic.LoadInt32(&count) != 2 {
t.Errorf("count:%d != 2", atomic.LoadInt32(&count))
}
})
}