From 01b05fde607927a64443f33d12207f0d5a1e70c7 Mon Sep 17 00:00:00 2001 From: David Hill Date: Mon, 17 Oct 2022 21:27:56 -0400 Subject: [PATCH] rpctest: Use context provided by the user --- internal/rpcserver/rpcserver_test.go | 4 +- internal/rpcserver/treasury_test.go | 11 +++--- rpctest/memwallet.go | 22 +++++------ rpctest/rpc_harness.go | 15 ++++--- rpctest/rpc_harness_test.go | 58 ++++++++++++++-------------- rpctest/utils.go | 15 +++---- rpctest/votingwallet.go | 2 +- rpctest/votingwallet_test.go | 8 ++-- 8 files changed, 66 insertions(+), 69 deletions(-) diff --git a/internal/rpcserver/rpcserver_test.go b/internal/rpcserver/rpcserver_test.go index 7f5f350966..a32c13b573 100644 --- a/internal/rpcserver/rpcserver_test.go +++ b/internal/rpcserver/rpcserver_test.go @@ -111,7 +111,8 @@ func TestRpcServer(t *testing.T) { // Initialize the primary mining node with a chain of length 125, // providing 25 mature coinbases to allow spending from for testing // purposes. - if err := harness.SetUp(true, 25); err != nil { + ctx := context.Background() + if err := harness.SetUp(ctx, true, 25); err != nil { // Even though the harness was not fully setup, it still needs // to be torn down to ensure all resources such as temp // directories are cleaned up. The error is intentionally @@ -163,7 +164,6 @@ func TestRpcServer(t *testing.T) { }, } - ctx := context.Background() for _, test := range tests { test.f(ctx, harness, t) t.Logf("=== Running test: %v ===", test.name) diff --git a/internal/rpcserver/treasury_test.go b/internal/rpcserver/treasury_test.go index 45683accb5..9d355eb604 100644 --- a/internal/rpcserver/treasury_test.go +++ b/internal/rpcserver/treasury_test.go @@ -234,7 +234,11 @@ func TestTreasury(t *testing.T) { if err != nil { t.Fatal(err) } - err = hn.SetUp(false, 0) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err = hn.SetUp(ctx, false, 0) if err != nil { t.Fatal(err) } @@ -244,9 +248,6 @@ func TestTreasury(t *testing.T) { t.Fatal(err) } - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - // Create the voting wallet. vw, err := rpctest.NewVotingWallet(ctx, hn) if err != nil { @@ -288,7 +289,7 @@ func TestTreasury(t *testing.T) { taddPrevOuts := make([]*wire.OutPoint, nbTAddPrevOuts) for i := 0; i < nbTAddPrevOuts; i++ { txOut := newTxOut(int64(taddInAmt), p2pkhScriptVer, p2pkhScript) - txHash, err := hn.SendOutputs([]*wire.TxOut{txOut}, defaultFeeRate) + txHash, err := hn.SendOutputs(ctx, []*wire.TxOut{txOut}, defaultFeeRate) if err != nil { t.Fatal(err) } diff --git a/rpctest/memwallet.go b/rpctest/memwallet.go index fd940a9a7d..80a8e27d16 100644 --- a/rpctest/memwallet.go +++ b/rpctest/memwallet.go @@ -357,7 +357,7 @@ func (m *memWallet) UnwindBlock(header []byte) { // newAddress returns a new address from the wallet's hd key chain. It also // loads the address into the RPC client's transaction filter to ensure any // transactions that involve it are delivered via the notifications. -func (m *memWallet) newAddress() (stdaddr.Address, error) { +func (m *memWallet) newAddress(ctx context.Context) (stdaddr.Address, error) { tracef(m.t, "memwallet.newAddress") defer tracef(m.t, "memwallet.newAddress exit") @@ -377,7 +377,7 @@ func (m *memWallet) newAddress() (stdaddr.Address, error) { return nil, err } - err = m.rpc.LoadTxFilter(context.Background(), false, + err = m.rpc.LoadTxFilter(ctx, false, []stdaddr.Address{addr}, nil) if err != nil { return nil, err @@ -393,11 +393,11 @@ func (m *memWallet) newAddress() (stdaddr.Address, error) { // NewAddress returns a fresh address spendable by the wallet. // // This function is safe for concurrent access. -func (m *memWallet) NewAddress() (stdaddr.Address, error) { +func (m *memWallet) NewAddress(ctx context.Context) (stdaddr.Address, error) { m.Lock() defer m.Unlock() - return m.newAddress() + return m.newAddress(ctx) } // fundTx attempts to fund a transaction sending amt coins. The coins are @@ -406,7 +406,7 @@ func (m *memWallet) NewAddress() (stdaddr.Address, error) { // atoms-per-byte. // // NOTE: The memWallet's mutex must be held when this function is called. -func (m *memWallet) fundTx(tx *wire.MsgTx, amt dcrutil.Amount, feeRate dcrutil.Amount) error { +func (m *memWallet) fundTx(ctx context.Context, tx *wire.MsgTx, amt dcrutil.Amount, feeRate dcrutil.Amount) error { tracef(m.t, "memwallet.fundTx") defer tracef(m.t, "memwallet.fundTx exit") @@ -449,7 +449,7 @@ func (m *memWallet) fundTx(tx *wire.MsgTx, amt dcrutil.Amount, feeRate dcrutil.A // output to the transaction reserved for change. changeVal := amtSelected - amt - reqFee if changeVal > 0 { - addr, err := m.newAddress() + addr, err := m.newAddress(ctx) if err != nil { return err } @@ -473,16 +473,16 @@ func (m *memWallet) fundTx(tx *wire.MsgTx, amt dcrutil.Amount, feeRate dcrutil.A // SendOutputs creates, then sends a transaction paying to the specified output // while observing the passed fee rate. The passed fee rate should be expressed // in atoms-per-byte. -func (m *memWallet) SendOutputs(outputs []*wire.TxOut, feeRate dcrutil.Amount) (*chainhash.Hash, error) { +func (m *memWallet) SendOutputs(ctx context.Context, outputs []*wire.TxOut, feeRate dcrutil.Amount) (*chainhash.Hash, error) { tracef(m.t, "memwallet.SendOutputs") defer tracef(m.t, "memwallet.SendOutputs exit") - tx, err := m.CreateTransaction(outputs, feeRate) + tx, err := m.CreateTransaction(ctx, outputs, feeRate) if err != nil { return nil, err } - return m.rpc.SendRawTransaction(context.Background(), tx, true) + return m.rpc.SendRawTransaction(ctx, tx, true) } // CreateTransaction returns a fully signed transaction paying to the specified @@ -490,7 +490,7 @@ func (m *memWallet) SendOutputs(outputs []*wire.TxOut, feeRate dcrutil.Amount) ( // expressed in atoms-per-byte. // // This function is safe for concurrent access. -func (m *memWallet) CreateTransaction(outputs []*wire.TxOut, feeRate dcrutil.Amount) (*wire.MsgTx, error) { +func (m *memWallet) CreateTransaction(ctx context.Context, outputs []*wire.TxOut, feeRate dcrutil.Amount) (*wire.MsgTx, error) { tracef(m.t, "memwallet.CreateTransaction") defer tracef(m.t, "memwallet.CreateTransaction exit") @@ -508,7 +508,7 @@ func (m *memWallet) CreateTransaction(outputs []*wire.TxOut, feeRate dcrutil.Amo } // Attempt to fund the transaction with spendable utxos. - if err := m.fundTx(tx, outputAmt, feeRate); err != nil { + if err := m.fundTx(ctx, tx, outputAmt, feeRate); err != nil { return nil, err } diff --git a/rpctest/rpc_harness.go b/rpctest/rpc_harness.go index 2c0f3ba167..9535d2aab0 100644 --- a/rpctest/rpc_harness.go +++ b/rpctest/rpc_harness.go @@ -239,7 +239,7 @@ func New(t *testing.T, activeNet *chaincfg.Params, handlers *rpcclient.Notificat // // NOTE: This method and TearDown should always be called from the same // goroutine as they are not concurrent safe. -func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error { +func (h *Harness) SetUp(ctx context.Context, createTestChain bool, numMatureOutputs uint32) error { // Start the dcrd node itself. This spawns a new process which will be // managed if err := h.node.start(); err != nil { @@ -248,7 +248,6 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error { if err := h.connectRPCClient(); err != nil { return err } - ctx := context.Background() h.wallet.Start() // Filter transactions that pay to the coinbase associated with the @@ -361,8 +360,8 @@ func (h *Harness) connectRPCClient() error { // wallet. // // This function is safe for concurrent access. -func (h *Harness) NewAddress() (stdaddr.Address, error) { - return h.wallet.NewAddress() +func (h *Harness) NewAddress(ctx context.Context) (stdaddr.Address, error) { + return h.wallet.NewAddress(ctx) } // ConfirmedBalance returns the confirmed balance of the Harness' internal @@ -378,8 +377,8 @@ func (h *Harness) ConfirmedBalance() dcrutil.Amount { // according to targetOutputs. // // This function is safe for concurrent access. -func (h *Harness) SendOutputs(targetOutputs []*wire.TxOut, feeRate dcrutil.Amount) (*chainhash.Hash, error) { - return h.wallet.SendOutputs(targetOutputs, feeRate) +func (h *Harness) SendOutputs(ctx context.Context, targetOutputs []*wire.TxOut, feeRate dcrutil.Amount) (*chainhash.Hash, error) { + return h.wallet.SendOutputs(ctx, targetOutputs, feeRate) } // CreateTransaction returns a fully signed transaction paying to the specified @@ -392,8 +391,8 @@ func (h *Harness) SendOutputs(targetOutputs []*wire.TxOut, feeRate dcrutil.Amoun // returned to the pool of spendable outputs. // // This function is safe for concurrent access. -func (h *Harness) CreateTransaction(targetOutputs []*wire.TxOut, feeRate dcrutil.Amount) (*wire.MsgTx, error) { - return h.wallet.CreateTransaction(targetOutputs, feeRate) +func (h *Harness) CreateTransaction(ctx context.Context, targetOutputs []*wire.TxOut, feeRate dcrutil.Amount) (*wire.MsgTx, error) { + return h.wallet.CreateTransaction(ctx, targetOutputs, feeRate) } // UnlockOutputs unlocks any outputs which were previously marked as diff --git a/rpctest/rpc_harness_test.go b/rpctest/rpc_harness_test.go index f6ed9f65a7..e32269606f 100644 --- a/rpctest/rpc_harness_test.go +++ b/rpctest/rpc_harness_test.go @@ -33,7 +33,7 @@ func testSendOutputs(ctx context.Context, r *Harness, t *testing.T) { genSpend := func(amt dcrutil.Amount) *chainhash.Hash { // Grab a fresh address from the wallet. - addr, err := r.NewAddress() + addr, err := r.NewAddress(ctx) if err != nil { t.Fatalf("unable to get new address: %v", err) } @@ -42,7 +42,7 @@ func testSendOutputs(ctx context.Context, r *Harness, t *testing.T) { // mature coinbase outputs. addrScriptVer, addrScript := addr.PaymentScript() output := newTxOut(int64(amt), addrScriptVer, addrScript) - txid, err := r.SendOutputs([]*wire.TxOut{output}, 10) + txid, err := r.SendOutputs(ctx, []*wire.TxOut{output}, 10) if err != nil { t.Fatalf("coinbase spend failed: %v", err) } @@ -137,7 +137,7 @@ func testConnectNode(ctx context.Context, r *Harness, t *testing.T) { if err != nil { t.Fatal(err) } - if err := harness.SetUp(false, 0); err != nil { + if err := harness.SetUp(ctx, false, 0); err != nil { t.Fatalf("unable to complete rpctest setup: %v", err) } defer func() { @@ -147,7 +147,7 @@ func testConnectNode(ctx context.Context, r *Harness, t *testing.T) { // Establish a p2p connection from our new local harness to the main // harness. - if err := ConnectNode(harness, r); err != nil { + if err := ConnectNode(ctx, harness, r); err != nil { t.Fatalf("unable to connect local to main harness: %v", err) } @@ -188,14 +188,14 @@ func testDisconnectNode(ctx context.Context, r *Harness, t *testing.T) { if err != nil { t.Fatal(err) } - if err := harness.SetUp(false, 0); err != nil { + if err := harness.SetUp(ctx, false, 0); err != nil { t.Fatalf("unable to complete rpctest setup: %v", err) } defer harness.TearDown() // Establish a p2p connection from our new local harness to the main // harness. - if err := ConnectNode(harness, r); err != nil { + if err := ConnectNode(ctx, harness, r); err != nil { t.Fatalf("unable to connect local to main harness: %v", err) } @@ -211,7 +211,7 @@ func testDisconnectNode(ctx context.Context, r *Harness, t *testing.T) { // Re-connect the nodes. We'll perform the test in the reverse direction now // and assert that the nodes remain connected and that RemoveNode() fails. - if err := ConnectNode(harness, r); err != nil { + if err := ConnectNode(ctx, harness, r); err != nil { t.Fatalf("unable to connect local to main harness: %v", err) } @@ -238,14 +238,14 @@ func testNodesConnected(ctx context.Context, r *Harness, t *testing.T) { if err != nil { t.Fatal(err) } - if err := harness.SetUp(false, 0); err != nil { + if err := harness.SetUp(ctx, false, 0); err != nil { t.Fatalf("unable to complete rpctest setup: %v", err) } defer harness.TearDown() // Establish a p2p connection from our new local harness to the main // harness. - if err := ConnectNode(harness, r); err != nil { + if err := ConnectNode(ctx, harness, r); err != nil { t.Fatalf("unable to connect local to main harness: %v", err) } @@ -372,7 +372,7 @@ func testJoinMempools(ctx context.Context, r *Harness, t *testing.T) { if err != nil { t.Fatal(err) } - if err := harness.SetUp(false, 0); err != nil { + if err := harness.SetUp(ctx, false, 0); err != nil { t.Fatalf("unable to complete rpctest setup: %v", err) } defer harness.TearDown() @@ -381,13 +381,13 @@ func testJoinMempools(ctx context.Context, r *Harness, t *testing.T) { // Both mempools should be considered synced as they are empty. // Therefore, this should return instantly. - if err := JoinNodes(nodeSlice, Mempools); err != nil { + if err := JoinNodes(ctx, nodeSlice, Mempools); err != nil { t.Fatalf("unable to join node on mempools: %v", err) } // Generate a coinbase spend to a new address within the main harness' // mempool. - addr, err := r.NewAddress() + addr, err := r.NewAddress(ctx) if err != nil { t.Fatalf("unable to get new address: %v", err) } @@ -396,7 +396,7 @@ func testJoinMempools(ctx context.Context, r *Harness, t *testing.T) { t.Fatalf("unable to generate pkscript to addr: %v", err) } output := newTxOut(5e8, addrScriptVer, addrScript) - testTx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) + testTx, err := r.CreateTransaction(ctx, []*wire.TxOut{output}, 10) if err != nil { t.Fatalf("coinbase spend failed: %v", err) } @@ -436,7 +436,7 @@ func testJoinMempools(ctx context.Context, r *Harness, t *testing.T) { // should be blocked on the JoinNodes call. poolsSynced := make(chan error) go func() { - if err := JoinNodes(nodeSlice, Mempools); err != nil { + if err := JoinNodes(ctx, nodeSlice, Mempools); err != nil { err = fmt.Errorf("unable to join node on mempools: %w", err) poolsSynced <- err return @@ -454,10 +454,10 @@ func testJoinMempools(ctx context.Context, r *Harness, t *testing.T) { // Establish an outbound connection from the local harness to the main // harness and wait for the chains to be synced. - if err := ConnectNode(harness, r); err != nil { + if err := ConnectNode(ctx, harness, r); err != nil { t.Fatalf("unable to connect harnesses: %v", err) } - if err := JoinNodes(nodeSlice, Blocks); err != nil { + if err := JoinNodes(ctx, nodeSlice, Blocks); err != nil { t.Fatalf("unable to join node on blocks: %v", err) } @@ -481,7 +481,7 @@ func testJoinMempools(ctx context.Context, r *Harness, t *testing.T) { } } -func testJoinBlocks(_ context.Context, r *Harness, t *testing.T) { +func testJoinBlocks(ctx context.Context, r *Harness, t *testing.T) { tracef(t, "testJoinBlocks start") defer tracef(t, "testJoinBlocks end") @@ -491,7 +491,7 @@ func testJoinBlocks(_ context.Context, r *Harness, t *testing.T) { if err != nil { t.Fatal(err) } - if err := harness.SetUp(false, 0); err != nil { + if err := harness.SetUp(ctx, false, 0); err != nil { t.Fatalf("unable to complete rpctest setup: %v", err) } defer harness.TearDown() @@ -499,7 +499,7 @@ func testJoinBlocks(_ context.Context, r *Harness, t *testing.T) { nodeSlice := []*Harness{r, harness} blocksSynced := make(chan error) go func() { - if err := JoinNodes(nodeSlice, Blocks); err != nil { + if err := JoinNodes(ctx, nodeSlice, Blocks); err != nil { blocksSynced <- fmt.Errorf("unable to join node on blocks: %w", err) return } @@ -519,7 +519,7 @@ func testJoinBlocks(_ context.Context, r *Harness, t *testing.T) { // Connect the local harness to the main harness which will sync the // chains. - if err := ConnectNode(harness, r); err != nil { + if err := ConnectNode(ctx, harness, r); err != nil { t.Fatalf("unable to connect harnesses: %v", err) } @@ -537,7 +537,7 @@ func testJoinBlocks(_ context.Context, r *Harness, t *testing.T) { } } -func testMemWalletReorg(_ context.Context, r *Harness, t *testing.T) { +func testMemWalletReorg(ctx context.Context, r *Harness, t *testing.T) { tracef(t, "testMemWalletReorg start") defer tracef(t, "testMemWalletReorg end") @@ -547,7 +547,7 @@ func testMemWalletReorg(_ context.Context, r *Harness, t *testing.T) { if err != nil { t.Fatal(err) } - if err := harness.SetUp(true, 5); err != nil { + if err := harness.SetUp(ctx, true, 5); err != nil { t.Fatalf("unable to complete rpctest setup: %v", err) } defer harness.TearDown() @@ -562,11 +562,11 @@ func testMemWalletReorg(_ context.Context, r *Harness, t *testing.T) { // Now connect this local harness to the main harness then wait for // their chains to synchronize. - if err := ConnectNode(harness, r); err != nil { + if err := ConnectNode(ctx, harness, r); err != nil { t.Fatalf("unable to connect harnesses: %v", err) } nodeSlice := []*Harness{r, harness} - if err := JoinNodes(nodeSlice, Blocks); err != nil { + if err := JoinNodes(ctx, nodeSlice, Blocks); err != nil { t.Fatalf("unable to join node on blocks: %v", err) } @@ -581,7 +581,7 @@ func testMemWalletReorg(_ context.Context, r *Harness, t *testing.T) { } } -func testMemWalletLockedOutputs(_ context.Context, r *Harness, t *testing.T) { +func testMemWalletLockedOutputs(ctx context.Context, r *Harness, t *testing.T) { tracef(t, "testMemWalletLockedOutputs start") defer tracef(t, "testMemWalletLockedOutputs end") @@ -589,14 +589,14 @@ func testMemWalletLockedOutputs(_ context.Context, r *Harness, t *testing.T) { startingBalance := r.ConfirmedBalance() // First, create a signed transaction spending some outputs. - addr, err := r.NewAddress() + addr, err := r.NewAddress(ctx) if err != nil { t.Fatalf("unable to generate new address: %v", err) } pkScriptVer, pkScript := addr.PaymentScript() outputAmt := dcrutil.Amount(50 * dcrutil.AtomsPerCoin) output := newTxOut(int64(outputAmt), pkScriptVer, pkScript) - tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) + tx, err := r.CreateTransaction(ctx, []*wire.TxOut{output}, 10) if err != nil { t.Fatalf("unable to create transaction: %v", err) } @@ -629,7 +629,8 @@ func TestHarness(t *testing.T) { // Initialize the main mining node with a chain of length 42, providing // 25 mature coinbases to allow spending from for testing purposes. - if err = mainHarness.SetUp(true, numMatureOutputs); err != nil { + ctx := context.Background() + if err = mainHarness.SetUp(ctx, true, numMatureOutputs); err != nil { // Even though the harness was not fully setup, it still needs // to be torn down to ensure all resources such as temp // directories are cleaned up. The error is intentionally @@ -661,7 +662,6 @@ func TestHarness(t *testing.T) { // Current tip should be at a height of numMatureOutputs plus the // required number of blocks for coinbase maturity plus an additional // block for the premine block. - ctx := context.Background() nodeInfo, err := mainHarness.Node.GetInfo(ctx) if err != nil { t.Fatalf("unable to execute getinfo on node: %v", err) diff --git a/rpctest/utils.go b/rpctest/utils.go index d8b5ab1d9a..bb1c347071 100644 --- a/rpctest/utils.go +++ b/rpctest/utils.go @@ -38,19 +38,18 @@ const ( // passed JoinType. This function be used to ensure all active test // harnesses are at a consistent state before proceeding to an assertion or // check within rpc tests. -func JoinNodes(nodes []*Harness, joinType JoinType) error { +func JoinNodes(ctx context.Context, nodes []*Harness, joinType JoinType) error { switch joinType { case Blocks: - return syncBlocks(nodes) + return syncBlocks(ctx, nodes) case Mempools: - return syncMempools(nodes) + return syncMempools(ctx, nodes) } return nil } // syncMempools blocks until all nodes have identical mempools. -func syncMempools(nodes []*Harness) error { - ctx := context.Background() +func syncMempools(ctx context.Context, nodes []*Harness) error { poolsMatch := false for !poolsMatch { @@ -82,9 +81,8 @@ func syncMempools(nodes []*Harness) error { } // syncBlocks blocks until all nodes report the same block height. -func syncBlocks(nodes []*Harness) error { +func syncBlocks(ctx context.Context, nodes []*Harness) error { blocksMatch := false - ctx := context.Background() for !blocksMatch { retry: @@ -113,11 +111,10 @@ func syncBlocks(nodes []*Harness) error { // harness and the "to" harness. The connection made is flagged as persistent, // therefore in the case of disconnects, "from" will attempt to reestablish a // connection to the "to" harness. -func ConnectNode(from *Harness, to *Harness) error { +func ConnectNode(ctx context.Context, from *Harness, to *Harness) error { tracef(from.t, "ConnectNode start") defer tracef(from.t, "ConnectNode end") - ctx := context.Background() peerInfo, err := from.Node.GetPeerInfo(ctx) if err != nil { return err diff --git a/rpctest/votingwallet.go b/rpctest/votingwallet.go index 8071ae9864..7b19544e20 100644 --- a/rpctest/votingwallet.go +++ b/rpctest/votingwallet.go @@ -246,7 +246,7 @@ func (w *VotingWallet) Start(ctx context.Context) error { outputs[i] = wire.NewTxOut(value, w.p2pkh) } - txid, err := w.hn.SendOutputs(outputs, feeRate) + txid, err := w.hn.SendOutputs(ctx, outputs, feeRate) if err != nil { return fmt.Errorf("unable to fund voting wallet: %v", err) } diff --git a/rpctest/votingwallet_test.go b/rpctest/votingwallet_test.go index 36bb145145..b8cd68b9d2 100644 --- a/rpctest/votingwallet_test.go +++ b/rpctest/votingwallet_test.go @@ -88,7 +88,10 @@ func TestMinimalVotingWallet(t *testing.T) { t.Fatal(err) } - err = hn.SetUp(true, 8) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err = hn.SetUp(ctx, true, 8) if err != nil { t.Fatal(err) } @@ -106,9 +109,6 @@ func TestMinimalVotingWallet(t *testing.T) { }, } - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - for _, tc := range testCases { var vw *VotingWallet success := t.Run(tc.name, func(t1 *testing.T) {