Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/test_framework.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2014-2016 The Bitcoin Core developers | # Copyright (c) 2014-2016 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Base class for RPC testing.""" | """Base class for RPC testing.""" | ||||
from collections import deque | from collections import deque | ||||
from enum import Enum | from enum import Enum | ||||
import logging | import logging | ||||
import optparse | import argparse | ||||
import os | import os | ||||
import pdb | import pdb | ||||
import shutil | import shutil | ||||
import sys | import sys | ||||
import tempfile | import tempfile | ||||
import time | import time | ||||
import traceback | import traceback | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | def __init__(self): | ||||
"""Sets test framework defaults. Do not override this method. Instead, override the set_test_params() method""" | """Sets test framework defaults. Do not override this method. Instead, override the set_test_params() method""" | ||||
self.setup_clean_chain = False | self.setup_clean_chain = False | ||||
self.nodes = [] | self.nodes = [] | ||||
self.mocktime = 0 | self.mocktime = 0 | ||||
def main(self): | def main(self): | ||||
"""Main function. This should not be overridden by the subclass test scripts.""" | """Main function. This should not be overridden by the subclass test scripts.""" | ||||
parser = optparse.OptionParser(usage="%prog [options]") | parser = argparse.ArgumentParser(usage="%(prog)s [options]") | ||||
parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", | parser.add_argument("--nocleanup", dest="nocleanup", default=False, action="store_true", | ||||
help="Leave bitcoinds and test.* datadir on exit or error") | help="Leave bitcoinds and test.* datadir on exit or error") | ||||
parser.add_option("--noshutdown", dest="noshutdown", default=False, action="store_true", | parser.add_argument("--noshutdown", dest="noshutdown", default=False, action="store_true", | ||||
help="Don't stop bitcoinds after the test execution") | help="Don't stop bitcoinds after the test execution") | ||||
parser.add_option("--srcdir", dest="srcdir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../../../src"), | parser.add_argument("--srcdir", dest="srcdir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../../../src"), | ||||
help="Source directory containing bitcoind/bitcoin-cli (default: %default)") | help="Source directory containing bitcoind/bitcoin-cli (default: %default)") | ||||
parser.add_option("--cachedir", dest="cachedir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../../cache"), | parser.add_argument("--cachedir", dest="cachedir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../../cache"), | ||||
help="Directory for caching pregenerated datadirs") | help="Directory for caching pregenerated datadirs") | ||||
parser.add_option("--tmpdir", dest="tmpdir", | parser.add_argument("--tmpdir", dest="tmpdir", | ||||
help="Root directory for datadirs") | help="Root directory for datadirs") | ||||
parser.add_option("-l", "--loglevel", dest="loglevel", default="INFO", | parser.add_argument("-l", "--loglevel", dest="loglevel", default="INFO", | ||||
help="log events at this level and higher to the console. Can be set to DEBUG, INFO, WARNING, ERROR or CRITICAL. Passing --loglevel DEBUG will output all logs to console. Note that logs at all levels are always written to the test_framework.log file in the temporary test directory.") | help="log events at this level and higher to the console. Can be set to DEBUG, INFO, WARNING, ERROR or CRITICAL. Passing --loglevel DEBUG will output all logs to console. Note that logs at all levels are always written to the test_framework.log file in the temporary test directory.") | ||||
parser.add_option("--tracerpc", dest="trace_rpc", default=False, action="store_true", | parser.add_argument("--tracerpc", dest="trace_rpc", default=False, action="store_true", | ||||
help="Print out all RPC calls as they are made") | help="Print out all RPC calls as they are made") | ||||
parser.add_option("--portseed", dest="port_seed", default=os.getpid(), type='int', | parser.add_argument("--portseed", dest="port_seed", default=os.getpid(), type=int, | ||||
help="The seed to use for assigning port numbers (default: current process id)") | help="The seed to use for assigning port numbers (default: current process id)") | ||||
parser.add_option("--coveragedir", dest="coveragedir", | parser.add_argument("--coveragedir", dest="coveragedir", | ||||
help="Write tested RPC commands into this directory") | help="Write tested RPC commands into this directory") | ||||
parser.add_option("--configfile", dest="configfile", | parser.add_argument("--configfile", dest="configfile", | ||||
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_argument("--pdbonfailure", dest="pdbonfailure", default=False, action="store_true", | ||||
help="Attach a python debugger if test fails") | help="Attach a python debugger if test fails") | ||||
self.add_options(parser) | self.add_options(parser) | ||||
(self.options, self.args) = parser.parse_args() | self.options = parser.parse_args() | ||||
self.set_test_params() | self.set_test_params() | ||||
assert hasattr( | assert hasattr( | ||||
self, "num_nodes"), "Test must set self.num_nodes in set_test_params()" | self, "num_nodes"), "Test must set self.num_nodes in set_test_params()" | ||||
PortSeed.n = self.options.port_seed | PortSeed.n = self.options.port_seed | ||||
os.environ['PATH'] = self.options.srcdir + ":" + \ | os.environ['PATH'] = self.options.srcdir + ":" + \ | ||||
▲ Show 20 Lines • Show All 372 Lines • ▼ Show 20 Lines | class ComparisonTestFramework(BitcoinTestFramework): | ||||
- 2 binaries: 1 test binary, 1 ref binary | - 2 binaries: 1 test binary, 1 ref binary | ||||
- n>2 binaries: 1 test binary, n-1 ref binaries""" | - n>2 binaries: 1 test binary, n-1 ref binaries""" | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 2 | self.num_nodes = 2 | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
def add_options(self, parser): | def add_options(self, parser): | ||||
parser.add_option("--testbinary", dest="testbinary", | parser.add_argument("--testbinary", dest="testbinary", | ||||
default=os.getenv("BITCOIND", "bitcoind"), | default=os.getenv("BITCOIND", "bitcoind"), | ||||
help="bitcoind binary to test") | help="bitcoind binary to test") | ||||
parser.add_option("--refbinary", dest="refbinary", | parser.add_argument("--refbinary", dest="refbinary", | ||||
default=os.getenv("BITCOIND", "bitcoind"), | default=os.getenv("BITCOIND", "bitcoind"), | ||||
help="bitcoind binary to use for reference nodes (if any)") | help="bitcoind binary to use for reference nodes (if any)") | ||||
def setup_network(self): | def setup_network(self): | ||||
extra_args = [['-whitelist=127.0.0.1']] * self.num_nodes | extra_args = [['-whitelist=127.0.0.1']] * self.num_nodes | ||||
if hasattr(self, "extra_args"): | if hasattr(self, "extra_args"): | ||||
extra_args = self.extra_args | extra_args = self.extra_args | ||||
self.add_nodes(self.num_nodes, extra_args, | self.add_nodes(self.num_nodes, extra_args, | ||||
binary=[self.options.testbinary] + | binary=[self.options.testbinary] + | ||||
[self.options.refbinary] * (self.num_nodes - 1)) | [self.options.refbinary] * (self.num_nodes - 1)) | ||||
self.start_nodes() | self.start_nodes() | ||||
class SkipTest(Exception): | class SkipTest(Exception): | ||||
"""This exception is raised to skip a test""" | """This exception is raised to skip a test""" | ||||
def __init__(self, message): | def __init__(self, message): | ||||
self.message = message | self.message = message |