xref: /petsc/config/report_tests.py (revision 098d3641e4b83b3c24d877ebb022794e96f17f6f)
18ccd5183SScott Kruger#!/usr/bin/env python
25b6bfdb9SJed Brownfrom __future__ import print_function
391bc3e46SScott Krugerimport glob, os, re
48ccd5183SScott Krugerimport optparse
53054ff8cSScott Krugerimport inspect
63054ff8cSScott Kruger
78ccd5183SScott Kruger"""
88ccd5183SScott KrugerQuick script for parsing the output of the test system and summarizing the results.
98ccd5183SScott Kruger"""
108ccd5183SScott Kruger
113054ff8cSScott Krugerdef inInstallDir():
123054ff8cSScott Kruger  """
133054ff8cSScott Kruger  When petsc is installed then this file in installed in:
143054ff8cSScott Kruger       <PREFIX>/share/petsc/examples/config/gmakegentest.py
153054ff8cSScott Kruger  otherwise the path is:
163054ff8cSScott Kruger       <PETSC_DIR>/config/gmakegentest.py
173054ff8cSScott Kruger  We use this difference to determine if we are in installdir
183054ff8cSScott Kruger  """
193054ff8cSScott Kruger  thisscriptdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
203054ff8cSScott Kruger  dirlist=thisscriptdir.split(os.path.sep)
213054ff8cSScott Kruger  if len(dirlist)>4:
223054ff8cSScott Kruger    lastfour=os.path.sep.join(dirlist[len(dirlist)-4:])
233054ff8cSScott Kruger    if lastfour==os.path.join('share','petsc','examples','config'):
243054ff8cSScott Kruger      return True
253054ff8cSScott Kruger    else:
263054ff8cSScott Kruger      return False
273054ff8cSScott Kruger  else:
283054ff8cSScott Kruger    return False
293054ff8cSScott Kruger
3032f4009dSScott Krugerdef summarize_results(directory,make,ntime,etime):
318ccd5183SScott Kruger  ''' Loop over all of the results files and summarize the results'''
328ccd5183SScott Kruger  startdir=os.path.realpath(os.path.curdir)
336d7e7da8SJed Brown  try:
348ccd5183SScott Kruger    os.chdir(directory)
356d7e7da8SJed Brown  except OSError:
366d7e7da8SJed Brown    print('# No tests run')
376d7e7da8SJed Brown    return
38bbf1c217SScott Kruger  summary={'total':0,'success':0,'failed':0,'failures':[],'todo':0,'skip':0,
39bbf1c217SScott Kruger           'time':0}
40bbf1c217SScott Kruger  timesummary={}
41bbf1c217SScott Kruger  timelist=[]
428ccd5183SScott Kruger  for cfile in glob.glob('*.counts'):
43100ef3c7SJed Brown    with open(cfile, 'r') as f:
44100ef3c7SJed Brown      for line in f:
45100ef3c7SJed Brown        l = line.split()
46521be42fSScott Kruger        if l[0] == 'failures':
47d8e31410SScott Kruger           if len(l)>1:
480bffd254SScott Kruger             summary[l[0]] += l[1:]
49521be42fSScott Kruger        elif l[0] == 'time':
50521be42fSScott Kruger           if len(l)==1: continue
51521be42fSScott Kruger           summary[l[0]] += float(l[1])
52521be42fSScott Kruger           timesummary[cfile]=float(l[1])
53521be42fSScott Kruger           timelist.append(float(l[1]))
54d8e31410SScott Kruger        elif l[0] not in summary:
55d8e31410SScott Kruger           continue
56521be42fSScott Kruger        else:
57521be42fSScott Kruger           summary[l[0]] += int(l[1])
58a2766241SScott Kruger
5991bc3e46SScott Kruger  failstr=' '.join(summary['failures'])
60100ef3c7SJed Brown  print("\n# -------------")
61100ef3c7SJed Brown  print("#   Summary    ")
62100ef3c7SJed Brown  print("# -------------")
631a3f486dSScott Kruger  if failstr.strip(): print("# FAILED " + failstr)
648ccd5183SScott Kruger
658ccd5183SScott Kruger  for t in "success failed todo skip".split():
668ccd5183SScott Kruger    percent=summary[t]/float(summary['total'])*100
67100ef3c7SJed Brown    print("# %s %d/%d tests (%3.1f%%)" % (t, summary[t], summary['total'], percent))
6832f4009dSScott Kruger  print("#")
6932f4009dSScott Kruger  if etime:
7032f4009dSScott Kruger    print("# Wall clock time for tests: %s sec"% etime)
7132f4009dSScott Kruger  print("# Approximate CPU time (not incl. build time): %s sec"% summary['time'])
7291bc3e46SScott Kruger
73c687a870SSatish Balay  if failstr.strip():
7491bc3e46SScott Kruger      fail_targets=(
7591bc3e46SScott Kruger          re.sub('(?<=[0-9]_\w)_.*','',
7691bc3e46SScott Kruger          re.sub('cmd-','',
77521be42fSScott Kruger          re.sub('diff-','',failstr+' ')))
7891bc3e46SScott Kruger          )
79d8e31410SScott Kruger      # Strip off characters from subtests
80d8e31410SScott Kruger      fail_list=[]
81d8e31410SScott Kruger      for failure in fail_targets.split():
82d8e31410SScott Kruger        if failure.count('-')>1:
83*098d3641SScott Kruger            fail_list.append('-'.join(failure.split('-')[:-1]))
84d8e31410SScott Kruger        else:
85d8e31410SScott Kruger            fail_list.append(failure)
86d8e31410SScott Kruger      fail_list=list(set(fail_list))
87d8e31410SScott Kruger      fail_targets=' '.join(fail_list)
883054ff8cSScott Kruger
893054ff8cSScott Kruger      #Make the message nice
903054ff8cSScott Kruger      makefile="gmakefile.test" if inInstallDir() else "gmakefile"
913054ff8cSScott Kruger
9291bc3e46SScott Kruger      print("#\n# To rerun failed tests: ")
933054ff8cSScott Kruger      print("#     "+make+" -f "+makefile+" test search='" + fail_targets.strip()+"'")
94bbf1c217SScott Kruger
95bbf1c217SScott Kruger  if ntime>0:
96d8e31410SScott Kruger      print("#\n# Timing summary: ")
97bbf1c217SScott Kruger      timelist=list(set(timelist))
98bbf1c217SScott Kruger      timelist.sort(reverse=True)
99bbf1c217SScott Kruger      nlim=(ntime if ntime<len(timelist) else len(timelist))
100bbf1c217SScott Kruger      # Do a double loop to sort in order
101bbf1c217SScott Kruger      for timelimit in timelist[0:nlim]:
102bbf1c217SScott Kruger        for cf in timesummary:
103bbf1c217SScott Kruger          if timesummary[cf] == timelimit:
104521be42fSScott Kruger              print("#   %s: %.2f sec" % (re.sub('.counts','',cf), timesummary[cf]))
105bbf1c217SScott Kruger
1068ccd5183SScott Kruger  return
1078ccd5183SScott Kruger
1088ccd5183SScott Krugerdef main():
1098ccd5183SScott Kruger    parser = optparse.OptionParser(usage="%prog [options]")
1108ccd5183SScott Kruger    parser.add_option('-d', '--directory', dest='directory',
1118ccd5183SScott Kruger                      help='Directory containing results of petsc test system',
112e57812dcSJed Brown                      default=os.path.join(os.environ.get('PETSC_ARCH',''),
113bbf1c217SScott Kruger                                           'tests','counts'))
11432f4009dSScott Kruger    parser.add_option('-e', '--elapsed_time', dest='elapsed_time',
11532f4009dSScott Kruger                      help='Report elapsed time in output',
11632f4009dSScott Kruger                      default=None)
1173054ff8cSScott Kruger    parser.add_option('-m', '--make', dest='make',
1183054ff8cSScott Kruger                      help='make executable to report in summary',
1193054ff8cSScott Kruger                      default='make')
120bbf1c217SScott Kruger    parser.add_option('-t', '--time', dest='time',
121bbf1c217SScott Kruger                      help='-t n: Report on the n number expensive jobs',
122bbf1c217SScott Kruger                      default=0)
1238ccd5183SScott Kruger    options, args = parser.parse_args()
1248ccd5183SScott Kruger
1258ccd5183SScott Kruger    # Process arguments
1268ccd5183SScott Kruger    if len(args) > 0:
1278ccd5183SScott Kruger      parser.print_usage()
1288ccd5183SScott Kruger      return
1298ccd5183SScott Kruger
13032f4009dSScott Kruger    summarize_results(options.directory,options.make,int(options.time),options.elapsed_time)
1318ccd5183SScott Kruger
1328ccd5183SScott Krugerif __name__ == "__main__":
1338ccd5183SScott Kruger        main()
134