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 }