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