Skip to content

Conversation

@jnewbery
Copy link
Contributor

Continues #10082

TestNode is a class responsible for all state related to a bitcoind node
under test. It stores local state, is responsible for tracking the
bitcoind process and delegates unrecognised messages to the RPC
connection.

This commit changes start_nodes and stop_nodes to start and stop the
bitcoind nodes in parallel, making test setup and teardown much faster.

On my vm, this changeset reduces total test_runner runtime for the base set of tests
(including building the cache) from 263s to 195s (a 25% speedup). Note that the time
reported by test_runner does not include time spent building the cache:

with TestNode:

→ date +"%T" ; ./test_runner.py -q ; date +"%T"
12:48:04
..................................................................................................................................................................................................................................................................................................................................
TEST                           | STATUS    | DURATION

abandonconflict.py             | ✓ Passed  | 12 s
bip68-112-113-p2p.py           | ✓ Passed  | 19 s
blockchain.py                  | ✓ Passed  | 8 s 
bumpfee.py                     | ✓ Passed  | 13 s
decodescript.py                | ✓ Passed  | 3 s 
disablewallet.py               | ✓ Passed  | 3 s 
disconnect_ban.py              | ✓ Passed  | 6 s 
fundrawtransaction.py          | ✓ Passed  | 37 s
getchaintips.py                | ✓ Passed  | 4 s 
httpbasics.py                  | ✓ Passed  | 3 s 
import-rescan.py               | ✓ Passed  | 4 s 
importmulti.py                 | ✓ Passed  | 6 s 
importprunedfunds.py           | ✓ Passed  | 3 s 
invalidblockrequest.py         | ✓ Passed  | 4 s 
invalidtxrequest.py            | ✓ Passed  | 4 s 
keypool.py                     | ✓ Passed  | 7 s 
listsinceblock.py              | ✓ Passed  | 4 s 
listtransactions.py            | ✓ Passed  | 33 s
mempool_limit.py               | ✓ Passed  | 4 s 
mempool_persist.py             | ✓ Passed  | 15 s
mempool_reorg.py               | ✓ Passed  | 4 s 
mempool_resurrect_test.py      | ✓ Passed  | 3 s 
mempool_spendcoinbase.py       | ✓ Passed  | 3 s 
merkle_blocks.py               | ✓ Passed  | 3 s 
multi_rpc.py                   | ✓ Passed  | 4 s 
net.py                         | ✓ Passed  | 3 s 
nulldummy.py                   | ✓ Passed  | 3 s 
p2p-compactblocks.py           | ✓ Passed  | 28 s
p2p-fullblocktest.py           | ✓ Passed  | 126 s
p2p-leaktests.py               | ✓ Passed  | 8 s 
p2p-mempool.py                 | ✓ Passed  | 3 s 
p2p-segwit.py                  | ✓ Passed  | 59 s
p2p-versionbits-warning.py     | ✓ Passed  | 8 s 
preciousblock.py               | ✓ Passed  | 3 s 
prioritise_transaction.py      | ✓ Passed  | 5 s 
proxy_test.py                  | ✓ Passed  | 3 s 
rawtransactions.py             | ✓ Passed  | 9 s 
receivedby.py                  | ✓ Passed  | 19 s
reindex.py                     | ✓ Passed  | 12 s
rest.py                        | ✓ Passed  | 9 s 
rpcnamedargs.py                | ✓ Passed  | 3 s 
segwit.py                      | ✓ Passed  | 7 s 
sendheaders.py                 | ✓ Passed  | 24 s
signmessages.py                | ✓ Passed  | 3 s 
signrawtransactions.py         | ✓ Passed  | 3 s 
txn_clone.py                   | ✓ Passed  | 4 s 
txn_doublespend.py --mineblock | ✓ Passed  | 4 s 
uptime.py                      | ✓ Passed  | 3 s 
wallet-accounts.py             | ✓ Passed  | 3 s 
wallet-dump.py                 | ✓ Passed  | 7 s 
wallet-encryption.py           | ✓ Passed  | 8 s 
wallet-hd.py                   | ✓ Passed  | 15 s
wallet.py                      | ✓ Passed  | 31 s
walletbackup.py                | ✓ Passed  | 104 s
zapwallettxes.py               | ✓ Passed  | 9 s 
zmq_test.py                    | ○ Skipped | 0 s 

ALL                            | ✓ Passed  | 735 s (accumulated)
Runtime: 189 s

12:51:19

master:

→ date +"%T" ; ./test_runner.py -q ; date +"%T"
12:40:13
..........................................................................................................................................................................................................................................................................................................................................................................................................................................
TEST                           | STATUS    | DURATION

abandonconflict.py             | ✓ Passed  | 15 s
bip68-112-113-p2p.py           | ✓ Passed  | 19 s
blockchain.py                  | ✓ Passed  | 8 s
bumpfee.py                     | ✓ Passed  | 20 s
decodescript.py                | ✓ Passed  | 3 s
disablewallet.py               | ✓ Passed  | 3 s
disconnect_ban.py              | ✓ Passed  | 8 s
fundrawtransaction.py          | ✓ Passed  | 36 s
getchaintips.py                | ✓ Passed  | 11 s
httpbasics.py                  | ✓ Passed  | 7 s
import-rescan.py               | ✓ Passed  | 16 s
importmulti.py                 | ✓ Passed  | 10 s
importprunedfunds.py           | ✓ Passed  | 5 s
invalidblockrequest.py         | ✓ Passed  | 4 s
invalidtxrequest.py            | ✓ Passed  | 3 s
keypool.py                     | ✓ Passed  | 7 s
listsinceblock.py              | ✓ Passed  | 11 s
listtransactions.py            | ✓ Passed  | 37 s
mempool_limit.py               | ✓ Passed  | 4 s
mempool_persist.py             | ✓ Passed  | 23 s
mempool_reorg.py               | ✓ Passed  | 7 s
mempool_resurrect_test.py      | ✓ Passed  | 3 s
mempool_spendcoinbase.py       | ✓ Passed  | 3 s
merkle_blocks.py               | ✓ Passed  | 10 s
multi_rpc.py                   | ✓ Passed  | 6 s
net.py                         | ✓ Passed  | 6 s
nulldummy.py                   | ✓ Passed  | 3 s
p2p-compactblocks.py           | ✓ Passed  | 30 s
p2p-fullblocktest.py           | ✓ Passed  | 126 s
p2p-leaktests.py               | ✓ Passed  | 8 s
p2p-mempool.py                 | ✓ Passed  | 3 s
p2p-segwit.py                  | ✓ Passed  | 62 s
p2p-versionbits-warning.py     | ✓ Passed  | 8 s
preciousblock.py               | ✓ Passed  | 8 s
prioritise_transaction.py      | ✓ Passed  | 7 s
proxy_test.py                  | ✓ Passed  | 10 s
rawtransactions.py             | ✓ Passed  | 15 s
receivedby.py                  | ✓ Passed  | 28 s
reindex.py                     | ✓ Passed  | 12 s
rest.py                        | ✓ Passed  | 12 s
rpcnamedargs.py                | ✓ Passed  | 3 s
segwit.py                      | ✓ Passed  | 12 s
sendheaders.py                 | ✓ Passed  | 26 s
signmessages.py                | ✓ Passed  | 3 s
signrawtransactions.py         | ✓ Passed  | 3 s
txn_clone.py                   | ✓ Passed  | 10 s
txn_doublespend.py --mineblock | ✓ Passed  | 10 s
uptime.py                      | ✓ Passed  | 3 s
wallet-accounts.py             | ✓ Passed  | 3 s
wallet-dump.py                 | ✓ Passed  | 6 s
wallet-encryption.py           | ✓ Passed  | 8 s
wallet-hd.py                   | ✓ Passed  | 18 s
wallet.py                      | ✓ Passed  | 69 s
walletbackup.py                | ✓ Passed  | 130 s
zapwallettxes.py               | ✓ Passed  | 15 s
zmq_test.py                    | ○ Skipped | 0 s

ALL                            | ✓ Passed  | 936 s (accumulated)
Runtime: 242 s

12:44:36

@jnewbery
Copy link
Contributor Author

Wallet tests were failing on Travis because bitcoind startup was timing out. Increasing timeout from 2.5s to 10s for Travis.

@meshcollider
Copy link
Contributor

Concept ACK e538dbf, looks good but haven't tested or gone through thoroughly

@laanwj
Copy link
Member

laanwj commented Jul 10, 2017

The speed-up is nice, also like the idea of launching nodes in parallel. Concept ACK.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks. Removed

@jnewbery
Copy link
Contributor Author

fixed @jtimon's review comment and rebased.

@jnewbery jnewbery force-pushed the testnode2 branch 2 times, most recently from 16b9588 to 997680c Compare July 24, 2017 15:35
@jnewbery
Copy link
Contributor Author

rebased with TestNode changes for multiwallet.

@maflcko
Copy link
Member

maflcko commented Aug 8, 2017

Needs rebase

@jnewbery
Copy link
Contributor Author

jnewbery commented Aug 9, 2017

rebased

@MarcoFalke @kallewoof @jimmysong @NicolasDorier I'd love some review of this if any of you have time.

Copy link
Contributor

@jimmysong jimmysong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK. Couple of nits and one thing I don't get.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little harder to read than something like this:

for attempt in range(40):
    ...
    time.sleep(0.25)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. changed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for as e

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do? wallet_path is for sure a string, but how do you divide the rpc object by a string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By magic :)

Take a look at

def __truediv__(self, relative_uri):
and
def __truediv__(self, relative_uri):

The interface here is supposed to be similar to Python's pathlib

This functionality was added to support the multiwallet endpoints in 979d0b8 . Take a look at the multiwallet.py test to see how it's currently used.

@NicolasDorier
Copy link
Contributor

utACK 2d189c89f6ecdb846a046bdd57883e190df7b3bf I am a big fan of this idea, it makes writing tests so much easier.

Copy link
Contributor

@kallewoof kallewoof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK with one nit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not allow None for extra_args? I'm generally wary of passing in objects as defaults, as if those default objects are ever altered, the altered version will be passed as the default in future calls.

E.g. try the following snippet:

def foo(x=[]):
    x.append(5)
    print(x)

foo()
foo()
foo()

You will get as output

[5]
[5, 5]
[5, 5, 5]

Copy link
Contributor

@NicolasDorier NicolasDorier Aug 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow I did not know.

But even if it was not the case, I think that the user should be able to pass null (Nothing), when he means "default value".

This code can be easily fixed by keeping the default value to Nothing and first line, checking if extra_args is nothing, if that is the case, init extra_args to an empty array.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally didn't catch that, but I've run into this in the past and it's pretty nasty to debug unless you know to look for it. I agree with the others, put this back to None.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null in Python is None, so yeah, I think None should be the default here and just set it to [] if it's None at the start.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Thanks @kallewoof , I wasn't aware of that, but it makes perfect sense.

Changed the default argument to None as suggested.

@jnewbery jnewbery force-pushed the testnode2 branch 2 times, most recently from db74b1a to cb8579b Compare August 14, 2017 16:17
Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK cb8579b, but needs some nits and apparent regressions fixed.

w1 = self.nodes[0].get_wallet_rpc("w1")
w2 = self.nodes[0].get_wallet_rpc("w2")
w3 = self.nodes[0].get_wallet_rpc("w3")
wallet_bad = self.nodes[0].get_wallet_rpc("wallet/bad")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Should be get_wallet_rpc('bad') to qualify for refactor-only.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


def start(self):
"""Start the node."""
# import pdb; pdb.set_trace()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: debug artifact

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

return rpcs

if self.options.coveragedir is not None:
coverage.write_all_rpc_commands(self.options.coveragedir, node.rpc)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing for node in nodes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

assert not self.bitcoind_processes.values() # All connections must be gone now
for node in self.nodes:
node.stop_node()
# All connections must be gone now
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove outdated comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

self.rpc_connected = True
self.url = self.rpc.url
self.log.debug("RPC successfully started")
return True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: No need to return a value if it is never used. Can be replaced by a plain return.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

try:
for i in range(num_nodes):
rpcs.append(self.start_node(i, dirname, extra_args[i], rpchost, timewait=timewait, binary=binary[i]))
nodes.append(TestNode(i, dirname, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stderr must be set to not None. Otherwise, we will ignore any output to stderr, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same as the existing behaviour. start_nodes() currently calls start_node() without the stderr argument set, so it defaults to None.

This could be changed in a future PR.

TestNode is a class responsible for all state related to a bitcoind node
under test. It stores local state, is responsible for tracking the
bitcoind process and delegates unrecognised messages to the RPC
connection.

This commit changes start_nodes and stop_nodes to start and stop the
bitcoind nodes in parallel, making test setup and teardown much faster.
@jnewbery
Copy link
Contributor Author

Thanks for the review @MarcoFalke - I've addressed all your nits (except the stderr in start_nodes() which I think maintains existing behaviour).

I've updated and squashed the commits. Unsquashed history is here: https://github.com/jnewbery/bitcoin/tree/pr10711.1 if you just want to see what's changed.

@maflcko
Copy link
Member

maflcko commented Aug 15, 2017

re-utACK 7897338, thanks for addressing the feedback.

I keep a local copy of all commits, so no need to provide branches of the history for me.

@maflcko maflcko merged commit 7897338 into bitcoin:master Aug 15, 2017
maflcko pushed a commit that referenced this pull request Aug 15, 2017
7897338 [tests] Introduce TestNode (John Newbery)

Pull request description:

  Continues #10082

  TestNode is a class responsible for all state related to a bitcoind node
  under test. It stores local state, is responsible for tracking the
  bitcoind process and delegates unrecognised messages to the RPC
  connection.

  This commit changes start_nodes and stop_nodes to start and stop the
  bitcoind nodes in parallel, making test setup and teardown much faster.

  On my vm, this changeset reduces total test_runner runtime for the base set of tests
  (including building the cache) from 263s to 195s (a 25% speedup). Note that the time
  reported by test_runner does not include time spent building the cache:

  *with TestNode*:
  ```
  → date +"%T" ; ./test_runner.py -q ; date +"%T"
  12:48:04
  ..................................................................................................................................................................................................................................................................................................................................
  TEST                           | STATUS    | DURATION

  abandonconflict.py             | ✓ Passed  | 12 s
  bip68-112-113-p2p.py           | ✓ Passed  | 19 s
  blockchain.py                  | ✓ Passed  | 8 s
  bumpfee.py                     | ✓ Passed  | 13 s
  decodescript.py                | ✓ Passed  | 3 s
  disablewallet.py               | ✓ Passed  | 3 s
  disconnect_ban.py              | ✓ Passed  | 6 s
  fundrawtransaction.py          | ✓ Passed  | 37 s
  getchaintips.py                | ✓ Passed  | 4 s
  httpbasics.py                  | ✓ Passed  | 3 s
  import-rescan.py               | ✓ Passed  | 4 s
  importmulti.py                 | ✓ Passed  | 6 s
  importprunedfunds.py           | ✓ Passed  | 3 s
  invalidblockrequest.py         | ✓ Passed  | 4 s
  invalidtxrequest.py            | ✓ Passed  | 4 s
  keypool.py                     | ✓ Passed  | 7 s
  listsinceblock.py              | ✓ Passed  | 4 s
  listtransactions.py            | ✓ Passed  | 33 s
  mempool_limit.py               | ✓ Passed  | 4 s
  mempool_persist.py             | ✓ Passed  | 15 s
  mempool_reorg.py               | ✓ Passed  | 4 s
  mempool_resurrect_test.py      | ✓ Passed  | 3 s
  mempool_spendcoinbase.py       | ✓ Passed  | 3 s
  merkle_blocks.py               | ✓ Passed  | 3 s
  multi_rpc.py                   | ✓ Passed  | 4 s
  net.py                         | ✓ Passed  | 3 s
  nulldummy.py                   | ✓ Passed  | 3 s
  p2p-compactblocks.py           | ✓ Passed  | 28 s
  p2p-fullblocktest.py           | ✓ Passed  | 126 s
  p2p-leaktests.py               | ✓ Passed  | 8 s
  p2p-mempool.py                 | ✓ Passed  | 3 s
  p2p-segwit.py                  | ✓ Passed  | 59 s
  p2p-versionbits-warning.py     | ✓ Passed  | 8 s
  preciousblock.py               | ✓ Passed  | 3 s
  prioritise_transaction.py      | ✓ Passed  | 5 s
  proxy_test.py                  | ✓ Passed  | 3 s
  rawtransactions.py             | ✓ Passed  | 9 s
  receivedby.py                  | ✓ Passed  | 19 s
  reindex.py                     | ✓ Passed  | 12 s
  rest.py                        | ✓ Passed  | 9 s
  rpcnamedargs.py                | ✓ Passed  | 3 s
  segwit.py                      | ✓ Passed  | 7 s
  sendheaders.py                 | ✓ Passed  | 24 s
  signmessages.py                | ✓ Passed  | 3 s
  signrawtransactions.py         | ✓ Passed  | 3 s
  txn_clone.py                   | ✓ Passed  | 4 s
  txn_doublespend.py --mineblock | ✓ Passed  | 4 s
  uptime.py                      | ✓ Passed  | 3 s
  wallet-accounts.py             | ✓ Passed  | 3 s
  wallet-dump.py                 | ✓ Passed  | 7 s
  wallet-encryption.py           | ✓ Passed  | 8 s
  wallet-hd.py                   | ✓ Passed  | 15 s
  wallet.py                      | ✓ Passed  | 31 s
  walletbackup.py                | ✓ Passed  | 104 s
  zapwallettxes.py               | ✓ Passed  | 9 s
  zmq_test.py                    | ○ Skipped | 0 s

  ALL                            | ✓ Passed  | 735 s (accumulated)
  Runtime: 189 s

  12:51:19
  ```

  *master*:
  ```
  → date +"%T" ; ./test_runner.py -q ; date +"%T"
  12:40:13
  ..........................................................................................................................................................................................................................................................................................................................................................................................................................................
  TEST                           | STATUS    | DURATION

  abandonconflict.py             | ✓ Passed  | 15 s
  bip68-112-113-p2p.py           | ✓ Passed  | 19 s
  blockchain.py                  | ✓ Passed  | 8 s
  bumpfee.py                     | ✓ Passed  | 20 s
  decodescript.py                | ✓ Passed  | 3 s
  disablewallet.py               | ✓ Passed  | 3 s
  disconnect_ban.py              | ✓ Passed  | 8 s
  fundrawtransaction.py          | ✓ Passed  | 36 s
  getchaintips.py                | ✓ Passed  | 11 s
  httpbasics.py                  | ✓ Passed  | 7 s
  import-rescan.py               | ✓ Passed  | 16 s
  importmulti.py                 | ✓ Passed  | 10 s
  importprunedfunds.py           | ✓ Passed  | 5 s
  invalidblockrequest.py         | ✓ Passed  | 4 s
  invalidtxrequest.py            | ✓ Passed  | 3 s
  keypool.py                     | ✓ Passed  | 7 s
  listsinceblock.py              | ✓ Passed  | 11 s
  listtransactions.py            | ✓ Passed  | 37 s
  mempool_limit.py               | ✓ Passed  | 4 s
  mempool_persist.py             | ✓ Passed  | 23 s
  mempool_reorg.py               | ✓ Passed  | 7 s
  mempool_resurrect_test.py      | ✓ Passed  | 3 s
  mempool_spendcoinbase.py       | ✓ Passed  | 3 s
  merkle_blocks.py               | ✓ Passed  | 10 s
  multi_rpc.py                   | ✓ Passed  | 6 s
  net.py                         | ✓ Passed  | 6 s
  nulldummy.py                   | ✓ Passed  | 3 s
  p2p-compactblocks.py           | ✓ Passed  | 30 s
  p2p-fullblocktest.py           | ✓ Passed  | 126 s
  p2p-leaktests.py               | ✓ Passed  | 8 s
  p2p-mempool.py                 | ✓ Passed  | 3 s
  p2p-segwit.py                  | ✓ Passed  | 62 s
  p2p-versionbits-warning.py     | ✓ Passed  | 8 s
  preciousblock.py               | ✓ Passed  | 8 s
  prioritise_transaction.py      | ✓ Passed  | 7 s
  proxy_test.py                  | ✓ Passed  | 10 s
  rawtransactions.py             | ✓ Passed  | 15 s
  receivedby.py                  | ✓ Passed  | 28 s
  reindex.py                     | ✓ Passed  | 12 s
  rest.py                        | ✓ Passed  | 12 s
  rpcnamedargs.py                | ✓ Passed  | 3 s
  segwit.py                      | ✓ Passed  | 12 s
  sendheaders.py                 | ✓ Passed  | 26 s
  signmessages.py                | ✓ Passed  | 3 s
  signrawtransactions.py         | ✓ Passed  | 3 s
  txn_clone.py                   | ✓ Passed  | 10 s
  txn_doublespend.py --mineblock | ✓ Passed  | 10 s
  uptime.py                      | ✓ Passed  | 3 s
  wallet-accounts.py             | ✓ Passed  | 3 s
  wallet-dump.py                 | ✓ Passed  | 6 s
  wallet-encryption.py           | ✓ Passed  | 8 s
  wallet-hd.py                   | ✓ Passed  | 18 s
  wallet.py                      | ✓ Passed  | 69 s
  walletbackup.py                | ✓ Passed  | 130 s
  zapwallettxes.py               | ✓ Passed  | 15 s
  zmq_test.py                    | ○ Skipped | 0 s

  ALL                            | ✓ Passed  | 936 s (accumulated)
  Runtime: 242 s

  12:44:36
  ```

Tree-SHA512: 6dfc4c11fd0caf7de6954c93679cf22c3df0acc6f432e616d1151062a61f456faa8ae2fe670b427868af55bb564802df84c8fd76e90b4b338750dbc23f46ad88
@jnewbery jnewbery deleted the testnode2 branch August 15, 2017 21:44
maflcko pushed a commit that referenced this pull request Aug 24, 2017
c6ec435 [tests] Add bitcoin_cli.py test script (John Newbery)
b23549f [tests] add TestNodeCLI class for calling bitcoin-cli for a node (John Newbery)

Pull request description:

  We don't test bitcoin-cli at all. That means that we can miss inconsistencies between the bitcoin-cli client and the RPC interface, such as #10698 and #10747. It also means that the various bitcoin-cli options and features are untested and regressions could be silently introduced.

  Let's fix that.

  This PR adds bitcoin-cli testing in the python functional test_framework:

  1. Add a bitcoin_cli.py test script that tests bitcoin-cli. At the moment it only tests that the result of `getinfo` is the same if you run it as an RPC or through bitcoin-cli, but can easily be extended to test additional bitcoin-cli features

  **EDIT: `--usecli` option is moved to a separate PR. This PR now only covers the bitcoin_cli.py test.**

  2. ~Add a `--usecli` option to the test framework. This changes the test to use bitcoin-cli for all RPC calls instead of using direct HTTP requests. This is somewhat experimental. It works for most tests, but there are some cases where it can't work transparently because:~
  - ~the testcase is asserting on a specific error code, and bitcoin-cli returns a different error code from the direct RPC~
  - ~we're sending a very large RPC request (eg `submitblock`) and it can't be serialized into a shell bitcoin-cli call.~

  ~I think that even though `--usecli` doesn't work on all tests, it's still a useful experimental feature. Future potential enhancements:~
  - ~enhance the framework to automatically skip tests that are known to fail with bitcoin-cli if the `--usecli` option is used.~
  - ~run a subset of tests in Travis with `-usecli`~

  This builds on and requires the `TestNode` PR #10711 . As an aside, this is a good demonstration of how tidy it is to add additional features/interfaces now that test node logic/state is encapsulated in a TestNode class.

  Addresses #10791

Tree-SHA512: a1e6be12e8e007f6f67b3d3bbcd142d835787300831eb38e6027a1ad25ca9d79c4bc99a41b19e31ee95205cba1b3b2d21a688b5909316aad70bfc2b4eb6d8a52
maflcko pushed a commit to maflcko/bitcoin-core that referenced this pull request Oct 3, 2017
TestNode is a class responsible for all state related to a bitcoind node
under test. It stores local state, is responsible for tracking the
bitcoind process and delegates unrecognised messages to the RPC
connection.

This commit changes start_nodes and stop_nodes to start and stop the
bitcoind nodes in parallel, making test setup and teardown much faster.

Github-Pull: bitcoin#10711
Rebased-From: 7897338
codablock pushed a commit to codablock/dash that referenced this pull request Sep 24, 2019
7897338 [tests] Introduce TestNode (John Newbery)

Pull request description:

  Continues bitcoin#10082

  TestNode is a class responsible for all state related to a bitcoind node
  under test. It stores local state, is responsible for tracking the
  bitcoind process and delegates unrecognised messages to the RPC
  connection.

  This commit changes start_nodes and stop_nodes to start and stop the
  bitcoind nodes in parallel, making test setup and teardown much faster.

  On my vm, this changeset reduces total test_runner runtime for the base set of tests
  (including building the cache) from 263s to 195s (a 25% speedup). Note that the time
  reported by test_runner does not include time spent building the cache:

  *with TestNode*:
  ```
  → date +"%T" ; ./test_runner.py -q ; date +"%T"
  12:48:04
  ..................................................................................................................................................................................................................................................................................................................................
  TEST                           | STATUS    | DURATION

  abandonconflict.py             | ✓ Passed  | 12 s
  bip68-112-113-p2p.py           | ✓ Passed  | 19 s
  blockchain.py                  | ✓ Passed  | 8 s
  bumpfee.py                     | ✓ Passed  | 13 s
  decodescript.py                | ✓ Passed  | 3 s
  disablewallet.py               | ✓ Passed  | 3 s
  disconnect_ban.py              | ✓ Passed  | 6 s
  fundrawtransaction.py          | ✓ Passed  | 37 s
  getchaintips.py                | ✓ Passed  | 4 s
  httpbasics.py                  | ✓ Passed  | 3 s
  import-rescan.py               | ✓ Passed  | 4 s
  importmulti.py                 | ✓ Passed  | 6 s
  importprunedfunds.py           | ✓ Passed  | 3 s
  invalidblockrequest.py         | ✓ Passed  | 4 s
  invalidtxrequest.py            | ✓ Passed  | 4 s
  keypool.py                     | ✓ Passed  | 7 s
  listsinceblock.py              | ✓ Passed  | 4 s
  listtransactions.py            | ✓ Passed  | 33 s
  mempool_limit.py               | ✓ Passed  | 4 s
  mempool_persist.py             | ✓ Passed  | 15 s
  mempool_reorg.py               | ✓ Passed  | 4 s
  mempool_resurrect_test.py      | ✓ Passed  | 3 s
  mempool_spendcoinbase.py       | ✓ Passed  | 3 s
  merkle_blocks.py               | ✓ Passed  | 3 s
  multi_rpc.py                   | ✓ Passed  | 4 s
  net.py                         | ✓ Passed  | 3 s
  nulldummy.py                   | ✓ Passed  | 3 s
  p2p-compactblocks.py           | ✓ Passed  | 28 s
  p2p-fullblocktest.py           | ✓ Passed  | 126 s
  p2p-leaktests.py               | ✓ Passed  | 8 s
  p2p-mempool.py                 | ✓ Passed  | 3 s
  p2p-segwit.py                  | ✓ Passed  | 59 s
  p2p-versionbits-warning.py     | ✓ Passed  | 8 s
  preciousblock.py               | ✓ Passed  | 3 s
  prioritise_transaction.py      | ✓ Passed  | 5 s
  proxy_test.py                  | ✓ Passed  | 3 s
  rawtransactions.py             | ✓ Passed  | 9 s
  receivedby.py                  | ✓ Passed  | 19 s
  reindex.py                     | ✓ Passed  | 12 s
  rest.py                        | ✓ Passed  | 9 s
  rpcnamedargs.py                | ✓ Passed  | 3 s
  segwit.py                      | ✓ Passed  | 7 s
  sendheaders.py                 | ✓ Passed  | 24 s
  signmessages.py                | ✓ Passed  | 3 s
  signrawtransactions.py         | ✓ Passed  | 3 s
  txn_clone.py                   | ✓ Passed  | 4 s
  txn_doublespend.py --mineblock | ✓ Passed  | 4 s
  uptime.py                      | ✓ Passed  | 3 s
  wallet-accounts.py             | ✓ Passed  | 3 s
  wallet-dump.py                 | ✓ Passed  | 7 s
  wallet-encryption.py           | ✓ Passed  | 8 s
  wallet-hd.py                   | ✓ Passed  | 15 s
  wallet.py                      | ✓ Passed  | 31 s
  walletbackup.py                | ✓ Passed  | 104 s
  zapwallettxes.py               | ✓ Passed  | 9 s
  zmq_test.py                    | ○ Skipped | 0 s

  ALL                            | ✓ Passed  | 735 s (accumulated)
  Runtime: 189 s

  12:51:19
  ```

  *master*:
  ```
  → date +"%T" ; ./test_runner.py -q ; date +"%T"
  12:40:13
  ..........................................................................................................................................................................................................................................................................................................................................................................................................................................
  TEST                           | STATUS    | DURATION

  abandonconflict.py             | ✓ Passed  | 15 s
  bip68-112-113-p2p.py           | ✓ Passed  | 19 s
  blockchain.py                  | ✓ Passed  | 8 s
  bumpfee.py                     | ✓ Passed  | 20 s
  decodescript.py                | ✓ Passed  | 3 s
  disablewallet.py               | ✓ Passed  | 3 s
  disconnect_ban.py              | ✓ Passed  | 8 s
  fundrawtransaction.py          | ✓ Passed  | 36 s
  getchaintips.py                | ✓ Passed  | 11 s
  httpbasics.py                  | ✓ Passed  | 7 s
  import-rescan.py               | ✓ Passed  | 16 s
  importmulti.py                 | ✓ Passed  | 10 s
  importprunedfunds.py           | ✓ Passed  | 5 s
  invalidblockrequest.py         | ✓ Passed  | 4 s
  invalidtxrequest.py            | ✓ Passed  | 3 s
  keypool.py                     | ✓ Passed  | 7 s
  listsinceblock.py              | ✓ Passed  | 11 s
  listtransactions.py            | ✓ Passed  | 37 s
  mempool_limit.py               | ✓ Passed  | 4 s
  mempool_persist.py             | ✓ Passed  | 23 s
  mempool_reorg.py               | ✓ Passed  | 7 s
  mempool_resurrect_test.py      | ✓ Passed  | 3 s
  mempool_spendcoinbase.py       | ✓ Passed  | 3 s
  merkle_blocks.py               | ✓ Passed  | 10 s
  multi_rpc.py                   | ✓ Passed  | 6 s
  net.py                         | ✓ Passed  | 6 s
  nulldummy.py                   | ✓ Passed  | 3 s
  p2p-compactblocks.py           | ✓ Passed  | 30 s
  p2p-fullblocktest.py           | ✓ Passed  | 126 s
  p2p-leaktests.py               | ✓ Passed  | 8 s
  p2p-mempool.py                 | ✓ Passed  | 3 s
  p2p-segwit.py                  | ✓ Passed  | 62 s
  p2p-versionbits-warning.py     | ✓ Passed  | 8 s
  preciousblock.py               | ✓ Passed  | 8 s
  prioritise_transaction.py      | ✓ Passed  | 7 s
  proxy_test.py                  | ✓ Passed  | 10 s
  rawtransactions.py             | ✓ Passed  | 15 s
  receivedby.py                  | ✓ Passed  | 28 s
  reindex.py                     | ✓ Passed  | 12 s
  rest.py                        | ✓ Passed  | 12 s
  rpcnamedargs.py                | ✓ Passed  | 3 s
  segwit.py                      | ✓ Passed  | 12 s
  sendheaders.py                 | ✓ Passed  | 26 s
  signmessages.py                | ✓ Passed  | 3 s
  signrawtransactions.py         | ✓ Passed  | 3 s
  txn_clone.py                   | ✓ Passed  | 10 s
  txn_doublespend.py --mineblock | ✓ Passed  | 10 s
  uptime.py                      | ✓ Passed  | 3 s
  wallet-accounts.py             | ✓ Passed  | 3 s
  wallet-dump.py                 | ✓ Passed  | 6 s
  wallet-encryption.py           | ✓ Passed  | 8 s
  wallet-hd.py                   | ✓ Passed  | 18 s
  wallet.py                      | ✓ Passed  | 69 s
  walletbackup.py                | ✓ Passed  | 130 s
  zapwallettxes.py               | ✓ Passed  | 15 s
  zmq_test.py                    | ○ Skipped | 0 s

  ALL                            | ✓ Passed  | 936 s (accumulated)
  Runtime: 242 s

  12:44:36
  ```

Tree-SHA512: 6dfc4c11fd0caf7de6954c93679cf22c3df0acc6f432e616d1151062a61f456faa8ae2fe670b427868af55bb564802df84c8fd76e90b4b338750dbc23f46ad88
codablock pushed a commit to codablock/dash that referenced this pull request Sep 24, 2019
c6ec435 [tests] Add bitcoin_cli.py test script (John Newbery)
b23549f [tests] add TestNodeCLI class for calling bitcoin-cli for a node (John Newbery)

Pull request description:

  We don't test bitcoin-cli at all. That means that we can miss inconsistencies between the bitcoin-cli client and the RPC interface, such as bitcoin#10698 and bitcoin#10747. It also means that the various bitcoin-cli options and features are untested and regressions could be silently introduced.

  Let's fix that.

  This PR adds bitcoin-cli testing in the python functional test_framework:

  1. Add a bitcoin_cli.py test script that tests bitcoin-cli. At the moment it only tests that the result of `getinfo` is the same if you run it as an RPC or through bitcoin-cli, but can easily be extended to test additional bitcoin-cli features

  **EDIT: `--usecli` option is moved to a separate PR. This PR now only covers the bitcoin_cli.py test.**

  2. ~Add a `--usecli` option to the test framework. This changes the test to use bitcoin-cli for all RPC calls instead of using direct HTTP requests. This is somewhat experimental. It works for most tests, but there are some cases where it can't work transparently because:~
  - ~the testcase is asserting on a specific error code, and bitcoin-cli returns a different error code from the direct RPC~
  - ~we're sending a very large RPC request (eg `submitblock`) and it can't be serialized into a shell bitcoin-cli call.~

  ~I think that even though `--usecli` doesn't work on all tests, it's still a useful experimental feature. Future potential enhancements:~
  - ~enhance the framework to automatically skip tests that are known to fail with bitcoin-cli if the `--usecli` option is used.~
  - ~run a subset of tests in Travis with `-usecli`~

  This builds on and requires the `TestNode` PR bitcoin#10711 . As an aside, this is a good demonstration of how tidy it is to add additional features/interfaces now that test node logic/state is encapsulated in a TestNode class.

  Addresses bitcoin#10791

Tree-SHA512: a1e6be12e8e007f6f67b3d3bbcd142d835787300831eb38e6027a1ad25ca9d79c4bc99a41b19e31ee95205cba1b3b2d21a688b5909316aad70bfc2b4eb6d8a52
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants