diff --git a/scripts/zfs-tests.sh b/scripts/zfs-tests.sh index 80b7f26e5750..60499e09e249 100755 --- a/scripts/zfs-tests.sh +++ b/scripts/zfs-tests.sh @@ -52,7 +52,7 @@ ITERATIONS=1 ZFS_DBGMSG="$STF_SUITE/callbacks/zfs_dbgmsg.ksh" ZFS_DMESG="$STF_SUITE/callbacks/zfs_dmesg.ksh" UNAME=$(uname -s) -RERUN="no" +RERUN="" # Override some defaults if on FreeBSD if [ "$UNAME" = "FreeBSD" ] ; then @@ -703,22 +703,35 @@ ${TEST_RUNNER} ${QUIET:+-q} \ -i "${STF_SUITE}" \ -I "${ITERATIONS}" \ 2>&1 | tee "$RESULTS_FILE" -if [ "$RERUN" = "yes" ]; then - cp "$RESULTS_FILE" "$REPORT_FILE" +# +# Analyze the results. +# +${ZTS_REPORT} ${RERUN:+--no-maybes} "$RESULTS_FILE" >"$REPORT_FILE" +RESULT=$? + +if [ "$RESULT" -eq "2" ] && [ -n "$RERUN" ]; then + MAYBES="$($ZTS_REPORT --list-maybes)" + TEMP_RESULTS_FILE=$(mktemp -u -t zts-results-tmp.XXXXX -p "$FILEDIR") + TEST_LIST=$(mktemp -u -t test-list.XXXXX -p "$FILEDIR") + grep "^Test:.*\[FAIL\]" "$RESULTS_FILE" >"$TEMP_RESULTS_FILE" + for test_name in $MAYBES; do + grep "$test_name " "$TEMP_RESULTS_FILE" >>"$TEST_LIST" + done ${TEST_RUNNER} ${QUIET:+-q} \ -c "${RUNFILES}" \ -T "${TAGS}" \ -i "${STF_SUITE}" \ -I "${ITERATIONS}" \ - -l "${REPORT_FILE}" \ + -l "${TEST_LIST}" \ 2>&1 | tee "$RESULTS_FILE" + # + # Analyze the results. + # + ${ZTS_REPORT} --no-maybes "$RESULTS_FILE" >"$REPORT_FILE" + RESULT=$? fi -# -# Analyze the results. -# -${ZTS_REPORT} "$RESULTS_FILE" >"$REPORT_FILE" -RESULT=$? + cat "$REPORT_FILE" RESULTS_DIR=$(awk '/^Log directory/ { print $3 }' "$RESULTS_FILE") diff --git a/tests/test-runner/bin/zts-report.py.in b/tests/test-runner/bin/zts-report.py.in index ce43d204fc9d..963bce55fe47 100755 --- a/tests/test-runner/bin/zts-report.py.in +++ b/tests/test-runner/bin/zts-report.py.in @@ -21,6 +21,7 @@ import os import re import sys +import argparse # # This script parses the stdout of zfstest, which has this format: @@ -379,11 +380,31 @@ def process_results(pathname): return d +class ListMaybesAction(argparse.Action): + def __init__(self, + option_strings, + dest="SUPPRESS", + default="SUPPRESS", + help="list flaky tests and exit"): + super().__init__( + option_strings=option_strings, + dest=dest, + default=default, + nargs=0, + help=help) + def __call__(self, parser, namespace, values, option_string=None): + for test in maybe: + print(test) + sys.exit(0) if __name__ == "__main__": - if len(sys.argv) != 2: - usage('usage: %s ' % sys.argv[0]) - results = process_results(sys.argv[1]) + parser = argparse.ArgumentParser(description='Analyze ZTS logs') + parser.add_argument('logfile') + parser.add_argument('--list-maybes', action=ListMaybesAction) + parser.add_argument('--no-maybes', action='store_false', dest='maybes') + args = parser.parse_args() + + results = process_results(args.logfile) if summary['total'] == 0: print("\n\nNo test results were found.") @@ -392,6 +413,7 @@ if __name__ == "__main__": expected = [] unexpected = [] + all_maybes = True for test in list(results.keys()): if results[test] == "PASS": @@ -404,11 +426,16 @@ if __name__ == "__main__": if setup in maybe and maybe[setup][0] == "SKIP": continue - if ((test not in known or results[test] not in known[test][0]) and - (test not in maybe or results[test] not in maybe[test][0])): - unexpected.append(test) - else: + if (test in known and results[test] in known[test][0]): expected.append(test) + elif test in maybe and results[test] in maybe[test][0]: + if results[test] == 'SKIP' or args.maybes: + expected.append(test) + elif not args.maybes: + unexpected.append(test) + else: + unexpected.append(test) + all_maybes = False print("\nTests with results other than PASS that are expected:") for test in sorted(expected): @@ -454,5 +481,7 @@ if __name__ == "__main__": if len(unexpected) == 0: sys.exit(0) + elif not args.maybes and all_maybes: + sys.exit(2) else: sys.exit(1)