xref: /petsc/config/report_tests.py (revision feff33ee0b5b037fa8f9f294dede656a2f85cc47)
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,etime):
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        if l[0] == 'failures':
47           if len(l)>1:
48             summary[l[0]] += l[1:]
49        elif l[0] == 'time':
50           if len(l)==1: continue
51           summary[l[0]] += float(l[1])
52           timesummary[cfile]=float(l[1])
53           timelist.append(float(l[1]))
54        elif l[0] not in summary:
55           continue
56        else:
57           summary[l[0]] += int(l[1])
58
59  failstr=' '.join(summary['failures'])
60  print("\n# -------------")
61  print("#   Summary    ")
62  print("# -------------")
63  if failstr.strip(): print("# FAILED " + failstr)
64
65  for t in "success failed todo skip".split():
66    percent=summary[t]/float(summary['total'])*100
67    print("# %s %d/%d tests (%3.1f%%)" % (t, summary[t], summary['total'], percent))
68  print("#")
69  if etime:
70    print("# Wall clock time for tests: %s sec"% etime)
71  print("# Approximate CPU time (not incl. build time): %s sec"% summary['time'])
72
73  if failstr.strip():
74      fail_targets=(
75          re.sub('(?<=[0-9]_\w)_.*','',
76          re.sub('cmd-','',
77          re.sub('diff-','',failstr+' ')))
78          )
79      # Strip off characters from subtests
80      fail_list=[]
81      for failure in fail_targets.split():
82        if failure.count('-')>1:
83            fail_list.append('-'.join(name.split('-')[:-1]))
84        else:
85            fail_list.append(failure)
86      fail_list=list(set(fail_list))
87      fail_targets=' '.join(fail_list)
88
89      #Make the message nice
90      makefile="gmakefile.test" if inInstallDir() else "gmakefile"
91
92      print("#\n# To rerun failed tests: ")
93      print("#     "+make+" -f "+makefile+" test search='" + fail_targets.strip()+"'")
94
95  if ntime>0:
96      print("#\n# Timing summary: ")
97      timelist=list(set(timelist))
98      timelist.sort(reverse=True)
99      nlim=(ntime if ntime<len(timelist) else len(timelist))
100      # Do a double loop to sort in order
101      for timelimit in timelist[0:nlim]:
102        for cf in timesummary:
103          if timesummary[cf] == timelimit:
104              print("#   %s: %.2f sec" % (re.sub('.counts','',cf), timesummary[cf]))
105
106  return
107
108def main():
109    parser = optparse.OptionParser(usage="%prog [options]")
110    parser.add_option('-d', '--directory', dest='directory',
111                      help='Directory containing results of petsc test system',
112                      default=os.path.join(os.environ.get('PETSC_ARCH',''),
113                                           'tests','counts'))
114    parser.add_option('-e', '--elapsed_time', dest='elapsed_time',
115                      help='Report elapsed time in output',
116                      default=None)
117    parser.add_option('-m', '--make', dest='make',
118                      help='make executable to report in summary',
119                      default='make')
120    parser.add_option('-t', '--time', dest='time',
121                      help='-t n: Report on the n number expensive jobs',
122                      default=0)
123    options, args = parser.parse_args()
124
125    # Process arguments
126    if len(args) > 0:
127      parser.print_usage()
128      return
129
130    summarize_results(options.directory,options.make,int(options.time),options.elapsed_time)
131
132if __name__ == "__main__":
133        main()
134