tests: have combine_logs default to most recent test dir
This commit is contained in:
parent
a4eaaa6ac5
commit
4aabadbf44
2 changed files with 51 additions and 9 deletions
|
@ -2,7 +2,9 @@
|
||||||
"""Combine logs from multiple bitcoin nodes as well as the test_framework log.
|
"""Combine logs from multiple bitcoin nodes as well as the test_framework log.
|
||||||
|
|
||||||
This streams the combined log output to stdout. Use combine_logs.py > outputfile
|
This streams the combined log output to stdout. Use combine_logs.py > outputfile
|
||||||
to write to an outputfile."""
|
to write to an outputfile.
|
||||||
|
|
||||||
|
If no argument is provided, the most recent test directory will be used."""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
from collections import defaultdict, namedtuple
|
from collections import defaultdict, namedtuple
|
||||||
|
@ -11,6 +13,13 @@ import itertools
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
# N.B.: don't import any local modules here - this script must remain executable
|
||||||
|
# without the parent module installed.
|
||||||
|
|
||||||
|
# Should match same symbol in `test_framework.test_framework`.
|
||||||
|
TMPDIR_PREFIX = "bitcoin_func_test_"
|
||||||
|
|
||||||
# Matches on the date format at the start of the log event
|
# Matches on the date format at the start of the log event
|
||||||
TIMESTAMP_PATTERN = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{6})?Z")
|
TIMESTAMP_PATTERN = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{6})?Z")
|
||||||
|
@ -19,22 +28,30 @@ LogEvent = namedtuple('LogEvent', ['timestamp', 'source', 'event'])
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main function. Parses args, reads the log files and renders them as text or html."""
|
"""Main function. Parses args, reads the log files and renders them as text or html."""
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
parser = argparse.ArgumentParser(usage='%(prog)s [options] <test temporary directory>', description=__doc__)
|
description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
|
||||||
|
parser.add_argument(
|
||||||
|
'testdir', nargs='?', default='',
|
||||||
|
help=('temporary test directory to combine logs from. '
|
||||||
|
'Defaults to the most recent'))
|
||||||
parser.add_argument('-c', '--color', dest='color', action='store_true', help='outputs the combined log with events colored by source (requires posix terminal colors. Use less -r for viewing)')
|
parser.add_argument('-c', '--color', dest='color', action='store_true', help='outputs the combined log with events colored by source (requires posix terminal colors. Use less -r for viewing)')
|
||||||
parser.add_argument('--html', dest='html', action='store_true', help='outputs the combined log as html. Requires jinja2. pip install jinja2')
|
parser.add_argument('--html', dest='html', action='store_true', help='outputs the combined log as html. Requires jinja2. pip install jinja2')
|
||||||
args, unknown_args = parser.parse_known_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.html and args.color:
|
if args.html and args.color:
|
||||||
print("Only one out of --color or --html should be specified")
|
print("Only one out of --color or --html should be specified")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# There should only be one unknown argument - the path of the temporary test directory
|
testdir = args.testdir or find_latest_test_dir()
|
||||||
if len(unknown_args) != 1:
|
|
||||||
print("Unexpected arguments" + str(unknown_args))
|
if not testdir:
|
||||||
|
print("No test directories found")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
log_events = read_logs(unknown_args[0])
|
if not args.testdir:
|
||||||
|
print("Opening latest test directory: {}".format(testdir), file=sys.stderr)
|
||||||
|
|
||||||
|
log_events = read_logs(testdir)
|
||||||
|
|
||||||
print_logs(log_events, color=args.color, html=args.html)
|
print_logs(log_events, color=args.color, html=args.html)
|
||||||
|
|
||||||
|
@ -53,6 +70,29 @@ def read_logs(tmp_dir):
|
||||||
|
|
||||||
return heapq.merge(*[get_log_events(source, f) for source, f in files])
|
return heapq.merge(*[get_log_events(source, f) for source, f in files])
|
||||||
|
|
||||||
|
|
||||||
|
def find_latest_test_dir():
|
||||||
|
"""Returns the latest tmpfile test directory prefix."""
|
||||||
|
tmpdir = tempfile.gettempdir()
|
||||||
|
|
||||||
|
def join_tmp(basename):
|
||||||
|
return os.path.join(tmpdir, basename)
|
||||||
|
|
||||||
|
def is_valid_test_tmpdir(basename):
|
||||||
|
fullpath = join_tmp(basename)
|
||||||
|
return (
|
||||||
|
os.path.isdir(fullpath)
|
||||||
|
and basename.startswith(TMPDIR_PREFIX)
|
||||||
|
and os.access(fullpath, os.R_OK)
|
||||||
|
)
|
||||||
|
|
||||||
|
testdir_paths = [
|
||||||
|
join_tmp(name) for name in os.listdir(tmpdir) if is_valid_test_tmpdir(name)
|
||||||
|
]
|
||||||
|
|
||||||
|
return max(testdir_paths, key=os.path.getmtime) if testdir_paths else None
|
||||||
|
|
||||||
|
|
||||||
def get_log_events(source, logfile):
|
def get_log_events(source, logfile):
|
||||||
"""Generator function that returns individual log events.
|
"""Generator function that returns individual log events.
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ TEST_EXIT_PASSED = 0
|
||||||
TEST_EXIT_FAILED = 1
|
TEST_EXIT_FAILED = 1
|
||||||
TEST_EXIT_SKIPPED = 77
|
TEST_EXIT_SKIPPED = 77
|
||||||
|
|
||||||
|
TMPDIR_PREFIX = "bitcoin_func_test_"
|
||||||
|
|
||||||
|
|
||||||
class SkipTest(Exception):
|
class SkipTest(Exception):
|
||||||
"""This exception is raised to skip a test"""
|
"""This exception is raised to skip a test"""
|
||||||
|
@ -151,7 +153,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||||
self.options.tmpdir = os.path.abspath(self.options.tmpdir)
|
self.options.tmpdir = os.path.abspath(self.options.tmpdir)
|
||||||
os.makedirs(self.options.tmpdir, exist_ok=False)
|
os.makedirs(self.options.tmpdir, exist_ok=False)
|
||||||
else:
|
else:
|
||||||
self.options.tmpdir = tempfile.mkdtemp(prefix="test")
|
self.options.tmpdir = tempfile.mkdtemp(prefix=TMPDIR_PREFIX)
|
||||||
self._start_logging()
|
self._start_logging()
|
||||||
|
|
||||||
self.log.debug('Setting up network thread')
|
self.log.debug('Setting up network thread')
|
||||||
|
|
Loading…
Reference in a new issue