bitbucket.org/number571/tendermint@v0.8.14/internal/mempool/v1/priority_queue_test.go (about) 1 package v1 2 3 import ( 4 "math/rand" 5 "sort" 6 "sync" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestTxPriorityQueue(t *testing.T) { 14 pq := NewTxPriorityQueue() 15 numTxs := 1000 16 17 priorities := make([]int, numTxs) 18 19 var wg sync.WaitGroup 20 for i := 1; i <= numTxs; i++ { 21 priorities[i-1] = i 22 wg.Add(1) 23 24 go func(i int) { 25 pq.PushTx(&WrappedTx{ 26 priority: int64(i), 27 timestamp: time.Now(), 28 }) 29 30 wg.Done() 31 }(i) 32 } 33 34 sort.Sort(sort.Reverse(sort.IntSlice(priorities))) 35 36 wg.Wait() 37 require.Equal(t, numTxs, pq.NumTxs()) 38 39 // Wait a second and push a tx with a duplicate priority 40 time.Sleep(time.Second) 41 now := time.Now() 42 pq.PushTx(&WrappedTx{ 43 priority: 1000, 44 timestamp: now, 45 }) 46 require.Equal(t, 1001, pq.NumTxs()) 47 48 tx := pq.PopTx() 49 require.Equal(t, 1000, pq.NumTxs()) 50 require.Equal(t, int64(1000), tx.priority) 51 require.NotEqual(t, now, tx.timestamp) 52 53 gotPriorities := make([]int, 0) 54 for pq.NumTxs() > 0 { 55 gotPriorities = append(gotPriorities, int(pq.PopTx().priority)) 56 } 57 58 require.Equal(t, priorities, gotPriorities) 59 } 60 61 func TestTxPriorityQueue_GetEvictableTxs(t *testing.T) { 62 pq := NewTxPriorityQueue() 63 rng := rand.New(rand.NewSource(time.Now().UnixNano())) 64 65 values := make([]int, 1000) 66 67 for i := 0; i < 1000; i++ { 68 tx := make([]byte, 5) // each tx is 5 bytes 69 _, err := rng.Read(tx) 70 require.NoError(t, err) 71 72 x := rng.Intn(100000) 73 pq.PushTx(&WrappedTx{ 74 tx: tx, 75 priority: int64(x), 76 }) 77 78 values[i] = x 79 } 80 81 sort.Ints(values) 82 83 max := values[len(values)-1] 84 min := values[0] 85 totalSize := int64(len(values) * 5) 86 87 testCases := []struct { 88 name string 89 priority, txSize, totalSize, cap int64 90 expectedLen int 91 }{ 92 { 93 name: "larest priority; single tx", 94 priority: int64(max + 1), 95 txSize: 5, 96 totalSize: totalSize, 97 cap: totalSize, 98 expectedLen: 1, 99 }, 100 { 101 name: "larest priority; multi tx", 102 priority: int64(max + 1), 103 txSize: 17, 104 totalSize: totalSize, 105 cap: totalSize, 106 expectedLen: 4, 107 }, 108 { 109 name: "larest priority; out of capacity", 110 priority: int64(max + 1), 111 txSize: totalSize + 1, 112 totalSize: totalSize, 113 cap: totalSize, 114 expectedLen: 0, 115 }, 116 { 117 name: "smallest priority; no tx", 118 priority: int64(min - 1), 119 txSize: 5, 120 totalSize: totalSize, 121 cap: totalSize, 122 expectedLen: 0, 123 }, 124 { 125 name: "small priority; no tx", 126 priority: int64(min), 127 txSize: 5, 128 totalSize: totalSize, 129 cap: totalSize, 130 expectedLen: 0, 131 }, 132 } 133 134 for _, tc := range testCases { 135 tc := tc 136 137 t.Run(tc.name, func(t *testing.T) { 138 evictTxs := pq.GetEvictableTxs(tc.priority, tc.txSize, tc.totalSize, tc.cap) 139 require.Len(t, evictTxs, tc.expectedLen) 140 }) 141 } 142 } 143 144 func TestTxPriorityQueue_RemoveTx(t *testing.T) { 145 pq := NewTxPriorityQueue() 146 rng := rand.New(rand.NewSource(time.Now().UnixNano())) 147 numTxs := 1000 148 149 values := make([]int, numTxs) 150 151 for i := 0; i < numTxs; i++ { 152 x := rng.Intn(100000) 153 pq.PushTx(&WrappedTx{ 154 priority: int64(x), 155 }) 156 157 values[i] = x 158 } 159 160 require.Equal(t, numTxs, pq.NumTxs()) 161 162 sort.Ints(values) 163 max := values[len(values)-1] 164 165 wtx := pq.txs[pq.NumTxs()/2] 166 pq.RemoveTx(wtx) 167 require.Equal(t, numTxs-1, pq.NumTxs()) 168 require.Equal(t, int64(max), pq.PopTx().priority) 169 require.Equal(t, numTxs-2, pq.NumTxs()) 170 171 require.NotPanics(t, func() { 172 pq.RemoveTx(&WrappedTx{heapIndex: numTxs}) 173 pq.RemoveTx(&WrappedTx{heapIndex: numTxs + 1}) 174 }) 175 require.Equal(t, numTxs-2, pq.NumTxs()) 176 }