github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/queue/priority_queue_test.go (about) 1 package queue 2 3 import ( 4 "fmt" 5 "testing" 6 "unsafe" 7 8 "github.com/stretchr/testify/assert" 9 ) 10 11 type employee struct { 12 name string 13 age int 14 salary int64 15 } 16 17 func TestPriorityQueueItemAlignmentAndSize(t *testing.T) { 18 item := NewPriorityQueueItem[*employee](&employee{age: 10, name: "p0"}, 1) 19 t.Logf("item alignment size: %d\n", unsafe.Alignof(item)) 20 prototype := item.(*pqItem[*employee]) 21 t.Logf("item prototype alignment size: %d\n", unsafe.Alignof(prototype)) 22 t.Logf("item prototype value alignment size: %d\n", unsafe.Alignof(prototype.value)) 23 t.Logf("item prototype priority alignment size: %d\n", unsafe.Alignof(prototype.priority)) 24 t.Logf("item prototype index alignment size: %d\n", unsafe.Alignof(prototype.index)) 25 t.Logf("item prototype size: %d\n", unsafe.Sizeof(prototype)) 26 t.Logf("item prototype value size: %d\n", unsafe.Sizeof(prototype.value)) 27 t.Logf("item prototype priority size: %d\n", unsafe.Sizeof(prototype.priority)) 28 t.Logf("item prototype index size: %d\n", unsafe.Sizeof(prototype.index)) 29 } 30 31 func TestPriorityQueue_MinValueAsHighPriority(t *testing.T) { 32 pq := NewArrayPriorityQueue[*employee]( 33 WithArrayPriorityQueueEnableThreadSafe[*employee](), 34 WithArrayPriorityQueueCapacity[*employee](32), 35 WithArrayPriorityQueueComparator[*employee](func(i, j ReadOnlyPQItem[*employee]) CmpEnum { 36 res := i.Priority() - j.Priority() 37 if res > 0 { 38 return iGTj 39 } else if res < 0 { 40 return iLTj 41 } 42 return iEQj 43 }), 44 ) 45 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 10, name: "p0"}, 1)) 46 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 101, name: "p1"}, 101)) 47 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 10, name: "p2"}, 10)) 48 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 200, name: "p3"}, 200)) 49 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 3, name: "p4"}, 3)) 50 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 1, name: "p5"}, 1)) 51 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 5, name: "p6"}, 5)) 52 53 expectedPriorities := []int64{1, 1, 3, 5, 10, 101, 200} 54 for i, priority := range expectedPriorities { 55 item := pq.Pop() 56 t.Logf("%v, priority: %d", item.Value(), item.Priority()) 57 assert.Equal(t, priority, item.Priority(), "priority", i) 58 } 59 } 60 61 func TestPriorityQueue_MaxValueAsHighPriority(t *testing.T) { 62 pq := NewArrayPriorityQueue[*employee]( 63 WithArrayPriorityQueueEnableThreadSafe[*employee](), 64 WithArrayPriorityQueueCapacity[*employee](32), 65 WithArrayPriorityQueueComparator[*employee](func(i, j ReadOnlyPQItem[*employee]) CmpEnum { 66 res := j.Priority() - i.Priority() 67 if res > 0 { 68 return iGTj 69 } else if res < 0 { 70 return iLTj 71 } 72 return iEQj 73 }), 74 ) 75 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 10, name: "p0"}, 1)) 76 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 101, name: "p1"}, 101)) 77 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 10, name: "p2"}, 10)) 78 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 200, name: "p3"}, 200)) 79 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 3, name: "p4"}, 3)) 80 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 1, name: "p5"}, 1)) 81 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 5, name: "p6"}, 5)) 82 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 200, name: "p7"}, 201)) 83 84 expectedPriorities := []int64{201, 200, 101, 10, 5, 3, 1, 1} 85 for i, priority := range expectedPriorities { 86 item := pq.Pop() 87 t.Logf("%v, priority: %d", item.Value(), item.Priority()) 88 assert.Equal(t, priority, item.Priority(), "priority", i) 89 } 90 } 91 92 func TestPriorityQueue_MinValueAsHighPriority_Peek(t *testing.T) { 93 pq := NewArrayPriorityQueue[*employee]( 94 WithArrayPriorityQueueEnableThreadSafe[*employee](), 95 WithArrayPriorityQueueCapacity[*employee](32), 96 WithArrayPriorityQueueComparator[*employee](func(i, j ReadOnlyPQItem[*employee]) CmpEnum { 97 res := i.Priority() - j.Priority() 98 if res > 0 { 99 return iGTj 100 } else if res < 0 { 101 return iLTj 102 } 103 return iEQj 104 }), 105 ) 106 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 200, name: "p3"}, 200)) 107 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 200, name: "p7"}, 201)) 108 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 10, name: "p2"}, 10)) 109 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 3, name: "p4"}, 3)) 110 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 10, name: "p0"}, 1)) 111 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 101, name: "p1"}, 101)) 112 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 1, name: "p5"}, 1)) 113 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 5, name: "p6"}, 5)) 114 115 expectedPriorities := []int64{1, 1, 3, 5, 10, 101, 200, 201} 116 for i, priority := range expectedPriorities { 117 peekItem := pq.Peek() 118 t.Logf("peek item: %v, priority: %d", peekItem.Value(), peekItem.Priority()) 119 item := pq.Pop() 120 t.Logf("%v, priority: %d", item.Value(), item.Priority()) 121 assert.Equal(t, priority, item.Priority(), "priority", i) 122 } 123 } 124 125 func TestPriorityQueue_MaxValueAsHighPriority_Peek(t *testing.T) { 126 pq := NewArrayPriorityQueue[*employee]( 127 WithArrayPriorityQueueEnableThreadSafe[*employee](), 128 WithArrayPriorityQueueCapacity[*employee](32), 129 WithArrayPriorityQueueComparator[*employee](func(i, j ReadOnlyPQItem[*employee]) CmpEnum { 130 res := j.Priority() - i.Priority() 131 if res > 0 { 132 return iGTj 133 } else if res < 0 { 134 return iLTj 135 } 136 return iEQj 137 }), 138 ) 139 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 10, name: "p0"}, 1)) 140 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 101, name: "p1"}, 101)) 141 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 10, name: "p2"}, 10)) 142 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 200, name: "p3"}, 200)) 143 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 3, name: "p4"}, 3)) 144 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 1, name: "p5"}, 1)) 145 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 5, name: "p6"}, 5)) 146 pq.Push(NewPriorityQueueItem[*employee](&employee{age: 200, name: "p7"}, 201)) 147 148 expectedPriorities := []int64{201, 200, 101, 10, 5, 3, 1, 1} 149 for i, priority := range expectedPriorities { 150 peekItem := pq.Peek() 151 t.Logf("peek item: %v, priority: %d", peekItem.Value(), peekItem.Priority()) 152 item := pq.Pop() 153 t.Logf("%v, priority: %d", item.Value(), item.Priority()) 154 assert.Equal(t, priority, item.Priority(), "priority", i) 155 } 156 } 157 158 func BenchmarkArrayPriorityQueue_Push(b *testing.B) { 159 var list = make([]PQItem[*employee], 0, b.N) 160 for i := 0; i < b.N; i++ { 161 e := NewPriorityQueueItem[*employee](&employee{age: i, name: fmt.Sprintf("p%d", i)}, int64(i)) 162 list = append(list, e) 163 } 164 b.ResetTimer() 165 pq := NewArrayPriorityQueue[*employee]( 166 WithArrayPriorityQueueEnableThreadSafe[*employee](), 167 WithArrayPriorityQueueCapacity[*employee](32), 168 WithArrayPriorityQueueComparator[*employee](func(i, j ReadOnlyPQItem[*employee]) CmpEnum { 169 res := j.Priority() - i.Priority() 170 if res > 0 { 171 return iGTj 172 } else if res < 0 { 173 return iLTj 174 } 175 return iEQj 176 }), 177 ) 178 for i := 0; i < b.N; i++ { 179 pq.Push(list[i]) 180 } 181 b.ReportAllocs() 182 } 183 184 func BenchmarkArrayPriorityQueue_Pop(b *testing.B) { 185 var list = make([]PQItem[*employee], 0, b.N) 186 for i := 0; i < b.N; i++ { 187 e := NewPriorityQueueItem[*employee](&employee{age: i, name: fmt.Sprintf("p%d", i)}, int64(i)) 188 list = append(list, e) 189 } 190 pq := NewArrayPriorityQueue[*employee]( 191 WithArrayPriorityQueueEnableThreadSafe[*employee](), 192 WithArrayPriorityQueueCapacity[*employee](32), 193 ) 194 for i := 0; i < b.N; i++ { 195 pq.Push(list[i]) 196 } 197 b.ResetTimer() 198 for i := 0; i < b.N; i++ { 199 _ = pq.Pop() 200 } 201 b.ReportAllocs() 202 }