mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
Merge #18986: tests: Add capability to disable RPC timeout in functional tests
38c3dd9c706e7e84b2a4dbaf1424a3f1c3b694fc docs: Add notes on how to diasble rpc timeout in functional tests while attatching gdb. (codeShark149)
784ae096259955ea7a294114f5c021c9489d2717 test: Add capability to disable RPC timeout in functional tests. (codeShark149)
Pull request description:
Many times, especially while debugging RPC callbacks to core using gdb, the test timeout kicks in before the response can get back. This can be annoying and requires restarting the functional test as well as gdb attachment.
This PR adds a `--notimeout` flag into `test_framework` and sets the `rpc_timeout` accordingly if the flag is set.
The same effect can be achieved with newly added `--factor` flag but keeping a separate flag that explicitly disables the timeout can be easier for new testers to find it out and separates its purpose from the `--factor` flag.
Requesting review ryanofsky jnewbery as per the IRC discussion.
Update: After initial round of review, the approach is modified to accommodate the functionality in already existing `--factor` flag. `--factor` is changed to `--timeout-factor` to express its intent better.
ACKs for top commit:
MarcoFalke:
ACK 38c3dd9c706e7e84b2a4dbaf1424a3f1c3b694fc and thanks for fixing up all my typos 😅
jnewbery:
ACK 38c3dd9c706e7e84b2a4dbaf1424a3f1c3b694fc.
Tree-SHA512: 9458dd1010288c62f8bb83f7a4893284fbbf938882dd65fc9e08810a910db07ef676e3100266028e5d4c8ce407b2267b3860595015da070c84a9d4a9816797db
This commit is contained in:
parent
60cfe097be
commit
c0e3829631
@ -237,6 +237,10 @@ gdb /home/example/dashd <pid>
|
||||
Note: gdb attach step may require ptrace_scope to be modified, or `sudo` preceding the `gdb`.
|
||||
See this link for considerations: https://www.kernel.org/doc/Documentation/security/Yama.txt
|
||||
|
||||
Often while debugging rpc calls from functional tests, the test might reach timeout before
|
||||
process can return a response. Use `--timeout-factor 0` to disable all rpc timeouts for that partcular
|
||||
functional test. Ex: `test/functional/wallet_hd.py --timeout-factor 0`.
|
||||
|
||||
##### Profiling
|
||||
|
||||
An easy way to profile node performance during functional tests is provided
|
||||
|
@ -154,9 +154,9 @@ class P2PConnection(asyncio.Protocol):
|
||||
def is_connected(self):
|
||||
return self._transport is not None
|
||||
|
||||
def peer_connect(self, dstaddr, dstport, *, net, factor, uacomment=None):
|
||||
def peer_connect(self, dstaddr, dstport, *, net, timeout_factor, uacomment=None):
|
||||
assert not self.is_connected
|
||||
self.factor = factor
|
||||
self.timeout_factor = timeout_factor
|
||||
self.dstaddr = dstaddr
|
||||
self.dstport = dstport
|
||||
# The initial message to send after the connection was made:
|
||||
@ -441,7 +441,7 @@ class P2PInterface(P2PConnection):
|
||||
# Connection helper methods
|
||||
|
||||
def wait_until(self, test_function, timeout):
|
||||
wait_until(test_function, timeout=timeout, lock=mininode_lock, factor=self.factor)
|
||||
wait_until(test_function, timeout=timeout, lock=mininode_lock, timeout_factor=self.timeout_factor)
|
||||
|
||||
def wait_for_disconnect(self, timeout=60):
|
||||
test_function = lambda: not self.is_connected
|
||||
|
@ -123,7 +123,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
self.extra_args_from_options = []
|
||||
self.set_test_params()
|
||||
self.parse_args()
|
||||
self.rpc_timeout = int(self.rpc_timeout * self.options.factor) # optionally, increase timeout by a factor
|
||||
if self.options.timeout_factor == 0 :
|
||||
self.options.timeout_factor = 99999
|
||||
self.rpc_timeout = int(self.rpc_timeout * self.options.timeout_factor) # optionally, increase timeout by a factor
|
||||
|
||||
def main(self):
|
||||
"""Main function. This should not be overridden by the subclass test scripts."""
|
||||
@ -189,7 +191,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
help="run nodes under the valgrind memory error detector: expect at least a ~10x slowdown, valgrind 3.14 or later required")
|
||||
parser.add_argument("--randomseed", type=int,
|
||||
help="set a random seed for deterministically reproducing a previous test run")
|
||||
parser.add_argument('--factor', type=float, default=1.0, help='adjust test timeouts by a factor')
|
||||
parser.add_argument('--timeout-factor', dest="timeout_factor", type=float, default=1.0, help='adjust test timeouts by a factor. Setting it to 0 disables all timeouts')
|
||||
self.add_options(parser)
|
||||
# Running TestShell in a Jupyter notebook causes an additional -f argument
|
||||
# To keep TestShell from failing with an "unrecognized argument" error, we add a dummy "-f" argument
|
||||
@ -442,7 +444,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
chain=self.chain,
|
||||
rpchost=rpchost,
|
||||
timewait=self.rpc_timeout,
|
||||
factor=self.options.factor,
|
||||
timeout_factor=self.options.timeout_factor,
|
||||
bitcoind=binary[i],
|
||||
bitcoin_cli=self.options.bitcoincli,
|
||||
mocktime=self.mocktime,
|
||||
@ -616,7 +618,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
extra_args_from_options=self.extra_args_from_options,
|
||||
rpchost=None,
|
||||
timewait=self.rpc_timeout,
|
||||
factor=self.options.factor,
|
||||
timeout_factor=self.options.timeout_factor,
|
||||
bitcoind=self.options.bitcoind,
|
||||
bitcoin_cli=self.options.bitcoincli,
|
||||
mocktime=self.mocktime,
|
||||
|
@ -62,7 +62,7 @@ class TestNode():
|
||||
To make things easier for the test writer, any unrecognised messages will
|
||||
be dispatched to the RPC connection."""
|
||||
|
||||
def __init__(self, i, datadir, extra_args_from_options, *, chain, rpchost, timewait, factor, bitcoind, bitcoin_cli, mocktime, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False):
|
||||
def __init__(self, i, datadir, extra_args_from_options, *, chain, rpchost, timewait, timeout_factor, bitcoind, bitcoin_cli, mocktime, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False):
|
||||
"""
|
||||
Kwargs:
|
||||
start_perf (bool): If True, begin profiling the node with `perf` as soon as
|
||||
@ -131,7 +131,7 @@ class TestNode():
|
||||
self.perf_subprocesses = {}
|
||||
|
||||
self.p2ps = []
|
||||
self.factor = factor
|
||||
self.timeout_factor = timeout_factor
|
||||
|
||||
AddressKeyPair = collections.namedtuple('AddressKeyPair', ['address', 'key'])
|
||||
PRIV_KEYS = [
|
||||
@ -253,7 +253,7 @@ class TestNode():
|
||||
# The wait is done here to make tests as robust as possible
|
||||
# and prevent racy tests and intermittent failures as much
|
||||
# as possible. Some tests might not need this, but the
|
||||
# overhead is trivial, and the added gurantees are worth
|
||||
# overhead is trivial, and the added guarantees are worth
|
||||
# the minimal performance cost.
|
||||
self.log.debug("RPC successfully started")
|
||||
if self.use_cli:
|
||||
@ -338,13 +338,13 @@ class TestNode():
|
||||
return True
|
||||
|
||||
def wait_until_stopped(self, timeout=BITCOIND_PROC_WAIT_TIMEOUT):
|
||||
wait_until(self.is_node_stopped, timeout=timeout, factor=self.factor)
|
||||
wait_until(self.is_node_stopped, timeout=timeout, timeout_factor=self.timeout_factor)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def assert_debug_log(self, expected_msgs, unexpected_msgs=None, timeout=2):
|
||||
if unexpected_msgs is None:
|
||||
unexpected_msgs = []
|
||||
time_end = time.time() + timeout * self.factor
|
||||
time_end = time.time() + timeout * self.timeout_factor
|
||||
chain = get_chain_folder(self.datadir, self.chain)
|
||||
debug_log = os.path.join(self.datadir, chain, 'debug.log')
|
||||
with open(debug_log, encoding='utf-8') as dl:
|
||||
@ -502,7 +502,7 @@ class TestNode():
|
||||
if 'dstaddr' not in kwargs:
|
||||
kwargs['dstaddr'] = '127.0.0.1'
|
||||
|
||||
p2p_conn.peer_connect(**kwargs, net=self.chain, factor=self.factor)()
|
||||
p2p_conn.peer_connect(**kwargs, net=self.chain, timeout_factor=self.timeout_factor)()
|
||||
self.p2ps.append(p2p_conn)
|
||||
if wait_for_verack:
|
||||
# Wait for the node to send us the version and verack
|
||||
@ -516,7 +516,7 @@ class TestNode():
|
||||
# transaction that will be added to the mempool as soon as we return here.
|
||||
#
|
||||
# So syncing here is redundant when we only want to send a message, but the cost is low (a few milliseconds)
|
||||
# in comparision to the upside of making tests less fragile and unexpected intermittent errors less likely.
|
||||
# in comparison to the upside of making tests less fragile and unexpected intermittent errors less likely.
|
||||
p2p_conn.sync_with_ping()
|
||||
|
||||
return p2p_conn
|
||||
|
@ -227,10 +227,10 @@ def str_to_b64str(string):
|
||||
def satoshi_round(amount):
|
||||
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
|
||||
|
||||
def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), sleep=0.05, factor=1.0, lock=None, do_assert=True, allow_exception=False):
|
||||
def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), sleep=0.05, timeout_factor=1.0, lock=None, do_assert=True, allow_exception=False):
|
||||
if attempts == float('inf') and timeout == float('inf'):
|
||||
timeout = 60
|
||||
timeout = timeout * factor
|
||||
timeout = timeout * timeout_factor
|
||||
attempt = 0
|
||||
timeout *= Options.timeout_scale
|
||||
time_end = time.time() + timeout
|
||||
|
Loading…
Reference in New Issue
Block a user