Skip to content

Commit

Permalink
Add / improve tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
andreibancioiu committed Dec 12, 2024
1 parent 5070c54 commit 853f676
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 20 deletions.
29 changes: 21 additions & 8 deletions testscommon/txcachemocks/mempoolHostMock.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import (

// MempoolHostMock -
type MempoolHostMock struct {
minGasLimit uint64
minGasPrice uint64
gasPerDataByte uint64
gasPriceModifier float64
minGasLimit uint64
minGasPrice uint64
gasPerDataByte uint64
gasPriceModifier float64
extraGasLimitForGuarded uint64
extraGasLimitForRelayed uint64

ComputeTxFeeCalled func(tx data.TransactionWithFeeHandler) *big.Int
GetTransferredValueCalled func(tx data.TransactionHandler) *big.Int
Expand All @@ -21,10 +23,12 @@ type MempoolHostMock struct {
// NewMempoolHostMock -
func NewMempoolHostMock() *MempoolHostMock {
return &MempoolHostMock{
minGasLimit: 50000,
minGasPrice: 1000000000,
gasPerDataByte: 1500,
gasPriceModifier: 0.01,
minGasLimit: 50_000,
minGasPrice: 1_000_000_000,
gasPerDataByte: 1500,
gasPriceModifier: 0.01,
extraGasLimitForGuarded: 50_000,
extraGasLimitForRelayed: 50_000,
}
}

Expand All @@ -39,6 +43,15 @@ func (mock *MempoolHostMock) ComputeTxFee(tx data.TransactionWithFeeHandler) *bi
gasPriceForProcessing := uint64(float64(gasPriceForMovement) * mock.gasPriceModifier)

gasLimitForMovement := mock.minGasLimit + dataLength*mock.gasPerDataByte

if txAsGuarded, ok := tx.(data.GuardedTransactionHandler); ok && len(txAsGuarded.GetGuardianAddr()) > 0 {
gasLimitForMovement += mock.extraGasLimitForGuarded
}

if txAsRelayed, ok := tx.(data.RelayedTransactionHandler); ok && len(txAsRelayed.GetRelayerAddr()) > 0 {
gasLimitForMovement += mock.extraGasLimitForRelayed
}

if tx.GetGasLimit() < gasLimitForMovement {
panic("tx.GetGasLimit() < gasLimitForMovement")
}
Expand Down
133 changes: 133 additions & 0 deletions txcache/selectionSessionWrapper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package txcache

import (
"math/big"
"testing"

"github.com/multiversx/mx-chain-storage-go/testscommon/txcachemocks"
"github.com/stretchr/testify/require"
)

func TestSelectionSessionWrapper_accumulateConsumedBalance(t *testing.T) {
host := txcachemocks.NewMempoolHostMock()

t.Run("when sender is fee payer", func(t *testing.T) {
session := txcachemocks.NewSelectionSessionMock()
sessionWrapper := newSelectionSessionWrapper(session)

a := createTx([]byte("a-7"), "a", 7)
b := createTx([]byte("a-8"), "a", 8).withValue(oneQuintillionBig)

a.precomputeFields(host)
b.precomputeFields(host)

sessionWrapper.accumulateConsumedBalance(a)
require.Equal(t, "50000000000000", sessionWrapper.getAccountRecord([]byte("a")).consumedBalance.String())

sessionWrapper.accumulateConsumedBalance(b)
require.Equal(t, "1000100000000000000", sessionWrapper.getAccountRecord([]byte("a")).consumedBalance.String())
})

t.Run("when relayer is fee payer", func(t *testing.T) {
session := txcachemocks.NewSelectionSessionMock()
sessionWrapper := newSelectionSessionWrapper(session)

a := createTx([]byte("a-7"), "a", 7).withRelayer([]byte("b")).withGasLimit(100_000)
b := createTx([]byte("a-8"), "a", 8).withValue(oneQuintillionBig).withRelayer([]byte("b")).withGasLimit(100_000)

a.precomputeFields(host)
b.precomputeFields(host)

sessionWrapper.accumulateConsumedBalance(a)
require.Equal(t, "0", sessionWrapper.getAccountRecord([]byte("a")).consumedBalance.String())
require.Equal(t, "100000000000000", sessionWrapper.getAccountRecord([]byte("b")).consumedBalance.String())

sessionWrapper.accumulateConsumedBalance(b)
require.Equal(t, "1000000000000000000", sessionWrapper.getAccountRecord([]byte("a")).consumedBalance.String())
require.Equal(t, "200000000000000", sessionWrapper.getAccountRecord([]byte("b")).consumedBalance.String())
})
}

func TestSelectionSessionWrapper_detectWillFeeExceedBalance(t *testing.T) {
host := txcachemocks.NewMempoolHostMock()

t.Run("unknown", func(t *testing.T) {
session := txcachemocks.NewSelectionSessionMock()
sessionWrapper := newSelectionSessionWrapper(session)

a := createTx([]byte("tx-1"), "alice", 42)
a.precomputeFields(host)

require.False(t, sessionWrapper.detectWillFeeExceedBalance(a))
})

t.Run("will not exceed for (a) and (b), but will exceed for (c)", func(t *testing.T) {
a := createTx([]byte("tx-1"), "alice", 42)
b := createTx([]byte("tx-2"), "alice", 43).withValue(oneQuintillionBig)
c := createTx([]byte("tx-3"), "alice", 44).withValue(oneQuintillionBig)

a.precomputeFields(host)
b.precomputeFields(host)
c.precomputeFields(host)

session := txcachemocks.NewSelectionSessionMock()
sessionWrapper := newSelectionSessionWrapper(session)

session.SetBalance([]byte("alice"), big.NewInt(oneQuintillion+50000000000000+1))
recordAlice := sessionWrapper.getAccountRecord([]byte("alice"))
require.Equal(t, "0", recordAlice.consumedBalance.String())
require.Equal(t, "1000050000000000001", recordAlice.initialBalance.String())

require.False(t, sessionWrapper.detectWillFeeExceedBalance(a))

sessionWrapper.accumulateConsumedBalance(a)

require.Equal(t, "50000000000000", recordAlice.consumedBalance.String())

// Even though, in reality, that will be an invalid (but executable) transaction (insufficient balance).
require.False(t, sessionWrapper.detectWillFeeExceedBalance(b))

sessionWrapper.accumulateConsumedBalance(b)

require.Equal(t, "1000100000000000000", recordAlice.consumedBalance.String())
require.True(t, sessionWrapper.detectWillFeeExceedBalance(c))
})

t.Run("will not exceed for (a) and (b), but will exceed for (c) (with relayed)", func(t *testing.T) {
a := createTx([]byte("tx-1"), "alice", 42).withRelayer([]byte("carol")).withGasLimit(100_000)
b := createTx([]byte("tx-2"), "alice", 43).withValue(oneQuintillionBig).withRelayer([]byte("carol")).withGasLimit(100_000)
c := createTx([]byte("tx-3"), "alice", 44).withValue(oneQuintillionBig).withRelayer([]byte("carol")).withGasLimit(100_000)

a.precomputeFields(host)
b.precomputeFields(host)
c.precomputeFields(host)

session := txcachemocks.NewSelectionSessionMock()
sessionWrapper := newSelectionSessionWrapper(session)

session.SetBalance([]byte("alice"), big.NewInt(oneQuintillion))
session.SetBalance([]byte("carol"), big.NewInt(100000000000000+100000000000000+1))
recordAlice := sessionWrapper.getAccountRecord([]byte("alice"))
recordCarol := sessionWrapper.getAccountRecord([]byte("carol"))
require.Equal(t, "0", recordAlice.consumedBalance.String())
require.Equal(t, "1000000000000000000", recordAlice.initialBalance.String())
require.Equal(t, "0", recordCarol.consumedBalance.String())
require.Equal(t, "200000000000001", recordCarol.initialBalance.String())

require.False(t, sessionWrapper.detectWillFeeExceedBalance(a))

sessionWrapper.accumulateConsumedBalance(a)

require.Equal(t, "0", recordAlice.consumedBalance.String())
require.Equal(t, "100000000000000", recordCarol.consumedBalance.String())

require.False(t, sessionWrapper.detectWillFeeExceedBalance(b))

sessionWrapper.accumulateConsumedBalance(b)

require.Equal(t, "1000000000000000000", recordAlice.consumedBalance.String())
require.Equal(t, "200000000000000", recordCarol.consumedBalance.String())
require.True(t, sessionWrapper.detectWillFeeExceedBalance(c))
})
}

6 changes: 6 additions & 0 deletions txcache/testutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ func (wrappedTx *WrappedTransaction) withValue(value *big.Int) *WrappedTransacti
return wrappedTx
}

func (wrappedTx *WrappedTransaction) withRelayer(relayer []byte) *WrappedTransaction {
tx := wrappedTx.Tx.(*transaction.Transaction)
tx.RelayerAddr = relayer
return wrappedTx
}

func createFakeSenderAddress(senderTag int) []byte {
bytes := make([]byte, 32)
binary.LittleEndian.PutUint64(bytes, uint64(senderTag))
Expand Down
13 changes: 1 addition & 12 deletions txcache/wrappedTransaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"testing"

"github.com/multiversx/mx-chain-core-go/data"
"github.com/multiversx/mx-chain-core-go/data/transaction"
"github.com/multiversx/mx-chain-storage-go/testscommon/txcachemocks"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -98,17 +97,7 @@ func TestWrappedTransaction_decideFeePayer(t *testing.T) {
})

t.Run("when relayer is fee payer", func(t *testing.T) {
tx := &WrappedTransaction{
Tx: &transaction.Transaction{
SndAddr: []byte("a"),
Nonce: 7,
GasLimit: 1_000_000,
GasPrice: oneBillion,
RelayerAddr: []byte("b"),
},
TxHash: []byte("abba"),
}

tx := createTx([]byte("a"), "a", 1).withRelayer([]byte("b")).withGasLimit(100_000)
tx.precomputeFields(host)

require.Nil(t, tx.TransferredValue)
Expand Down

0 comments on commit 853f676

Please sign in to comment.