22# Copyright (c) 2014-2016 The Bitcoin Core developers
33# Distributed under the MIT software license, see the accompanying
44# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5-
65"""
7- Run Regression Test Suite
6+ rpc-tests.py - run regression test suite
87
98This 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.
1210
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.
1812
1913For a description of arguments recognized by test scripts, see
2014`qa/pull-tester/test_framework/test_framework.py:BitcoinTestFramework.main`.
2115
2216"""
2317
18+ import argparse
19+ import configparser
2420import os
2521import time
2622import shutil
2925import tempfile
3026import re
3127
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
10331 'wallet-hd.py' ,
10432 'walletbackup.py' ,
10533 # vv Tests less than 5m vv
15684 'listsinceblock.py' ,
15785 'p2p-leaktests.py' ,
15886]
159- if ENABLE_ZMQ :
160- testScripts .append ('zmq_test.py' )
16187
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
16396 'pruning.py' ,
16497 # vv Tests less than 20m vv
16598 'smartfees.py' ,
189122 'replace-by-fee.py' ,
190123]
191124
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 )
192161
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 )
203188
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' ])
207205 sys .exit (0 )
208206
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/'
210221
211- if ENABLE_COVERAGE :
222+ flags = ["--srcdir=" + src_dir ] + args
223+ flags .append ("--cachedir=%s/qa/cache" % build_dir )
224+
225+ if enable_coverage :
212226 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 :
217227 flags .append (coverage .flag )
228+ print ("Initializing coverage directory at %s\n " % coverage .dir )
229+ else :
230+ coverage = None
218231
219- if len (test_list ) > 1 and run_parallel > 1 :
232+ if len (test_list ) > 1 and jobs > 1 :
220233 # Populate cache
221- subprocess .check_output ([RPC_TESTS_DIR + 'create_cache.py' ] + flags )
234+ subprocess .check_output ([tests_dir + 'create_cache.py' ] + flags )
222235
223236 #Run Tests
224- max_len_name = len ( max ( test_list , key = len ))
237+ all_passed = True
225238 time_sum = 0
226239 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 ))
228244 results = BOLD [1 ] + "%s | %s | %s\n \n " % ("TEST" .ljust (max_len_name ), "PASSED" , "DURATION" ) + BOLD [0 ]
229- all_passed = True
230245 for _ in range (len (test_list )):
231246 (name , stdout , stderr , passed , duration ) = job_queue .get_next ()
232247 all_passed = all_passed and passed
@@ -235,8 +250,10 @@ def runtests():
235250 print ('\n ' + BOLD [1 ] + name + BOLD [0 ] + ":" )
236251 print ('' if passed else stdout + '\n ' , end = '' )
237252 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 )
239253 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+
240257 results += BOLD [1 ] + "\n %s | %s | %s s (accumulated)" % ("ALL" .ljust (max_len_name ), str (all_passed ).ljust (6 ), time_sum ) + BOLD [0 ]
241258 print (results )
242259 print ("\n Runtime: %s s" % (int (time .time () - time0 )))
@@ -249,15 +266,15 @@ def runtests():
249266
250267 sys .exit (not all_passed )
251268
252-
253269class RPCTestHandler :
254270 """
255271 Trigger the testscrips passed in via the list.
256272 """
257273
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 ):
259275 assert (num_tests_parallel >= 1 )
260276 self .num_jobs = num_tests_parallel
277+ self .tests_dir = tests_dir
261278 self .test_list = test_list
262279 self .flags = flags
263280 self .num_running = 0
@@ -277,7 +294,7 @@ def get_next(self):
277294 log_stderr = tempfile .SpooledTemporaryFile (max_size = 2 ** 16 )
278295 self .jobs .append ((t ,
279296 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 ,
281298 universal_newlines = True ,
282299 stdout = log_stdout ,
283300 stderr = log_stderr ),
@@ -342,10 +359,10 @@ def _get_uncovered_rpc_commands(self):
342359
343360 """
344361 # 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.'
347364
348- coverage_ref_filename = os .path .join (self .dir , REFERENCE_FILENAME )
365+ coverage_ref_filename = os .path .join (self .dir , reference_filename )
349366 coverage_filenames = set ()
350367 all_cmds = set ()
351368 covered_cmds = set ()
@@ -358,7 +375,7 @@ def _get_uncovered_rpc_commands(self):
358375
359376 for root , dirs , files in os .walk (self .dir ):
360377 for filename in files :
361- if filename .startswith (COVERAGE_FILE_PREFIX ):
378+ if filename .startswith (coverage_file_prefix ):
362379 coverage_filenames .add (os .path .join (root , filename ))
363380
364381 for filename in coverage_filenames :
@@ -369,4 +386,4 @@ def _get_uncovered_rpc_commands(self):
369386
370387
371388if __name__ == '__main__' :
372- runtests ()
389+ main ()
0 commit comments