129921a8fSScott Kruger#!/usr/bin/env python 229921a8fSScott Kruger 329921a8fSScott Krugerimport os,shutil, string, re 429921a8fSScott Krugerfrom distutils.sysconfig import parse_makefile 529921a8fSScott Krugerimport sys 66ac365aeSScott Krugerimport logging, time 729921a8fSScott Krugerimport types 829921a8fSScott Krugersys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) 929921a8fSScott Krugerfrom cmakegen import Mistakes, stripsplit, AUTODIRS, SKIPDIRS 1029921a8fSScott Krugerfrom cmakegen import defaultdict # collections.defaultdict, with fallback for python-2.4 1129921a8fSScott Krugerfrom gmakegen import * 1229921a8fSScott Kruger 1329921a8fSScott Krugerimport inspect 1429921a8fSScott Krugerthisscriptdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) 1529921a8fSScott Krugersys.path.insert(0,thisscriptdir) 1629921a8fSScott Krugerimport testparse 1729921a8fSScott Krugerimport example_template 1829921a8fSScott Kruger 1929921a8fSScott Krugerclass generateExamples(Petsc): 2029921a8fSScott Kruger """ 2129921a8fSScott Kruger gmakegen.py has basic structure for finding the files, writing out 2229921a8fSScott Kruger the dependencies, etc. 2329921a8fSScott Kruger """ 24*e551db17SScott Kruger def __init__(self,petsc_dir=None, petsc_arch=None, testdir=None, verbose=False, single_ex=False, srcdir=None): 25*e551db17SScott Kruger super(generateExamples, self).__init__(petsc_dir, petsc_arch, verbose) 2629921a8fSScott Kruger 2729921a8fSScott Kruger self.single_ex=single_ex 28*e551db17SScott Kruger 29*e551db17SScott Kruger # Determine if we are running from an install directory: 30*e551db17SScott Kruger dirlist=thisscriptdir.split("/") 31*e551db17SScott Kruger if len(dirlist)>4: 32*e551db17SScott Kruger lastfour="/".join(dirlist[len(dirlist)-4:]) 33*e551db17SScott Kruger installdir="/".join(dirlist[0:len(dirlist)-4]) 34*e551db17SScott Kruger srcdir=os.path.join(os.path.dirname(thisscriptdir),'src') 35*e551db17SScott Kruger self.inInstallDir=True if lastfour=='share/petsc/examples/config' else False 36*e551db17SScott Kruger else: 37*e551db17SScott Kruger self.inInstallDir=False 38*e551db17SScott Kruger 39*e551db17SScott Kruger if not self.inInstallDir: 4029921a8fSScott Kruger self.arch_dir=os.path.join(self.petsc_dir,self.petsc_arch) 41*e551db17SScott Kruger else: 42*e551db17SScott Kruger self.arch_dir=installdir 43*e551db17SScott Kruger 44*e551db17SScott Kruger # Do some initialization 45*e551db17SScott Kruger if testdir: 46*e551db17SScott Kruger # If full path given, then use it, otherwise assume relative to arch_dir 47*e551db17SScott Kruger if testdir.strip().startswith("/"): 48*e551db17SScott Kruger self.testroot_dir=testdir.strip() 49*e551db17SScott Kruger else: 50*e551db17SScott Kruger self.testroot_dir=os.path.join(self.arch_dir,testdir.strip()) 51*e551db17SScott Kruger else: 52*e551db17SScott Kruger self.testroot_dir=os.path.join(self.arch_dir,"tests") 53*e551db17SScott Kruger 54*e551db17SScott Kruger if srcdir: 55*e551db17SScott Kruger self.srcdir=srcdir 56*e551db17SScott Kruger else: 57*e551db17SScott Kruger if not self.inInstallDir: 58*e551db17SScott Kruger self.srcdir=os.path.join(self.petsc_dir,'src') 59*e551db17SScott Kruger else: 60*e551db17SScott Kruger self.srcdir=srcdir 61*e551db17SScott Kruger 6229921a8fSScott Kruger self.ptNaming=True 6329921a8fSScott Kruger # Whether to write out a useful debugging 6429921a8fSScott Kruger #if verbose: self.summarize=True 6529921a8fSScott Kruger self.summarize=True 6629921a8fSScott Kruger 6729921a8fSScott Kruger # For help in setting the requirements 6812df5dc0SToby Isaac self.precision_types="single double __float128 int32".split() 6929921a8fSScott Kruger self.integer_types="int32 int64".split() 7029921a8fSScott Kruger self.languages="fortran cuda cxx".split() # Always requires C so do not list 7129921a8fSScott Kruger 7229921a8fSScott Kruger # Things that are not test 7329921a8fSScott Kruger self.buildkeys=testparse.buildkeys 7429921a8fSScott Kruger 7529921a8fSScott Kruger # Adding a dictionary for storing sources, objects, and tests 7629921a8fSScott Kruger # to make building the dependency tree easier 7729921a8fSScott Kruger self.sources={} 7829921a8fSScott Kruger self.objects={} 7929921a8fSScott Kruger self.tests={} 8029921a8fSScott Kruger for pkg in PKGS: 8129921a8fSScott Kruger self.sources[pkg]={} 8229921a8fSScott Kruger self.objects[pkg]=[] 8329921a8fSScott Kruger self.tests[pkg]={} 8429921a8fSScott Kruger for lang in LANGS: 8529921a8fSScott Kruger self.sources[pkg][lang]={} 8629921a8fSScott Kruger self.sources[pkg][lang]['srcs']=[] 8729921a8fSScott Kruger self.tests[pkg][lang]={} 8829921a8fSScott Kruger 8929921a8fSScott Kruger if not os.path.isdir(self.testroot_dir): os.makedirs(self.testroot_dir) 900357d61fSScott Kruger 910357d61fSScott Kruger self.indent=" " 9229921a8fSScott Kruger return 9329921a8fSScott Kruger 9429921a8fSScott Kruger def nameSpace(self,srcfile,srcdir): 9529921a8fSScott Kruger """ 9629921a8fSScott Kruger Because the scripts have a non-unique naming, the pretty-printing 9729921a8fSScott Kruger needs to convey the srcdir and srcfile. There are two ways of doing this. 9829921a8fSScott Kruger """ 9929921a8fSScott Kruger if self.ptNaming: 10029921a8fSScott Kruger cdir=srcdir.split('src')[1].lstrip("/").rstrip("/") 10129921a8fSScott Kruger prefix=cdir.replace('/examples/','_').replace("/","_")+"-" 10229921a8fSScott Kruger nameString=prefix+srcfile 10329921a8fSScott Kruger else: 10429921a8fSScott Kruger #nameString=srcdir+": "+srcfile 10529921a8fSScott Kruger nameString=srcfile 10629921a8fSScott Kruger return nameString 10729921a8fSScott Kruger 10829921a8fSScott Kruger def getLanguage(self,srcfile): 10929921a8fSScott Kruger """ 11029921a8fSScott Kruger Based on the source, determine associated language as found in gmakegen.LANGS 11129921a8fSScott Kruger Can we just return srcext[1:\] now? 11229921a8fSScott Kruger """ 11329921a8fSScott Kruger langReq=None 11429921a8fSScott Kruger srcext=os.path.splitext(srcfile)[-1] 11529921a8fSScott Kruger if srcext in ".F90".split(): langReq="F90" 11629921a8fSScott Kruger if srcext in ".F".split(): langReq="F" 11729921a8fSScott Kruger if srcext in ".cxx".split(): langReq="cxx" 11829921a8fSScott Kruger if srcext == ".cu": langReq="cu" 11929921a8fSScott Kruger if srcext == ".c": langReq="c" 1200aac2865SBarry Smith #if not langReq: print "ERROR: ", srcext, srcfile 12129921a8fSScott Kruger return langReq 12229921a8fSScott Kruger 12396d5c3b5SScott Kruger def _getLoopVars(self,inDict,testname, isSubtest=False): 124e9b06b45SScott Kruger """ 125e9b06b45SScott Kruger Given: 'args: -bs {{1 2 3 4 5}} -pc_type {{cholesky sor}} -ksp_monitor' 126e9b06b45SScott Kruger Return: 12796d5c3b5SScott Kruger inDict['args']: -ksp_monitor 12896d5c3b5SScott Kruger inDict['subargs']: -bs ${bs} -pc_type ${pc_type} 1290357d61fSScott Kruger loopVars['subargs']['varlist']=['bs' 'pc_type'] # Don't worry about OrderedDict 1307827e0d6SScott Kruger loopVars['subargs']['bs']=[["bs"],["1 2 3 4 5"]] 1317827e0d6SScott Kruger loopVars['subargs']['pc_type']=[["pc_type"],["cholesky sor"]] 13296d5c3b5SScott Kruger subst should be passed in instead of inDict 133e9b06b45SScott Kruger """ 1340357d61fSScott Kruger loopVars={}; newargs="" 13596d5c3b5SScott Kruger lkeys=inDict.keys() 13696d5c3b5SScott Kruger lsuffix='_' 137aae9f2d9SScott Kruger from testparse import parseLoopArgs 1380357d61fSScott Kruger for key in lkeys: 13996d5c3b5SScott Kruger if type(inDict[key])!=types.StringType: continue 14096d5c3b5SScott Kruger keystr = str(inDict[key]) 1410357d61fSScott Kruger akey=('subargs' if key=='args' else key) # what to assign 142862148f4SScott Kruger if akey not in inDict: inDict[akey]='' 1430357d61fSScott Kruger varlist=[] 144e9b06b45SScott Kruger for varset in re.split('-(?=[a-zA-Z])',keystr): 145e9b06b45SScott Kruger if not varset.strip(): continue 146aae9f2d9SScott Kruger if '{{' in varset: 147aae9f2d9SScott Kruger keyvar,lvars,ftype=parseLoopArgs(varset) 148862148f4SScott Kruger if akey not in loopVars: loopVars[akey]={} 1497827e0d6SScott Kruger varlist.append(keyvar) 1502521ea3cSScott Kruger loopVars[akey][keyvar]=[keyvar,lvars] 1517827e0d6SScott Kruger if akey=='nsize': 15296d5c3b5SScott Kruger inDict[akey] = '${' + keyvar + '}' 15396d5c3b5SScott Kruger lsuffix+=akey+'-'+inDict[akey]+'_' 1547827e0d6SScott Kruger else: 15596d5c3b5SScott Kruger inDict[akey] += ' -'+keyvar+' ${' + keyvar + '}' 15696d5c3b5SScott Kruger lsuffix+=keyvar+'-${' + keyvar + '}_' 1577827e0d6SScott Kruger else: 1587827e0d6SScott Kruger if key=='args': newargs+=" -"+varset.strip() 1590357d61fSScott Kruger if len(varlist)>0: loopVars[akey]['varlist']=varlist 1608ba3acebSToby Isaac 1610357d61fSScott Kruger 1620357d61fSScott Kruger # For subtests, args are always substituted in (not top level) 1630357d61fSScott Kruger if isSubtest: 16496d5c3b5SScott Kruger inDict['subargs']+=" "+newargs.strip() 16596d5c3b5SScott Kruger inDict['args']='' 166862148f4SScott Kruger if 'label_suffix' in inDict: 16796d5c3b5SScott Kruger inDict['label_suffix']+=lsuffix.rstrip('_') 1680357d61fSScott Kruger else: 16996d5c3b5SScott Kruger inDict['label_suffix']=lsuffix.rstrip('_') 17096d5c3b5SScott Kruger else: 17196d5c3b5SScott Kruger if len(loopVars.keys())>0: 17296d5c3b5SScott Kruger inDict['args']=newargs.strip() 17396d5c3b5SScott Kruger inDict['label_suffix']=lsuffix.rstrip('_') 1740357d61fSScott Kruger if len(loopVars.keys())>0: 175e9b06b45SScott Kruger return loopVars 1760357d61fSScott Kruger else: 1770357d61fSScott Kruger return None 1788ba3acebSToby Isaac 17929921a8fSScott Kruger def getArgLabel(self,testDict): 18029921a8fSScott Kruger """ 18129921a8fSScott Kruger In all of the arguments in the test dictionary, create a simple 18229921a8fSScott Kruger string for searching within the makefile system. For simplicity in 18329921a8fSScott Kruger search, remove "-", for strings, etc. 18429921a8fSScott Kruger Also, concatenate the arg commands 18529921a8fSScott Kruger For now, ignore nsize -- seems hard to search for anyway 18629921a8fSScott Kruger """ 18729921a8fSScott Kruger # Collect all of the args associated with a test 188862148f4SScott Kruger argStr=("" if 'args' not in testDict else testDict['args']) 189862148f4SScott Kruger if 'subtests' in testDict: 19029921a8fSScott Kruger for stest in testDict["subtests"]: 19129921a8fSScott Kruger sd=testDict[stest] 192862148f4SScott Kruger argStr=argStr+("" if 'args' not in sd else sd['args']) 19329921a8fSScott Kruger 19429921a8fSScott Kruger # Now go through and cleanup 19529921a8fSScott Kruger argStr=re.sub('{{(.*?)}}',"",argStr) 19629921a8fSScott Kruger argStr=re.sub('-'," ",argStr) 19729921a8fSScott Kruger for digit in string.digits: argStr=re.sub(digit," ",argStr) 19829921a8fSScott Kruger argStr=re.sub("\.","",argStr) 19929921a8fSScott Kruger argStr=re.sub(",","",argStr) 20029921a8fSScott Kruger argStr=re.sub('\+',' ',argStr) 20129921a8fSScott Kruger argStr=re.sub(' +',' ',argStr) # Remove repeated white space 20229921a8fSScott Kruger return argStr.strip() 20329921a8fSScott Kruger 20429921a8fSScott Kruger def addToSources(self,exfile,root,srcDict): 20529921a8fSScott Kruger """ 20629921a8fSScott Kruger Put into data structure that allows easy generation of makefile 20729921a8fSScott Kruger """ 208*e551db17SScott Kruger rpath=os.path.join('src',os.path.relpath(root,self.srcdir)) 209*e551db17SScott Kruger pkg=rpath.split("/")[1] 21029921a8fSScott Kruger fullfile=os.path.join(root,exfile) 211*e551db17SScott Kruger relpfile=os.path.join(rpath,exfile) 21229921a8fSScott Kruger lang=self.getLanguage(exfile) 2130aac2865SBarry Smith if not lang: return 21429921a8fSScott Kruger self.sources[pkg][lang]['srcs'].append(relpfile) 215862148f4SScott Kruger if 'depends' in srcDict: 21629921a8fSScott Kruger depSrc=srcDict['depends'] 21729921a8fSScott Kruger depObj=os.path.splitext(depSrc)[0]+".o" 21829921a8fSScott Kruger self.sources[pkg][lang][exfile]=depObj 21929921a8fSScott Kruger 22029921a8fSScott Kruger # In gmakefile, ${TESTDIR} var specifies the object compilation 22129921a8fSScott Kruger testsdir=self.relpath(self.petsc_dir,root)+"/" 22229921a8fSScott Kruger objfile="${TESTDIR}/"+testsdir+os.path.splitext(exfile)[0]+".o" 22329921a8fSScott Kruger self.objects[pkg].append(objfile) 22429921a8fSScott Kruger return 22529921a8fSScott Kruger 22629921a8fSScott Kruger def addToTests(self,test,root,exfile,execname,testDict): 22729921a8fSScott Kruger """ 22829921a8fSScott Kruger Put into data structure that allows easy generation of makefile 22929921a8fSScott Kruger Organized by languages to allow testing of languages 23029921a8fSScott Kruger """ 231*e551db17SScott Kruger rpath=os.path.join('src',os.path.relpath(root,self.srcdir)) 232*e551db17SScott Kruger pkg=rpath.split("/")[1] 23329921a8fSScott Kruger #nmtest=self.nameSpace(test,root) 23429921a8fSScott Kruger nmtest=os.path.join(rpath,test) 23529921a8fSScott Kruger lang=self.getLanguage(exfile) 2360aac2865SBarry Smith if not lang: return 23729921a8fSScott Kruger self.tests[pkg][lang][nmtest]={} 23829921a8fSScott Kruger self.tests[pkg][lang][nmtest]['exfile']=os.path.join(rpath,exfile) 23929921a8fSScott Kruger self.tests[pkg][lang][nmtest]['exec']=execname 24029921a8fSScott Kruger self.tests[pkg][lang][nmtest]['argLabel']=self.getArgLabel(testDict) 24129921a8fSScott Kruger return 24229921a8fSScott Kruger 24329921a8fSScott Kruger def getExecname(self,exfile,root): 24429921a8fSScott Kruger """ 24529921a8fSScott Kruger Generate bash script using template found next to this file. 24629921a8fSScott Kruger This file is read in at constructor time to avoid file I/O 24729921a8fSScott Kruger """ 248*e551db17SScott Kruger rpath=os.path.join('src',os.path.relpath(root,self.srcdir)) 24929921a8fSScott Kruger if self.single_ex: 25029921a8fSScott Kruger execname=rpath.split("/")[1]+"-ex" 25129921a8fSScott Kruger else: 25229921a8fSScott Kruger execname=os.path.splitext(exfile)[0] 25329921a8fSScott Kruger return execname 25429921a8fSScott Kruger 25529921a8fSScott Kruger def getSubstVars(self,testDict,rpath,testname): 25629921a8fSScott Kruger """ 25729921a8fSScott Kruger Create a dictionary with all of the variables that get substituted 25829921a8fSScott Kruger into the template commands found in example_template.py 25929921a8fSScott Kruger """ 26029921a8fSScott Kruger subst={} 26196d5c3b5SScott Kruger 26296d5c3b5SScott Kruger # Handle defaults of testparse.acceptedkeys (e.g., ignores subtests) 263862148f4SScott Kruger if 'nsize' not in testDict: testDict['nsize']=1 2640a091e3eSScott Kruger if 'timeoutfactor' not in testDict: testDict['timeoutfactor']="1" 26596d5c3b5SScott Kruger for ak in testparse.acceptedkeys: 26696d5c3b5SScott Kruger if ak=='test': continue 267862148f4SScott Kruger subst[ak]=(testDict[ak] if ak in testDict else '') 26896d5c3b5SScott Kruger 26996d5c3b5SScott Kruger # Now do other variables 27096d5c3b5SScott Kruger subst['execname']=testDict['execname'] 271862148f4SScott Kruger if 'filter' in testDict: 27296d5c3b5SScott Kruger subst['filter']="'"+testDict['filter']+"'" # Quotes are tricky - overwrite 27368a9e459SScott Kruger 27496d5c3b5SScott Kruger # Others 27596d5c3b5SScott Kruger subst['subargs']='' # Default. For variables override 276*e551db17SScott Kruger subst['srcdir']=os.path.join(os.path.dirname(self.srcdir),rpath) 27768a9e459SScott Kruger subst['label_suffix']='' 27896d5c3b5SScott Kruger subst['comments']="\n#".join(subst['comments'].split("\n")) 27968a9e459SScott Kruger if subst['comments']: subst['comments']="#"+subst['comments'] 28096d5c3b5SScott Kruger subst['exec']="../"+subst['execname'] 28129921a8fSScott Kruger subst['testroot']=self.testroot_dir 28229921a8fSScott Kruger subst['testname']=testname 28309cf0baaSJed Brown dp = self.conf.get('DATAFILESPATH','') 28409cf0baaSJed Brown subst['datafilespath_line'] = 'DATAFILESPATH=${DATAFILESPATH:-"'+dp+'"}' 28529921a8fSScott Kruger 2860bcc1aabSScott Kruger # This is used to label some matrices 2870bcc1aabSScott Kruger subst['petsc_index_size']=str(self.conf['PETSC_INDEX_SIZE']) 2880bcc1aabSScott Kruger subst['petsc_scalar_size']=str(self.conf['PETSC_SCALAR_SIZE']) 2890bcc1aabSScott Kruger 29029921a8fSScott Kruger # These can have for loops and are treated separately later 29196d5c3b5SScott Kruger subst['nsize']=str(subst['nsize']) 29229921a8fSScott Kruger 29329921a8fSScott Kruger #Conf vars 29426646c0bSSatish Balay if self.petsc_arch.find('valgrind')>=0: 29526646c0bSSatish Balay subst['mpiexec']='petsc_mpiexec_valgrind ' + self.conf['MPIEXEC'] 29626646c0bSSatish Balay else: 29726646c0bSSatish Balay subst['mpiexec']=self.conf['MPIEXEC'] 2984c8d737cSSatish Balay subst['petsc_dir']=self.petsc_dir # not self.conf['PETSC_DIR'] as this could be windows path 2990a091e3eSScott Kruger subst['petsc_arch']=self.petsc_arch 300*e551db17SScott Kruger if not self.inInstallDir: 301*e551db17SScott Kruger subst['CONFIG_DIR']=os.path.join(self.petsc_dir,'config') 302*e551db17SScott Kruger else: 303*e551db17SScott Kruger subst['CONFIG_DIR']=os.path.join(os.path.dirname(self.srcdir),'config') 30429921a8fSScott Kruger subst['diff']=self.conf['DIFF'] 30529921a8fSScott Kruger subst['rm']=self.conf['RM'] 30629921a8fSScott Kruger subst['grep']=self.conf['GREP'] 307d6f00007SSatish Balay subst['petsc_lib_dir']=self.conf['PETSC_LIB_DIR'] 3080eb9b082SSatish Balay subst['wpetsc_dir']=self.conf['wPETSC_DIR'] 30929921a8fSScott Kruger 3103bcca444SScott Kruger # Output file is special because of subtests override 3113bcca444SScott Kruger defroot=(re.sub("run","",testname) if testname.startswith("run") else testname) 3123bcca444SScott Kruger if not "_" in defroot: defroot=defroot+"_1" 3133bcca444SScott Kruger subst['defroot']=defroot 3143bcca444SScott Kruger subst['label']=self.nameSpace(defroot,subst['srcdir']) 3153bcca444SScott Kruger subst['redirect_file']=defroot+".tmp" 316862148f4SScott Kruger if 'output_file' not in testDict: 3173bcca444SScott Kruger subst['output_file']="output/"+defroot+".out" 3183bcca444SScott Kruger # Add in the full path here. 3193bcca444SScott Kruger subst['output_file']=os.path.join(subst['srcdir'],subst['output_file']) 3203bcca444SScott Kruger if not os.path.isfile(os.path.join(self.petsc_dir,subst['output_file'])): 3213bcca444SScott Kruger if not subst['TODO']: 3223bcca444SScott Kruger print "Warning: "+subst['output_file']+" not found." 3233bcca444SScott Kruger # Worry about alt files here -- see 3243bcca444SScott Kruger # src/snes/examples/tutorials/output/ex22*.out 3253bcca444SScott Kruger altlist=[subst['output_file']] 3263bcca444SScott Kruger for i in range(1,3): 3273bcca444SScott Kruger altroot=defroot+"_alt" 3283bcca444SScott Kruger if i==2: altroot=altroot+"_2" 3293bcca444SScott Kruger af="output/"+altroot+".out" 3303bcca444SScott Kruger srcaf=os.path.join(subst['srcdir'],af) 3313bcca444SScott Kruger fullaf=os.path.join(self.petsc_dir,srcaf) 3323bcca444SScott Kruger if os.path.isfile(fullaf): altlist.append(srcaf) 3333bcca444SScott Kruger if len(altlist)>1: subst['altfiles']=altlist 3343bcca444SScott Kruger #if len(altlist)>1: print "Found alt files: ",altlist 3353bcca444SScott Kruger 33629921a8fSScott Kruger return subst 33729921a8fSScott Kruger 3380357d61fSScott Kruger def getCmds(self,subst,i): 33929921a8fSScott Kruger """ 34029921a8fSScott Kruger Generate bash script using template found next to this file. 34129921a8fSScott Kruger This file is read in at constructor time to avoid file I/O 34229921a8fSScott Kruger """ 3430357d61fSScott Kruger nindnt=i # the start and has to be consistent with below 3447a853109SScott Kruger cmdindnt=self.indent*nindnt 34529921a8fSScott Kruger cmdLines="" 34668a9e459SScott Kruger 34729921a8fSScott Kruger # MPI is the default -- but we have a few odd commands 34896d5c3b5SScott Kruger if not subst['command']: 3497a853109SScott Kruger cmd=cmdindnt+self._substVars(subst,example_template.mpitest) 35029921a8fSScott Kruger else: 3517a853109SScott Kruger cmd=cmdindnt+self._substVars(subst,example_template.commandtest) 3527a853109SScott Kruger cmdLines+=cmd+"\n"+cmdindnt+"res=$?\n\n" 35329921a8fSScott Kruger 3547a853109SScott Kruger cmdLines+=cmdindnt+'if test $res = 0; then\n' 3557a853109SScott Kruger diffindnt=self.indent*(nindnt+1) 35664ca018dSScott Kruger if not subst['filter_output']: 357862148f4SScott Kruger if 'altfiles' not in subst: 3587a853109SScott Kruger cmd=diffindnt+self._substVars(subst,example_template.difftest) 35964ca018dSScott Kruger else: 3603bcca444SScott Kruger # Have to do it by hand a bit because of variable number of alt files 3613bcca444SScott Kruger rf=subst['redirect_file'] 3627a853109SScott Kruger cmd=diffindnt+example_template.difftest.split('@')[0] 3633bcca444SScott Kruger for i in range(len(subst['altfiles'])): 3643bcca444SScott Kruger af=subst['altfiles'][i] 3653bcca444SScott Kruger cmd+=af+' '+rf+' > diff-${testname}-'+str(i)+'.out 2> diff-${testname}-'+str(i)+'.out' 3663bcca444SScott Kruger if i!=len(subst['altfiles'])-1: 3673bcca444SScott Kruger cmd+=' || ${diff_exe} ' 3683bcca444SScott Kruger else: 3693bcca444SScott Kruger cmd+='" diff-${testname}.out diff-${testname}.out diff-${label}' 3703bcca444SScott Kruger cmd+=subst['label_suffix']+' ""' # Quotes are painful 3713bcca444SScott Kruger else: 3727a853109SScott Kruger cmd=diffindnt+self._substVars(subst,example_template.filterdifftest) 37368a9e459SScott Kruger cmdLines+=cmd+"\n" 3747a853109SScott Kruger cmdLines+=cmdindnt+'else\n' 3757a853109SScott Kruger cmdLines+=diffindnt+'printf "ok ${label} # SKIP Command failed so no diff\\n"\n' 3767a853109SScott Kruger cmdLines+=cmdindnt+'fi\n' 37729921a8fSScott Kruger return cmdLines 37829921a8fSScott Kruger 37929921a8fSScott Kruger def _substVars(self,subst,origStr): 38029921a8fSScott Kruger """ 3817827e0d6SScott Kruger Substitute variables 38229921a8fSScott Kruger """ 38329921a8fSScott Kruger Str=origStr 38429921a8fSScott Kruger for subkey in subst: 38529921a8fSScott Kruger if type(subst[subkey])!=types.StringType: continue 38629921a8fSScott Kruger patt="@"+subkey.upper()+"@" 38729921a8fSScott Kruger Str=re.sub(patt,subst[subkey],Str) 38829921a8fSScott Kruger return Str 38929921a8fSScott Kruger 39009cf0baaSJed Brown def _writeTodoSkip(self,fh,tors,reasons,footer): 39168a9e459SScott Kruger """ 39268a9e459SScott Kruger Write out the TODO and SKIP lines in the file 39368a9e459SScott Kruger The TODO or SKIP variable, tors, should be lower case 39468a9e459SScott Kruger """ 39568a9e459SScott Kruger TORS=tors.upper() 39668a9e459SScott Kruger template=eval("example_template."+tors+"line") 39709cf0baaSJed Brown tsStr=re.sub("@"+TORS+"COMMENT@",', '.join(reasons),template) 39809cf0baaSJed Brown tab = '' 3992f2809e3SToby Isaac if reasons: 4002f2809e3SToby Isaac fh.write('if ! $force; then\n') 4012f2809e3SToby Isaac tab = tab + ' ' 40209cf0baaSJed Brown if reasons == ["Requires DATAFILESPATH"]: 40309cf0baaSJed Brown # The only reason not to run is DATAFILESPATH, which we check at run-time 4042f2809e3SToby Isaac fh.write(tab + 'if test -z "${DATAFILESPATH}"; then\n') 4052f2809e3SToby Isaac tab = tab + ' ' 40609cf0baaSJed Brown if reasons: 4072f2809e3SToby Isaac fh.write(tab+tsStr+"\n" + tab + "total=1; "+tors+"=1\n") 40809cf0baaSJed Brown fh.write(tab+footer+"\n") 40909cf0baaSJed Brown fh.write(tab+"exit\n") 41009cf0baaSJed Brown if reasons == ["Requires DATAFILESPATH"]: 41109cf0baaSJed Brown fh.write(' fi\n') 4122f2809e3SToby Isaac if reasons: 4132f2809e3SToby Isaac fh.write('fi\n') 41409cf0baaSJed Brown fh.write('\n\n') 41568a9e459SScott Kruger return 41668a9e459SScott Kruger 4178ba3acebSToby Isaac def getLoopVarsHead(self,loopVars,i): 4180357d61fSScott Kruger """ 4190357d61fSScott Kruger Generate a nicely indented string with the format loops 4200357d61fSScott Kruger Here is what the data structure looks like 4210357d61fSScott Kruger loopVars['subargs']['varlist']=['bs' 'pc_type'] # Don't worry about OrderedDict 4220357d61fSScott Kruger loopVars['subargs']['bs']=["i","1 2 3 4 5"] 4230357d61fSScott Kruger loopVars['subargs']['pc_type']=["j","cholesky sor"] 4240357d61fSScott Kruger """ 4250357d61fSScott Kruger outstr=''; indnt=self.indent 4268ba3acebSToby Isaac for key in loopVars: 4270357d61fSScott Kruger for var in loopVars[key]['varlist']: 4280357d61fSScott Kruger varval=loopVars[key][var] 4290357d61fSScott Kruger outstr += indnt * i + "for "+varval[0]+" in "+varval[1]+"; do\n" 4308ba3acebSToby Isaac i = i + 1 4318ba3acebSToby Isaac return (outstr,i) 4328ba3acebSToby Isaac 4338ba3acebSToby Isaac def getLoopVarsFoot(self,loopVars,i): 4340357d61fSScott Kruger outstr=''; indnt=self.indent 4358ba3acebSToby Isaac for key in loopVars: 4360357d61fSScott Kruger for var in loopVars[key]['varlist']: 4378ba3acebSToby Isaac i = i - 1 4380357d61fSScott Kruger outstr += indnt * i + "done\n" 4398ba3acebSToby Isaac return (outstr,i) 4408ba3acebSToby Isaac 44129921a8fSScott Kruger def genRunScript(self,testname,root,isRun,srcDict): 44229921a8fSScott Kruger """ 44329921a8fSScott Kruger Generate bash script using template found next to this file. 44429921a8fSScott Kruger This file is read in at constructor time to avoid file I/O 44529921a8fSScott Kruger """ 44629921a8fSScott Kruger # runscript_dir directory has to be consistent with gmakefile 44729921a8fSScott Kruger testDict=srcDict[testname] 448*e551db17SScott Kruger rpath=os.path.join('src',os.path.relpath(root,self.srcdir)) 44929921a8fSScott Kruger runscript_dir=os.path.join(self.testroot_dir,rpath) 45029921a8fSScott Kruger if not os.path.isdir(runscript_dir): os.makedirs(runscript_dir) 45129921a8fSScott Kruger fh=open(os.path.join(runscript_dir,testname+".sh"),"w") 45229921a8fSScott Kruger petscvarfile=os.path.join(self.arch_dir,'lib','petsc','conf','petscvariables') 45329921a8fSScott Kruger 45496d5c3b5SScott Kruger # Get variables to go into shell scripts. last time testDict used 45529921a8fSScott Kruger subst=self.getSubstVars(testDict,rpath,testname) 45696d5c3b5SScott Kruger loopVars = self._getLoopVars(subst,testname) # Alters subst as well 45796d5c3b5SScott Kruger #if '33_' in testname: print subst['subargs'] 45829921a8fSScott Kruger 45964ca018dSScott Kruger #Handle runfiles 460862148f4SScott Kruger for lfile in subst.get('localrunfiles','').split(): 461*e551db17SScott Kruger fullfile=os.path.join(root,lfile) 46264ca018dSScott Kruger shutil.copy(fullfile,runscript_dir) 46364ca018dSScott Kruger # Check subtests for local runfiles 464862148f4SScott Kruger for stest in subst.get("subtests",[]): 465862148f4SScott Kruger for lfile in testDict[stest].get('localrunfiles','').split(): 466*e551db17SScott Kruger fullfile=os.path.join(root,lfile) 46764ca018dSScott Kruger shutil.copy(fullfile,self.runscript_dir) 46864ca018dSScott Kruger 46929921a8fSScott Kruger # Now substitute the key variables into the header and footer 47029921a8fSScott Kruger header=self._substVars(subst,example_template.header) 4710bcc1aabSScott Kruger # The header is done twice to enable @...@ in header 4720bcc1aabSScott Kruger header=self._substVars(subst,header) 4735e7f8670SScott Kruger footer=re.sub('@TESTROOT@',subst['testroot'],example_template.footer) 47429921a8fSScott Kruger 47529921a8fSScott Kruger # Start writing the file 47629921a8fSScott Kruger fh.write(header+"\n") 47729921a8fSScott Kruger 47829921a8fSScott Kruger # If there is a TODO or a SKIP then we do it before writing out the 47929921a8fSScott Kruger # rest of the command (which is useful for working on the test) 48029921a8fSScott Kruger # SKIP and TODO can be for the source file or for the runs 48109cf0baaSJed Brown self._writeTodoSkip(fh,'todo',[s for s in [srcDict.get('TODO',''), testDict.get('TODO','')] if s],footer) 48209cf0baaSJed Brown self._writeTodoSkip(fh,'skip',srcDict.get('SKIP',[]) + testDict.get('SKIP',[]),footer) 48329921a8fSScott Kruger 48429921a8fSScott Kruger j=0 # for indentation 48529921a8fSScott Kruger 4860357d61fSScott Kruger if loopVars: 4878ba3acebSToby Isaac (loopHead,j) = self.getLoopVarsHead(loopVars,j) 4888ba3acebSToby Isaac if (loopHead): fh.write(loopHead+"\n") 48929921a8fSScott Kruger 49029921a8fSScott Kruger # Subtests are special 491862148f4SScott Kruger if 'subtests' in testDict: 49229921a8fSScott Kruger substP=subst # Subtests can inherit args but be careful 49329921a8fSScott Kruger for stest in testDict["subtests"]: 4941e4ea733SToby Isaac subst=substP.copy() 4950357d61fSScott Kruger subst.update(testDict[stest]) 4960357d61fSScott Kruger subst['nsize']=str(subst['nsize']) 4977827e0d6SScott Kruger sLoopVars = self._getLoopVars(subst,testname,isSubtest=True) 4987827e0d6SScott Kruger #if '10_9' in testname: print sLoopVars 4990357d61fSScott Kruger if sLoopVars: 5008ba3acebSToby Isaac (sLoopHead,j) = self.getLoopVarsHead(sLoopVars,j) 5010357d61fSScott Kruger fh.write(sLoopHead+"\n") 5020357d61fSScott Kruger fh.write(self.getCmds(subst,j)+"\n") 5030357d61fSScott Kruger if sLoopVars: 5048ba3acebSToby Isaac (sLoopFoot,j) = self.getLoopVarsFoot(sLoopVars,j) 5050357d61fSScott Kruger fh.write(sLoopFoot+"\n") 50629921a8fSScott Kruger else: 50729921a8fSScott Kruger fh.write(self.getCmds(subst,j)+"\n") 5088ba3acebSToby Isaac 5090357d61fSScott Kruger if loopVars: 5108ba3acebSToby Isaac (loopFoot,j) = self.getLoopVarsFoot(loopVars,j) 5110357d61fSScott Kruger fh.write(loopFoot+"\n") 51229921a8fSScott Kruger 51329921a8fSScott Kruger fh.write(footer+"\n") 514b181ea86SSatish Balay os.chmod(os.path.join(runscript_dir,testname+".sh"),0755) 5157827e0d6SScott Kruger #if '10_9' in testname: sys.exit() 51629921a8fSScott Kruger return 51729921a8fSScott Kruger 51829921a8fSScott Kruger def genScriptsAndInfo(self,exfile,root,srcDict): 51929921a8fSScott Kruger """ 52029921a8fSScott Kruger Generate scripts from the source file, determine if built, etc. 52129921a8fSScott Kruger For every test in the exfile with info in the srcDict: 52229921a8fSScott Kruger 1. Determine if it needs to be run for this arch 52329921a8fSScott Kruger 2. Generate the script 52429921a8fSScott Kruger 3. Generate the data needed to write out the makefile in a 52529921a8fSScott Kruger convenient way 52629921a8fSScott Kruger All tests are *always* run, but some may be SKIP'd per the TAP standard 52729921a8fSScott Kruger """ 52829921a8fSScott Kruger debug=False 52929921a8fSScott Kruger execname=self.getExecname(exfile,root) 53029921a8fSScott Kruger isBuilt=self._isBuilt(exfile,srcDict) 53129921a8fSScott Kruger for test in srcDict: 53229921a8fSScott Kruger if test in self.buildkeys: continue 53329921a8fSScott Kruger if debug: print self.nameSpace(exfile,root), test 53429921a8fSScott Kruger srcDict[test]['execname']=execname # Convenience in generating scripts 53529921a8fSScott Kruger isRun=self._isRun(srcDict[test]) 53629921a8fSScott Kruger self.genRunScript(test,root,isRun,srcDict) 53729921a8fSScott Kruger srcDict[test]['isrun']=isRun 53829921a8fSScott Kruger self.addToTests(test,root,exfile,execname,srcDict[test]) 53929921a8fSScott Kruger 54029921a8fSScott Kruger # This adds to datastructure for building deps 541a8eb4092SScott Kruger if isBuilt: self.addToSources(exfile,root,srcDict) 54229921a8fSScott Kruger return 54329921a8fSScott Kruger 54429921a8fSScott Kruger def _isBuilt(self,exfile,srcDict): 54529921a8fSScott Kruger """ 54629921a8fSScott Kruger Determine if this file should be built. 54729921a8fSScott Kruger """ 54829921a8fSScott Kruger # Get the language based on file extension 54909cf0baaSJed Brown srcDict['SKIP'] = [] 55029921a8fSScott Kruger lang=self.getLanguage(exfile) 551c2426ab2SScott Kruger if (lang=="F" or lang=="F90"): 552c2426ab2SScott Kruger if not self.have_fortran: 55309cf0baaSJed Brown srcDict["SKIP"].append("Fortran required for this test") 554c2426ab2SScott Kruger elif lang=="F90" and 'PETSC_USING_F90FREEFORM' not in self.conf: 555c2426ab2SScott Kruger srcDict["SKIP"].append("Fortran f90freeform required for this test") 556862148f4SScott Kruger if lang=="cu" and 'PETSC_HAVE_CUDA' not in self.conf: 55709cf0baaSJed Brown srcDict["SKIP"].append("CUDA required for this test") 558862148f4SScott Kruger if lang=="cxx" and 'PETSC_HAVE_CXX' not in self.conf: 55909cf0baaSJed Brown srcDict["SKIP"].append("C++ required for this test") 56029921a8fSScott Kruger 56129921a8fSScott Kruger # Deprecated source files 56209cf0baaSJed Brown if srcDict.get("TODO"): 56309cf0baaSJed Brown return False 56429921a8fSScott Kruger 56529921a8fSScott Kruger # isRun can work with srcDict to handle the requires 566862148f4SScott Kruger if "requires" in srcDict: 56729921a8fSScott Kruger if len(srcDict["requires"])>0: 56829921a8fSScott Kruger return self._isRun(srcDict) 56929921a8fSScott Kruger 57009cf0baaSJed Brown return srcDict['SKIP'] == [] 57129921a8fSScott Kruger 57229921a8fSScott Kruger 57329921a8fSScott Kruger def _isRun(self,testDict): 57429921a8fSScott Kruger """ 57529921a8fSScott Kruger Based on the requirements listed in the src file and the petscconf.h 57629921a8fSScott Kruger info, determine whether this test should be run or not. 57729921a8fSScott Kruger """ 57829921a8fSScott Kruger indent=" " 57929921a8fSScott Kruger debug=False 58029921a8fSScott Kruger 58109cf0baaSJed Brown if 'SKIP' not in testDict: 58209cf0baaSJed Brown testDict['SKIP'] = [] 58329921a8fSScott Kruger # MPI requirements 584862148f4SScott Kruger if testDict.get('nsize',1)>1 and 'MPI_IS_MPIUNI' in self.conf: 58529921a8fSScott Kruger if debug: print indent+"Cannot run parallel tests" 58609cf0baaSJed Brown testDict['SKIP'].append("Parallel test with serial build") 58729921a8fSScott Kruger 58829921a8fSScott Kruger # The requirements for the test are the sum of all the run subtests 589862148f4SScott Kruger if 'subtests' in testDict: 590862148f4SScott Kruger if 'requires' not in testDict: testDict['requires']="" 59129921a8fSScott Kruger for stest in testDict['subtests']: 592862148f4SScott Kruger if 'requires' in testDict[stest]: 593862148f4SScott Kruger testDict['requires']+=" "+testDict[stest]['requires'] 59429921a8fSScott Kruger 59529921a8fSScott Kruger 59629921a8fSScott Kruger # Now go through all requirements 597862148f4SScott Kruger if 'requires' in testDict: 59829921a8fSScott Kruger for requirement in testDict['requires'].split(): 59929921a8fSScott Kruger requirement=requirement.strip() 60029921a8fSScott Kruger if not requirement: continue 60129921a8fSScott Kruger if debug: print indent+"Requirement: ", requirement 60229921a8fSScott Kruger isNull=False 60329921a8fSScott Kruger if requirement.startswith("!"): 60429921a8fSScott Kruger requirement=requirement[1:]; isNull=True 60529921a8fSScott Kruger # Precision requirement for reals 60629921a8fSScott Kruger if requirement in self.precision_types: 60729921a8fSScott Kruger if self.conf['PETSC_PRECISION']==requirement: 60809cf0baaSJed Brown if isNull: 60909cf0baaSJed Brown testDict['SKIP'].append("not "+requirement+" required") 61009cf0baaSJed Brown continue 6114bb4d03dSScott Kruger continue # Success 61209cf0baaSJed Brown elif not isNull: 61309cf0baaSJed Brown testDict['SKIP'].append(requirement+" required") 61409cf0baaSJed Brown continue 61529921a8fSScott Kruger # Precision requirement for ints 61629921a8fSScott Kruger if requirement in self.integer_types: 61729921a8fSScott Kruger if requirement=="int32": 61829921a8fSScott Kruger if self.conf['PETSC_SIZEOF_INT']==4: 61909cf0baaSJed Brown if isNull: 62009cf0baaSJed Brown testDict['SKIP'].append("not int32 required") 62109cf0baaSJed Brown continue 6224bb4d03dSScott Kruger continue # Success 62309cf0baaSJed Brown elif not isNull: 62409cf0baaSJed Brown testDict['SKIP'].append("int32 required") 62509cf0baaSJed Brown continue 62629921a8fSScott Kruger if requirement=="int64": 62729921a8fSScott Kruger if self.conf['PETSC_SIZEOF_INT']==8: 62809cf0baaSJed Brown if isNull: 62909cf0baaSJed Brown testDict['SKIP'].append("NOT int64 required") 63009cf0baaSJed Brown continue 6314bb4d03dSScott Kruger continue # Success 63209cf0baaSJed Brown elif not isNull: 63309cf0baaSJed Brown testDict['SKIP'].append("int64 required") 63409cf0baaSJed Brown continue 63529921a8fSScott Kruger # Datafilespath 63609cf0baaSJed Brown if requirement=="datafilespath" and not isNull: 63709cf0baaSJed Brown testDict['SKIP'].append("Requires DATAFILESPATH") 63809cf0baaSJed Brown continue 63929921a8fSScott Kruger # Defines -- not sure I have comments matching 6408304fa3fSScott Kruger if "define(" in requirement.lower(): 64129921a8fSScott Kruger reqdef=requirement.split("(")[1].split(")")[0] 64209cf0baaSJed Brown if reqdef in self.conf: 64329921a8fSScott Kruger if isNull: 64409cf0baaSJed Brown testDict['SKIP'].append("Null requirement not met: "+requirement) 64509cf0baaSJed Brown continue 6464bb4d03dSScott Kruger continue # Success 6474bb4d03dSScott Kruger elif not isNull: 64809cf0baaSJed Brown testDict['SKIP'].append("Required: "+requirement) 64909cf0baaSJed Brown continue 65029921a8fSScott Kruger 65129921a8fSScott Kruger # Rest should be packages that we can just get from conf 65209cf0baaSJed Brown if requirement == "complex": 65309cf0baaSJed Brown petscconfvar="PETSC_USE_COMPLEX" 65409cf0baaSJed Brown else: 65509cf0baaSJed Brown petscconfvar="PETSC_HAVE_"+requirement.upper() 65629921a8fSScott Kruger if self.conf.get(petscconfvar): 65729921a8fSScott Kruger if isNull: 65809cf0baaSJed Brown testDict['SKIP'].append("Not "+petscconfvar+" requirement not met") 65909cf0baaSJed Brown continue 6604bb4d03dSScott Kruger continue # Success 661df3aec83SJed Brown elif not isNull: 66229921a8fSScott Kruger if debug: print "requirement not found: ", requirement 66309cf0baaSJed Brown testDict['SKIP'].append(petscconfvar+" requirement not met") 66409cf0baaSJed Brown continue 66529921a8fSScott Kruger 66609cf0baaSJed Brown return testDict['SKIP'] == [] 66729921a8fSScott Kruger 66829921a8fSScott Kruger def genPetscTests_summarize(self,dataDict): 66929921a8fSScott Kruger """ 67029921a8fSScott Kruger Required method to state what happened 67129921a8fSScott Kruger """ 67229921a8fSScott Kruger if not self.summarize: return 67329921a8fSScott Kruger indent=" " 674cfaa06beSSatish Balay fhname=os.path.join(self.testroot_dir,'GenPetscTests_summarize.txt') 67529921a8fSScott Kruger fh=open(fhname,"w") 67664ca018dSScott Kruger #print "See ", fhname 67729921a8fSScott Kruger for root in dataDict: 678*e551db17SScott Kruger relroot=os.path.join('src',os.path.relpath(root,self.srcdir)) 67929921a8fSScott Kruger pkg=relroot.split("/")[1] 68029921a8fSScott Kruger fh.write(relroot+"\n") 68129921a8fSScott Kruger allSrcs=[] 682*e551db17SScott Kruger for lang in LANGS: allSrcs+=self.sources[pkg][lang]['srcs'] 68329921a8fSScott Kruger for exfile in dataDict[root]: 68429921a8fSScott Kruger # Basic information 68529921a8fSScott Kruger fullfile=os.path.join(root,exfile) 686*e551db17SScott Kruger rfile=os.path.join('src',os.path.relpath(root,self.srcdir)) 68729921a8fSScott Kruger builtStatus=(" Is built" if rfile in allSrcs else " Is NOT built") 68829921a8fSScott Kruger fh.write(indent+exfile+indent*4+builtStatus+"\n") 68929921a8fSScott Kruger 69029921a8fSScott Kruger for test in dataDict[root][exfile]: 69129921a8fSScott Kruger if test in self.buildkeys: continue 69229921a8fSScott Kruger line=indent*2+test 69329921a8fSScott Kruger fh.write(line+"\n") 69429921a8fSScott Kruger # Looks nice to have the keys in order 69529921a8fSScott Kruger #for key in dataDict[root][exfile][test]: 69629921a8fSScott Kruger for key in "isrun abstracted nsize args requires script".split(): 697862148f4SScott Kruger if key not in dataDict[root][exfile][test]: continue 69829921a8fSScott Kruger line=indent*3+key+": "+str(dataDict[root][exfile][test][key]) 69929921a8fSScott Kruger fh.write(line+"\n") 70029921a8fSScott Kruger fh.write("\n") 70129921a8fSScott Kruger fh.write("\n") 70229921a8fSScott Kruger fh.write("\n") 70329921a8fSScott Kruger #fh.write("\nClass Sources\n"+str(self.sources)+"\n") 70429921a8fSScott Kruger #fh.write("\nClass Tests\n"+str(self.tests)+"\n") 70529921a8fSScott Kruger fh.close() 70629921a8fSScott Kruger return 70729921a8fSScott Kruger 70829921a8fSScott Kruger def genPetscTests(self,root,dirs,files,dataDict): 70929921a8fSScott Kruger """ 71029921a8fSScott Kruger Go through and parse the source files in the directory to generate 71129921a8fSScott Kruger the examples based on the metadata contained in the source files 71229921a8fSScott Kruger """ 71329921a8fSScott Kruger debug=False 71429921a8fSScott Kruger # Use examplesAnalyze to get what the makefles think are sources 71529921a8fSScott Kruger #self.examplesAnalyze(root,dirs,files,anlzDict) 71629921a8fSScott Kruger 71729921a8fSScott Kruger dataDict[root]={} 71829921a8fSScott Kruger 71929921a8fSScott Kruger for exfile in files: 72029921a8fSScott Kruger #TST: Until we replace files, still leaving the orginals as is 72129921a8fSScott Kruger #if not exfile.startswith("new_"+"ex"): continue 72262197512SBarry Smith #if not exfile.startswith("ex"): continue 72329921a8fSScott Kruger 72429921a8fSScott Kruger # Convenience 72529921a8fSScott Kruger fullex=os.path.join(root,exfile) 726*e551db17SScott Kruger relpfile=os.path.join('src',os.path.relpath(fullex,self.srcdir)) 72729921a8fSScott Kruger if debug: print relpfile 72896d5c3b5SScott Kruger dataDict[root].update(testparse.parseTestFile(fullex,0)) 72929921a8fSScott Kruger # Need to check and make sure tests are in the file 73029921a8fSScott Kruger # if verbosity>=1: print relpfile 731862148f4SScott Kruger if exfile in dataDict[root]: 73229921a8fSScott Kruger self.genScriptsAndInfo(exfile,root,dataDict[root][exfile]) 73329921a8fSScott Kruger 73429921a8fSScott Kruger return 73529921a8fSScott Kruger 73629921a8fSScott Kruger def walktree(self,top,action="printFiles"): 73729921a8fSScott Kruger """ 73829921a8fSScott Kruger Walk a directory tree, starting from 'top' 73929921a8fSScott Kruger """ 74029921a8fSScott Kruger #print "action", action 74129921a8fSScott Kruger # Goal of action is to fill this dictionary 74229921a8fSScott Kruger dataDict={} 74329921a8fSScott Kruger for root, dirs, files in os.walk(top, topdown=False): 74429921a8fSScott Kruger if not "examples" in root: continue 74529921a8fSScott Kruger if not os.path.isfile(os.path.join(root,"makefile")): continue 74629921a8fSScott Kruger bname=os.path.basename(root.rstrip("/")) 74729921a8fSScott Kruger if bname=="tests" or bname=="tutorials": 74829921a8fSScott Kruger eval("self."+action+"(root,dirs,files,dataDict)") 74929921a8fSScott Kruger if type(top) != types.StringType: 75029921a8fSScott Kruger raise TypeError("top must be a string") 75129921a8fSScott Kruger # Now summarize this dictionary 75229921a8fSScott Kruger eval("self."+action+"_summarize(dataDict)") 75329921a8fSScott Kruger return dataDict 75429921a8fSScott Kruger 755b0790570SJed Brown def gen_gnumake(self, fd): 75629921a8fSScott Kruger """ 75729921a8fSScott Kruger Overwrite of the method in the base PETSc class 75829921a8fSScott Kruger """ 75929921a8fSScott Kruger def write(stem, srcs): 76029921a8fSScott Kruger for lang in LANGS: 761*e551db17SScott Kruger if self.inInstallDir: 762*e551db17SScott Kruger if len(srcs[lang]['srcs'])>0: 763*e551db17SScott Kruger fd.write('%(stem)s.%(lang)s := $(EXAMPLESDIR)/%(srcs)s\n' % dict(stem=stem, lang=lang, srcs=' $(EXAMPLESDIR)/'.join(srcs[lang]['srcs']))) 764*e551db17SScott Kruger else: 765*e551db17SScott Kruger fd.write('%(stem)s.%(lang)s := %(srcs)s\n' % dict(stem=stem, lang=lang, srcs=' '.join(srcs[lang]['srcs']))) 766*e551db17SScott Kruger else: 76729921a8fSScott Kruger fd.write('%(stem)s.%(lang)s := %(srcs)s\n' % dict(stem=stem, lang=lang, srcs=' '.join(srcs[lang]['srcs']))) 76829921a8fSScott Kruger for pkg in PKGS: 76929921a8fSScott Kruger srcs = self.gen_pkg(pkg) 770b0790570SJed Brown write('testsrcs-' + pkg, srcs) 77129921a8fSScott Kruger return self.gendeps 77229921a8fSScott Kruger 77329921a8fSScott Kruger def gen_pkg(self, pkg): 77429921a8fSScott Kruger """ 77529921a8fSScott Kruger Overwrite of the method in the base PETSc class 77629921a8fSScott Kruger """ 77729921a8fSScott Kruger return self.sources[pkg] 77829921a8fSScott Kruger 77929921a8fSScott Kruger def write_gnumake(self,dataDict): 78029921a8fSScott Kruger """ 78129921a8fSScott Kruger Write out something similar to files from gmakegen.py 78229921a8fSScott Kruger 78329921a8fSScott Kruger Test depends on script which also depends on source 78429921a8fSScott Kruger file, but since I don't have a good way generating 78529921a8fSScott Kruger acting on a single file (oops) just depend on 78629921a8fSScott Kruger executable which in turn will depend on src file 78729921a8fSScott Kruger """ 78868f6ad6bSScott Kruger # Different options for how to set up the targets 78968f6ad6bSScott Kruger compileExecsFirst=False 79068f6ad6bSScott Kruger 79129921a8fSScott Kruger # Open file 792*e551db17SScott Kruger arch_files = os.path.join(self.arch_dir,'lib','petsc','conf', 'testfiles') 79329921a8fSScott Kruger fd = open(arch_files, 'w') 79429921a8fSScott Kruger 79529921a8fSScott Kruger # Write out the sources 796b0790570SJed Brown gendeps = self.gen_gnumake(fd) 79729921a8fSScott Kruger 79829921a8fSScott Kruger # Write out the tests and execname targets 79929921a8fSScott Kruger fd.write("\n#Tests and executables\n") # Delimiter 80029921a8fSScott Kruger 80129921a8fSScott Kruger for pkg in PKGS: 80229921a8fSScott Kruger # These grab the ones that are built 80329921a8fSScott Kruger for lang in LANGS: 80485a27222SJed Brown testdeps=[] 80529921a8fSScott Kruger for ftest in self.tests[pkg][lang]: 80629921a8fSScott Kruger test=os.path.basename(ftest) 80729921a8fSScott Kruger basedir=os.path.dirname(ftest) 80885a27222SJed Brown testdeps.append(self.nameSpace(test,basedir)) 809612eee3eSJed Brown fd.write("test-"+pkg+"."+lang+" := "+' '.join(testdeps)+"\n") 81065ea9442SJed Brown fd.write('test-%s.%s : $(test-%s.%s)\n' % (pkg, lang, pkg, lang)) 81129921a8fSScott Kruger 81229921a8fSScott Kruger # test targets 81329921a8fSScott Kruger for ftest in self.tests[pkg][lang]: 81429921a8fSScott Kruger test=os.path.basename(ftest) 81529921a8fSScott Kruger basedir=os.path.dirname(ftest) 81629921a8fSScott Kruger testdir="${TESTDIR}/"+basedir+"/" 81729921a8fSScott Kruger nmtest=self.nameSpace(test,basedir) 81829921a8fSScott Kruger rundir=os.path.join(testdir,test) 81929921a8fSScott Kruger #print test, nmtest 82029921a8fSScott Kruger script=test+".sh" 82129921a8fSScott Kruger 82229921a8fSScott Kruger # Deps 82329921a8fSScott Kruger exfile=self.tests[pkg][lang][ftest]['exfile'] 824*e551db17SScott Kruger fullex=os.path.join(os.path.dirname(self.srcdir),exfile) 82529921a8fSScott Kruger localexec=self.tests[pkg][lang][ftest]['exec'] 82629921a8fSScott Kruger execname=os.path.join(testdir,localexec) 82768f6ad6bSScott Kruger fullscript=os.path.join(testdir,script) 82868f6ad6bSScott Kruger tmpfile=os.path.join(testdir,test,test+".tmp") 82929921a8fSScott Kruger 830b91d4a07SJed Brown # *.counts depends on the script and either executable (will 831b91d4a07SJed Brown # be run) or the example source file (SKIP or TODO) 832b91d4a07SJed Brown fd.write('%s.counts : %s %s\n' 833b91d4a07SJed Brown % (os.path.join('$(TESTDIR)/counts', nmtest), 834b91d4a07SJed Brown fullscript, 835b91d4a07SJed Brown execname if exfile in self.sources[pkg][lang]['srcs'] else fullex)) 83629921a8fSScott Kruger # Now write the args: 837612eee3eSJed Brown fd.write(nmtest+"_ARGS := '"+self.tests[pkg][lang][ftest]['argLabel']+"'\n") 838df2e1f37SScott Kruger 839612eee3eSJed Brown fd.close() 84029921a8fSScott Kruger return 84129921a8fSScott Kruger 84229921a8fSScott Kruger def writeHarness(self,output,dataDict): 84329921a8fSScott Kruger """ 84429921a8fSScott Kruger This is set up to write out multiple harness even if only gnumake 84529921a8fSScott Kruger is supported now 84629921a8fSScott Kruger """ 84729921a8fSScott Kruger eval("self.write_"+output+"(dataDict)") 84829921a8fSScott Kruger return 84929921a8fSScott Kruger 850*e551db17SScott Krugerdef main(petsc_dir=None, petsc_arch=None, output=None, verbose=False, single_ex=False, srcdir=None, testdir=None): 85129921a8fSScott Kruger if output is None: 85229921a8fSScott Kruger output = 'gnumake' 85329921a8fSScott Kruger 85429921a8fSScott Kruger 855*e551db17SScott Kruger pEx=generateExamples(petsc_dir=petsc_dir, petsc_arch=petsc_arch, 856*e551db17SScott Kruger verbose=verbose, single_ex=single_ex, srcdir=srcdir, 857*e551db17SScott Kruger testdir=testdir) 858*e551db17SScott Kruger dataDict=pEx.walktree(os.path.join(pEx.srcdir),action="genPetscTests") 85929921a8fSScott Kruger pEx.writeHarness(output,dataDict) 86029921a8fSScott Kruger 86129921a8fSScott Krugerif __name__ == '__main__': 86229921a8fSScott Kruger import optparse 86329921a8fSScott Kruger parser = optparse.OptionParser() 86429921a8fSScott Kruger parser.add_option('--verbose', help='Show mismatches between makefiles and the filesystem', action='store_true', default=False) 86529921a8fSScott Kruger parser.add_option('--petsc-arch', help='Set PETSC_ARCH different from environment', default=os.environ.get('PETSC_ARCH')) 866*e551db17SScott Kruger parser.add_option('--srcdir', help='Set location of sources different from PETSC_DIR/src', default=None) 86729921a8fSScott Kruger parser.add_option('--output', help='Location to write output file', default=None) 86829921a8fSScott Kruger parser.add_option('-s', '--single_executable', dest='single_executable', action="store_false", help='Whether there should be single executable per src subdir. Default is false') 869*e551db17SScott Kruger parser.add_option('-t', '--testdir', dest='testdir', help='Test directory: PETSC_DIR/PETSC_ARCH/testdir. Default is "tests"') 870*e551db17SScott Kruger opts, extra_args = parser.parse_args() 87129921a8fSScott Kruger opts, extra_args = parser.parse_args() 87229921a8fSScott Kruger if extra_args: 87329921a8fSScott Kruger import sys 87429921a8fSScott Kruger sys.stderr.write('Unknown arguments: %s\n' % ' '.join(extra_args)) 87529921a8fSScott Kruger exit(1) 876*e551db17SScott Kruger main(petsc_arch=opts.petsc_arch, output=opts.output, verbose=opts.verbose, 877*e551db17SScott Kruger single_ex=opts.single_executable, srcdir=opts.srcdir, testdir=opts.testdir) 878