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