xref: /petsc/config/report_tests.py (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
1#!/usr/bin/env python
2from __future__ import print_function
3import glob, os, re
4import optparse
5import inspect
6
7"""
8Quick script for parsing the output of the test system and summarizing the results.
9"""
10
11def inInstallDir():
12  """
13  When petsc is installed then this file in installed in:
14       <PREFIX>/share/petsc/examples/config/gmakegentest.py
15  otherwise the path is:
16       <PETSC_DIR>/config/gmakegentest.py
17  We use this difference to determine if we are in installdir
18  """
19  thisscriptdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
20  dirlist=thisscriptdir.split(os.path.sep)
21  if len(dirlist)>4:
22    lastfour=os.path.sep.join(dirlist[len(dirlist)-4:])
23    if lastfour==os.path.join('share','petsc','examples','config'):
24      return True
25    else:
26      return False
27  else:
28    return False
29
30def summarize_results(directory,make,ntime):
31  ''' Loop over all of the results files and summarize the results'''
32  startdir=os.path.realpath(os.path.curdir)
33  try:
34    os.chdir(directory)
35  except OSError:
36    print('# No tests run')
37    return
38  summary={'total':0,'success':0,'failed':0,'failures':[],'todo':0,'skip':0,
39           'time':0}
40  timesummary={}
41  timelist=[]
42  for cfile in glob.glob('*.counts'):
43    with open(cfile, 'r') as f:
44      for line in f:
45        l = line.split()
46        summary[l[0]] += l[1:] if l[0] == 'failures' else int(l[1])
47        if l[0] == 'time' and int(l[1])>0:
48            timesummary[cfile]=int(l[1])
49            timelist.append(int(l[1]))
50
51  failstr=' '.join(summary['failures'])
52  print("\n# -------------")
53  print("#   Summary    ")
54  print("# -------------")
55  if failstr.strip(): print("# FAILED " + failstr)
56
57  for t in "success failed todo skip".split():
58    percent=summary[t]/float(summary['total'])*100
59    print("# %s %d/%d tests (%3.1f%%)" % (t, summary[t], summary['total'], percent))
60  print("#\n# Approximate time (not incl. build time): %s sec"% summary['time'])
61
62  if failstr.strip():
63      fail_targets=(
64          re.sub('(?<=[0-9]_\w)_.*','',
65          re.sub('_1 ',' ',
66          re.sub('cmd-','',
67          re.sub('diff-','',failstr+' '))))
68          )
69      # Need to make sure we have a unique list
70      fail_targets=' '.join(list(set(fail_targets.split())))
71
72      #Make the message nice
73      makefile="gmakefile.test" if inInstallDir() else "gmakefile"
74
75      print("#\n# To rerun failed tests: ")
76      print("#     "+make+" -f "+makefile+" test search='" + fail_targets.strip()+"'")
77
78  if ntime>0:
79      print("# Timing summary: ")
80      timelist=list(set(timelist))
81      timelist.sort(reverse=True)
82      nlim=(ntime if ntime<len(timelist) else len(timelist))
83      # Do a double loop to sort in order
84      for timelimit in timelist[0:nlim]:
85        for cf in timesummary:
86          if timesummary[cf] == timelimit:
87              print("# %s: %d sec" % (re.sub('.counts','',cf), timesummary[cf]))
88
89  return
90
91def main():
92    parser = optparse.OptionParser(usage="%prog [options]")
93    parser.add_option('-d', '--directory', dest='directory',
94                      help='Directory containing results of petsc test system',
95                      default=os.path.join(os.environ.get('PETSC_ARCH',''),
96                                           'tests','counts'))
97    parser.add_option('-m', '--make', dest='make',
98                      help='make executable to report in summary',
99                      default='make')
100    parser.add_option('-t', '--time', dest='time',
101                      help='-t n: Report on the n number expensive jobs',
102                      default=0)
103    options, args = parser.parse_args()
104
105    # Process arguments
106    if len(args) > 0:
107      parser.print_usage()
108      return
109
110    summarize_results(options.directory,options.make,int(options.time))
111
112if __name__ == "__main__":
113        main()
114