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  }