190 lines
3.6 KiB
Go
190 lines
3.6 KiB
Go
|
|
// Copyright 2020-2024 guonaihong, antlabs. All rights reserved.
|
||
|
|
//
|
||
|
|
// mit license
|
||
|
|
package timer
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"math"
|
||
|
|
"sync/atomic"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func Test_maxVal(t *testing.T) {
|
||
|
|
|
||
|
|
if maxVal() != uint64(math.MaxUint32) {
|
||
|
|
t.Error("maxVal() != uint64(math.MaxUint32)")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func Test_LevelMax(t *testing.T) {
|
||
|
|
if levelMax(1) != uint64(1<<(nearShift+levelShift)) {
|
||
|
|
t.Error("levelMax(1) != uint64(1<<(nearShift+levelShift))")
|
||
|
|
}
|
||
|
|
|
||
|
|
if levelMax(2) != uint64(1<<(nearShift+2*levelShift)) {
|
||
|
|
t.Error("levelMax(2) != uint64(1<<(nearShift+2*levelShift))")
|
||
|
|
}
|
||
|
|
|
||
|
|
if levelMax(3) != uint64(1<<(nearShift+3*levelShift)) {
|
||
|
|
t.Error("levelMax(3) != uint64(1<<(nearShift+3*levelShift))")
|
||
|
|
}
|
||
|
|
|
||
|
|
if levelMax(4) != uint64(1<<(nearShift+4*levelShift)) {
|
||
|
|
t.Error("levelMax(4) != uint64(1<<(nearShift+4*levelShift))")
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
func Test_GenVersion(t *testing.T) {
|
||
|
|
if genVersionHeight(1, 0xf) != uint64(0x0001000f00000000) {
|
||
|
|
t.Error("genVersionHeight(1, 0xf) != uint64(0x0001000f00000000)")
|
||
|
|
}
|
||
|
|
|
||
|
|
if genVersionHeight(1, 64) != uint64(0x0001004000000000) {
|
||
|
|
t.Error("genVersionHeight(2, 0xf) != uint64(0x0001004000000000)")
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// 测试1小时
|
||
|
|
func Test_hour(t *testing.T) {
|
||
|
|
tw := newTimeWheel()
|
||
|
|
|
||
|
|
testHour := new(bool)
|
||
|
|
done := make(chan struct{}, 1)
|
||
|
|
tw.AfterFunc(time.Hour, func() {
|
||
|
|
*testHour = true
|
||
|
|
done <- struct{}{}
|
||
|
|
})
|
||
|
|
|
||
|
|
expire := getExpire(time.Hour, 0)
|
||
|
|
for i := 0; i < int(expire)+10; i++ {
|
||
|
|
get10Ms := func() time.Duration {
|
||
|
|
return tw.curTimePoint + 1
|
||
|
|
}
|
||
|
|
tw.run(get10Ms)
|
||
|
|
}
|
||
|
|
|
||
|
|
select {
|
||
|
|
case <-done:
|
||
|
|
case <-time.After(time.Second / 100):
|
||
|
|
}
|
||
|
|
|
||
|
|
if *testHour == false {
|
||
|
|
t.Error("testHour == false")
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// 测试周期性定时器, 5s
|
||
|
|
func Test_ScheduleFunc_5s(t *testing.T) {
|
||
|
|
tw := newTimeWheel()
|
||
|
|
|
||
|
|
var first5 int32
|
||
|
|
ctx, cancel := context.WithCancel(context.Background())
|
||
|
|
|
||
|
|
const total = int32(1000)
|
||
|
|
|
||
|
|
testTime := time.Second * 5
|
||
|
|
|
||
|
|
tw.ScheduleFunc(testTime, func() {
|
||
|
|
atomic.AddInt32(&first5, 1)
|
||
|
|
if atomic.LoadInt32(&first5) == total {
|
||
|
|
cancel()
|
||
|
|
}
|
||
|
|
|
||
|
|
})
|
||
|
|
|
||
|
|
expire := getExpire(testTime*time.Duration(total), 0)
|
||
|
|
for i := 0; i <= int(expire)+10; i++ {
|
||
|
|
get10Ms := func() time.Duration {
|
||
|
|
return tw.curTimePoint + 1
|
||
|
|
}
|
||
|
|
tw.run(get10Ms)
|
||
|
|
}
|
||
|
|
|
||
|
|
select {
|
||
|
|
case <-ctx.Done():
|
||
|
|
case <-time.After(time.Second / 100):
|
||
|
|
}
|
||
|
|
|
||
|
|
if total != first5 {
|
||
|
|
t.Errorf("total:%d != first5:%d\n", total, first5)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 测试周期性定时器, 1hour
|
||
|
|
func Test_ScheduleFunc_hour(t *testing.T) {
|
||
|
|
tw := newTimeWheel()
|
||
|
|
|
||
|
|
var first5 int32
|
||
|
|
ctx, cancel := context.WithCancel(context.Background())
|
||
|
|
|
||
|
|
const total = int32(100)
|
||
|
|
testTime := time.Hour
|
||
|
|
|
||
|
|
tw.ScheduleFunc(testTime, func() {
|
||
|
|
atomic.AddInt32(&first5, 1)
|
||
|
|
if atomic.LoadInt32(&first5) == total {
|
||
|
|
cancel()
|
||
|
|
}
|
||
|
|
|
||
|
|
})
|
||
|
|
|
||
|
|
expire := getExpire(testTime*time.Duration(total), 0)
|
||
|
|
for i := 0; i <= int(expire)+10; i++ {
|
||
|
|
get10Ms := func() time.Duration {
|
||
|
|
return tw.curTimePoint + 1
|
||
|
|
}
|
||
|
|
tw.run(get10Ms)
|
||
|
|
}
|
||
|
|
|
||
|
|
select {
|
||
|
|
case <-ctx.Done():
|
||
|
|
case <-time.After(time.Second / 100):
|
||
|
|
}
|
||
|
|
|
||
|
|
if total != first5 {
|
||
|
|
t.Errorf("total:%d != first5:%d\n", total, first5)
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// 测试周期性定时器, 1day
|
||
|
|
func Test_ScheduleFunc_day(t *testing.T) {
|
||
|
|
tw := newTimeWheel()
|
||
|
|
|
||
|
|
var first5 int32
|
||
|
|
ctx, cancel := context.WithCancel(context.Background())
|
||
|
|
|
||
|
|
const total = int32(10)
|
||
|
|
testTime := time.Hour * 24
|
||
|
|
|
||
|
|
tw.ScheduleFunc(testTime, func() {
|
||
|
|
atomic.AddInt32(&first5, 1)
|
||
|
|
if atomic.LoadInt32(&first5) == total {
|
||
|
|
cancel()
|
||
|
|
}
|
||
|
|
|
||
|
|
})
|
||
|
|
|
||
|
|
expire := getExpire(testTime*time.Duration(total), 0)
|
||
|
|
for i := 0; i <= int(expire)+10; i++ {
|
||
|
|
get10Ms := func() time.Duration {
|
||
|
|
return tw.curTimePoint + 1
|
||
|
|
}
|
||
|
|
tw.run(get10Ms)
|
||
|
|
}
|
||
|
|
|
||
|
|
select {
|
||
|
|
case <-ctx.Done():
|
||
|
|
case <-time.After(time.Second / 100):
|
||
|
|
}
|
||
|
|
|
||
|
|
if total != first5 {
|
||
|
|
t.Errorf("total:%d != first5:%d\n", total, first5)
|
||
|
|
}
|
||
|
|
}
|