Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_runner.py
Show All 19 Lines | |||||
import os | import os | ||||
import time | import time | ||||
import shutil | import shutil | ||||
import signal | import signal | ||||
import sys | import sys | ||||
import subprocess | import subprocess | ||||
import tempfile | import tempfile | ||||
import re | import re | ||||
import logging | |||||
BOLD = ("", "") | BOLD = ("", "") | ||||
RED = ("", "") | RED = ("", "") | ||||
GREEN = ("", "") | GREEN = ("", "") | ||||
if os.name == 'posix': | if os.name == 'posix': | ||||
# primitive formatting on supported | # primitive formatting on supported | ||||
# terminal via ANSI escape sequences: | # terminal via ANSI escape sequences: | ||||
BOLD = ('\033[0m', '\033[1m') | BOLD = ('\033[0m', '\033[1m') | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | def main(): | ||||
parser.add_argument('--extended', action='store_true', | parser.add_argument('--extended', action='store_true', | ||||
help='run the extended test suite in addition to the basic tests') | help='run the extended test suite in addition to the basic tests') | ||||
parser.add_argument('--force', '-f', action='store_true', | parser.add_argument('--force', '-f', action='store_true', | ||||
help='run tests even on platforms where they are disabled by default (e.g. windows).') | help='run tests even on platforms where they are disabled by default (e.g. windows).') | ||||
parser.add_argument('--help', '-h', '-?', | parser.add_argument('--help', '-h', '-?', | ||||
action='store_true', help='print help text and exit') | action='store_true', help='print help text and exit') | ||||
parser.add_argument('--jobs', '-j', type=int, default=4, | parser.add_argument('--jobs', '-j', type=int, default=4, | ||||
help='how many test scripts to run in parallel. Default=4.') | help='how many test scripts to run in parallel. Default=4.') | ||||
parser.add_argument('--quiet', '-q', action='store_true', | |||||
help='only print results summary and failure logs') | |||||
args, unknown_args = parser.parse_known_args() | args, unknown_args = parser.parse_known_args() | ||||
# Create a set to store arguments and create the passon string | # Create a set to store arguments and create the passon string | ||||
tests = set(arg for arg in unknown_args if arg[:2] != "--") | tests = set(arg for arg in unknown_args if arg[:2] != "--") | ||||
passon_args = [arg for arg in unknown_args if arg[:2] == "--"] | passon_args = [arg for arg in unknown_args if arg[:2] == "--"] | ||||
# Read config generated by configure. | # Read config generated by configure. | ||||
config = configparser.ConfigParser() | config = configparser.ConfigParser() | ||||
configfile = os.path.abspath(os.path.dirname(__file__)) + "/../config.ini" | configfile = os.path.abspath(os.path.dirname(__file__)) + "/../config.ini" | ||||
config.read_file(open(configfile)) | config.read_file(open(configfile)) | ||||
passon_args.append("--configfile=%s" % configfile) | passon_args.append("--configfile=%s" % configfile) | ||||
# Set up logging | |||||
logging_level = logging.INFO if args.quiet else logging.DEBUG | |||||
logging.basicConfig(format='%(message)s', level=logging_level) | |||||
enable_wallet = config["components"].getboolean("ENABLE_WALLET") | enable_wallet = config["components"].getboolean("ENABLE_WALLET") | ||||
enable_utils = config["components"].getboolean("ENABLE_UTILS") | enable_utils = config["components"].getboolean("ENABLE_UTILS") | ||||
enable_bitcoind = config["components"].getboolean("ENABLE_BITCOIND") | enable_bitcoind = config["components"].getboolean("ENABLE_BITCOIND") | ||||
if config["environment"]["EXEEXT"] == ".exe" and not args.force: | if config["environment"]["EXEEXT"] == ".exe" and not args.force: | ||||
# https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9 | # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9 | ||||
# https://github.com/bitcoin/bitcoin/pull/5677#issuecomment-136646964 | # https://github.com/bitcoin/bitcoin/pull/5677#issuecomment-136646964 | ||||
print( | print( | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=False, args=[]): | ||||
tests_dir = src_dir + '/test/functional/' | tests_dir = src_dir + '/test/functional/' | ||||
flags = ["--srcdir={}".format(src_dir)] + args | flags = ["--srcdir={}".format(src_dir)] + args | ||||
flags.append("--cachedir=%s/test/cache" % build_dir) | flags.append("--cachedir=%s/test/cache" % build_dir) | ||||
if enable_coverage: | if enable_coverage: | ||||
coverage = RPCCoverage() | coverage = RPCCoverage() | ||||
flags.append(coverage.flag) | flags.append(coverage.flag) | ||||
print("Initializing coverage directory at {dir}\n".format( | logging.debug("Initializing coverage directory at %s" % coverage.dir) | ||||
dir=coverage.dir)) | |||||
else: | else: | ||||
coverage = None | coverage = None | ||||
if len(test_list) > 1 and jobs > 1: | if len(test_list) > 1 and jobs > 1: | ||||
# Populate cache | # Populate cache | ||||
subprocess.check_output([tests_dir + 'create_cache.py'] + flags) | subprocess.check_output([tests_dir + 'create_cache.py'] + flags) | ||||
# Run Tests | # Run Tests | ||||
all_passed = True | all_passed = True | ||||
time_sum = 0 | time_sum = 0 | ||||
time0 = time.time() | time0 = time.time() | ||||
job_queue = TestHandler(jobs, tests_dir, test_list, flags) | job_queue = TestHandler(jobs, tests_dir, test_list, flags) | ||||
max_len_name = len(max(test_list, key=len)) | max_len_name = len(max(test_list, key=len)) | ||||
results = BOLD[1] + "%s | %s | %s\n\n" % ( | results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % ( | ||||
"TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] | "TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] | ||||
for _ in range(len(test_list)): | for _ in range(len(test_list)): | ||||
(name, stdout, stderr, status, duration) = job_queue.get_next() | (name, stdout, stderr, status, duration) = job_queue.get_next() | ||||
all_passed = all_passed and status != "Failed" | all_passed = all_passed and status != "Failed" | ||||
time_sum += duration | time_sum += duration | ||||
print('\n' + BOLD[1] + name + BOLD[0] + ":") | |||||
print('' if status == "Passed" else stdout + '\n', end='') | |||||
print('' if stderr == '' else 'stderr:\n' + stderr + '\n', end='') | |||||
print("Pass: {bold}{result}{unbold}, Duration: {duration}s\n".format( | |||||
bold=BOLD[1], result=status, unbold=BOLD[0], duration=duration)) | |||||
result = "{name} | {passed} | {duration}s\n".format(name=name.ljust( | |||||
max_len_name), passed=str(status).ljust(6), duration=duration) | |||||
if status == "Passed": | if status == "Passed": | ||||
results += GREEN[1] + result + GREEN[0] | logging.debug("\n%s%s%s passed, Duration: %s s" % | ||||
(BOLD[1], name, BOLD[0], duration)) | |||||
elif status == "Skipped": | |||||
logging.debug("\n%s%s%s skipped" % (BOLD[1], name, BOLD[0])) | |||||
else: | else: | ||||
results += RED[1] + result + RED[0] | print("\n%s%s%s failed, Duration: %s s\n" % | ||||
(BOLD[1], name, BOLD[0], duration)) | |||||
print(BOLD[1] + 'stdout:\n' + BOLD[0] + stdout + '\n') | |||||
print(BOLD[1] + 'stderr:\n' + BOLD[0] + stderr + '\n') | |||||
results += "%s | %s | %s s\n" % (name.ljust(max_len_name), | |||||
status.ljust(7), duration) | |||||
results += BOLD[1] + "\n{name} | {passed} | {duration}s (accumulated)".format( | results += BOLD[1] + "\n{name} | {passed} | {duration}s (accumulated)".format( | ||||
name="ALL".ljust(max_len_name), passed=str(all_passed).ljust(6), duration=time_sum) + BOLD[0] | name="ALL".ljust(max_len_name), passed=str(all_passed).ljust(6), duration=time_sum) + BOLD[0] | ||||
print(results) | print(results) | ||||
print("\nRuntime: {} s".format(int(time.time() - time0))) | print("\nRuntime: {} s".format(int(time.time() - time0))) | ||||
if coverage: | if coverage: | ||||
coverage.report_rpc_coverage() | coverage.report_rpc_coverage() | ||||
print("Cleaning up coverage data") | logging.debug("Cleaning up coverage data") | ||||
coverage.cleanup() | coverage.cleanup() | ||||
sys.exit(not all_passed) | sys.exit(not all_passed) | ||||
class TestHandler: | class TestHandler: | ||||
""" | """ | ||||
▲ Show 20 Lines • Show All 150 Lines • Show Last 20 Lines |