github.com/benz9527/toy-box/algo@v0.0.0-20240221120937-66c0c6bd5abd/queue/delay_queue_test.go (about) 1 package queue 2 3 import ( 4 "context" 5 "github.com/stretchr/testify/assert" 6 "testing" 7 "time" 8 "unsafe" 9 ) 10 11 func TestDelayQueueAlignmentAndSize(t *testing.T) { 12 dq := NewArrayDelayQueue[*person](32) 13 t.Logf("dq aligment size: %d\n", unsafe.Alignof(dq)) 14 prototype := dq.(*arrayDQ[*person]) 15 t.Logf("dq prototype alignment size: %d\n", unsafe.Alignof(prototype)) 16 t.Logf("dq prototype wake up channel alignment size: %d\n", unsafe.Alignof(prototype.wakeUpC)) 17 t.Logf("dq prototype priority queue alignment size: %d\n", unsafe.Alignof(prototype.pq)) 18 t.Logf("dq prototype sleeping alignment size: %d\n", unsafe.Alignof(prototype.sleeping)) 19 t.Logf("dq prototype mu alignment size: %d\n", unsafe.Alignof(prototype.mu)) 20 t.Logf("dq prototype lock alignment size: %d\n", unsafe.Alignof(prototype.lock)) 21 22 t.Logf("dq size: %d\n", unsafe.Sizeof(dq)) 23 t.Logf("dq prototype size: %d\n", unsafe.Sizeof(prototype)) 24 t.Logf("dq prototype wake up channel size: %d\n", unsafe.Sizeof(prototype.wakeUpC)) 25 t.Logf("dq prototype priority queue size: %d\n", unsafe.Sizeof(prototype.pq)) 26 t.Logf("dq prototype sleeping size: %d\n", unsafe.Sizeof(prototype.sleeping)) 27 t.Logf("dq prototype mu size: %d\n", unsafe.Sizeof(prototype.mu)) 28 t.Logf("dq prototype lock size: %d\n", unsafe.Sizeof(prototype.lock)) 29 30 assert.Equal(t, uintptr(48), unsafe.Sizeof(*prototype)) 31 } 32 33 func TestDelayQueue_Poll(t *testing.T) { 34 dq := NewArrayDelayQueue[*person](32) 35 36 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) 37 defer cancel() 38 receiver, err := dq.Poll(ctx, 39 func() int64 { 40 return time.Now().UnixMilli() 41 }, 42 ) 43 assert.NoError(t, err) 44 45 ms := time.Now().UnixMilli() 46 _ = dq.Offer(&person{age: 10, name: "p0", salary: ms + 110}, ms+110) 47 _ = dq.Offer(&person{age: 101, name: "p1", salary: ms + 501}, ms+501) 48 _ = dq.Offer(&person{age: 10, name: "p2", salary: ms + 155}, ms+155) 49 _ = dq.Offer(&person{age: 200, name: "p3", salary: ms + 210}, ms+210) 50 _ = dq.Offer(&person{age: 3, name: "p4", salary: ms + 60}, ms+60) 51 _ = dq.Offer(&person{age: 1, name: "p5", salary: ms + 110}, ms+110) 52 _ = dq.Offer(&person{age: 5, name: "p6", salary: ms + 250}, ms+250) 53 _ = dq.Offer(&person{age: 200, name: "p7", salary: ms + 301}, ms+302) 54 55 expectedCount := 8 56 actualCount := 0 57 defer func() { 58 assert.Equal(t, expectedCount, actualCount) 59 }() 60 for { 61 select { 62 case item, ok := <-receiver: 63 if !ok { 64 t.Log("receiver channel closed") 65 return 66 } 67 t.Logf("current time ms: %d, item: %v\n", time.Now().UnixMilli(), item) 68 actualCount++ 69 } 70 } 71 } 72 73 func TestDelayQueue_PollToChannel(t *testing.T) { 74 75 dq := NewArrayDelayQueue[*person](32) 76 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) 77 defer cancel() 78 receiver := make(chan *person) 79 go func() { 80 err := dq.PollToChannel(ctx, 81 func() int64 { 82 return time.Now().UnixMilli() 83 }, 84 receiver, 85 ) 86 assert.NoError(t, err) 87 }() 88 89 ms := time.Now().UnixMilli() 90 _ = dq.Offer(&person{age: 10, name: "p0", salary: ms + 110}, ms+110) 91 _ = dq.Offer(&person{age: 101, name: "p1", salary: ms + 501}, ms+501) 92 _ = dq.Offer(&person{age: 10, name: "p2", salary: ms + 155}, ms+155) 93 _ = dq.Offer(&person{age: 200, name: "p3", salary: ms + 210}, ms+210) 94 _ = dq.Offer(&person{age: 3, name: "p4", salary: ms + 60}, ms+60) 95 _ = dq.Offer(&person{age: 1, name: "p5", salary: ms + 110}, ms+110) 96 _ = dq.Offer(&person{age: 5, name: "p6", salary: ms + 250}, ms+250) 97 _ = dq.Offer(&person{age: 200, name: "p7", salary: ms + 301}, ms+301) 98 99 expectedCount := 8 100 actualCount := 0 101 defer func() { 102 assert.LessOrEqual(t, actualCount, expectedCount) 103 }() 104 105 time.AfterFunc(300*time.Millisecond, func() { 106 close(receiver) 107 }) 108 for { 109 select { 110 case item, ok := <-receiver: 111 if !ok { 112 t.Log("receiver channel closed") 113 time.Sleep(100 * time.Millisecond) 114 return 115 } 116 t.Logf("current time ms: %d, item: %v\n", time.Now().UnixMilli(), item) 117 actualCount++ 118 } 119 } 120 } 121 122 func BenchmarkDelayQueue_Poll(b *testing.B) { 123 dq := NewArrayDelayQueue[*person](32) 124 125 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(b.N+10)*time.Millisecond) 126 defer cancel() 127 receiver, err := dq.Poll(ctx, 128 func() int64 { 129 return time.Now().UnixMilli() 130 }, 131 ) 132 assert.NoError(b, err) 133 ms := time.Now().UnixMilli() 134 b.ResetTimer() 135 for i := 0; i < b.N; i++ { 136 _ = dq.Offer(&person{age: i, name: "p", salary: int64(i)}, ms+int64(i)) 137 } 138 139 defer func() { 140 b.StopTimer() 141 b.ReportAllocs() 142 }() 143 144 for { 145 select { 146 case _, ok := <-receiver: 147 if !ok { 148 return 149 } 150 } 151 } 152 }