2
2
# Copyright (c) 2014-2016 The Bitcoin Core developers
3
3
# Distributed under the MIT software license, see the accompanying
4
4
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
-
6
5
"""
7
- Run Regression Test Suite
6
+ rpc-tests.py - run regression test suite
8
7
9
8
This module calls down into individual test cases via subprocess. It will
10
- forward all unrecognized arguments onto the individual test scripts, other
11
- than:
9
+ forward all unrecognized arguments onto the individual test scripts.
12
10
13
- - `-extended`: run the "extended" test suite in addition to the basic one.
14
- - `-win`: signal that this is running in a Windows environment, and we
15
- should run the tests.
16
- - `--coverage`: this generates a basic coverage report for the RPC
17
- interface.
11
+ RPC tests are disabled on Windows by default. Use --force to run them anyway.
18
12
19
13
For a description of arguments recognized by test scripts, see
20
14
`qa/pull-tester/test_framework/test_framework.py:BitcoinTestFramework.main`.
21
15
22
16
"""
23
17
18
+ import argparse
19
+ import configparser
24
20
import os
25
21
import time
26
22
import shutil
29
25
import tempfile
30
26
import re
31
27
32
- sys .path .append ("qa/pull-tester/" )
33
- from tests_config import *
34
-
35
- BOLD = ("" ,"" )
36
- if os .name == 'posix' :
37
- # primitive formatting on supported
38
- # terminal via ANSI escape sequences:
39
- BOLD = ('\033 [0m' , '\033 [1m' )
40
-
41
- RPC_TESTS_DIR = SRCDIR + '/qa/rpc-tests/'
42
-
43
- #If imported values are not defined then set to zero (or disabled)
44
- if 'ENABLE_WALLET' not in vars ():
45
- ENABLE_WALLET = 0
46
- if 'ENABLE_BITCOIND' not in vars ():
47
- ENABLE_BITCOIND = 0
48
- if 'ENABLE_UTILS' not in vars ():
49
- ENABLE_UTILS = 0
50
- if 'ENABLE_ZMQ' not in vars ():
51
- ENABLE_ZMQ = 0
52
-
53
- ENABLE_COVERAGE = 0
54
-
55
- #Create a set to store arguments and create the passon string
56
- opts = set ()
57
- passon_args = []
58
- PASSON_REGEX = re .compile ("^--" )
59
- PARALLEL_REGEX = re .compile ('^-parallel=' )
60
-
61
- print_help = False
62
- run_parallel = 4
63
-
64
- for arg in sys .argv [1 :]:
65
- if arg == "--help" or arg == "-h" or arg == "-?" :
66
- print_help = True
67
- break
68
- if arg == '--coverage' :
69
- ENABLE_COVERAGE = 1
70
- elif PASSON_REGEX .match (arg ):
71
- passon_args .append (arg )
72
- elif PARALLEL_REGEX .match (arg ):
73
- run_parallel = int (arg .split (sep = '=' , maxsplit = 1 )[1 ])
74
- else :
75
- opts .add (arg )
76
-
77
- #Set env vars
78
- if "BITCOIND" not in os .environ :
79
- os .environ ["BITCOIND" ] = BUILDDIR + '/src/bitcoind' + EXEEXT
80
-
81
- if EXEEXT == ".exe" and "-win" not in opts :
82
- # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9
83
- # https://github.com/bitcoin/bitcoin/pull/5677#issuecomment-136646964
84
- print ("Win tests currently disabled by default. Use -win option to enable" )
85
- sys .exit (0 )
86
-
87
- if not (ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1 ):
88
- print ("No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" )
89
- sys .exit (0 )
90
-
91
- # python3-zmq may not be installed. Handle this gracefully and with some helpful info
92
- if ENABLE_ZMQ :
93
- try :
94
- import zmq
95
- except ImportError :
96
- print ("ERROR: \" import zmq\" failed. Set ENABLE_ZMQ=0 or "
97
- "to run zmq tests, see dependency info in /qa/README.md." )
98
- # ENABLE_ZMQ=0
99
- raise
100
-
101
- testScripts = [
102
- # longest test should go first, to favor running tests in parallel
28
+ BASE_SCRIPTS = [
29
+ # Scripts that are run by the travis build process.
30
+ # Longest test should go first, to favor running tests in parallel
103
31
'wallet-hd.py' ,
104
32
'walletbackup.py' ,
105
33
# vv Tests less than 5m vv
156
84
'listsinceblock.py' ,
157
85
'p2p-leaktests.py' ,
158
86
]
159
- if ENABLE_ZMQ :
160
- testScripts .append ('zmq_test.py' )
161
87
162
- testScriptsExt = [
88
+ ZMQ_SCRIPTS = [
89
+ # ZMQ test can only be run if bitcoin was built with zmq-enabled.
90
+ # call rpc_tests.py with -nozmq to explicitly exclude these tests.
91
+ "zmq_test.py" ]
92
+
93
+ EXTENDED_SCRIPTS = [
94
+ # These tests are not run by the travis build process.
95
+ # Longest test should go first, to favor running tests in parallel
163
96
'pruning.py' ,
164
97
# vv Tests less than 20m vv
165
98
'smartfees.py' ,
189
122
'replace-by-fee.py' ,
190
123
]
191
124
125
+ ALL_SCRIPTS = BASE_SCRIPTS + ZMQ_SCRIPTS + EXTENDED_SCRIPTS
126
+
127
+ def main ():
128
+ # Parse arguments and pass through unrecognised args
129
+ parser = argparse .ArgumentParser (add_help = False ,
130
+ usage = '%(prog)s [rpc-test.py options] [script options] [scripts]' ,
131
+ description = __doc__ ,
132
+ epilog = '''
133
+ Help text and arguments for individual test script:''' ,
134
+ formatter_class = argparse .RawTextHelpFormatter )
135
+ parser .add_argument ('--coverage' , action = 'store_true' , help = 'generate a basic coverage report for the RPC interface' )
136
+ parser .add_argument ('--extended' , action = 'store_true' , help = 'run the extended test suite in addition to the basic tests' )
137
+ parser .add_argument ('--force' , '-f' , action = 'store_true' , help = 'run tests even on platforms where they are disabled by default (e.g. windows).' )
138
+ parser .add_argument ('--help' , '-h' , '-?' , action = 'store_true' , help = 'print help text and exit' )
139
+ parser .add_argument ('--jobs' , '-j' , type = int , default = 4 , help = 'how many test scripts to run in parallel. Default=4.' )
140
+ parser .add_argument ('--nozmq' , action = 'store_true' , help = 'do not run the zmq tests' )
141
+ args , unknown_args = parser .parse_known_args ()
142
+
143
+ # Create a set to store arguments and create the passon string
144
+ tests = set (arg for arg in unknown_args if arg [:2 ] != "--" )
145
+ passon_args = [arg for arg in unknown_args if arg [:2 ] == "--" ]
146
+
147
+ # Read config generated by configure.
148
+ config = configparser .ConfigParser ()
149
+ config .read_file (open (os .path .dirname (__file__ ) + "/tests_config.ini" ))
150
+
151
+ enable_wallet = config ["components" ].getboolean ("ENABLE_WALLET" )
152
+ enable_utils = config ["components" ].getboolean ("ENABLE_UTILS" )
153
+ enable_bitcoind = config ["components" ].getboolean ("ENABLE_BITCOIND" )
154
+ enable_zmq = config ["components" ].getboolean ("ENABLE_ZMQ" ) and not args .nozmq
155
+
156
+ if config ["environment" ]["EXEEXT" ] == ".exe" and not args .force :
157
+ # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9
158
+ # https://github.com/bitcoin/bitcoin/pull/5677#issuecomment-136646964
159
+ print ("Tests currently disabled on Windows by default. Use --force option to enable" )
160
+ sys .exit (0 )
192
161
193
- def runtests ():
194
- test_list = []
195
- if '-extended' in opts :
196
- test_list = testScripts + testScriptsExt
197
- elif len (opts ) == 0 or (len (opts ) == 1 and "-win" in opts ):
198
- test_list = testScripts
199
- else :
200
- for t in testScripts + testScriptsExt :
201
- if t in opts or re .sub (".py$" , "" , t ) in opts :
202
- test_list .append (t )
162
+ if not (enable_wallet and enable_utils and enable_bitcoind ):
163
+ print ("No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" )
164
+ print ("Rerun `configure` with -enable-wallet, -with-utils and -with-daemon and rerun make" )
165
+ sys .exit (0 )
166
+
167
+ # python3-zmq may not be installed. Handle this gracefully and with some helpful info
168
+ if enable_zmq :
169
+ try :
170
+ import zmq
171
+ except ImportError :
172
+ print ("ERROR: \" import zmq\" failed. Use -nozmq to run without the ZMQ tests."
173
+ "To run zmq tests, see dependency info in /qa/README.md." )
174
+ raise
175
+
176
+ # Build list of tests
177
+ if tests :
178
+ # Individual tests have been specified. Run specified tests that exist
179
+ # in the ALL_SCRIPTS list. Accept the name with or without .py extension.
180
+ test_list = [t for t in ALL_SCRIPTS if
181
+ (t in tests or re .sub (".py$" , "" , t ) in tests )]
182
+ if not test_list :
183
+ print ("No valid test scripts specified. Check that your test is in one "
184
+ "of the test lists in rpc-tests.py or run rpc-tests.py with no arguments to run all tests" )
185
+ print ("Scripts not found:" )
186
+ print (tests )
187
+ sys .exit (0 )
203
188
204
- if print_help :
205
- # Only print help of the first script and exit
206
- subprocess .check_call ((RPC_TESTS_DIR + test_list [0 ]).split () + ['-h' ])
189
+ else :
190
+ # No individual tests have been specified. Run base tests, and
191
+ # optionally ZMQ tests and extended tests.
192
+ test_list = BASE_SCRIPTS
193
+ if enable_zmq :
194
+ test_list += ZMQ_SCRIPTS
195
+ if args .extended :
196
+ test_list += EXTENDED_SCRIPTS
197
+ # TODO: BASE_SCRIPTS and EXTENDED_SCRIPTS are sorted by runtime
198
+ # (for parallel running efficiency). This combined list will is no
199
+ # longer sorted.
200
+
201
+ if args .help :
202
+ # Print help for rpc-tests.py, then print help of the first script and exit.
203
+ parser .print_help ()
204
+ subprocess .check_call ((config ["environment" ]["SRCDIR" ] + '/qa/rpc-tests/' + test_list [0 ]).split () + ['-h' ])
207
205
sys .exit (0 )
208
206
209
- coverage = None
207
+ run_tests (test_list , config ["environment" ]["SRCDIR" ], config ["environment" ]["BUILDDIR" ], config ["environment" ]["EXEEXT" ], args .jobs , args .coverage , passon_args )
208
+
209
+ def run_tests (test_list , src_dir , build_dir , exeext , jobs = 1 , enable_coverage = False , args = []):
210
+ BOLD = ("" ,"" )
211
+ if os .name == 'posix' :
212
+ # primitive formatting on supported
213
+ # terminal via ANSI escape sequences:
214
+ BOLD = ('\033 [0m' , '\033 [1m' )
215
+
216
+ #Set env vars
217
+ if "BITCOIND" not in os .environ :
218
+ os .environ ["BITCOIND" ] = build_dir + '/src/bitcoind' + exeext
219
+
220
+ tests_dir = src_dir + '/qa/rpc-tests/'
210
221
211
- if ENABLE_COVERAGE :
222
+ flags = ["--srcdir=" + src_dir ] + args
223
+ flags .append ("--cachedir=%s/qa/cache" % build_dir )
224
+
225
+ if enable_coverage :
212
226
coverage = RPCCoverage ()
213
- print ("Initializing coverage directory at %s\n " % coverage .dir )
214
- flags = ["--srcdir=%s/src" % BUILDDIR ] + passon_args
215
- flags .append ("--cachedir=%s/qa/cache" % BUILDDIR )
216
- if coverage :
217
227
flags .append (coverage .flag )
228
+ print ("Initializing coverage directory at %s\n " % coverage .dir )
229
+ else :
230
+ coverage = None
218
231
219
- if len (test_list ) > 1 and run_parallel > 1 :
232
+ if len (test_list ) > 1 and jobs > 1 :
220
233
# Populate cache
221
- subprocess .check_output ([RPC_TESTS_DIR + 'create_cache.py' ] + flags )
234
+ subprocess .check_output ([tests_dir + 'create_cache.py' ] + flags )
222
235
223
236
#Run Tests
224
- max_len_name = len ( max ( test_list , key = len ))
237
+ all_passed = True
225
238
time_sum = 0
226
239
time0 = time .time ()
227
- job_queue = RPCTestHandler (run_parallel , test_list , flags )
240
+
241
+ job_queue = RPCTestHandler (jobs , tests_dir , test_list , flags )
242
+
243
+ max_len_name = len (max (test_list , key = len ))
228
244
results = BOLD [1 ] + "%s | %s | %s\n \n " % ("TEST" .ljust (max_len_name ), "PASSED" , "DURATION" ) + BOLD [0 ]
229
- all_passed = True
230
245
for _ in range (len (test_list )):
231
246
(name , stdout , stderr , passed , duration ) = job_queue .get_next ()
232
247
all_passed = all_passed and passed
@@ -235,8 +250,10 @@ def runtests():
235
250
print ('\n ' + BOLD [1 ] + name + BOLD [0 ] + ":" )
236
251
print ('' if passed else stdout + '\n ' , end = '' )
237
252
print ('' if stderr == '' else 'stderr:\n ' + stderr + '\n ' , end = '' )
238
- results += "%s | %s | %s s\n " % (name .ljust (max_len_name ), str (passed ).ljust (6 ), duration )
239
253
print ("Pass: %s%s%s, Duration: %s s\n " % (BOLD [1 ], passed , BOLD [0 ], duration ))
254
+
255
+ results += "%s | %s | %s s\n " % (name .ljust (max_len_name ), str (passed ).ljust (6 ), duration )
256
+
240
257
results += BOLD [1 ] + "\n %s | %s | %s s (accumulated)" % ("ALL" .ljust (max_len_name ), str (all_passed ).ljust (6 ), time_sum ) + BOLD [0 ]
241
258
print (results )
242
259
print ("\n Runtime: %s s" % (int (time .time () - time0 )))
@@ -249,15 +266,15 @@ def runtests():
249
266
250
267
sys .exit (not all_passed )
251
268
252
-
253
269
class RPCTestHandler :
254
270
"""
255
271
Trigger the testscrips passed in via the list.
256
272
"""
257
273
258
- def __init__ (self , num_tests_parallel , test_list = None , flags = None ):
274
+ def __init__ (self , num_tests_parallel , tests_dir , test_list = None , flags = None ):
259
275
assert (num_tests_parallel >= 1 )
260
276
self .num_jobs = num_tests_parallel
277
+ self .tests_dir = tests_dir
261
278
self .test_list = test_list
262
279
self .flags = flags
263
280
self .num_running = 0
@@ -277,7 +294,7 @@ def get_next(self):
277
294
log_stderr = tempfile .SpooledTemporaryFile (max_size = 2 ** 16 )
278
295
self .jobs .append ((t ,
279
296
time .time (),
280
- subprocess .Popen ((RPC_TESTS_DIR + t ).split () + self .flags + port_seed ,
297
+ subprocess .Popen ((self . tests_dir + t ).split () + self .flags + port_seed ,
281
298
universal_newlines = True ,
282
299
stdout = log_stdout ,
283
300
stderr = log_stderr ),
@@ -342,10 +359,10 @@ def _get_uncovered_rpc_commands(self):
342
359
343
360
"""
344
361
# This is shared from `qa/rpc-tests/test-framework/coverage.py`
345
- REFERENCE_FILENAME = 'rpc_interface.txt'
346
- COVERAGE_FILE_PREFIX = 'coverage.'
362
+ reference_filename = 'rpc_interface.txt'
363
+ coverage_file_prefix = 'coverage.'
347
364
348
- coverage_ref_filename = os .path .join (self .dir , REFERENCE_FILENAME )
365
+ coverage_ref_filename = os .path .join (self .dir , reference_filename )
349
366
coverage_filenames = set ()
350
367
all_cmds = set ()
351
368
covered_cmds = set ()
@@ -358,7 +375,7 @@ def _get_uncovered_rpc_commands(self):
358
375
359
376
for root , dirs , files in os .walk (self .dir ):
360
377
for filename in files :
361
- if filename .startswith (COVERAGE_FILE_PREFIX ):
378
+ if filename .startswith (coverage_file_prefix ):
362
379
coverage_filenames .add (os .path .join (root , filename ))
363
380
364
381
for filename in coverage_filenames :
@@ -369,4 +386,4 @@ def _get_uncovered_rpc_commands(self):
369
386
370
387
371
388
if __name__ == '__main__' :
372
- runtests ()
389
+ main ()
0 commit comments