The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #!/usr/bin/env @PYTHON_SHEBANG@
    2 
    3 #
    4 # This file and its contents are supplied under the terms of the
    5 # Common Development and Distribution License ("CDDL"), version 1.0.
    6 # You may only use this file in accordance with the terms of version
    7 # 1.0 of the CDDL.
    8 #
    9 # A full copy of the text of the CDDL should have accompanied this
   10 # source.  A copy of the CDDL is also available via the Internet at
   11 # http://www.illumos.org/license/CDDL.
   12 #
   13 
   14 #
   15 # Copyright (c) 2017 by Delphix. All rights reserved.
   16 # Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
   17 #
   18 # This script must remain compatible with Python 3.6+.
   19 #
   20 
   21 import os
   22 import re
   23 import sys
   24 import argparse
   25 
   26 #
   27 # This script parses the stdout of zfstest, which has this format:
   28 #
   29 # Test: /path/to/testa (run as root) [00:00] [PASS]
   30 # Test: /path/to/testb (run as jkennedy) [00:00] [PASS]
   31 # Test: /path/to/testc (run as root) [00:00] [FAIL]
   32 # [...many more results...]
   33 #
   34 # Results Summary
   35 # FAIL      22
   36 # SKIP      32
   37 # PASS    1156
   38 #
   39 # Running Time:   02:50:31
   40 # Percent passed: 95.5%
   41 # Log directory:  /var/tmp/test_results/20180615T205926
   42 #
   43 
   44 #
   45 # Common generic reasons for a test or test group to be skipped.
   46 #
   47 # Some test cases are known to fail in ways which are not harmful or dangerous.
   48 # In these cases simply mark the test as a known failure until it can be
   49 # updated and the issue resolved.  Note that it's preferable to open a unique
   50 # issue on the GitHub issue tracker for each test case failure.
   51 #
   52 known_reason = 'Known issue'
   53 
   54 #
   55 # Some tests require that a test user be able to execute the zfs utilities.
   56 # This may not be possible when testing in-tree due to the default permissions
   57 # on the user's home directory.  When testing this can be resolved by granting
   58 # group read access.
   59 #
   60 # chmod 0750 $HOME
   61 #
   62 exec_reason = 'Test user execute permissions required for utilities'
   63 
   64 #
   65 # Some tests require that the kernel supports renameat2 syscall.
   66 #
   67 renameat2_reason = 'Kernel renameat2 support required'
   68 
   69 #
   70 # Some tests require the O_TMPFILE flag which was first introduced in the
   71 # 3.11 kernel.
   72 #
   73 tmpfile_reason = 'Kernel O_TMPFILE support required'
   74 
   75 #
   76 # Some tests require the statx(2) system call on Linux which was first
   77 # introduced in the 4.11 kernel.
   78 #
   79 statx_reason = 'Kernel statx(2) system call required on Linux'
   80 
   81 #
   82 # Some tests require that the lsattr utility support the project id feature.
   83 #
   84 project_id_reason = 'lsattr with set/show project ID required'
   85 
   86 #
   87 # Some tests require that the kernel support user namespaces.
   88 #
   89 user_ns_reason = 'Kernel user namespace support required'
   90 
   91 #
   92 # Some rewind tests can fail since nothing guarantees that old MOS blocks
   93 # are not overwritten.  Snapshots protect datasets and data files but not
   94 # the MOS.  Reasonable efforts are made in the test case to increase the
   95 # odds that some txgs will have their MOS data left untouched, but it is
   96 # never a sure thing.
   97 #
   98 rewind_reason = 'Arbitrary pool rewind is not guaranteed'
   99 
  100 #
  101 # Some tests require a minimum version of the fio benchmark utility.
  102 # Older distributions such as CentOS 6.x only provide fio-2.0.13.
  103 #
  104 fio_reason = 'Fio v2.3 or newer required'
  105 
  106 #
  107 # Some tests require that the DISKS provided support the discard operation.
  108 # Normally this is not an issue because loop back devices are used for DISKS
  109 # and they support discard (TRIM/UNMAP).
  110 #
  111 trim_reason = 'DISKS must support discard (TRIM/UNMAP)'
  112 
  113 #
  114 # Some tests on FreeBSD require the fspacectl(2) system call and the
  115 # truncate(1) utility supporting the -d option.  The system call was first
  116 # introduced in FreeBSD version 1400032.
  117 #
  118 fspacectl_reason = 'fspacectl(2) and truncate -d support required'
  119 
  120 #
  121 # Some tests are not applicable to a platform or need to be updated to operate
  122 # in the manor required by the platform.  Any tests which are skipped for this
  123 # reason will be suppressed in the final analysis output.
  124 #
  125 na_reason = "Not applicable"
  126 
  127 #
  128 # Some test cases doesn't have all requirements to run on Github actions CI.
  129 #
  130 ci_reason = 'CI runner doesn\'t have all requirements'
  131 
  132 #
  133 # Idmapped mount is only supported in kernel version >= 5.12
  134 #
  135 idmap_reason = 'Idmapped mount needs kernel 5.12+'
  136 
  137 #
  138 # These tests are known to fail, thus we use this list to prevent these
  139 # failures from failing the job as a whole; only unexpected failures
  140 # bubble up to cause this script to exit with a non-zero exit status.
  141 #
  142 # Format: { 'test-name': ['expected result', 'issue-number | reason'] }
  143 #
  144 # For each known failure it is recommended to link to a GitHub issue by
  145 # setting the reason to the issue number.  Alternately, one of the generic
  146 # reasons listed above can be used.
  147 #
  148 known = {
  149     'casenorm/mixed_none_lookup_ci': ['FAIL', 7633],
  150     'casenorm/mixed_formd_lookup_ci': ['FAIL', 7633],
  151     'cli_root/zpool_import/import_rewind_device_replaced':
  152         ['FAIL', rewind_reason],
  153     'cli_user/misc/zfs_share_001_neg': ['SKIP', na_reason],
  154     'cli_user/misc/zfs_unshare_001_neg': ['SKIP', na_reason],
  155     'privilege/setup': ['SKIP', na_reason],
  156     'refreserv/refreserv_004_pos': ['FAIL', known_reason],
  157     'rootpool/setup': ['SKIP', na_reason],
  158     'rsend/rsend_008_pos': ['SKIP', 6066],
  159     'vdev_zaps/vdev_zaps_007_pos': ['FAIL', known_reason],
  160 }
  161 
  162 if sys.platform.startswith('freebsd'):
  163     known.update({
  164         'cli_root/zfs_receive/receive-o-x_props_override':
  165             ['FAIL', known_reason],
  166         'cli_root/zpool_wait/zpool_wait_trim_basic': ['SKIP', trim_reason],
  167         'cli_root/zpool_wait/zpool_wait_trim_cancel': ['SKIP', trim_reason],
  168         'cli_root/zpool_wait/zpool_wait_trim_flag': ['SKIP', trim_reason],
  169         'cli_root/zfs_unshare/zfs_unshare_008_pos': ['SKIP', na_reason],
  170         'link_count/link_count_001': ['SKIP', na_reason],
  171         'casenorm/mixed_create_failure': ['FAIL', 13215],
  172         'mmap/mmap_sync_001_pos': ['SKIP', na_reason],
  173     })
  174 elif sys.platform.startswith('linux'):
  175     known.update({
  176         'casenorm/mixed_formd_lookup': ['FAIL', 7633],
  177         'casenorm/mixed_formd_delete': ['FAIL', 7633],
  178         'casenorm/sensitive_formd_lookup': ['FAIL', 7633],
  179         'casenorm/sensitive_formd_delete': ['FAIL', 7633],
  180         'removal/removal_with_zdb': ['SKIP', known_reason],
  181         'cli_root/zfs_unshare/zfs_unshare_002_pos': ['SKIP', na_reason],
  182     })
  183 
  184 
  185 #
  186 # These tests may occasionally fail or be skipped.  We want there failures
  187 # to be reported but only unexpected failures should bubble up to cause
  188 # this script to exit with a non-zero exit status.
  189 #
  190 # Format: { 'test-name': ['expected result', 'issue-number | reason'] }
  191 #
  192 # For each known failure it is recommended to link to a GitHub issue by
  193 # setting the reason to the issue number.  Alternately, one of the generic
  194 # reasons listed above can be used.
  195 #
  196 maybe = {
  197     'append/threadsappend_001_pos': ['FAIL', 6136],
  198     'chattr/setup': ['SKIP', exec_reason],
  199     'crtime/crtime_001_pos': ['SKIP', statx_reason],
  200     'cli_root/zdb/zdb_006_pos': ['FAIL', known_reason],
  201     'cli_root/zfs_destroy/zfs_destroy_dev_removal_condense':
  202         ['FAIL', known_reason],
  203     'cli_root/zfs_get/zfs_get_004_pos': ['FAIL', known_reason],
  204     'cli_root/zfs_get/zfs_get_009_pos': ['SKIP', 5479],
  205     'cli_root/zfs_rollback/zfs_rollback_001_pos': ['FAIL', known_reason],
  206     'cli_root/zfs_rollback/zfs_rollback_002_pos': ['FAIL', known_reason],
  207     'cli_root/zfs_snapshot/zfs_snapshot_002_neg': ['FAIL', known_reason],
  208     'cli_root/zfs_unshare/zfs_unshare_006_pos': ['SKIP', na_reason],
  209     'cli_root/zpool_add/zpool_add_004_pos': ['FAIL', known_reason],
  210     'cli_root/zpool_destroy/zpool_destroy_001_pos': ['SKIP', 6145],
  211     'cli_root/zpool_import/zpool_import_missing_003_pos': ['SKIP', 6839],
  212     'cli_root/zpool_initialize/zpool_initialize_import_export':
  213         ['FAIL', 11948],
  214     'cli_root/zpool_labelclear/zpool_labelclear_removed':
  215         ['FAIL', known_reason],
  216     'cli_root/zpool_trim/setup': ['SKIP', trim_reason],
  217     'cli_root/zpool_upgrade/zpool_upgrade_004_pos': ['FAIL', 6141],
  218     'delegate/setup': ['SKIP', exec_reason],
  219     'fallocate/fallocate_punch-hole': ['SKIP', fspacectl_reason],
  220     'history/history_004_pos': ['FAIL', 7026],
  221     'history/history_005_neg': ['FAIL', 6680],
  222     'history/history_006_neg': ['FAIL', 5657],
  223     'history/history_008_pos': ['FAIL', known_reason],
  224     'history/history_010_pos': ['SKIP', exec_reason],
  225     'io/mmap': ['SKIP', fio_reason],
  226     'largest_pool/largest_pool_001_pos': ['FAIL', known_reason],
  227     'mmp/mmp_on_uberblocks': ['FAIL', known_reason],
  228     'pam/setup': ['SKIP', "pamtester might be not available"],
  229     'pool_checkpoint/checkpoint_discard_busy': ['FAIL', 11946],
  230     'projectquota/setup': ['SKIP', exec_reason],
  231     'removal/removal_condense_export': ['FAIL', known_reason],
  232     'renameat2/setup': ['SKIP', renameat2_reason],
  233     'reservation/reservation_008_pos': ['FAIL', 7741],
  234     'reservation/reservation_018_pos': ['FAIL', 5642],
  235     'snapshot/clone_001_pos': ['FAIL', known_reason],
  236     'snapshot/snapshot_009_pos': ['FAIL', 7961],
  237     'snapshot/snapshot_010_pos': ['FAIL', 7961],
  238     'snapused/snapused_004_pos': ['FAIL', 5513],
  239     'tmpfile/setup': ['SKIP', tmpfile_reason],
  240     'trim/setup': ['SKIP', trim_reason],
  241     'upgrade/upgrade_projectquota_001_pos': ['SKIP', project_id_reason],
  242     'user_namespace/setup': ['SKIP', user_ns_reason],
  243     'userquota/setup': ['SKIP', exec_reason],
  244     'vdev_zaps/vdev_zaps_004_pos': ['FAIL', known_reason],
  245     'zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos': ['FAIL', 5848],
  246 }
  247 
  248 if sys.platform.startswith('freebsd'):
  249     maybe.update({
  250         'cli_root/zfs_copies/zfs_copies_002_pos': ['FAIL', known_reason],
  251         'cli_root/zfs_inherit/zfs_inherit_001_neg': ['FAIL', known_reason],
  252         'cli_root/zfs_share/zfs_share_concurrent_shares':
  253             ['FAIL', known_reason],
  254         'cli_root/zpool_import/zpool_import_012_pos': ['FAIL', known_reason],
  255         'delegate/zfs_allow_003_pos': ['FAIL', known_reason],
  256         'inheritance/inherit_001_pos': ['FAIL', 11829],
  257         'resilver/resilver_restart_001': ['FAIL', known_reason],
  258         'pool_checkpoint/checkpoint_big_rewind': ['FAIL', 12622],
  259         'pool_checkpoint/checkpoint_indirect': ['FAIL', 12623],
  260     })
  261 elif sys.platform.startswith('linux'):
  262     maybe.update({
  263         'cli_root/zfs_rename/zfs_rename_002_pos': ['FAIL', known_reason],
  264         'cli_root/zpool_reopen/zpool_reopen_003_pos': ['FAIL', known_reason],
  265         'fault/auto_online_002_pos': ['FAIL', 11889],
  266         'fault/auto_spare_002_pos': ['FAIL', 11889],
  267         'fault/auto_spare_multiple': ['FAIL', 11889],
  268         'fault/auto_spare_shared': ['FAIL', 11889],
  269         'fault/decompress_fault': ['FAIL', 11889],
  270         'io/io_uring': ['SKIP', 'io_uring support required'],
  271         'limits/filesystem_limit': ['SKIP', known_reason],
  272         'limits/snapshot_limit': ['SKIP', known_reason],
  273         'mmp/mmp_active_import': ['FAIL', known_reason],
  274         'mmp/mmp_exported_import': ['FAIL', known_reason],
  275         'mmp/mmp_inactive_import': ['FAIL', known_reason],
  276         'zvol/zvol_misc/zvol_misc_snapdev': ['FAIL', 12621],
  277         'zvol/zvol_misc/zvol_misc_volmode': ['FAIL', known_reason],
  278         'idmap_mount/idmap_mount_001': ['SKIP', idmap_reason],
  279         'idmap_mount/idmap_mount_002': ['SKIP', idmap_reason],
  280         'idmap_mount/idmap_mount_003': ['SKIP', idmap_reason],
  281         'idmap_mount/idmap_mount_004': ['SKIP', idmap_reason],
  282         'idmap_mount/idmap_mount_005': ['SKIP', idmap_reason],
  283     })
  284 
  285 
  286 # Not all Github actions runners have scsi_debug module, so we may skip
  287 #   some tests which use it.
  288 if os.environ.get('CI') == 'true':
  289     known.update({
  290         'cli_root/zpool_expand/zpool_expand_001_pos': ['SKIP', ci_reason],
  291         'cli_root/zpool_expand/zpool_expand_003_neg': ['SKIP', ci_reason],
  292         'cli_root/zpool_expand/zpool_expand_005_pos': ['SKIP', ci_reason],
  293         'cli_root/zpool_reopen/setup': ['SKIP', ci_reason],
  294         'cli_root/zpool_reopen/zpool_reopen_001_pos': ['SKIP', ci_reason],
  295         'cli_root/zpool_reopen/zpool_reopen_002_pos': ['SKIP', ci_reason],
  296         'cli_root/zpool_reopen/zpool_reopen_003_pos': ['SKIP', ci_reason],
  297         'cli_root/zpool_reopen/zpool_reopen_004_pos': ['SKIP', ci_reason],
  298         'cli_root/zpool_reopen/zpool_reopen_005_pos': ['SKIP', ci_reason],
  299         'cli_root/zpool_reopen/zpool_reopen_006_neg': ['SKIP', ci_reason],
  300         'cli_root/zpool_reopen/zpool_reopen_007_pos': ['SKIP', ci_reason],
  301         'cli_root/zpool_split/zpool_split_wholedisk': ['SKIP', ci_reason],
  302         'fault/auto_offline_001_pos': ['SKIP', ci_reason],
  303         'fault/auto_online_001_pos': ['SKIP', ci_reason],
  304         'fault/auto_online_002_pos': ['SKIP', ci_reason],
  305         'fault/auto_replace_001_pos': ['SKIP', ci_reason],
  306         'fault/auto_spare_ashift': ['SKIP', ci_reason],
  307         'fault/auto_spare_shared': ['SKIP', ci_reason],
  308         'procfs/pool_state': ['SKIP', ci_reason],
  309     })
  310 
  311     maybe.update({
  312         'events/events_002_pos': ['FAIL', 11546],
  313     })
  314 
  315 
  316 def process_results(pathname):
  317     try:
  318         f = open(pathname)
  319     except IOError as e:
  320         print('Error opening file:', e)
  321         sys.exit(1)
  322 
  323     prefix = '/zfs-tests/tests/(?:functional|perf/regression)/'
  324     pattern = \
  325         r'^Test(?:\s+\(\S+\))?:' + \
  326         rf'\s*\S*{prefix}(\S+)' + \
  327         r'\s*\(run as (\S+)\)\s*\[(\S+)\]\s*\[(\S+)\]'
  328     pattern_log = r'^\s*Log directory:\s*(\S*)'
  329 
  330     d = {}
  331     logdir = 'Could not determine log directory.'
  332     for line in f.readlines():
  333         m = re.match(pattern, line)
  334         if m and len(m.groups()) == 4:
  335             d[m.group(1)] = m.group(4)
  336             continue
  337 
  338         m = re.match(pattern_log, line)
  339         if m:
  340             logdir = m.group(1)
  341 
  342     return d, logdir
  343 
  344 
  345 class ListMaybesAction(argparse.Action):
  346     def __init__(self,
  347                  option_strings,
  348                  dest="SUPPRESS",
  349                  default="SUPPRESS",
  350                  help="list flaky tests and exit"):
  351         super(ListMaybesAction, self).__init__(
  352             option_strings=option_strings,
  353             dest=dest,
  354             default=default,
  355             nargs=0,
  356             help=help)
  357 
  358     def __call__(self, parser, namespace, values, option_string=None):
  359         for test in maybe:
  360             print(test)
  361         sys.exit(0)
  362 
  363 
  364 if __name__ == "__main__":
  365     parser = argparse.ArgumentParser(description='Analyze ZTS logs')
  366     parser.add_argument('logfile')
  367     parser.add_argument('--list-maybes', action=ListMaybesAction)
  368     parser.add_argument('--no-maybes', action='store_false', dest='maybes')
  369     args = parser.parse_args()
  370 
  371     results, logdir = process_results(args.logfile)
  372 
  373     if not results:
  374         print("\n\nNo test results were found.")
  375         print("Log directory:", logdir)
  376         sys.exit(0)
  377 
  378     expected = []
  379     unexpected = []
  380     all_maybes = True
  381 
  382     for test in list(results.keys()):
  383         if results[test] == "PASS":
  384             continue
  385 
  386         setup = test.replace(os.path.basename(test), "setup")
  387         if results[test] == "SKIP" and test != setup:
  388             if setup in known and known[setup][0] == "SKIP":
  389                 continue
  390             if setup in maybe and maybe[setup][0] == "SKIP":
  391                 continue
  392 
  393         if (test in known and results[test] in known[test][0]):
  394             expected.append(test)
  395         elif test in maybe and results[test] in maybe[test][0]:
  396             if results[test] == 'SKIP' or args.maybes:
  397                 expected.append(test)
  398             elif not args.maybes:
  399                 unexpected.append(test)
  400         else:
  401             unexpected.append(test)
  402             all_maybes = False
  403 
  404     print("\nTests with results other than PASS that are expected:")
  405     for test in sorted(expected):
  406         issue_url = 'https://github.com/openzfs/zfs/issues/'
  407 
  408         # Include the reason why the result is expected, given the following:
  409         # 1. Suppress test results which set the "Not applicable" reason.
  410         # 2. Numerical reasons are assumed to be GitHub issue numbers.
  411         # 3. When an entire test group is skipped only report the setup reason.
  412         if test in known:
  413             if known[test][1] == na_reason:
  414                 continue
  415             elif isinstance(known[test][1], int):
  416                 expect = f"{issue_url}{known[test][1]}"
  417             else:
  418                 expect = known[test][1]
  419         elif test in maybe:
  420             if isinstance(maybe[test][1], int):
  421                 expect = f"{issue_url}{maybe[test][1]}"
  422             else:
  423                 expect = maybe[test][1]
  424         elif setup in known and known[setup][0] == "SKIP" and setup != test:
  425             continue
  426         elif setup in maybe and maybe[setup][0] == "SKIP" and setup != test:
  427             continue
  428         else:
  429             expect = "UNKNOWN REASON"
  430         print(f"    {results[test]} {test} ({expect})")
  431 
  432     print("\nTests with result of PASS that are unexpected:")
  433     for test in sorted(known.keys()):
  434         # We probably should not be silently ignoring the case
  435         # where "test" is not in "results".
  436         if test not in results or results[test] != "PASS":
  437             continue
  438         print(f"    {results[test]} {test} (expected {known[test][0]})")
  439 
  440     print("\nTests with results other than PASS that are unexpected:")
  441     for test in sorted(unexpected):
  442         expect = "PASS" if test not in known else known[test][0]
  443         print(f"    {results[test]} {test} (expected {expect})")
  444 
  445     if len(unexpected) == 0:
  446         sys.exit(0)
  447     elif not args.maybes and all_maybes:
  448         sys.exit(2)
  449     else:
  450         sys.exit(1)

Cache object: 4bf3e8440f41e2637f64a7e2bf0a66aa


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.