[tests] allow tests to be run with --usecli

test_framework accepts a new --usecli parameter. Running the test with
this parameter will cause all RPCs to be sent through bitcoin-cli rather
than directly over http. By default, individual test cases do not
support --usecli, and self.supports_cli must be set to True in the
set_test_params method.

We can make supports_cli default to True in future once we know which
tests will fail with use_cli.
This commit is contained in:
John Newbery 2017-07-11 13:14:18 -04:00
parent ff9a363ff7
commit f6ade9ce1a
3 changed files with 24 additions and 9 deletions

View file

@ -16,6 +16,7 @@ class CreateCache(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 0 self.num_nodes = 0
self.supports_cli = True
def setup_network(self): def setup_network(self):
pass pass

View file

@ -62,6 +62,7 @@ class BitcoinTestFramework():
self.setup_clean_chain = False self.setup_clean_chain = False
self.nodes = [] self.nodes = []
self.mocktime = 0 self.mocktime = 0
self.supports_cli = False
self.set_test_params() self.set_test_params()
assert hasattr(self, "num_nodes"), "Test must set self.num_nodes in set_test_params()" assert hasattr(self, "num_nodes"), "Test must set self.num_nodes in set_test_params()"
@ -91,6 +92,8 @@ class BitcoinTestFramework():
help="Location of the test framework config file") help="Location of the test framework config file")
parser.add_option("--pdbonfailure", dest="pdbonfailure", default=False, action="store_true", parser.add_option("--pdbonfailure", dest="pdbonfailure", default=False, action="store_true",
help="Attach a python debugger if test fails") help="Attach a python debugger if test fails")
parser.add_option("--usecli", dest="usecli", default=False, action="store_true",
help="use bitcoin-cli instead of RPC for all commands")
self.add_options(parser) self.add_options(parser)
(self.options, self.args) = parser.parse_args() (self.options, self.args) = parser.parse_args()
@ -113,6 +116,8 @@ class BitcoinTestFramework():
success = TestStatus.FAILED success = TestStatus.FAILED
try: try:
if self.options.usecli and not self.supports_cli:
raise SkipTest("--usecli specified but test does not support using CLI")
self.setup_chain() self.setup_chain()
self.setup_network() self.setup_network()
self.run_test() self.run_test()
@ -213,7 +218,7 @@ class BitcoinTestFramework():
assert_equal(len(extra_args), num_nodes) assert_equal(len(extra_args), num_nodes)
assert_equal(len(binary), num_nodes) assert_equal(len(binary), num_nodes)
for i in range(num_nodes): for i in range(num_nodes):
self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir)) self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, use_cli=self.options.usecli))
def start_node(self, i, extra_args=None, stderr=None): def start_node(self, i, extra_args=None, stderr=None):
"""Start a bitcoind""" """Start a bitcoind"""

View file

@ -42,7 +42,7 @@ class TestNode():
To make things easier for the test writer, any unrecognised messages will To make things easier for the test writer, any unrecognised messages will
be dispatched to the RPC connection.""" be dispatched to the RPC connection."""
def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir): def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir, use_cli=False):
self.index = i self.index = i
self.datadir = os.path.join(dirname, "node" + str(i)) self.datadir = os.path.join(dirname, "node" + str(i))
self.rpchost = rpchost self.rpchost = rpchost
@ -62,6 +62,7 @@ class TestNode():
self.args = [self.binary, "-datadir=" + self.datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i] self.args = [self.binary, "-datadir=" + self.datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i]
self.cli = TestNodeCLI(os.getenv("BITCOINCLI", "bitcoin-cli"), self.datadir) self.cli = TestNodeCLI(os.getenv("BITCOINCLI", "bitcoin-cli"), self.datadir)
self.use_cli = use_cli
self.running = False self.running = False
self.process = None self.process = None
@ -73,9 +74,12 @@ class TestNode():
self.p2ps = [] self.p2ps = []
def __getattr__(self, name): def __getattr__(self, name):
"""Dispatches any unrecognised messages to the RPC connection.""" """Dispatches any unrecognised messages to the RPC connection or a CLI instance."""
assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection" if self.use_cli:
return getattr(self.rpc, name) return getattr(self.cli, name)
else:
assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection"
return getattr(self.rpc, name)
def start(self, extra_args=None, stderr=None): def start(self, extra_args=None, stderr=None):
"""Start the node.""" """Start the node."""
@ -114,10 +118,13 @@ class TestNode():
raise AssertionError("Unable to connect to bitcoind") raise AssertionError("Unable to connect to bitcoind")
def get_wallet_rpc(self, wallet_name): def get_wallet_rpc(self, wallet_name):
assert self.rpc_connected if self.use_cli:
assert self.rpc return self.cli("-rpcwallet={}".format(wallet_name))
wallet_path = "wallet/%s" % wallet_name else:
return self.rpc / wallet_path assert self.rpc_connected
assert self.rpc
wallet_path = "wallet/%s" % wallet_name
return self.rpc / wallet_path
def stop_node(self): def stop_node(self):
"""Stop the node.""" """Stop the node."""
@ -210,6 +217,7 @@ class TestNodeCLI():
self.binary = binary self.binary = binary
self.datadir = datadir self.datadir = datadir
self.input = None self.input = None
self.log = logging.getLogger('TestFramework.bitcoincli')
def __call__(self, *args, input=None): def __call__(self, *args, input=None):
# TestNodeCLI is callable with bitcoin-cli command-line args # TestNodeCLI is callable with bitcoin-cli command-line args
@ -240,6 +248,7 @@ class TestNodeCLI():
if named_args: if named_args:
p_args += ["-named"] p_args += ["-named"]
p_args += [command] + pos_args + named_args p_args += [command] + pos_args + named_args
self.log.debug("Running bitcoin-cli command: %s" % command)
process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
cli_stdout, cli_stderr = process.communicate(input=self.input) cli_stdout, cli_stderr = process.communicate(input=self.input)
returncode = process.poll() returncode = process.poll()