-
Notifications
You must be signed in to change notification settings - Fork 237
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update relayTransactions unit tests. (#1623)
* [NOD-1344] relaytransactions: simple unit tests * [NOD-1344] Add mid-complexity unit tests for relaytransactions * Improve TestHandleRelayedTransactionssub tests * Improve TestHandleRequestedTransactions sub tests * [NOD-1344] Fix Simple call test * [NOD-1344] Fix tests after redesign * Divide transactionrelay_test.go to 2 separated tests and updates the tests. * Changes due to review:change the test files name and the test function names, adds new comments and fix typo. * Delete an unnecessary comparison to True in the if statement condition. * Update the branch to v0.11.0-dev. Co-authored-by: karim1king <[email protected]> Co-authored-by: tal <[email protected]> Co-authored-by: Svarog <[email protected]>
- Loading branch information
1 parent
fa16c30
commit ab89efe
Showing
2 changed files
with
277 additions
and
0 deletions.
There are no files selected for viewing
189 changes: 189 additions & 0 deletions
189
app/protocol/flows/transactionrelay/handle_relayed_transactions_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
package transactionrelay_test | ||
|
||
import ( | ||
"errors" | ||
"github.com/kaspanet/kaspad/app/protocol/flows/transactionrelay" | ||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors" | ||
"github.com/kaspanet/kaspad/domain" | ||
"github.com/kaspanet/kaspad/domain/consensus" | ||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" | ||
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils" | ||
"github.com/kaspanet/kaspad/infrastructure/logger" | ||
"github.com/kaspanet/kaspad/util/panics" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/kaspanet/kaspad/app/appmessage" | ||
"github.com/kaspanet/kaspad/infrastructure/config" | ||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter" | ||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" | ||
) | ||
|
||
type mocTransactionsRelayContext struct { | ||
netAdapter *netadapter.NetAdapter | ||
domain domain.Domain | ||
sharedRequestedTransactions *transactionrelay.SharedRequestedTransactions | ||
} | ||
|
||
func (m *mocTransactionsRelayContext) NetAdapter() *netadapter.NetAdapter { | ||
return m.netAdapter | ||
} | ||
|
||
func (m *mocTransactionsRelayContext) Domain() domain.Domain { | ||
return m.domain | ||
} | ||
|
||
func (m *mocTransactionsRelayContext) SharedRequestedTransactions() *transactionrelay.SharedRequestedTransactions { | ||
return m.sharedRequestedTransactions | ||
} | ||
|
||
func (m *mocTransactionsRelayContext) Broadcast(appmessage.Message) error { | ||
return nil | ||
} | ||
|
||
func (m *mocTransactionsRelayContext) OnTransactionAddedToMempool() { | ||
} | ||
|
||
// TestHandleRelayedTransactionsNotFound tests the flow of HandleRelayedTransactions when the peer doesn't | ||
// have the requested transactions in the mempool. | ||
func TestHandleRelayedTransactionsNotFound(t *testing.T) { | ||
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { | ||
|
||
var log = logger.RegisterSubSystem("PROT") | ||
var spawn = panics.GoroutineWrapperFunc(log) | ||
factory := consensus.NewFactory() | ||
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestHandleRelayedTransactionsNotFound") | ||
if err != nil { | ||
t.Fatalf("Error setting up test consensus: %+v", err) | ||
} | ||
defer teardown(false) | ||
|
||
sharedRequestedTransactions := transactionrelay.NewSharedRequestedTransactions() | ||
adapter, err := netadapter.NewNetAdapter(config.DefaultConfig()) | ||
if err != nil { | ||
t.Fatalf("Failed to create a NetAdapter: %v", err) | ||
} | ||
domainInstance, err := domain.New(consensusConfig, tc.Database()) | ||
if err != nil { | ||
t.Fatalf("Failed to set up a domain instance: %v", err) | ||
} | ||
context := &mocTransactionsRelayContext{ | ||
netAdapter: adapter, | ||
domain: domainInstance, | ||
sharedRequestedTransactions: sharedRequestedTransactions, | ||
} | ||
incomingRoute := router.NewRoute() | ||
defer incomingRoute.Close() | ||
peerIncomingRoute := router.NewRoute() | ||
defer peerIncomingRoute.Close() | ||
|
||
txID1 := externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}) | ||
txID2 := externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}) | ||
txIDs := []*externalapi.DomainTransactionID{txID1, txID2} | ||
invMessage := appmessage.NewMsgInvTransaction(txIDs) | ||
err = incomingRoute.Enqueue(invMessage) | ||
if err != nil { | ||
t.Fatalf("Unexpected error from incomingRoute.Enqueue: %v", err) | ||
} | ||
// The goroutine is representing the peer's actions. | ||
spawn("peerResponseToTheTransactionsRequest", func() { | ||
msg, err := peerIncomingRoute.Dequeue() | ||
if err != nil { | ||
t.Fatalf("Dequeue: %v", err) | ||
} | ||
inv := msg.(*appmessage.MsgRequestTransactions) | ||
|
||
if len(txIDs) != len(inv.IDs) { | ||
t.Fatalf("TestHandleRelayedTransactions: expected %d transactions ID, but got %d", len(txIDs), len(inv.IDs)) | ||
} | ||
|
||
for i, id := range inv.IDs { | ||
if txIDs[i].String() != id.String() { | ||
t.Fatalf("TestHandleRelayedTransactions: expected equal txID: expected %s, but got %s", txIDs[i].String(), id.String()) | ||
} | ||
err = incomingRoute.Enqueue(appmessage.NewMsgTransactionNotFound(txIDs[i])) | ||
if err != nil { | ||
t.Fatalf("Unexpected error from incomingRoute.Enqueue: %v", err) | ||
} | ||
} | ||
// Insert an unexpected message type to stop the infinity loop. | ||
err = incomingRoute.Enqueue(&appmessage.MsgAddresses{}) | ||
if err != nil { | ||
t.Fatalf("Unexpected error from incomingRoute.Enqueue: %v", err) | ||
} | ||
}) | ||
|
||
err = transactionrelay.HandleRelayedTransactions(context, incomingRoute, peerIncomingRoute) | ||
// Since we inserted an unexpected message type to stop the infinity loop, | ||
// we expect the error will be infected from this specific message and also the | ||
// error will count as a protocol message. | ||
if protocolErr := (protocolerrors.ProtocolError{}); err == nil || !errors.As(err, &protocolErr) { | ||
t.Fatalf("Expected to protocol error") | ||
} else { | ||
if !protocolErr.ShouldBan { | ||
t.Fatalf("Exepcted shouldBan true, but got false.") | ||
} | ||
if !strings.Contains(err.Error(), "unexpected Addresses [code 3] message in the block relay flow while expecting an inv message") { | ||
t.Fatalf("Unexpected error: expected: an error due to existence of an Addresses message "+ | ||
"in the block relay flow, but got: %v", protocolErr.Cause) | ||
} | ||
} | ||
}) | ||
} | ||
|
||
// TestOnClosedIncomingRoute verifies that an appropriate error message will be returned when | ||
// trying to dequeue a message from a closed route. | ||
func TestOnClosedIncomingRoute(t *testing.T) { | ||
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { | ||
|
||
factory := consensus.NewFactory() | ||
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestOnClosedIncomingRoute") | ||
if err != nil { | ||
t.Fatalf("Error setting up test consensus: %+v", err) | ||
} | ||
defer teardown(false) | ||
|
||
sharedRequestedTransactions := transactionrelay.NewSharedRequestedTransactions() | ||
adapter, err := netadapter.NewNetAdapter(config.DefaultConfig()) | ||
if err != nil { | ||
t.Fatalf("Failed to creat a NetAdapter : %v", err) | ||
} | ||
domainInstance, err := domain.New(consensusConfig, tc.Database()) | ||
if err != nil { | ||
t.Fatalf("Failed to set up a domain instance: %v", err) | ||
} | ||
context := &mocTransactionsRelayContext{ | ||
netAdapter: adapter, | ||
domain: domainInstance, | ||
sharedRequestedTransactions: sharedRequestedTransactions, | ||
} | ||
incomingRoute := router.NewRoute() | ||
outgoingRoute := router.NewRoute() | ||
defer outgoingRoute.Close() | ||
|
||
txID := externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}) | ||
txIDs := []*externalapi.DomainTransactionID{txID} | ||
|
||
err = incomingRoute.Enqueue(&appmessage.MsgInvTransaction{TxIDs: txIDs}) | ||
if err != nil { | ||
t.Fatalf("Unexpected error from incomingRoute.Enqueue: %v", err) | ||
} | ||
incomingRoute.Close() | ||
err = transactionrelay.HandleRelayedTransactions(context, incomingRoute, outgoingRoute) | ||
if err == nil || !errors.Is(err, router.ErrRouteClosed) { | ||
t.Fatalf("Unexpected error: expected: %v, got : %v", router.ErrRouteClosed, err) | ||
} | ||
}) | ||
} |
88 changes: 88 additions & 0 deletions
88
app/protocol/flows/transactionrelay/handle_requested_transactions_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package transactionrelay_test | ||
|
||
import ( | ||
"github.com/kaspanet/kaspad/app/appmessage" | ||
"github.com/kaspanet/kaspad/app/protocol/flows/transactionrelay" | ||
"github.com/kaspanet/kaspad/domain" | ||
"github.com/kaspanet/kaspad/domain/consensus" | ||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" | ||
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils" | ||
"github.com/kaspanet/kaspad/infrastructure/config" | ||
"github.com/kaspanet/kaspad/infrastructure/logger" | ||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter" | ||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" | ||
"github.com/kaspanet/kaspad/util/panics" | ||
"github.com/pkg/errors" | ||
"testing" | ||
) | ||
|
||
// TestHandleRequestedTransactionsNotFound tests the flow of HandleRequestedTransactions | ||
// when the requested transactions don't found in the mempool. | ||
func TestHandleRequestedTransactionsNotFound(t *testing.T) { | ||
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { | ||
var log = logger.RegisterSubSystem("PROT") | ||
var spawn = panics.GoroutineWrapperFunc(log) | ||
factory := consensus.NewFactory() | ||
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestHandleRequestedTransactionsNotFound") | ||
if err != nil { | ||
t.Fatalf("Error setting up test Consensus: %+v", err) | ||
} | ||
defer teardown(false) | ||
|
||
sharedRequestedTransactions := transactionrelay.NewSharedRequestedTransactions() | ||
adapter, err := netadapter.NewNetAdapter(config.DefaultConfig()) | ||
if err != nil { | ||
t.Fatalf("Failed to create a NetAdapter: %v", err) | ||
} | ||
domainInstance, err := domain.New(consensusConfig, tc.Database()) | ||
if err != nil { | ||
t.Fatalf("Failed to set up a domain Instance: %v", err) | ||
} | ||
context := &mocTransactionsRelayContext{ | ||
netAdapter: adapter, | ||
domain: domainInstance, | ||
sharedRequestedTransactions: sharedRequestedTransactions, | ||
} | ||
incomingRoute := router.NewRoute() | ||
outgoingRoute := router.NewRoute() | ||
defer outgoingRoute.Close() | ||
|
||
txID1 := externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}) | ||
txID2 := externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}) | ||
txIDs := []*externalapi.DomainTransactionID{txID1, txID2} | ||
msg := appmessage.NewMsgRequestTransactions(txIDs) | ||
err = incomingRoute.Enqueue(msg) | ||
if err != nil { | ||
t.Fatalf("Unexpected error from incomingRoute.Enqueue: %v", err) | ||
} | ||
// The goroutine is representing the peer's actions. | ||
spawn("peerResponseToTheTransactionsMessages", func() { | ||
for i, id := range txIDs { | ||
msg, err := outgoingRoute.Dequeue() | ||
if err != nil { | ||
t.Fatalf("Dequeue: %s", err) | ||
} | ||
outMsg := msg.(*appmessage.MsgTransactionNotFound) | ||
if txIDs[i].String() != outMsg.ID.String() { | ||
t.Fatalf("TestHandleRelayedTransactions: expected equal txID: expected %s, but got %s", txIDs[i].String(), id.String()) | ||
} | ||
} | ||
// Closed the incomingRoute for stop the infinity loop. | ||
incomingRoute.Close() | ||
}) | ||
|
||
err = transactionrelay.HandleRequestedTransactions(context, incomingRoute, outgoingRoute) | ||
// Make sure the error is due to the closed route. | ||
if err == nil || !errors.Is(err, router.ErrRouteClosed) { | ||
t.Fatalf("Unexpected error: expected: %v, got : %v", router.ErrRouteClosed, err) | ||
} | ||
}) | ||
} |