Skip to content

Commit

Permalink
Add txpool tests (#636)
Browse files Browse the repository at this point in the history
  • Loading branch information
MakisChristou authored Jan 4, 2024
1 parent 869e9c5 commit ef71fc0
Show file tree
Hide file tree
Showing 5 changed files with 468 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ test:| go_version_check

test-coverage:| go_version_check
@go test -race -coverprofile=coverage.out -covermode=atomic $(PACKAGES)

@go tool cover -html=coverage.out
164 changes: 164 additions & 0 deletions txpool/blocklist_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package txpool

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/vechain/thor/v2/thor"
)

// SetupTempFile creates a temporary file with dummy data and returns the file path.
func SetupTempFile(t *testing.T, dummyData string) string {
tempFile, err := os.CreateTemp("", "test_blocklist_*.txt")
if err != nil {
t.Fatalf("Failed to create temp file: %s", err)
}
testFilePath := tempFile.Name()

err = os.WriteFile(testFilePath, []byte(dummyData), 0644)
if err != nil {
t.Fatalf("Failed to write to temp file: %s", err)
}

// Close the file and return its path.
tempFile.Close()
return testFilePath
}

func TestLoad(t *testing.T) {
dummyData := "0x25Df024637d4e56c1aE9563987Bf3e92C9f534c0\n0x25Df024637d4e56c1aE9563987Bf3e92C9f534c1"
testFilePath := SetupTempFile(t, dummyData)

var bl blocklist
err := bl.Load(testFilePath)
if err != nil {
t.Errorf("Load failed: %s", err)
}

// Clean up: delete the temporary file.
os.Remove(testFilePath)
}

func TestLoadWithError(t *testing.T) {
dummyData := "0x25Df024637d4\n0x25Df024637d4e56c1aE956"
testFilePath := SetupTempFile(t, dummyData)

var bl blocklist
err := bl.Load(testFilePath)
assert.Equal(t, err.Error(), "invalid length")
assert.False(t, IsBadTx(err))
assert.False(t, IsTxRejected(err))

// Clean up: delete the test file.
os.Remove(testFilePath)
}

func TestSave(t *testing.T) {
dummyData := "0x25Df024637d4e56c1aE9563987Bf3e92C9f534c0\n0x25Df024637d4e56c1aE9563987Bf3e92C9f534c1"
testFilePath := SetupTempFile(t, dummyData)

var bl blocklist
err := bl.Load(testFilePath)
if err != nil {
t.Errorf("Load failed: %s", err)
}

// Clean up: delete the test file.
os.Remove(testFilePath)

// Test the Load function.
err = bl.Save(testFilePath)
if err != nil {
t.Errorf("Load failed: %s", err)
}

fileContents, err := os.ReadFile(testFilePath)
str := string(fileContents)
assert.True(t, strings.Contains(str, "0x25df024637d4e56c1ae9563987bf3e92c9f534c0"))
assert.True(t, strings.Contains(str, "0x25df024637d4e56c1ae9563987bf3e92c9f534c1"))

// Clean up: delete the test file.
os.Remove(testFilePath)
}

func TestLen(t *testing.T) {
dummyData := "0x25Df024637d4e56c1aE9563987Bf3e92C9f534c0\n0x25Df024637d4e56c1aE9563987Bf3e92C9f534c1"
testFilePath := SetupTempFile(t, dummyData)

var bl blocklist
err := bl.Load(testFilePath)
if err != nil {
t.Errorf("Load failed: %s", err)
}

// Clean up: delete the test file.
os.Remove(testFilePath)

listLength := bl.Len()
assert.Equal(t, listLength, 2)
}

func TestFetch(t *testing.T) {
// Example data to be served by the mock server
data := "0x25Df024637d4e56c1aE9563987Bf3e92C9f534c0\n0x25Df024637d4e56c1aE9563987Bf3e92C9f534c1"

expectedAddresses := []thor.Address{
thor.MustParseAddress("0x25Df024637d4e56c1aE9563987Bf3e92C9f534c0"),
thor.MustParseAddress("0x25Df024637d4e56c1aE9563987Bf3e92C9f534c1"),
}

// Create a mock server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// You can check headers, methods, etc. here
if r.Header.Get("if-none-match") == "some-etag" {
w.WriteHeader(http.StatusNotModified)
return
}
fmt.Fprint(w, data)
}))
defer server.Close()

// Test scenarios
tests := []struct {
name string
etag *string
wantErr bool
}{
{"Successful Fetch", nil, false},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var bl blocklist
bl.list = make(map[thor.Address]bool)

// Set up ETAG if needed
if tt.etag != nil {
*tt.etag = "some-etag"
}

// Call the Fetch function
err := bl.Fetch(context.Background(), server.URL, tt.etag)

// Check for errors
if (err != nil) != tt.wantErr {
t.Errorf("Fetch() error = %v, wantErr %v", err, tt.wantErr)
return
}

// Check if the blocklist contains the expected addresses
for _, addr := range expectedAddresses {
if _, exists := bl.list[addr]; !exists {
t.Errorf("Fetch() missing address %s", addr)
}
}

})
}
}
61 changes: 61 additions & 0 deletions txpool/tx_object_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,70 @@ import (
"github.com/stretchr/testify/assert"
"github.com/vechain/thor/v2/genesis"
"github.com/vechain/thor/v2/muxdb"
"github.com/vechain/thor/v2/thor"
"github.com/vechain/thor/v2/tx"
)

func TestGetByID(t *testing.T) {
db := muxdb.NewMem()
repo := newChainRepo(db)

// Creating transactions
tx1 := newTx(repo.ChainTag(), nil, 21000, tx.BlockRef{}, 100, nil, tx.Features(0), genesis.DevAccounts()[0])
tx2 := newTx(repo.ChainTag(), nil, 21000, tx.BlockRef{}, 100, nil, tx.Features(0), genesis.DevAccounts()[1])

// Resolving transactions into txObjects
txObj1, _ := resolveTx(tx1, false)
txObj2, _ := resolveTx(tx2, false)

// Creating a new txObjectMap and adding transactions
m := newTxObjectMap()
assert.Nil(t, m.Add(txObj1, 1))
assert.Nil(t, m.Add(txObj2, 1))

// Testing GetByID
retrievedTxObj1 := m.GetByID(txObj1.ID())
assert.Equal(t, txObj1, retrievedTxObj1, "The retrieved transaction object should match the original for tx1")

retrievedTxObj2 := m.GetByID(txObj2.ID())
assert.Equal(t, txObj2, retrievedTxObj2, "The retrieved transaction object should match the original for tx2")

// Testing retrieval of a non-existing transaction
nonExistingTxID := thor.Bytes32{} // An arbitrary non-existing ID
retrievedTxObj3 := m.GetByID(nonExistingTxID)
assert.Nil(t, retrievedTxObj3, "Retrieving a non-existing transaction should return nil")
}

func TestFill(t *testing.T) {
db := muxdb.NewMem()
repo := newChainRepo(db)

// Creating transactions
tx1 := newTx(repo.ChainTag(), nil, 21000, tx.BlockRef{}, 100, nil, tx.Features(0), genesis.DevAccounts()[0])
tx2 := newTx(repo.ChainTag(), nil, 21000, tx.BlockRef{}, 100, nil, tx.Features(0), genesis.DevAccounts()[1])

// Resolving transactions into txObjects
txObj1, _ := resolveTx(tx1, false)
txObj2, _ := resolveTx(tx2, false)

// Creating a new txObjectMap
m := newTxObjectMap()

// Filling the map with transactions
m.Fill([]*txObject{txObj1, txObj2})

// Asserting the length of the map
assert.Equal(t, 2, m.Len(), "Map should contain only 2 unique transactions")

// Asserting the transactions are correctly added
assert.True(t, m.ContainsHash(txObj1.Hash()), "Map should contain txObj1")
assert.True(t, m.ContainsHash(txObj2.Hash()), "Map should contain txObj2")

// Asserting duplicate handling
assert.Equal(t, m.GetByID(txObj1.ID()), txObj1, "Duplicate tx1 should not be added again")
assert.Equal(t, m.GetByID(txObj2.ID()), txObj2, "txObj2 should be retrievable by ID")
}

func TestTxObjMap(t *testing.T) {
db := muxdb.NewMem()
repo := newChainRepo(db)
Expand Down
50 changes: 42 additions & 8 deletions txpool/tx_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,47 @@ func newDelegatedTx(chainTag byte, clauses []*tx.Clause, gas uint64, blockRef tx
return tx.WithSignature(sig)
}

func SetupTest() (genesis.DevAccount, *chain.Repository, *block.Block, *state.State) {
acc := genesis.DevAccounts()[0]

db := muxdb.NewMem()
repo := newChainRepo(db)
b0 := repo.GenesisBlock()
b1 := new(block.Builder).ParentID(b0.Header().ID()).GasLimit(10000000).TotalScore(100).Build()
repo.AddBlock(b1, nil, 0)
st := state.New(db, repo.GenesisBlock().Header().StateRoot(), 0, 0, 0)

return acc, repo, b1, st
}

func TestExecutableWithError(t *testing.T) {
acc, repo, b1, st := SetupTest()

tests := []struct {
tx *tx.Transaction
expected bool
expectedErr string
}{
{newTx(0, nil, 21000, tx.BlockRef{0}, 100, nil, tx.Features(0), acc), false, ""},
}

for _, tt := range tests {
txObj, err := resolveTx(tt.tx, false)
assert.Nil(t, err)

// pass custom headID
chain := repo.NewChain(thor.Bytes32{0})

exe, err := txObj.Executable(chain, st, b1.Header())
if tt.expectedErr != "" {
assert.Equal(t, tt.expectedErr, err.Error())
} else {
assert.Equal(t, err.Error(), "leveldb: not found")
assert.Equal(t, tt.expected, exe)
}
}
}

func TestSort(t *testing.T) {
objs := []*txObject{
{overallGasPrice: big.NewInt(10)},
Expand All @@ -99,14 +140,7 @@ func TestResolve(t *testing.T) {
}

func TestExecutable(t *testing.T) {
acc := genesis.DevAccounts()[0]

db := muxdb.NewMem()
repo := newChainRepo(db)
b0 := repo.GenesisBlock()
b1 := new(block.Builder).ParentID(b0.Header().ID()).GasLimit(10000000).TotalScore(100).Build()
repo.AddBlock(b1, nil, 0)
st := state.New(db, repo.GenesisBlock().Header().StateRoot(), 0, 0, 0)
acc, repo, b1, st := SetupTest()

tests := []struct {
tx *tx.Transaction
Expand Down
Loading

0 comments on commit ef71fc0

Please sign in to comment.