Skip to content

Commit 4e14afe

Browse files
author
MarcoFalke
committed
Merge #7971: [qa] Refactor test_framework and pull tester
fad3366 [qa] pull-tester: Adjust comment (MarcoFalke) fafb33c [qa] Stop other nodes, even when one fails to stop (MarcoFalke) 2222dae [qa] Update README.md (MarcoFalke) fabbf6b [qa] Refactor test_framework and pull tester (MarcoFalke)
2 parents 3e90fe6 + fad3366 commit 4e14afe

File tree

5 files changed

+79
-57
lines changed

5 files changed

+79
-57
lines changed

qa/README.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,25 @@ sudo apt-get install python3-zmq
1919
Running tests
2020
=============
2121

22-
You can run any single test by calling `qa/pull-tester/rpc-tests.py <testname>`.
22+
You can run any single test by calling
2323

24-
Or you can run any combination of tests by calling `qa/pull-tester/rpc-tests.py <testname1> <testname2> <testname3> ...`
24+
qa/pull-tester/rpc-tests.py <testname>
2525

26-
Run the regression test suite with `qa/pull-tester/rpc-tests.py`
26+
Or you can run any combination of tests by calling
2727

28-
Run all possible tests with `qa/pull-tester/rpc-tests.py -extended`
28+
qa/pull-tester/rpc-tests.py <testname1> <testname2> <testname3> ...
2929

30-
Possible options:
30+
Run the regression test suite with
31+
32+
qa/pull-tester/rpc-tests.py
33+
34+
Run all possible tests with
35+
36+
qa/pull-tester/rpc-tests.py -extended
37+
38+
If you want to create a basic coverage report for the rpc test suite, append `--coverage`.
39+
40+
Possible options, which apply to each individual test run:
3141

3242
```
3343
-h, --help show this help message and exit

qa/pull-tester/rpc-tests.py

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@
3131

3232
from tests_config import *
3333

34+
BOLD = ("","")
35+
if os.name == 'posix':
36+
# primitive formatting on supported
37+
# terminal via ANSI escape sequences:
38+
BOLD = ('\033[0m', '\033[1m')
39+
40+
RPC_TESTS_DIR = BUILDDIR + '/qa/rpc-tests/'
41+
3442
#If imported values are not defined then set to zero (or disabled)
3543
if 'ENABLE_WALLET' not in vars():
3644
ENABLE_WALLET=0
@@ -43,29 +51,29 @@
4351

4452
ENABLE_COVERAGE=0
4553

46-
#Create a set to store arguments and create the passOn string
54+
#Create a set to store arguments and create the passon string
4755
opts = set()
48-
passOn = ""
49-
p = re.compile("^--")
56+
passon_args = ""
57+
PASSON_REGEX = re.compile("^--")
5058

51-
bold = ("","")
52-
if (os.name == 'posix'):
53-
bold = ('\033[0m', '\033[1m')
59+
print_help = False
5460

5561
for arg in sys.argv[1:]:
62+
if arg == "--help" or arg == "-h" or arg == "-?":
63+
print_help = True
64+
break
5665
if arg == '--coverage':
5766
ENABLE_COVERAGE = 1
58-
elif (p.match(arg) or arg == "-h"):
59-
passOn += " " + arg
67+
elif PASSON_REGEX.match(arg):
68+
passon_args += " " + arg
6069
else:
6170
opts.add(arg)
6271

6372
#Set env vars
64-
buildDir = BUILDDIR
6573
if "BITCOIND" not in os.environ:
66-
os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT
74+
os.environ["BITCOIND"] = BUILDDIR + '/src/bitcoind' + EXEEXT
6775
if "BITCOINCLI" not in os.environ:
68-
os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT
76+
os.environ["BITCOINCLI"] = BUILDDIR + '/src/bitcoin-cli' + EXEEXT
6977

7078
if EXEEXT == ".exe" and "-win" not in opts:
7179
# https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9
@@ -153,48 +161,34 @@
153161
]
154162

155163
def runtests():
164+
test_list = []
165+
if '-extended' in opts:
166+
test_list = testScripts + testScriptsExt
167+
elif len(opts) == 0 or (len(opts) == 1 and "-win" in opts):
168+
test_list = testScripts
169+
else:
170+
for t in testScripts + testScriptsExt:
171+
if t in opts or re.sub(".py$", "", t) in opts:
172+
test_list.append(t)
173+
174+
if print_help:
175+
# Only print help of the first script and exit
176+
subprocess.check_call(RPC_TESTS_DIR + test_list[0] + ' -h', shell=True)
177+
sys.exit(0)
178+
156179
coverage = None
157180

158181
if ENABLE_COVERAGE:
159182
coverage = RPCCoverage()
160183
print("Initializing coverage directory at %s\n" % coverage.dir)
161-
162-
rpcTestDir = buildDir + '/qa/rpc-tests/'
163-
run_extended = '-extended' in opts
164-
cov_flag = coverage.flag if coverage else ''
165-
flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn)
184+
flags = " --srcdir %s/src %s %s" % (BUILDDIR, coverage.flag if coverage else '', passon_args)
166185

167186
#Run Tests
168-
for i in range(len(testScripts)):
169-
if (len(opts) == 0
170-
or (len(opts) == 1 and "-win" in opts )
171-
or run_extended
172-
or testScripts[i] in opts
173-
or re.sub(".py$", "", testScripts[i]) in opts ):
174-
175-
print("Running testscript %s%s%s ..." % (bold[1], testScripts[i], bold[0]))
176-
time0 = time.time()
177-
subprocess.check_call(
178-
rpcTestDir + testScripts[i] + flags, shell=True)
179-
print("Duration: %s s\n" % (int(time.time() - time0)))
180-
181-
# exit if help is called so we print just one set of
182-
# instructions
183-
p = re.compile(" -h| --help")
184-
if p.match(passOn):
185-
sys.exit(0)
186-
187-
# Run Extended Tests
188-
for i in range(len(testScriptsExt)):
189-
if (run_extended or testScriptsExt[i] in opts
190-
or re.sub(".py$", "", testScriptsExt[i]) in opts):
191-
192-
print(
193-
"Running 2nd level testscript "
194-
+ "%s%s%s ..." % (bold[1], testScriptsExt[i], bold[0]))
187+
for t in test_list:
188+
print("Running testscript %s%s%s ..." % (BOLD[1], t, BOLD[0]))
195189
time0 = time.time()
196190
subprocess.check_call(
197-
rpcTestDir + testScriptsExt[i] + flags, shell=True)
191+
RPC_TESTS_DIR + t + flags, shell=True)
198192
print("Duration: %s s\n" % (int(time.time() - time0)))
199193

200194
if coverage:

qa/rpc-tests/test_framework/test_framework.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def main(self):
115115

116116
if self.options.trace_rpc:
117117
import logging
118-
logging.basicConfig(level=logging.DEBUG)
118+
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
119119

120120
if self.options.coveragedir:
121121
enable_coverage(self.options.coveragedir)
@@ -148,6 +148,8 @@ def main(self):
148148
except Exception as e:
149149
print("Unexpected exception caught during testing: " + repr(e))
150150
traceback.print_tb(sys.exc_info()[2])
151+
except KeyboardInterrupt as e:
152+
print("Exiting after " + repr(e))
151153

152154
if not self.options.noshutdown:
153155
print("Stopping nodes")

qa/rpc-tests/test_framework/util.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from base64 import b64encode
1717
from decimal import Decimal, ROUND_DOWN
1818
import json
19+
import http.client
1920
import random
2021
import shutil
2122
import subprocess
@@ -28,6 +29,13 @@
2829

2930
COVERAGE_DIR = None
3031

32+
# The maximum number of nodes a single test can spawn
33+
MAX_NODES = 8
34+
# Don't assign rpc or p2p ports lower than this
35+
PORT_MIN = 11000
36+
# The number of ports to "reserve" for p2p and rpc, each
37+
PORT_RANGE = 5000
38+
3139
#Set Mocktime default to OFF.
3240
#MOCKTIME is only needed for scripts that use the
3341
#cached version of the blockchain. If the cached
@@ -82,9 +90,11 @@ def get_rpc_proxy(url, node_number, timeout=None):
8290

8391

8492
def p2p_port(n):
85-
return 11000 + n + os.getpid()%999
93+
assert(n <= MAX_NODES)
94+
return PORT_MIN + n + (MAX_NODES * os.getpid()) % (PORT_RANGE - 1 - MAX_NODES)
95+
8696
def rpc_port(n):
87-
return 12000 + n + os.getpid()%999
97+
return PORT_MIN + PORT_RANGE + n + (MAX_NODES * os.getpid()) % (PORT_RANGE -1 - MAX_NODES)
8898

8999
def check_json_precision():
90100
"""Make sure json library being used does not lose precision converting BTC values"""
@@ -292,8 +302,8 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None):
292302
"""
293303
Start multiple bitcoinds, return RPC connections to them
294304
"""
295-
if extra_args is None: extra_args = [ None for i in range(num_nodes) ]
296-
if binary is None: binary = [ None for i in range(num_nodes) ]
305+
if extra_args is None: extra_args = [ None for _ in range(num_nodes) ]
306+
if binary is None: binary = [ None for _ in range(num_nodes) ]
297307
rpcs = []
298308
try:
299309
for i in range(num_nodes):
@@ -307,13 +317,19 @@ def log_filename(dirname, n_node, logname):
307317
return os.path.join(dirname, "node"+str(n_node), "regtest", logname)
308318

309319
def stop_node(node, i):
310-
node.stop()
320+
try:
321+
node.stop()
322+
except http.client.CannotSendRequest as e:
323+
print("WARN: Unable to stop node: " + repr(e))
311324
bitcoind_processes[i].wait()
312325
del bitcoind_processes[i]
313326

314327
def stop_nodes(nodes):
315328
for node in nodes:
316-
node.stop()
329+
try:
330+
node.stop()
331+
except http.client.CannotSendRequest as e:
332+
print("WARN: Unable to stop node: " + repr(e))
317333
del nodes[:] # Emptying array closes connections as a side effect
318334

319335
def set_node_times(nodes, t):

qa/rpc-tests/walletbackup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
from test_framework.util import *
3838
from random import randint
3939
import logging
40-
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
40+
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO, stream=sys.stdout)
4141

4242
class WalletBackupTest(BitcoinTestFramework):
4343

0 commit comments

Comments
 (0)