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