This PR is too large for review and will need continually rebasing. This PR tracks the individual tasks to introduce a TestNode class. The individual commits are in separate PRs
Tasks:
- #10171 Add initialize chain / start node / stop node methods to TestFramework. Initially these are wrapper methods which call into the functions in util.py (not disruptive - only touches test_framework files)
- #10359 Update individual test cases to call
TestFramework.start_node()
etc (disruptive - touches all test cases, so will require rebases for open PRs) - #10556 Change TestFramework start/stop methods to contain the logic and remove the functions from util.py. Also move the stateful port and coverage functions into TestFramework (not disruptive - only touches test_framework files)
- #10711 Add the TestNode class (not disruptive - only touches test_framework files)
- #11182 Add p2p connections into the TestNode class (not disruptive - only touches test_framework files)
- #11182 Update individual test cases to use TestNode class (marginally disruptive - does not need to be done all at once)
This PR adds a TestNode class to the test_framework.py module. The goals for this are:
- Present a clean interface to the test writer
The test writer should be able to set up a desired network topology and not have to think too hard about how to start bitcoind instances and setup RPC/P2P connections to them.
To create a node with an RPC and a P2P connection, tests currently look something like this:
0 self.nodes = []
1 self.nodes.append(start_node(0, self.options.tmpdir))
2 node0 = SingleNodeConnCB()
3 connections = []
4 connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0))
5 node0.add_connection(connections[0])
6 NetworkThread().start() # Start up network handling in another thread
7 node0.wait_for_verack()
After this PR, that should be more like this:
0 self.num_nodes = 1
1 self.start_nodes()
2 self.nodes[0].add_p2p_connection()
the tester now has a TestNode instance self.nodes[0]
which he/she can use to send RPC commands, send P2P messages and register callbacks for received P2P messages.
- Remove global state from utils.py
There are currently several global state variables in utils.py (COVERAGE_DIR, PortSeed and bitcoind_processes). Having global state variables in the utils module is bad practice and makes importing from utils quite brittle. It also makes it difficult to add functionality to the test framework without inadvertently breaking something.