github.com/theQRL/go-zond@v0.1.1/common/prque/lazyqueue_test.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package prque 18 19 import ( 20 "math/rand" 21 "sync" 22 "testing" 23 "time" 24 25 "github.com/theQRL/go-zond/common/mclock" 26 ) 27 28 const ( 29 testItems = 1000 30 testPriorityStep = 100 31 testSteps = 1000000 32 testStepPeriod = time.Millisecond 33 testQueueRefresh = time.Second 34 testAvgRate = float64(testPriorityStep) / float64(testItems) / float64(testStepPeriod) 35 ) 36 37 type lazyItem struct { 38 p, maxp int64 39 last mclock.AbsTime 40 index int 41 } 42 43 func testPriority(a interface{}) int64 { 44 return a.(*lazyItem).p 45 } 46 47 func testMaxPriority(a interface{}, until mclock.AbsTime) int64 { 48 i := a.(*lazyItem) 49 dt := until - i.last 50 i.maxp = i.p + int64(float64(dt)*testAvgRate) 51 return i.maxp 52 } 53 54 func testSetIndex(a interface{}, i int) { 55 a.(*lazyItem).index = i 56 } 57 58 func TestLazyQueue(t *testing.T) { 59 clock := &mclock.Simulated{} 60 q := NewLazyQueue(testSetIndex, testPriority, testMaxPriority, clock, testQueueRefresh) 61 62 var ( 63 items [testItems]lazyItem 64 maxPri int64 65 ) 66 67 for i := range items[:] { 68 items[i].p = rand.Int63n(testPriorityStep * 10) 69 if items[i].p > maxPri { 70 maxPri = items[i].p 71 } 72 items[i].index = -1 73 q.Push(&items[i]) 74 } 75 76 var ( 77 lock sync.Mutex 78 wg sync.WaitGroup 79 stopCh = make(chan chan struct{}) 80 ) 81 defer wg.Wait() 82 wg.Add(1) 83 go func() { 84 defer wg.Done() 85 for { 86 select { 87 case <-clock.After(testQueueRefresh): 88 lock.Lock() 89 q.Refresh() 90 lock.Unlock() 91 case <-stopCh: 92 return 93 } 94 } 95 }() 96 97 for c := 0; c < testSteps; c++ { 98 i := rand.Intn(testItems) 99 lock.Lock() 100 items[i].p += rand.Int63n(testPriorityStep*2-1) + 1 101 if items[i].p > maxPri { 102 maxPri = items[i].p 103 } 104 items[i].last = clock.Now() 105 if items[i].p > items[i].maxp { 106 q.Update(items[i].index) 107 } 108 if rand.Intn(100) == 0 { 109 p := q.PopItem().(*lazyItem) 110 if p.p != maxPri { 111 lock.Unlock() 112 close(stopCh) 113 t.Fatalf("incorrect item (best known priority %d, popped %d)", maxPri, p.p) 114 } 115 q.Push(p) 116 } 117 lock.Unlock() 118 clock.Run(testStepPeriod) 119 clock.WaitForTimers(1) 120 } 121 122 close(stopCh) 123 }