|
|
- package mempool
-
- import (
- "math/rand"
- "sort"
- "sync"
- "testing"
- "time"
-
- "github.com/stretchr/testify/require"
- )
-
- func TestTxPriorityQueue(t *testing.T) {
- pq := NewTxPriorityQueue()
- numTxs := 1000
-
- priorities := make([]int, numTxs)
-
- var wg sync.WaitGroup
- for i := 1; i <= numTxs; i++ {
- priorities[i-1] = i
- wg.Add(1)
-
- go func(i int) {
- pq.PushTx(&WrappedTx{
- priority: int64(i),
- timestamp: time.Now(),
- })
-
- wg.Done()
- }(i)
- }
-
- sort.Sort(sort.Reverse(sort.IntSlice(priorities)))
-
- wg.Wait()
- require.Equal(t, numTxs, pq.NumTxs())
-
- // Wait a second and push a tx with a duplicate priority
- time.Sleep(time.Second)
- now := time.Now()
- pq.PushTx(&WrappedTx{
- priority: 1000,
- timestamp: now,
- })
- require.Equal(t, 1001, pq.NumTxs())
-
- tx := pq.PopTx()
- require.Equal(t, 1000, pq.NumTxs())
- require.Equal(t, int64(1000), tx.priority)
- require.NotEqual(t, now, tx.timestamp)
-
- gotPriorities := make([]int, 0)
- for pq.NumTxs() > 0 {
- gotPriorities = append(gotPriorities, int(pq.PopTx().priority))
- }
-
- require.Equal(t, priorities, gotPriorities)
- }
-
- func TestTxPriorityQueue_GetEvictableTxs(t *testing.T) {
- pq := NewTxPriorityQueue()
- rng := rand.New(rand.NewSource(time.Now().UnixNano()))
-
- values := make([]int, 1000)
-
- for i := 0; i < 1000; i++ {
- tx := make([]byte, 5) // each tx is 5 bytes
- _, err := rng.Read(tx)
- require.NoError(t, err)
-
- x := rng.Intn(100000)
- pq.PushTx(&WrappedTx{
- tx: tx,
- priority: int64(x),
- })
-
- values[i] = x
- }
-
- sort.Ints(values)
-
- max := values[len(values)-1]
- min := values[0]
- totalSize := int64(len(values) * 5)
-
- testCases := []struct {
- name string
- priority, txSize, totalSize, cap int64
- expectedLen int
- }{
- {
- name: "larest priority; single tx",
- priority: int64(max + 1),
- txSize: 5,
- totalSize: totalSize,
- cap: totalSize,
- expectedLen: 1,
- },
- {
- name: "larest priority; multi tx",
- priority: int64(max + 1),
- txSize: 17,
- totalSize: totalSize,
- cap: totalSize,
- expectedLen: 4,
- },
- {
- name: "larest priority; out of capacity",
- priority: int64(max + 1),
- txSize: totalSize + 1,
- totalSize: totalSize,
- cap: totalSize,
- expectedLen: 0,
- },
- {
- name: "smallest priority; no tx",
- priority: int64(min - 1),
- txSize: 5,
- totalSize: totalSize,
- cap: totalSize,
- expectedLen: 0,
- },
- {
- name: "small priority; no tx",
- priority: int64(min),
- txSize: 5,
- totalSize: totalSize,
- cap: totalSize,
- expectedLen: 0,
- },
- }
-
- for _, tc := range testCases {
- tc := tc
-
- t.Run(tc.name, func(t *testing.T) {
- evictTxs := pq.GetEvictableTxs(tc.priority, tc.txSize, tc.totalSize, tc.cap)
- require.Len(t, evictTxs, tc.expectedLen)
- })
- }
- }
-
- func TestTxPriorityQueue_RemoveTx(t *testing.T) {
- pq := NewTxPriorityQueue()
- rng := rand.New(rand.NewSource(time.Now().UnixNano()))
- numTxs := 1000
-
- values := make([]int, numTxs)
-
- for i := 0; i < numTxs; i++ {
- x := rng.Intn(100000)
- pq.PushTx(&WrappedTx{
- priority: int64(x),
- })
-
- values[i] = x
- }
-
- require.Equal(t, numTxs, pq.NumTxs())
-
- sort.Ints(values)
- max := values[len(values)-1]
-
- wtx := pq.txs[pq.NumTxs()/2]
- pq.RemoveTx(wtx)
- require.Equal(t, numTxs-1, pq.NumTxs())
- require.Equal(t, int64(max), pq.PopTx().priority)
- require.Equal(t, numTxs-2, pq.NumTxs())
-
- require.NotPanics(t, func() {
- pq.RemoveTx(&WrappedTx{heapIndex: numTxs})
- pq.RemoveTx(&WrappedTx{heapIndex: numTxs + 1})
- })
- require.Equal(t, numTxs-2, pq.NumTxs())
- }
|