github.com/iotexproject/iotex-core@v1.14.1-rc1/actpool/accountpool_test.go (about)

     1  package actpool
     2  
     3  import (
     4  	"math/big"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/iotexproject/iotex-core/action"
    11  )
    12  
    13  var (
    14  	_balance    = big.NewInt(0).SetBytes([]byte("100000000000000000000000"))
    15  	_expireTime = time.Hour
    16  )
    17  
    18  func TestAccountPool_PopPeek(t *testing.T) {
    19  	r := require.New(t)
    20  	t.Run("empty pool", func(t *testing.T) {
    21  		ap := newAccountPool()
    22  		r.Nil(ap.PopPeek())
    23  	})
    24  	t.Run("one action", func(t *testing.T) {
    25  		ap := newAccountPool()
    26  		tsf1, err := action.SignedTransfer(_addr2, _priKey1, 1, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    27  		r.NoError(err)
    28  		r.NoError(ap.PutAction(_addr1, nil, 0, _balance, _expireTime, tsf1))
    29  		r.Equal(tsf1, ap.PopPeek())
    30  		r.Equal(0, ap.Account(_addr1).Len())
    31  	})
    32  	t.Run("multiple actions in one account", func(t *testing.T) {
    33  		ap := newAccountPool()
    34  		tsf1, err := action.SignedTransfer(_addr1, _priKey1, 1, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    35  		r.NoError(err)
    36  		tsf2, err := action.SignedTransfer(_addr1, _priKey1, 2, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    37  		r.NoError(err)
    38  		r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf1))
    39  		r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf2))
    40  		r.Equal(tsf2, ap.PopPeek())
    41  		r.Equal(tsf1, ap.PopPeek())
    42  		r.Nil(ap.PopPeek())
    43  		r.Equal(0, ap.Account(_addr1).Len())
    44  	})
    45  	t.Run("peek with pending nonce", func(t *testing.T) {
    46  		ap := newAccountPool()
    47  		tsf1, err := action.SignedTransfer(_addr1, _priKey1, 1, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    48  		r.NoError(err)
    49  		tsf2, err := action.SignedTransfer(_addr2, _priKey2, 2, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    50  		r.NoError(err)
    51  		r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf1))
    52  		r.NoError(ap.PutAction(_addr2, nil, 1, _balance, _expireTime, tsf2))
    53  		r.Equal(tsf2, ap.PopPeek())
    54  		t.Run("even if with higher price", func(t *testing.T) {
    55  			tsf2, err := action.SignedTransfer(_addr2, _priKey2, 2, big.NewInt(100), nil, uint64(0), big.NewInt(2))
    56  			r.NoError(err)
    57  			r.NoError(ap.PutAction(_addr2, nil, 1, _balance, _expireTime, tsf2))
    58  			r.Equal(tsf2, ap.PopPeek())
    59  		})
    60  	})
    61  	t.Run("peek with lower gas price", func(t *testing.T) {
    62  		ap := newAccountPool()
    63  		tsf1, err := action.SignedTransfer(_addr1, _priKey1, 2, big.NewInt(100), nil, uint64(0), big.NewInt(2))
    64  		r.NoError(err)
    65  		tsf2, err := action.SignedTransfer(_addr2, _priKey2, 2, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    66  		r.NoError(err)
    67  		r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf1))
    68  		r.NoError(ap.PutAction(_addr2, nil, 1, _balance, _expireTime, tsf2))
    69  		r.Equal(tsf2, ap.PopPeek())
    70  		r.Equal(tsf1, ap.PopPeek())
    71  		t.Run("peek with pending nonce even if has higher price ", func(t *testing.T) {
    72  			tsf1, err = action.SignedTransfer(_addr1, _priKey1, 1, big.NewInt(100), nil, uint64(0), big.NewInt(2))
    73  			r.NoError(err)
    74  			tsf2, err = action.SignedTransfer(_addr1, _priKey2, 1, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    75  			r.NoError(err)
    76  			r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf1))
    77  			r.NoError(ap.PutAction(_addr2, nil, 1, _balance, _expireTime, tsf2))
    78  			r.Equal(tsf2, ap.PopPeek())
    79  			r.Equal(tsf1, ap.PopPeek())
    80  		})
    81  	})
    82  	t.Run("multiple actions in multiple accounts", func(t *testing.T) {
    83  		ap := newAccountPool()
    84  		tsf1, err := action.SignedTransfer(_addr1, _priKey1, 1, big.NewInt(100), nil, uint64(0), big.NewInt(2))
    85  		r.NoError(err)
    86  		tsf2, err := action.SignedTransfer(_addr2, _priKey1, 2, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    87  		r.NoError(err)
    88  		tsf3, err := action.SignedTransfer(_addr2, _priKey2, 2, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    89  		r.NoError(err)
    90  		tsf4, err := action.SignedTransfer(_addr2, _priKey2, 3, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    91  		r.NoError(err)
    92  		tsf5, err := action.SignedTransfer(_addr2, _priKey3, 1, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    93  		r.NoError(err)
    94  		tsf6, err := action.SignedTransfer(_addr2, _priKey3, 3, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    95  		r.NoError(err)
    96  		tsf7, err := action.SignedTransfer(_addr2, _priKey4, 2, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    97  		r.NoError(err)
    98  		tsf8, err := action.SignedTransfer(_addr2, _priKey4, 3, big.NewInt(100), nil, uint64(0), big.NewInt(1))
    99  		r.NoError(err)
   100  		r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf1))
   101  		r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf2))
   102  		r.NoError(ap.PutAction(_addr2, nil, 1, _balance, _expireTime, tsf3))
   103  		r.NoError(ap.PutAction(_addr2, nil, 1, _balance, _expireTime, tsf4))
   104  		r.NoError(ap.PutAction(_addr3, nil, 1, _balance, _expireTime, tsf5))
   105  		r.NoError(ap.PutAction(_addr3, nil, 1, _balance, _expireTime, tsf6))
   106  		r.NoError(ap.PutAction(_addr4, nil, 1, _balance, _expireTime, tsf7))
   107  		r.NoError(ap.PutAction(_addr4, nil, 1, _balance, _expireTime, tsf8))
   108  		r.Equal(tsf4, ap.PopPeek())
   109  		r.Equal(tsf3, ap.PopPeek())
   110  		r.Equal(tsf8, ap.PopPeek())
   111  		r.Equal(tsf7, ap.PopPeek())
   112  		r.Equal(tsf6, ap.PopPeek())
   113  		r.Equal(tsf5, ap.PopPeek())
   114  		r.Equal(tsf2, ap.PopPeek())
   115  		r.Equal(tsf1, ap.PopPeek())
   116  		r.Nil(ap.PopPeek())
   117  	})
   118  }
   119  
   120  func TestAccountPool_PopAccount(t *testing.T) {
   121  	r := require.New(t)
   122  	ap := newAccountPool()
   123  
   124  	// Create a sample account
   125  	tsf1, err := action.SignedTransfer(_addr1, _priKey1, 1, big.NewInt(100), nil, uint64(0), big.NewInt(1))
   126  	r.NoError(err)
   127  	r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf1))
   128  
   129  	// Test when the account exists
   130  	result := ap.PopAccount(_addr1)
   131  	r.Equal(1, result.Len())
   132  	r.Equal(tsf1, result.AllActs()[0])
   133  	r.Nil(ap.Account(_addr1))
   134  
   135  	// Test when the account does not exist
   136  	result = ap.PopAccount("nonExistentAddress")
   137  	r.Nil(result)
   138  }
   139  
   140  func TestAccountPool_Range(t *testing.T) {
   141  	r := require.New(t)
   142  	ap := newAccountPool()
   143  
   144  	// Create a sample account
   145  	tsf1, err := action.SignedTransfer(_addr1, _priKey1, 1, big.NewInt(100), nil, uint64(0), big.NewInt(1))
   146  	r.NoError(err)
   147  	tsf2, err := action.SignedTransfer(_addr1, _priKey1, 2, big.NewInt(100), nil, uint64(0), big.NewInt(1))
   148  	r.NoError(err)
   149  	tsf3, err := action.SignedTransfer(_addr1, _priKey2, 2, big.NewInt(100), nil, uint64(0), big.NewInt(1))
   150  	r.NoError(err)
   151  	tsf4, err := action.SignedTransfer(_addr1, _priKey2, 1, big.NewInt(100), nil, uint64(0), big.NewInt(2))
   152  	r.NoError(err)
   153  	r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf1))
   154  	r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf2))
   155  	r.NoError(ap.PutAction(_addr2, nil, 1, _balance, _expireTime, tsf3))
   156  	r.Equal(2, ap.Account(_addr1).Len())
   157  	r.Equal(1, ap.Account(_addr2).Len())
   158  	// Define a callback function
   159  	callback := func(addr string, acct ActQueue) {
   160  		if addr == _addr2 {
   161  			r.NoError(acct.Put(tsf4))
   162  		} else if addr == _addr1 {
   163  			acct.PopActionWithLargestNonce()
   164  		}
   165  	}
   166  	// Call the Range method
   167  	ap.Range(callback)
   168  	// Verify the results
   169  	r.Equal(1, ap.Account(_addr1).Len())
   170  	r.Equal(2, ap.Account(_addr2).Len())
   171  	r.Equal(tsf1, ap.PopPeek())
   172  	r.Equal(tsf3, ap.PopPeek())
   173  	r.Equal(tsf4, ap.PopPeek())
   174  	r.Nil(ap.PopPeek())
   175  }
   176  
   177  func TestAccountPool_DeleteIfEmpty(t *testing.T) {
   178  	r := require.New(t)
   179  	ap := newAccountPool()
   180  
   181  	// Create a sample account
   182  	tsf1, err := action.SignedTransfer(_addr1, _priKey1, 1, big.NewInt(100), nil, uint64(0), big.NewInt(1))
   183  	r.NoError(err)
   184  	r.NoError(ap.PutAction(_addr1, nil, 1, _balance, _expireTime, tsf1))
   185  
   186  	// Test when the account is not empty
   187  	ap.DeleteIfEmpty(_addr1)
   188  	r.NotNil(ap.Account(_addr1))
   189  
   190  	// Test when the account is empty
   191  	ap.PopPeek()
   192  	ap.DeleteIfEmpty(_addr1)
   193  	r.Nil(ap.Account(_addr1))
   194  }