| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- package service
- import (
- "errors"
- "sync/atomic"
- "testing"
- "time"
- "github.com/zeromicro/go-zero/core/collection"
- )
- func TestNewTimingWheelService_InitFail_NoPanicAndReturnError(t *testing.T) {
- original := newTimingWheel
- t.Cleanup(func() { newTimingWheel = original })
- newTimingWheel = func(_ time.Duration, _ int, _ collection.Execute) (*collection.TimingWheel, error) {
- return nil, errors.New("boom")
- }
- svc, err := NewTimingWheelService()
- if err == nil {
- t.Fatalf("期望返回 error,但得到 nil")
- }
- if svc != nil {
- t.Fatalf("期望返回 nil svc,但得到非空")
- }
- }
- func TestNewTimingWheelService_Success(t *testing.T) {
- svc, err := NewTimingWheelService()
- if err != nil {
- t.Fatalf("期望 err 为 nil,但得到: %v", err)
- }
- if svc == nil {
- t.Fatalf("期望 svc 非空,但得到 nil")
- }
- svc.Stop()
- }
- func TestNewTimingWheelService_ExecuteCallbackRunsFunc(t *testing.T) {
- original := newTimingWheel
- t.Cleanup(func() { newTimingWheel = original })
- var captured collection.Execute
- newTimingWheel = func(interval time.Duration, numSlots int, execute collection.Execute) (*collection.TimingWheel, error) {
- captured = execute
- return original(interval, numSlots, execute)
- }
- svc, err := NewTimingWheelService()
- if err != nil {
- t.Fatalf("期望 err 为 nil,但得到: %v", err)
- }
- if captured == nil {
- t.Fatalf("期望 captured 非空,但得到 nil")
- }
- called := false
- captured("k", func() { called = true })
- if !called {
- t.Fatalf("期望 execute 回调触发传入函数执行")
- }
- svc.Stop()
- }
- func TestTimingWheelService_Schedule_ExecutesOnce(t *testing.T) {
- original := newTimingWheel
- t.Cleanup(func() { newTimingWheel = original })
- newTimingWheel = func(_ time.Duration, _ int, execute collection.Execute) (*collection.TimingWheel, error) {
- return original(10*time.Millisecond, 128, execute)
- }
- svc, err := NewTimingWheelService()
- if err != nil {
- t.Fatalf("期望 err 为 nil,但得到: %v", err)
- }
- defer svc.Stop()
- ch := make(chan struct{}, 1)
- svc.Schedule("once", 30*time.Millisecond, func() { ch <- struct{}{} })
- select {
- case <-ch:
- case <-time.After(500 * time.Millisecond):
- t.Fatalf("等待任务执行超时")
- }
- select {
- case <-ch:
- t.Fatalf("任务不应重复执行")
- case <-time.After(80 * time.Millisecond):
- }
- }
- func TestTimingWheelService_Cancel_PreventsExecution(t *testing.T) {
- original := newTimingWheel
- t.Cleanup(func() { newTimingWheel = original })
- newTimingWheel = func(_ time.Duration, _ int, execute collection.Execute) (*collection.TimingWheel, error) {
- return original(10*time.Millisecond, 128, execute)
- }
- svc, err := NewTimingWheelService()
- if err != nil {
- t.Fatalf("期望 err 为 nil,但得到: %v", err)
- }
- defer svc.Stop()
- ch := make(chan struct{}, 1)
- svc.Schedule("cancel", 80*time.Millisecond, func() { ch <- struct{}{} })
- svc.Cancel("cancel")
- select {
- case <-ch:
- t.Fatalf("任务已取消,不应执行")
- case <-time.After(200 * time.Millisecond):
- }
- }
- func TestTimingWheelService_Schedule_AfterStop_LogsError(t *testing.T) {
- svc, err := NewTimingWheelService()
- if err != nil {
- t.Fatalf("期望 err 为 nil,但得到: %v", err)
- }
- svc.Stop()
- // Stop 后调用 Schedule 应走 error 日志路径,不应 panic
- svc.Schedule("after-stop", 100*time.Millisecond, func() {
- t.Fatal("不应被执行")
- })
- }
- func TestTimingWheelService_ScheduleRecurring_AfterStop_LogsError(t *testing.T) {
- svc, err := NewTimingWheelService()
- if err != nil {
- t.Fatalf("期望 err 为 nil,但得到: %v", err)
- }
- svc.Stop()
- // Stop 后调用 ScheduleRecurring 应走 error 日志路径,不应 panic
- svc.ScheduleRecurring("after-stop-rec", 100*time.Millisecond, func() {
- t.Fatal("不应被执行")
- })
- }
- func TestTimingWheelService_Stop_Idempotent(t *testing.T) {
- svc, err := NewTimingWheelService()
- if err != nil {
- t.Fatalf("期望 err 为 nil,但得到: %v", err)
- }
- svc.Stop()
- svc.Stop() // 第二次调用不应 panic
- }
- func TestTimingWheelService_ScheduleRecurring_ExecutesMultipleTimes(t *testing.T) {
- original := newTimingWheel
- t.Cleanup(func() { newTimingWheel = original })
- newTimingWheel = func(_ time.Duration, _ int, execute collection.Execute) (*collection.TimingWheel, error) {
- return original(10*time.Millisecond, 128, execute)
- }
- svc, err := NewTimingWheelService()
- if err != nil {
- t.Fatalf("期望 err 为 nil,但得到: %v", err)
- }
- defer svc.Stop()
- var count int32
- svc.ScheduleRecurring("rec", 30*time.Millisecond, func() { atomic.AddInt32(&count, 1) })
- deadline := time.Now().Add(500 * time.Millisecond)
- for atomic.LoadInt32(&count) < 2 && time.Now().Before(deadline) {
- time.Sleep(10 * time.Millisecond)
- }
- if atomic.LoadInt32(&count) < 2 {
- t.Fatalf("期望周期任务至少执行 2 次,但只执行了 %d 次", atomic.LoadInt32(&count))
- }
- }
|