Skip to content

Commit

Permalink
tests: have combine_logs default to most recent test dir
Browse files Browse the repository at this point in the history
Summary:
Have combine_logs.py default to the most recent test directory if no argument is provided.
Backport of Core [[bitcoin/bitcoin#14683 | PR14683]]

Test Plan:
```
ninja
../test/functional/feature_bip68_sequence.py --configfile=./test/config.ini
../test/functional/combine_logs.py -c
```

Reviewers: O1 Bitcoin ABC, #bitcoin_abc, Fabien

Reviewed By: O1 Bitcoin ABC, #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D7795
  • Loading branch information
jamesob authored and PiRK committed Oct 7, 2020
1 parent 6cfb292 commit c60eca0
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 12 deletions.
62 changes: 51 additions & 11 deletions test/functional/combine_logs.py
Expand Up @@ -2,7 +2,9 @@
"""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
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
from collections import defaultdict, namedtuple
Expand All @@ -12,6 +14,13 @@
import os
import re
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
TIMESTAMP_PATTERN = re.compile(
Expand All @@ -22,26 +31,36 @@

def main():
"""Main function. Parses args, reads the log files and renders them as text or html."""

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)')
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')
args, unknown_args = parser.parse_known_args()
help='outputs the combined log as html. '
'Requires jinja2. pip install jinja2')
args = parser.parse_args()

if args.html and args.color:
print("Only one out of --color or --html should be specified")
sys.exit(1)

# There should only be one unknown argument - the path of the temporary
# test directory
if len(unknown_args) != 1:
print("Unexpected arguments" + str(unknown_args))
testdir = args.testdir or find_latest_test_dir()

if not testdir:
print("No test directories found")
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)

Expand Down Expand Up @@ -74,6 +93,27 @@ def read_logs(tmp_dir):
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):
"""Generator function that returns individual log events.
Expand Down
4 changes: 3 additions & 1 deletion test/functional/test_framework/test_framework.py
Expand Up @@ -49,6 +49,8 @@ class TestStatus(Enum):
# Timestamp is Dec. 1st, 2019 at 00:00:00
TIMESTAMP_IN_THE_PAST = 1575158400

TMPDIR_PREFIX = "bitcoin_func_test_"


class SkipTest(Exception):
"""This exception is raised to skip a test"""
Expand Down Expand Up @@ -170,7 +172,7 @@ def main(self):
self.options.tmpdir = os.path.abspath(self.options.tmpdir)
os.makedirs(self.options.tmpdir, exist_ok=False)
else:
self.options.tmpdir = tempfile.mkdtemp(prefix="test")
self.options.tmpdir = tempfile.mkdtemp(prefix=TMPDIR_PREFIX)
self._start_logging()

# Seed the PRNG. Note that test runs are reproducible if and only if
Expand Down

0 comments on commit c60eca0

Please sign in to comment.