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 """ 24e551db17SScott Kruger def __init__(self,petsc_dir=None, petsc_arch=None, testdir=None, verbose=False, single_ex=False, srcdir=None): 25e551db17SScott Kruger super(generateExamples, self).__init__(petsc_dir, petsc_arch, verbose) 2629921a8fSScott Kruger 2729921a8fSScott Kruger self.single_ex=single_ex 28e551db17SScott Kruger 29*c173c275SScott Kruger # Set locations to handle movement 30*c173c275SScott Kruger if not self.inInstallDir(thisscriptdir): 3129921a8fSScott Kruger self.arch_dir=os.path.join(self.petsc_dir,self.petsc_arch) 32*c173c275SScott Kruger self.srcdir=os.path.join(self.petsc_dir,'src') 33e551db17SScott Kruger else: 34*c173c275SScott Kruger # set PETSC_ARCH to install directory to allow script to work in both 35*c173c275SScott Kruger dirlist=thisscriptdir.split(os.path.sep) 36*c173c275SScott Kruger installdir=os.path.sep.join(dirlist[0:len(dirlist)-4]) 37e551db17SScott Kruger self.arch_dir=installdir 38*c173c275SScott Kruger self.srcdir=os.path.join(os.path.dirname(thisscriptdir),'src') 39e551db17SScott Kruger 40e551db17SScott Kruger # Do some initialization 41e551db17SScott Kruger if testdir: 42e551db17SScott Kruger # If full path given, then use it, otherwise assume relative to arch_dir 43*c173c275SScott Kruger if testdir.strip().startswith(os.path.sep): 44e551db17SScott Kruger self.testroot_dir=testdir.strip() 45e551db17SScott Kruger else: 46e551db17SScott Kruger self.testroot_dir=os.path.join(self.arch_dir,testdir.strip()) 47e551db17SScott Kruger else: 48e551db17SScott Kruger self.testroot_dir=os.path.join(self.arch_dir,"tests") 49e551db17SScott Kruger 5029921a8fSScott Kruger self.ptNaming=True 5129921a8fSScott Kruger # Whether to write out a useful debugging 5229921a8fSScott Kruger #if verbose: self.summarize=True 5329921a8fSScott Kruger self.summarize=True 5429921a8fSScott Kruger 5529921a8fSScott Kruger # For help in setting the requirements 5612df5dc0SToby Isaac self.precision_types="single double __float128 int32".split() 5729921a8fSScott Kruger self.integer_types="int32 int64".split() 5829921a8fSScott Kruger self.languages="fortran cuda cxx".split() # Always requires C so do not list 5929921a8fSScott Kruger 6029921a8fSScott Kruger # Things that are not test 6129921a8fSScott Kruger self.buildkeys=testparse.buildkeys 6229921a8fSScott Kruger 6329921a8fSScott Kruger # Adding a dictionary for storing sources, objects, and tests 6429921a8fSScott Kruger # to make building the dependency tree easier 6529921a8fSScott Kruger self.sources={} 6629921a8fSScott Kruger self.objects={} 6729921a8fSScott Kruger self.tests={} 6829921a8fSScott Kruger for pkg in PKGS: 6929921a8fSScott Kruger self.sources[pkg]={} 7029921a8fSScott Kruger self.objects[pkg]=[] 7129921a8fSScott Kruger self.tests[pkg]={} 7229921a8fSScott Kruger for lang in LANGS: 7329921a8fSScott Kruger self.sources[pkg][lang]={} 7429921a8fSScott Kruger self.sources[pkg][lang]['srcs']=[] 7529921a8fSScott Kruger self.tests[pkg][lang]={} 7629921a8fSScott Kruger 7729921a8fSScott Kruger if not os.path.isdir(self.testroot_dir): os.makedirs(self.testroot_dir) 780357d61fSScott Kruger 790357d61fSScott Kruger self.indent=" " 8029921a8fSScott Kruger return 8129921a8fSScott Kruger 82*c173c275SScott Kruger def srcrelpath(self,rdir): 83*c173c275SScott Kruger """ 84*c173c275SScott Kruger Get relative path to source directory 85*c173c275SScott Kruger """ 86*c173c275SScott Kruger return os.path.join('src',os.path.relpath(rdir,self.srcdir)) 87*c173c275SScott Kruger 88*c173c275SScott Kruger def inInstallDir(self,thisscriptdir): 89*c173c275SScott Kruger """ 90*c173c275SScott Kruger When petsc is installed then this file in installed in: 91*c173c275SScott Kruger <PREFIX>/share/petsc/examples/config/gmakegentest.py 92*c173c275SScott Kruger otherwise the path is: 93*c173c275SScott Kruger <PETSC_DIR>/config/gmakegentest.py 94*c173c275SScott Kruger We use this difference to determine if we are in installdir 95*c173c275SScott Kruger """ 96*c173c275SScott Kruger dirlist=thisscriptdir.split(os.path.sep) 97*c173c275SScott Kruger if len(dirlist)>4: 98*c173c275SScott Kruger lastfour=os.path.sep.join(dirlist[len(dirlist)-4:]) 99*c173c275SScott Kruger if lastfour==os.path.join('share','petsc','examples','config'): 100*c173c275SScott Kruger return True 101*c173c275SScott Kruger else: 102*c173c275SScott Kruger return False 103*c173c275SScott Kruger else: 104*c173c275SScott Kruger return False 105*c173c275SScott Kruger 10629921a8fSScott Kruger def nameSpace(self,srcfile,srcdir): 10729921a8fSScott Kruger """ 10829921a8fSScott Kruger Because the scripts have a non-unique naming, the pretty-printing 10929921a8fSScott Kruger needs to convey the srcdir and srcfile. There are two ways of doing this. 11029921a8fSScott Kruger """ 11129921a8fSScott Kruger if self.ptNaming: 11229921a8fSScott Kruger cdir=srcdir.split('src')[1].lstrip("/").rstrip("/") 11329921a8fSScott Kruger prefix=cdir.replace('/examples/','_').replace("/","_")+"-" 11429921a8fSScott Kruger nameString=prefix+srcfile 11529921a8fSScott Kruger else: 11629921a8fSScott Kruger #nameString=srcdir+": "+srcfile 11729921a8fSScott Kruger nameString=srcfile 11829921a8fSScott Kruger return nameString 11929921a8fSScott Kruger 12029921a8fSScott Kruger def getLanguage(self,srcfile): 12129921a8fSScott Kruger """ 12229921a8fSScott Kruger Based on the source, determine associated language as found in gmakegen.LANGS 12329921a8fSScott Kruger Can we just return srcext[1:\] now? 12429921a8fSScott Kruger """ 12529921a8fSScott Kruger langReq=None 12629921a8fSScott Kruger srcext=os.path.splitext(srcfile)[-1] 12729921a8fSScott Kruger if srcext in ".F90".split(): langReq="F90" 12829921a8fSScott Kruger if srcext in ".F".split(): langReq="F" 12929921a8fSScott Kruger if srcext in ".cxx".split(): langReq="cxx" 13029921a8fSScott Kruger if srcext == ".cu": langReq="cu" 13129921a8fSScott Kruger if srcext == ".c": langReq="c" 1320aac2865SBarry Smith #if not langReq: print "ERROR: ", srcext, srcfile 13329921a8fSScott Kruger return langReq 13429921a8fSScott Kruger 13596d5c3b5SScott Kruger def _getLoopVars(self,inDict,testname, isSubtest=False): 136e9b06b45SScott Kruger """ 137e9b06b45SScott Kruger Given: 'args: -bs {{1 2 3 4 5}} -pc_type {{cholesky sor}} -ksp_monitor' 138e9b06b45SScott Kruger Return: 13996d5c3b5SScott Kruger inDict['args']: -ksp_monitor 14096d5c3b5SScott Kruger inDict['subargs']: -bs ${bs} -pc_type ${pc_type} 1410357d61fSScott Kruger loopVars['subargs']['varlist']=['bs' 'pc_type'] # Don't worry about OrderedDict 1427827e0d6SScott Kruger loopVars['subargs']['bs']=[["bs"],["1 2 3 4 5"]] 1437827e0d6SScott Kruger loopVars['subargs']['pc_type']=[["pc_type"],["cholesky sor"]] 14496d5c3b5SScott Kruger subst should be passed in instead of inDict 145e9b06b45SScott Kruger """ 1460357d61fSScott Kruger loopVars={}; newargs="" 14796d5c3b5SScott Kruger lkeys=inDict.keys() 14896d5c3b5SScott Kruger lsuffix='_' 149aae9f2d9SScott Kruger from testparse import parseLoopArgs 1500357d61fSScott Kruger for key in lkeys: 15196d5c3b5SScott Kruger if type(inDict[key])!=types.StringType: continue 15296d5c3b5SScott Kruger keystr = str(inDict[key]) 1530357d61fSScott Kruger akey=('subargs' if key=='args' else key) # what to assign 154862148f4SScott Kruger if akey not in inDict: inDict[akey]='' 1550357d61fSScott Kruger varlist=[] 156e9b06b45SScott Kruger for varset in re.split('-(?=[a-zA-Z])',keystr): 157e9b06b45SScott Kruger if not varset.strip(): continue 158aae9f2d9SScott Kruger if '{{' in varset: 159aae9f2d9SScott Kruger keyvar,lvars,ftype=parseLoopArgs(varset) 160862148f4SScott Kruger if akey not in loopVars: loopVars[akey]={} 1617827e0d6SScott Kruger varlist.append(keyvar) 1622521ea3cSScott Kruger loopVars[akey][keyvar]=[keyvar,lvars] 1637827e0d6SScott Kruger if akey=='nsize': 16496d5c3b5SScott Kruger inDict[akey] = '${' + keyvar + '}' 16596d5c3b5SScott Kruger lsuffix+=akey+'-'+inDict[akey]+'_' 1667827e0d6SScott Kruger else: 16796d5c3b5SScott Kruger inDict[akey] += ' -'+keyvar+' ${' + keyvar + '}' 16896d5c3b5SScott Kruger lsuffix+=keyvar+'-${' + keyvar + '}_' 1697827e0d6SScott Kruger else: 1707827e0d6SScott Kruger if key=='args': newargs+=" -"+varset.strip() 1710357d61fSScott Kruger if len(varlist)>0: loopVars[akey]['varlist']=varlist 1728ba3acebSToby Isaac 1730357d61fSScott Kruger 1740357d61fSScott Kruger # For subtests, args are always substituted in (not top level) 1750357d61fSScott Kruger if isSubtest: 17696d5c3b5SScott Kruger inDict['subargs']+=" "+newargs.strip() 17796d5c3b5SScott Kruger inDict['args']='' 178862148f4SScott Kruger if 'label_suffix' in inDict: 17996d5c3b5SScott Kruger inDict['label_suffix']+=lsuffix.rstrip('_') 1800357d61fSScott Kruger else: 18196d5c3b5SScott Kruger inDict['label_suffix']=lsuffix.rstrip('_') 18296d5c3b5SScott Kruger else: 18396d5c3b5SScott Kruger if len(loopVars.keys())>0: 18496d5c3b5SScott Kruger inDict['args']=newargs.strip() 18596d5c3b5SScott Kruger inDict['label_suffix']=lsuffix.rstrip('_') 1860357d61fSScott Kruger if len(loopVars.keys())>0: 187e9b06b45SScott Kruger return loopVars 1880357d61fSScott Kruger else: 1890357d61fSScott Kruger return None 1908ba3acebSToby Isaac 19129921a8fSScott Kruger def getArgLabel(self,testDict): 19229921a8fSScott Kruger """ 19329921a8fSScott Kruger In all of the arguments in the test dictionary, create a simple 19429921a8fSScott Kruger string for searching within the makefile system. For simplicity in 19529921a8fSScott Kruger search, remove "-", for strings, etc. 19629921a8fSScott Kruger Also, concatenate the arg commands 19729921a8fSScott Kruger For now, ignore nsize -- seems hard to search for anyway 19829921a8fSScott Kruger """ 19929921a8fSScott Kruger # Collect all of the args associated with a test 200862148f4SScott Kruger argStr=("" if 'args' not in testDict else testDict['args']) 201862148f4SScott Kruger if 'subtests' in testDict: 20229921a8fSScott Kruger for stest in testDict["subtests"]: 20329921a8fSScott Kruger sd=testDict[stest] 204862148f4SScott Kruger argStr=argStr+("" if 'args' not in sd else sd['args']) 20529921a8fSScott Kruger 20629921a8fSScott Kruger # Now go through and cleanup 20729921a8fSScott Kruger argStr=re.sub('{{(.*?)}}',"",argStr) 20829921a8fSScott Kruger argStr=re.sub('-'," ",argStr) 20929921a8fSScott Kruger for digit in string.digits: argStr=re.sub(digit," ",argStr) 21029921a8fSScott Kruger argStr=re.sub("\.","",argStr) 21129921a8fSScott Kruger argStr=re.sub(",","",argStr) 21229921a8fSScott Kruger argStr=re.sub('\+',' ',argStr) 21329921a8fSScott Kruger argStr=re.sub(' +',' ',argStr) # Remove repeated white space 21429921a8fSScott Kruger return argStr.strip() 21529921a8fSScott Kruger 21629921a8fSScott Kruger def addToSources(self,exfile,root,srcDict): 21729921a8fSScott Kruger """ 21829921a8fSScott Kruger Put into data structure that allows easy generation of makefile 21929921a8fSScott Kruger """ 220*c173c275SScott Kruger rpath=self.srcrelpath(root) 221*c173c275SScott Kruger pkg=rpath.split(os.path.sep)[1] 222e551db17SScott Kruger relpfile=os.path.join(rpath,exfile) 22329921a8fSScott Kruger lang=self.getLanguage(exfile) 2240aac2865SBarry Smith if not lang: return 22529921a8fSScott Kruger self.sources[pkg][lang]['srcs'].append(relpfile) 226862148f4SScott Kruger if 'depends' in srcDict: 22729921a8fSScott Kruger depSrc=srcDict['depends'] 22829921a8fSScott Kruger depObj=os.path.splitext(depSrc)[0]+".o" 22929921a8fSScott Kruger self.sources[pkg][lang][exfile]=depObj 23029921a8fSScott Kruger 23129921a8fSScott Kruger # In gmakefile, ${TESTDIR} var specifies the object compilation 232*c173c275SScott Kruger testsdir=self.srcrelpath(root)+"/" 23329921a8fSScott Kruger objfile="${TESTDIR}/"+testsdir+os.path.splitext(exfile)[0]+".o" 23429921a8fSScott Kruger self.objects[pkg].append(objfile) 23529921a8fSScott Kruger return 23629921a8fSScott Kruger 23729921a8fSScott Kruger def addToTests(self,test,root,exfile,execname,testDict): 23829921a8fSScott Kruger """ 23929921a8fSScott Kruger Put into data structure that allows easy generation of makefile 24029921a8fSScott Kruger Organized by languages to allow testing of languages 24129921a8fSScott Kruger """ 242*c173c275SScott Kruger rpath=self.srcrelpath(root) 243e551db17SScott Kruger pkg=rpath.split("/")[1] 24429921a8fSScott Kruger #nmtest=self.nameSpace(test,root) 24529921a8fSScott Kruger nmtest=os.path.join(rpath,test) 24629921a8fSScott Kruger lang=self.getLanguage(exfile) 2470aac2865SBarry Smith if not lang: return 24829921a8fSScott Kruger self.tests[pkg][lang][nmtest]={} 24929921a8fSScott Kruger self.tests[pkg][lang][nmtest]['exfile']=os.path.join(rpath,exfile) 25029921a8fSScott Kruger self.tests[pkg][lang][nmtest]['exec']=execname 25129921a8fSScott Kruger self.tests[pkg][lang][nmtest]['argLabel']=self.getArgLabel(testDict) 25229921a8fSScott Kruger return 25329921a8fSScott Kruger 25429921a8fSScott Kruger def getExecname(self,exfile,root): 25529921a8fSScott Kruger """ 25629921a8fSScott Kruger Generate bash script using template found next to this file. 25729921a8fSScott Kruger This file is read in at constructor time to avoid file I/O 25829921a8fSScott Kruger """ 259*c173c275SScott Kruger rpath=self.srcrelpath(root) 26029921a8fSScott Kruger if self.single_ex: 26129921a8fSScott Kruger execname=rpath.split("/")[1]+"-ex" 26229921a8fSScott Kruger else: 26329921a8fSScott Kruger execname=os.path.splitext(exfile)[0] 26429921a8fSScott Kruger return execname 26529921a8fSScott Kruger 26629921a8fSScott Kruger def getSubstVars(self,testDict,rpath,testname): 26729921a8fSScott Kruger """ 26829921a8fSScott Kruger Create a dictionary with all of the variables that get substituted 26929921a8fSScott Kruger into the template commands found in example_template.py 27029921a8fSScott Kruger """ 27129921a8fSScott Kruger subst={} 27296d5c3b5SScott Kruger 27396d5c3b5SScott Kruger # Handle defaults of testparse.acceptedkeys (e.g., ignores subtests) 274862148f4SScott Kruger if 'nsize' not in testDict: testDict['nsize']=1 2750a091e3eSScott Kruger if 'timeoutfactor' not in testDict: testDict['timeoutfactor']="1" 27696d5c3b5SScott Kruger for ak in testparse.acceptedkeys: 27796d5c3b5SScott Kruger if ak=='test': continue 278862148f4SScott Kruger subst[ak]=(testDict[ak] if ak in testDict else '') 27996d5c3b5SScott Kruger 28096d5c3b5SScott Kruger # Now do other variables 28196d5c3b5SScott Kruger subst['execname']=testDict['execname'] 282862148f4SScott Kruger if 'filter' in testDict: 28396d5c3b5SScott Kruger subst['filter']="'"+testDict['filter']+"'" # Quotes are tricky - overwrite 28468a9e459SScott Kruger 28596d5c3b5SScott Kruger # Others 28696d5c3b5SScott Kruger subst['subargs']='' # Default. For variables override 287e551db17SScott Kruger subst['srcdir']=os.path.join(os.path.dirname(self.srcdir),rpath) 28868a9e459SScott Kruger subst['label_suffix']='' 28996d5c3b5SScott Kruger subst['comments']="\n#".join(subst['comments'].split("\n")) 29068a9e459SScott Kruger if subst['comments']: subst['comments']="#"+subst['comments'] 29196d5c3b5SScott Kruger subst['exec']="../"+subst['execname'] 29229921a8fSScott Kruger subst['testroot']=self.testroot_dir 29329921a8fSScott Kruger subst['testname']=testname 29409cf0baaSJed Brown dp = self.conf.get('DATAFILESPATH','') 29509cf0baaSJed Brown subst['datafilespath_line'] = 'DATAFILESPATH=${DATAFILESPATH:-"'+dp+'"}' 29629921a8fSScott Kruger 2970bcc1aabSScott Kruger # This is used to label some matrices 2980bcc1aabSScott Kruger subst['petsc_index_size']=str(self.conf['PETSC_INDEX_SIZE']) 2990bcc1aabSScott Kruger subst['petsc_scalar_size']=str(self.conf['PETSC_SCALAR_SIZE']) 3000bcc1aabSScott Kruger 30129921a8fSScott Kruger # These can have for loops and are treated separately later 30296d5c3b5SScott Kruger subst['nsize']=str(subst['nsize']) 30329921a8fSScott Kruger 30429921a8fSScott Kruger #Conf vars 30526646c0bSSatish Balay if self.petsc_arch.find('valgrind')>=0: 30626646c0bSSatish Balay subst['mpiexec']='petsc_mpiexec_valgrind ' + self.conf['MPIEXEC'] 30726646c0bSSatish Balay else: 30826646c0bSSatish Balay subst['mpiexec']=self.conf['MPIEXEC'] 3094c8d737cSSatish Balay subst['petsc_dir']=self.petsc_dir # not self.conf['PETSC_DIR'] as this could be windows path 3100a091e3eSScott Kruger subst['petsc_arch']=self.petsc_arch 311e551db17SScott Kruger if not self.inInstallDir: 312e551db17SScott Kruger subst['CONFIG_DIR']=os.path.join(self.petsc_dir,'config') 313*c173c275SScott Kruger subst['PETSC_BINDIR']=os.path.join(self.petsc_dir,'bin') 314e551db17SScott Kruger else: 315e551db17SScott Kruger subst['CONFIG_DIR']=os.path.join(os.path.dirname(self.srcdir),'config') 316*c173c275SScott Kruger subst['PETSC_BINDIR']=os.path.join(self.petsc_dir,self.petsc_arch,'bin') 31729921a8fSScott Kruger subst['diff']=self.conf['DIFF'] 31829921a8fSScott Kruger subst['rm']=self.conf['RM'] 31929921a8fSScott Kruger subst['grep']=self.conf['GREP'] 320d6f00007SSatish Balay subst['petsc_lib_dir']=self.conf['PETSC_LIB_DIR'] 3210eb9b082SSatish Balay subst['wpetsc_dir']=self.conf['wPETSC_DIR'] 32229921a8fSScott Kruger 3233bcca444SScott Kruger # Output file is special because of subtests override 3243bcca444SScott Kruger defroot=(re.sub("run","",testname) if testname.startswith("run") else testname) 3253bcca444SScott Kruger if not "_" in defroot: defroot=defroot+"_1" 3263bcca444SScott Kruger subst['defroot']=defroot 3273bcca444SScott Kruger subst['label']=self.nameSpace(defroot,subst['srcdir']) 3283bcca444SScott Kruger subst['redirect_file']=defroot+".tmp" 329862148f4SScott Kruger if 'output_file' not in testDict: 3303bcca444SScott Kruger subst['output_file']="output/"+defroot+".out" 3313bcca444SScott Kruger # Add in the full path here. 3323bcca444SScott Kruger subst['output_file']=os.path.join(subst['srcdir'],subst['output_file']) 3333bcca444SScott Kruger if not os.path.isfile(os.path.join(self.petsc_dir,subst['output_file'])): 3343bcca444SScott Kruger if not subst['TODO']: 3353bcca444SScott Kruger print "Warning: "+subst['output_file']+" not found." 3363bcca444SScott Kruger # Worry about alt files here -- see 3373bcca444SScott Kruger # src/snes/examples/tutorials/output/ex22*.out 3383bcca444SScott Kruger altlist=[subst['output_file']] 3393bcca444SScott Kruger for i in range(1,3): 3403bcca444SScott Kruger altroot=defroot+"_alt" 3413bcca444SScott Kruger if i==2: altroot=altroot+"_2" 3423bcca444SScott Kruger af="output/"+altroot+".out" 3433bcca444SScott Kruger srcaf=os.path.join(subst['srcdir'],af) 3443bcca444SScott Kruger fullaf=os.path.join(self.petsc_dir,srcaf) 3453bcca444SScott Kruger if os.path.isfile(fullaf): altlist.append(srcaf) 3463bcca444SScott Kruger if len(altlist)>1: subst['altfiles']=altlist 3473bcca444SScott Kruger #if len(altlist)>1: print "Found alt files: ",altlist 3483bcca444SScott Kruger 34929921a8fSScott Kruger return subst 35029921a8fSScott Kruger 3510357d61fSScott Kruger def getCmds(self,subst,i): 35229921a8fSScott Kruger """ 35329921a8fSScott Kruger Generate bash script using template found next to this file. 35429921a8fSScott Kruger This file is read in at constructor time to avoid file I/O 35529921a8fSScott Kruger """ 3560357d61fSScott Kruger nindnt=i # the start and has to be consistent with below 3577a853109SScott Kruger cmdindnt=self.indent*nindnt 35829921a8fSScott Kruger cmdLines="" 35968a9e459SScott Kruger 36029921a8fSScott Kruger # MPI is the default -- but we have a few odd commands 36196d5c3b5SScott Kruger if not subst['command']: 3627a853109SScott Kruger cmd=cmdindnt+self._substVars(subst,example_template.mpitest) 36329921a8fSScott Kruger else: 3647a853109SScott Kruger cmd=cmdindnt+self._substVars(subst,example_template.commandtest) 3657a853109SScott Kruger cmdLines+=cmd+"\n"+cmdindnt+"res=$?\n\n" 36629921a8fSScott Kruger 3677a853109SScott Kruger cmdLines+=cmdindnt+'if test $res = 0; then\n' 3687a853109SScott Kruger diffindnt=self.indent*(nindnt+1) 36964ca018dSScott Kruger if not subst['filter_output']: 370862148f4SScott Kruger if 'altfiles' not in subst: 3717a853109SScott Kruger cmd=diffindnt+self._substVars(subst,example_template.difftest) 37264ca018dSScott Kruger else: 3733bcca444SScott Kruger # Have to do it by hand a bit because of variable number of alt files 3743bcca444SScott Kruger rf=subst['redirect_file'] 3757a853109SScott Kruger cmd=diffindnt+example_template.difftest.split('@')[0] 3763bcca444SScott Kruger for i in range(len(subst['altfiles'])): 3773bcca444SScott Kruger af=subst['altfiles'][i] 3783bcca444SScott Kruger cmd+=af+' '+rf+' > diff-${testname}-'+str(i)+'.out 2> diff-${testname}-'+str(i)+'.out' 3793bcca444SScott Kruger if i!=len(subst['altfiles'])-1: 3803bcca444SScott Kruger cmd+=' || ${diff_exe} ' 3813bcca444SScott Kruger else: 3823bcca444SScott Kruger cmd+='" diff-${testname}.out diff-${testname}.out diff-${label}' 3833bcca444SScott Kruger cmd+=subst['label_suffix']+' ""' # Quotes are painful 3843bcca444SScott Kruger else: 3857a853109SScott Kruger cmd=diffindnt+self._substVars(subst,example_template.filterdifftest) 38668a9e459SScott Kruger cmdLines+=cmd+"\n" 3877a853109SScott Kruger cmdLines+=cmdindnt+'else\n' 3887a853109SScott Kruger cmdLines+=diffindnt+'printf "ok ${label} # SKIP Command failed so no diff\\n"\n' 3897a853109SScott Kruger cmdLines+=cmdindnt+'fi\n' 39029921a8fSScott Kruger return cmdLines 39129921a8fSScott Kruger 39229921a8fSScott Kruger def _substVars(self,subst,origStr): 39329921a8fSScott Kruger """ 3947827e0d6SScott Kruger Substitute variables 39529921a8fSScott Kruger """ 39629921a8fSScott Kruger Str=origStr 39729921a8fSScott Kruger for subkey in subst: 39829921a8fSScott Kruger if type(subst[subkey])!=types.StringType: continue 39929921a8fSScott Kruger patt="@"+subkey.upper()+"@" 40029921a8fSScott Kruger Str=re.sub(patt,subst[subkey],Str) 40129921a8fSScott Kruger return Str 40229921a8fSScott Kruger 40309cf0baaSJed Brown def _writeTodoSkip(self,fh,tors,reasons,footer): 40468a9e459SScott Kruger """ 40568a9e459SScott Kruger Write out the TODO and SKIP lines in the file 40668a9e459SScott Kruger The TODO or SKIP variable, tors, should be lower case 40768a9e459SScott Kruger """ 40868a9e459SScott Kruger TORS=tors.upper() 40968a9e459SScott Kruger template=eval("example_template."+tors+"line") 41009cf0baaSJed Brown tsStr=re.sub("@"+TORS+"COMMENT@",', '.join(reasons),template) 41109cf0baaSJed Brown tab = '' 4122f2809e3SToby Isaac if reasons: 4132f2809e3SToby Isaac fh.write('if ! $force; then\n') 4142f2809e3SToby Isaac tab = tab + ' ' 41509cf0baaSJed Brown if reasons == ["Requires DATAFILESPATH"]: 41609cf0baaSJed Brown # The only reason not to run is DATAFILESPATH, which we check at run-time 4172f2809e3SToby Isaac fh.write(tab + 'if test -z "${DATAFILESPATH}"; then\n') 4182f2809e3SToby Isaac tab = tab + ' ' 41909cf0baaSJed Brown if reasons: 4202f2809e3SToby Isaac fh.write(tab+tsStr+"\n" + tab + "total=1; "+tors+"=1\n") 42109cf0baaSJed Brown fh.write(tab+footer+"\n") 42209cf0baaSJed Brown fh.write(tab+"exit\n") 42309cf0baaSJed Brown if reasons == ["Requires DATAFILESPATH"]: 42409cf0baaSJed Brown fh.write(' fi\n') 4252f2809e3SToby Isaac if reasons: 4262f2809e3SToby Isaac fh.write('fi\n') 42709cf0baaSJed Brown fh.write('\n\n') 42868a9e459SScott Kruger return 42968a9e459SScott Kruger 4308ba3acebSToby Isaac def getLoopVarsHead(self,loopVars,i): 4310357d61fSScott Kruger """ 4320357d61fSScott Kruger Generate a nicely indented string with the format loops 4330357d61fSScott Kruger Here is what the data structure looks like 4340357d61fSScott Kruger loopVars['subargs']['varlist']=['bs' 'pc_type'] # Don't worry about OrderedDict 4350357d61fSScott Kruger loopVars['subargs']['bs']=["i","1 2 3 4 5"] 4360357d61fSScott Kruger loopVars['subargs']['pc_type']=["j","cholesky sor"] 4370357d61fSScott Kruger """ 4380357d61fSScott Kruger outstr=''; indnt=self.indent 4398ba3acebSToby Isaac for key in loopVars: 4400357d61fSScott Kruger for var in loopVars[key]['varlist']: 4410357d61fSScott Kruger varval=loopVars[key][var] 4420357d61fSScott Kruger outstr += indnt * i + "for "+varval[0]+" in "+varval[1]+"; do\n" 4438ba3acebSToby Isaac i = i + 1 4448ba3acebSToby Isaac return (outstr,i) 4458ba3acebSToby Isaac 4468ba3acebSToby Isaac def getLoopVarsFoot(self,loopVars,i): 4470357d61fSScott Kruger outstr=''; indnt=self.indent 4488ba3acebSToby Isaac for key in loopVars: 4490357d61fSScott Kruger for var in loopVars[key]['varlist']: 4508ba3acebSToby Isaac i = i - 1 4510357d61fSScott Kruger outstr += indnt * i + "done\n" 4528ba3acebSToby Isaac return (outstr,i) 4538ba3acebSToby Isaac 45429921a8fSScott Kruger def genRunScript(self,testname,root,isRun,srcDict): 45529921a8fSScott Kruger """ 45629921a8fSScott Kruger Generate bash script using template found next to this file. 45729921a8fSScott Kruger This file is read in at constructor time to avoid file I/O 45829921a8fSScott Kruger """ 45929921a8fSScott Kruger # runscript_dir directory has to be consistent with gmakefile 46029921a8fSScott Kruger testDict=srcDict[testname] 461*c173c275SScott Kruger rpath=self.srcrelpath(root) 46229921a8fSScott Kruger runscript_dir=os.path.join(self.testroot_dir,rpath) 46329921a8fSScott Kruger if not os.path.isdir(runscript_dir): os.makedirs(runscript_dir) 46429921a8fSScott Kruger fh=open(os.path.join(runscript_dir,testname+".sh"),"w") 46529921a8fSScott Kruger petscvarfile=os.path.join(self.arch_dir,'lib','petsc','conf','petscvariables') 46629921a8fSScott Kruger 46796d5c3b5SScott Kruger # Get variables to go into shell scripts. last time testDict used 46829921a8fSScott Kruger subst=self.getSubstVars(testDict,rpath,testname) 46996d5c3b5SScott Kruger loopVars = self._getLoopVars(subst,testname) # Alters subst as well 47096d5c3b5SScott Kruger #if '33_' in testname: print subst['subargs'] 47129921a8fSScott Kruger 47264ca018dSScott Kruger #Handle runfiles 473862148f4SScott Kruger for lfile in subst.get('localrunfiles','').split(): 474e551db17SScott Kruger fullfile=os.path.join(root,lfile) 47564ca018dSScott Kruger shutil.copy(fullfile,runscript_dir) 47664ca018dSScott Kruger # Check subtests for local runfiles 477862148f4SScott Kruger for stest in subst.get("subtests",[]): 478862148f4SScott Kruger for lfile in testDict[stest].get('localrunfiles','').split(): 479e551db17SScott Kruger fullfile=os.path.join(root,lfile) 48064ca018dSScott Kruger shutil.copy(fullfile,self.runscript_dir) 48164ca018dSScott Kruger 48229921a8fSScott Kruger # Now substitute the key variables into the header and footer 48329921a8fSScott Kruger header=self._substVars(subst,example_template.header) 4840bcc1aabSScott Kruger # The header is done twice to enable @...@ in header 4850bcc1aabSScott Kruger header=self._substVars(subst,header) 4865e7f8670SScott Kruger footer=re.sub('@TESTROOT@',subst['testroot'],example_template.footer) 48729921a8fSScott Kruger 48829921a8fSScott Kruger # Start writing the file 48929921a8fSScott Kruger fh.write(header+"\n") 49029921a8fSScott Kruger 49129921a8fSScott Kruger # If there is a TODO or a SKIP then we do it before writing out the 49229921a8fSScott Kruger # rest of the command (which is useful for working on the test) 49329921a8fSScott Kruger # SKIP and TODO can be for the source file or for the runs 49409cf0baaSJed Brown self._writeTodoSkip(fh,'todo',[s for s in [srcDict.get('TODO',''), testDict.get('TODO','')] if s],footer) 49509cf0baaSJed Brown self._writeTodoSkip(fh,'skip',srcDict.get('SKIP',[]) + testDict.get('SKIP',[]),footer) 49629921a8fSScott Kruger 49729921a8fSScott Kruger j=0 # for indentation 49829921a8fSScott Kruger 4990357d61fSScott Kruger if loopVars: 5008ba3acebSToby Isaac (loopHead,j) = self.getLoopVarsHead(loopVars,j) 5018ba3acebSToby Isaac if (loopHead): fh.write(loopHead+"\n") 50229921a8fSScott Kruger 50329921a8fSScott Kruger # Subtests are special 504862148f4SScott Kruger if 'subtests' in testDict: 50529921a8fSScott Kruger substP=subst # Subtests can inherit args but be careful 50629921a8fSScott Kruger for stest in testDict["subtests"]: 5071e4ea733SToby Isaac subst=substP.copy() 5080357d61fSScott Kruger subst.update(testDict[stest]) 5090357d61fSScott Kruger subst['nsize']=str(subst['nsize']) 5107827e0d6SScott Kruger sLoopVars = self._getLoopVars(subst,testname,isSubtest=True) 5117827e0d6SScott Kruger #if '10_9' in testname: print sLoopVars 5120357d61fSScott Kruger if sLoopVars: 5138ba3acebSToby Isaac (sLoopHead,j) = self.getLoopVarsHead(sLoopVars,j) 5140357d61fSScott Kruger fh.write(sLoopHead+"\n") 5150357d61fSScott Kruger fh.write(self.getCmds(subst,j)+"\n") 5160357d61fSScott Kruger if sLoopVars: 5178ba3acebSToby Isaac (sLoopFoot,j) = self.getLoopVarsFoot(sLoopVars,j) 5180357d61fSScott Kruger fh.write(sLoopFoot+"\n") 51929921a8fSScott Kruger else: 52029921a8fSScott Kruger fh.write(self.getCmds(subst,j)+"\n") 5218ba3acebSToby Isaac 5220357d61fSScott Kruger if loopVars: 5238ba3acebSToby Isaac (loopFoot,j) = self.getLoopVarsFoot(loopVars,j) 5240357d61fSScott Kruger fh.write(loopFoot+"\n") 52529921a8fSScott Kruger 52629921a8fSScott Kruger fh.write(footer+"\n") 527b181ea86SSatish Balay os.chmod(os.path.join(runscript_dir,testname+".sh"),0755) 5287827e0d6SScott Kruger #if '10_9' in testname: sys.exit() 52929921a8fSScott Kruger return 53029921a8fSScott Kruger 53129921a8fSScott Kruger def genScriptsAndInfo(self,exfile,root,srcDict): 53229921a8fSScott Kruger """ 53329921a8fSScott Kruger Generate scripts from the source file, determine if built, etc. 53429921a8fSScott Kruger For every test in the exfile with info in the srcDict: 53529921a8fSScott Kruger 1. Determine if it needs to be run for this arch 53629921a8fSScott Kruger 2. Generate the script 53729921a8fSScott Kruger 3. Generate the data needed to write out the makefile in a 53829921a8fSScott Kruger convenient way 53929921a8fSScott Kruger All tests are *always* run, but some may be SKIP'd per the TAP standard 54029921a8fSScott Kruger """ 54129921a8fSScott Kruger debug=False 54229921a8fSScott Kruger execname=self.getExecname(exfile,root) 54329921a8fSScott Kruger isBuilt=self._isBuilt(exfile,srcDict) 54429921a8fSScott Kruger for test in srcDict: 54529921a8fSScott Kruger if test in self.buildkeys: continue 54629921a8fSScott Kruger if debug: print self.nameSpace(exfile,root), test 54729921a8fSScott Kruger srcDict[test]['execname']=execname # Convenience in generating scripts 54829921a8fSScott Kruger isRun=self._isRun(srcDict[test]) 54929921a8fSScott Kruger self.genRunScript(test,root,isRun,srcDict) 55029921a8fSScott Kruger srcDict[test]['isrun']=isRun 55129921a8fSScott Kruger self.addToTests(test,root,exfile,execname,srcDict[test]) 55229921a8fSScott Kruger 55329921a8fSScott Kruger # This adds to datastructure for building deps 554a8eb4092SScott Kruger if isBuilt: self.addToSources(exfile,root,srcDict) 55529921a8fSScott Kruger return 55629921a8fSScott Kruger 55729921a8fSScott Kruger def _isBuilt(self,exfile,srcDict): 55829921a8fSScott Kruger """ 55929921a8fSScott Kruger Determine if this file should be built. 56029921a8fSScott Kruger """ 56129921a8fSScott Kruger # Get the language based on file extension 56209cf0baaSJed Brown srcDict['SKIP'] = [] 56329921a8fSScott Kruger lang=self.getLanguage(exfile) 564c2426ab2SScott Kruger if (lang=="F" or lang=="F90"): 565c2426ab2SScott Kruger if not self.have_fortran: 56609cf0baaSJed Brown srcDict["SKIP"].append("Fortran required for this test") 567c2426ab2SScott Kruger elif lang=="F90" and 'PETSC_USING_F90FREEFORM' not in self.conf: 568c2426ab2SScott Kruger srcDict["SKIP"].append("Fortran f90freeform required for this test") 569862148f4SScott Kruger if lang=="cu" and 'PETSC_HAVE_CUDA' not in self.conf: 57009cf0baaSJed Brown srcDict["SKIP"].append("CUDA required for this test") 571862148f4SScott Kruger if lang=="cxx" and 'PETSC_HAVE_CXX' not in self.conf: 57209cf0baaSJed Brown srcDict["SKIP"].append("C++ required for this test") 57329921a8fSScott Kruger 57429921a8fSScott Kruger # Deprecated source files 57509cf0baaSJed Brown if srcDict.get("TODO"): 57609cf0baaSJed Brown return False 57729921a8fSScott Kruger 57829921a8fSScott Kruger # isRun can work with srcDict to handle the requires 579862148f4SScott Kruger if "requires" in srcDict: 58029921a8fSScott Kruger if len(srcDict["requires"])>0: 58129921a8fSScott Kruger return self._isRun(srcDict) 58229921a8fSScott Kruger 58309cf0baaSJed Brown return srcDict['SKIP'] == [] 58429921a8fSScott Kruger 58529921a8fSScott Kruger 58629921a8fSScott Kruger def _isRun(self,testDict): 58729921a8fSScott Kruger """ 58829921a8fSScott Kruger Based on the requirements listed in the src file and the petscconf.h 58929921a8fSScott Kruger info, determine whether this test should be run or not. 59029921a8fSScott Kruger """ 59129921a8fSScott Kruger indent=" " 59229921a8fSScott Kruger debug=False 59329921a8fSScott Kruger 59409cf0baaSJed Brown if 'SKIP' not in testDict: 59509cf0baaSJed Brown testDict['SKIP'] = [] 59629921a8fSScott Kruger # MPI requirements 597862148f4SScott Kruger if testDict.get('nsize',1)>1 and 'MPI_IS_MPIUNI' in self.conf: 59829921a8fSScott Kruger if debug: print indent+"Cannot run parallel tests" 59909cf0baaSJed Brown testDict['SKIP'].append("Parallel test with serial build") 60029921a8fSScott Kruger 60129921a8fSScott Kruger # The requirements for the test are the sum of all the run subtests 602862148f4SScott Kruger if 'subtests' in testDict: 603862148f4SScott Kruger if 'requires' not in testDict: testDict['requires']="" 60429921a8fSScott Kruger for stest in testDict['subtests']: 605862148f4SScott Kruger if 'requires' in testDict[stest]: 606862148f4SScott Kruger testDict['requires']+=" "+testDict[stest]['requires'] 60729921a8fSScott Kruger 60829921a8fSScott Kruger 60929921a8fSScott Kruger # Now go through all requirements 610862148f4SScott Kruger if 'requires' in testDict: 61129921a8fSScott Kruger for requirement in testDict['requires'].split(): 61229921a8fSScott Kruger requirement=requirement.strip() 61329921a8fSScott Kruger if not requirement: continue 61429921a8fSScott Kruger if debug: print indent+"Requirement: ", requirement 61529921a8fSScott Kruger isNull=False 61629921a8fSScott Kruger if requirement.startswith("!"): 61729921a8fSScott Kruger requirement=requirement[1:]; isNull=True 61829921a8fSScott Kruger # Precision requirement for reals 61929921a8fSScott Kruger if requirement in self.precision_types: 62029921a8fSScott Kruger if self.conf['PETSC_PRECISION']==requirement: 62109cf0baaSJed Brown if isNull: 62209cf0baaSJed Brown testDict['SKIP'].append("not "+requirement+" required") 62309cf0baaSJed Brown continue 6244bb4d03dSScott Kruger continue # Success 62509cf0baaSJed Brown elif not isNull: 62609cf0baaSJed Brown testDict['SKIP'].append(requirement+" required") 62709cf0baaSJed Brown continue 62829921a8fSScott Kruger # Precision requirement for ints 62929921a8fSScott Kruger if requirement in self.integer_types: 63029921a8fSScott Kruger if requirement=="int32": 63129921a8fSScott Kruger if self.conf['PETSC_SIZEOF_INT']==4: 63209cf0baaSJed Brown if isNull: 63309cf0baaSJed Brown testDict['SKIP'].append("not int32 required") 63409cf0baaSJed Brown continue 6354bb4d03dSScott Kruger continue # Success 63609cf0baaSJed Brown elif not isNull: 63709cf0baaSJed Brown testDict['SKIP'].append("int32 required") 63809cf0baaSJed Brown continue 63929921a8fSScott Kruger if requirement=="int64": 64029921a8fSScott Kruger if self.conf['PETSC_SIZEOF_INT']==8: 64109cf0baaSJed Brown if isNull: 64209cf0baaSJed Brown testDict['SKIP'].append("NOT int64 required") 64309cf0baaSJed Brown continue 6444bb4d03dSScott Kruger continue # Success 64509cf0baaSJed Brown elif not isNull: 64609cf0baaSJed Brown testDict['SKIP'].append("int64 required") 64709cf0baaSJed Brown continue 64829921a8fSScott Kruger # Datafilespath 64909cf0baaSJed Brown if requirement=="datafilespath" and not isNull: 65009cf0baaSJed Brown testDict['SKIP'].append("Requires DATAFILESPATH") 65109cf0baaSJed Brown continue 65229921a8fSScott Kruger # Defines -- not sure I have comments matching 6538304fa3fSScott Kruger if "define(" in requirement.lower(): 65429921a8fSScott Kruger reqdef=requirement.split("(")[1].split(")")[0] 65509cf0baaSJed Brown if reqdef in self.conf: 65629921a8fSScott Kruger if isNull: 65709cf0baaSJed Brown testDict['SKIP'].append("Null requirement not met: "+requirement) 65809cf0baaSJed Brown continue 6594bb4d03dSScott Kruger continue # Success 6604bb4d03dSScott Kruger elif not isNull: 66109cf0baaSJed Brown testDict['SKIP'].append("Required: "+requirement) 66209cf0baaSJed Brown continue 66329921a8fSScott Kruger 66429921a8fSScott Kruger # Rest should be packages that we can just get from conf 66509cf0baaSJed Brown if requirement == "complex": 66609cf0baaSJed Brown petscconfvar="PETSC_USE_COMPLEX" 66709cf0baaSJed Brown else: 66809cf0baaSJed Brown petscconfvar="PETSC_HAVE_"+requirement.upper() 66929921a8fSScott Kruger if self.conf.get(petscconfvar): 67029921a8fSScott Kruger if isNull: 67109cf0baaSJed Brown testDict['SKIP'].append("Not "+petscconfvar+" requirement not met") 67209cf0baaSJed Brown continue 6734bb4d03dSScott Kruger continue # Success 674df3aec83SJed Brown elif not isNull: 67529921a8fSScott Kruger if debug: print "requirement not found: ", requirement 67609cf0baaSJed Brown testDict['SKIP'].append(petscconfvar+" requirement not met") 67709cf0baaSJed Brown continue 67829921a8fSScott Kruger 67909cf0baaSJed Brown return testDict['SKIP'] == [] 68029921a8fSScott Kruger 68129921a8fSScott Kruger def genPetscTests_summarize(self,dataDict): 68229921a8fSScott Kruger """ 68329921a8fSScott Kruger Required method to state what happened 68429921a8fSScott Kruger """ 68529921a8fSScott Kruger if not self.summarize: return 68629921a8fSScott Kruger indent=" " 687cfaa06beSSatish Balay fhname=os.path.join(self.testroot_dir,'GenPetscTests_summarize.txt') 68829921a8fSScott Kruger fh=open(fhname,"w") 68964ca018dSScott Kruger #print "See ", fhname 69029921a8fSScott Kruger for root in dataDict: 691*c173c275SScott Kruger relroot=self.srcrelpath(root) 69229921a8fSScott Kruger pkg=relroot.split("/")[1] 69329921a8fSScott Kruger fh.write(relroot+"\n") 69429921a8fSScott Kruger allSrcs=[] 695e551db17SScott Kruger for lang in LANGS: allSrcs+=self.sources[pkg][lang]['srcs'] 69629921a8fSScott Kruger for exfile in dataDict[root]: 69729921a8fSScott Kruger # Basic information 698*c173c275SScott Kruger rfile=os.path.join(relroot,exfile) 69929921a8fSScott Kruger builtStatus=(" Is built" if rfile in allSrcs else " Is NOT built") 70029921a8fSScott Kruger fh.write(indent+exfile+indent*4+builtStatus+"\n") 70129921a8fSScott Kruger 70229921a8fSScott Kruger for test in dataDict[root][exfile]: 70329921a8fSScott Kruger if test in self.buildkeys: continue 70429921a8fSScott Kruger line=indent*2+test 70529921a8fSScott Kruger fh.write(line+"\n") 70629921a8fSScott Kruger # Looks nice to have the keys in order 70729921a8fSScott Kruger #for key in dataDict[root][exfile][test]: 70829921a8fSScott Kruger for key in "isrun abstracted nsize args requires script".split(): 709862148f4SScott Kruger if key not in dataDict[root][exfile][test]: continue 71029921a8fSScott Kruger line=indent*3+key+": "+str(dataDict[root][exfile][test][key]) 71129921a8fSScott Kruger fh.write(line+"\n") 71229921a8fSScott Kruger fh.write("\n") 71329921a8fSScott Kruger fh.write("\n") 71429921a8fSScott Kruger fh.write("\n") 71529921a8fSScott Kruger #fh.write("\nClass Sources\n"+str(self.sources)+"\n") 71629921a8fSScott Kruger #fh.write("\nClass Tests\n"+str(self.tests)+"\n") 71729921a8fSScott Kruger fh.close() 71829921a8fSScott Kruger return 71929921a8fSScott Kruger 72029921a8fSScott Kruger def genPetscTests(self,root,dirs,files,dataDict): 72129921a8fSScott Kruger """ 72229921a8fSScott Kruger Go through and parse the source files in the directory to generate 72329921a8fSScott Kruger the examples based on the metadata contained in the source files 72429921a8fSScott Kruger """ 72529921a8fSScott Kruger debug=False 72629921a8fSScott Kruger # Use examplesAnalyze to get what the makefles think are sources 72729921a8fSScott Kruger #self.examplesAnalyze(root,dirs,files,anlzDict) 72829921a8fSScott Kruger 72929921a8fSScott Kruger dataDict[root]={} 73029921a8fSScott Kruger 73129921a8fSScott Kruger for exfile in files: 73229921a8fSScott Kruger #TST: Until we replace files, still leaving the orginals as is 73329921a8fSScott Kruger #if not exfile.startswith("new_"+"ex"): continue 73462197512SBarry Smith #if not exfile.startswith("ex"): continue 73529921a8fSScott Kruger 73629921a8fSScott Kruger # Convenience 73729921a8fSScott Kruger fullex=os.path.join(root,exfile) 738*c173c275SScott Kruger relpfile=os.path.join(self.srcrelpath(root),exfile) 73929921a8fSScott Kruger if debug: print relpfile 74096d5c3b5SScott Kruger dataDict[root].update(testparse.parseTestFile(fullex,0)) 74129921a8fSScott Kruger # Need to check and make sure tests are in the file 74229921a8fSScott Kruger # if verbosity>=1: print relpfile 743862148f4SScott Kruger if exfile in dataDict[root]: 74429921a8fSScott Kruger self.genScriptsAndInfo(exfile,root,dataDict[root][exfile]) 74529921a8fSScott Kruger 74629921a8fSScott Kruger return 74729921a8fSScott Kruger 74829921a8fSScott Kruger def walktree(self,top,action="printFiles"): 74929921a8fSScott Kruger """ 75029921a8fSScott Kruger Walk a directory tree, starting from 'top' 75129921a8fSScott Kruger """ 75229921a8fSScott Kruger #print "action", action 75329921a8fSScott Kruger # Goal of action is to fill this dictionary 75429921a8fSScott Kruger dataDict={} 75529921a8fSScott Kruger for root, dirs, files in os.walk(top, topdown=False): 75629921a8fSScott Kruger if not "examples" in root: continue 75729921a8fSScott Kruger if not os.path.isfile(os.path.join(root,"makefile")): continue 75829921a8fSScott Kruger bname=os.path.basename(root.rstrip("/")) 75929921a8fSScott Kruger if bname=="tests" or bname=="tutorials": 76029921a8fSScott Kruger eval("self."+action+"(root,dirs,files,dataDict)") 76129921a8fSScott Kruger if type(top) != types.StringType: 76229921a8fSScott Kruger raise TypeError("top must be a string") 76329921a8fSScott Kruger # Now summarize this dictionary 76429921a8fSScott Kruger eval("self."+action+"_summarize(dataDict)") 76529921a8fSScott Kruger return dataDict 76629921a8fSScott Kruger 767b0790570SJed Brown def gen_gnumake(self, fd): 76829921a8fSScott Kruger """ 76929921a8fSScott Kruger Overwrite of the method in the base PETSc class 77029921a8fSScott Kruger """ 77129921a8fSScott Kruger def write(stem, srcs): 77229921a8fSScott Kruger for lang in LANGS: 773e551db17SScott Kruger if self.inInstallDir: 774e551db17SScott Kruger if len(srcs[lang]['srcs'])>0: 775*c173c275SScott Kruger fd.write('%(stem)s.%(lang)s := %(srcs)s\n' % dict(stem=stem, lang=lang, srcs=' '.join(srcs[lang]['srcs']))) 776e551db17SScott Kruger else: 777e551db17SScott Kruger fd.write('%(stem)s.%(lang)s := %(srcs)s\n' % dict(stem=stem, lang=lang, srcs=' '.join(srcs[lang]['srcs']))) 778e551db17SScott Kruger else: 77929921a8fSScott Kruger fd.write('%(stem)s.%(lang)s := %(srcs)s\n' % dict(stem=stem, lang=lang, srcs=' '.join(srcs[lang]['srcs']))) 78029921a8fSScott Kruger for pkg in PKGS: 78129921a8fSScott Kruger srcs = self.gen_pkg(pkg) 782b0790570SJed Brown write('testsrcs-' + pkg, srcs) 78329921a8fSScott Kruger return self.gendeps 78429921a8fSScott Kruger 78529921a8fSScott Kruger def gen_pkg(self, pkg): 78629921a8fSScott Kruger """ 78729921a8fSScott Kruger Overwrite of the method in the base PETSc class 78829921a8fSScott Kruger """ 78929921a8fSScott Kruger return self.sources[pkg] 79029921a8fSScott Kruger 79129921a8fSScott Kruger def write_gnumake(self,dataDict): 79229921a8fSScott Kruger """ 79329921a8fSScott Kruger Write out something similar to files from gmakegen.py 79429921a8fSScott Kruger 79529921a8fSScott Kruger Test depends on script which also depends on source 79629921a8fSScott Kruger file, but since I don't have a good way generating 79729921a8fSScott Kruger acting on a single file (oops) just depend on 79829921a8fSScott Kruger executable which in turn will depend on src file 79929921a8fSScott Kruger """ 80068f6ad6bSScott Kruger # Different options for how to set up the targets 80168f6ad6bSScott Kruger compileExecsFirst=False 80268f6ad6bSScott Kruger 80329921a8fSScott Kruger # Open file 804e551db17SScott Kruger arch_files = os.path.join(self.arch_dir,'lib','petsc','conf', 'testfiles') 80529921a8fSScott Kruger fd = open(arch_files, 'w') 80629921a8fSScott Kruger 80729921a8fSScott Kruger # Write out the sources 808b0790570SJed Brown gendeps = self.gen_gnumake(fd) 80929921a8fSScott Kruger 81029921a8fSScott Kruger # Write out the tests and execname targets 81129921a8fSScott Kruger fd.write("\n#Tests and executables\n") # Delimiter 81229921a8fSScott Kruger 81329921a8fSScott Kruger for pkg in PKGS: 81429921a8fSScott Kruger # These grab the ones that are built 81529921a8fSScott Kruger for lang in LANGS: 81685a27222SJed Brown testdeps=[] 81729921a8fSScott Kruger for ftest in self.tests[pkg][lang]: 81829921a8fSScott Kruger test=os.path.basename(ftest) 81929921a8fSScott Kruger basedir=os.path.dirname(ftest) 82085a27222SJed Brown testdeps.append(self.nameSpace(test,basedir)) 821612eee3eSJed Brown fd.write("test-"+pkg+"."+lang+" := "+' '.join(testdeps)+"\n") 82265ea9442SJed Brown fd.write('test-%s.%s : $(test-%s.%s)\n' % (pkg, lang, pkg, lang)) 82329921a8fSScott Kruger 82429921a8fSScott Kruger # test targets 82529921a8fSScott Kruger for ftest in self.tests[pkg][lang]: 82629921a8fSScott Kruger test=os.path.basename(ftest) 82729921a8fSScott Kruger basedir=os.path.dirname(ftest) 82829921a8fSScott Kruger testdir="${TESTDIR}/"+basedir+"/" 82929921a8fSScott Kruger nmtest=self.nameSpace(test,basedir) 83029921a8fSScott Kruger rundir=os.path.join(testdir,test) 83129921a8fSScott Kruger #print test, nmtest 83229921a8fSScott Kruger script=test+".sh" 83329921a8fSScott Kruger 83429921a8fSScott Kruger # Deps 83529921a8fSScott Kruger exfile=self.tests[pkg][lang][ftest]['exfile'] 836e551db17SScott Kruger fullex=os.path.join(os.path.dirname(self.srcdir),exfile) 83729921a8fSScott Kruger localexec=self.tests[pkg][lang][ftest]['exec'] 83829921a8fSScott Kruger execname=os.path.join(testdir,localexec) 83968f6ad6bSScott Kruger fullscript=os.path.join(testdir,script) 84068f6ad6bSScott Kruger tmpfile=os.path.join(testdir,test,test+".tmp") 84129921a8fSScott Kruger 842b91d4a07SJed Brown # *.counts depends on the script and either executable (will 843b91d4a07SJed Brown # be run) or the example source file (SKIP or TODO) 844b91d4a07SJed Brown fd.write('%s.counts : %s %s\n' 845b91d4a07SJed Brown % (os.path.join('$(TESTDIR)/counts', nmtest), 846b91d4a07SJed Brown fullscript, 847b91d4a07SJed Brown execname if exfile in self.sources[pkg][lang]['srcs'] else fullex)) 84829921a8fSScott Kruger # Now write the args: 849612eee3eSJed Brown fd.write(nmtest+"_ARGS := '"+self.tests[pkg][lang][ftest]['argLabel']+"'\n") 850df2e1f37SScott Kruger 851612eee3eSJed Brown fd.close() 85229921a8fSScott Kruger return 85329921a8fSScott Kruger 85429921a8fSScott Kruger def writeHarness(self,output,dataDict): 85529921a8fSScott Kruger """ 85629921a8fSScott Kruger This is set up to write out multiple harness even if only gnumake 85729921a8fSScott Kruger is supported now 85829921a8fSScott Kruger """ 85929921a8fSScott Kruger eval("self.write_"+output+"(dataDict)") 86029921a8fSScott Kruger return 86129921a8fSScott Kruger 862e551db17SScott Krugerdef main(petsc_dir=None, petsc_arch=None, output=None, verbose=False, single_ex=False, srcdir=None, testdir=None): 86329921a8fSScott Kruger if output is None: 86429921a8fSScott Kruger output = 'gnumake' 86529921a8fSScott Kruger 866*c173c275SScott Kruger # Allow petsc_arch to have both petsc_dir and petsc_arch for convenience 867*c173c275SScott Kruger if len(petsc_arch.split(os.path.sep))>1: 868*c173c275SScott Kruger petsc_dir,petsc_arch=os.path.split(petsc_arch.rstrip(os.path.sep)) 86929921a8fSScott Kruger 870e551db17SScott Kruger pEx=generateExamples(petsc_dir=petsc_dir, petsc_arch=petsc_arch, 871e551db17SScott Kruger verbose=verbose, single_ex=single_ex, srcdir=srcdir, 872e551db17SScott Kruger testdir=testdir) 873e551db17SScott Kruger dataDict=pEx.walktree(os.path.join(pEx.srcdir),action="genPetscTests") 87429921a8fSScott Kruger pEx.writeHarness(output,dataDict) 87529921a8fSScott Kruger 87629921a8fSScott Krugerif __name__ == '__main__': 87729921a8fSScott Kruger import optparse 87829921a8fSScott Kruger parser = optparse.OptionParser() 87929921a8fSScott Kruger parser.add_option('--verbose', help='Show mismatches between makefiles and the filesystem', action='store_true', default=False) 88029921a8fSScott Kruger parser.add_option('--petsc-arch', help='Set PETSC_ARCH different from environment', default=os.environ.get('PETSC_ARCH')) 881e551db17SScott Kruger parser.add_option('--srcdir', help='Set location of sources different from PETSC_DIR/src', default=None) 88229921a8fSScott Kruger parser.add_option('--output', help='Location to write output file', default=None) 88329921a8fSScott 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') 884e551db17SScott Kruger parser.add_option('-t', '--testdir', dest='testdir', help='Test directory: PETSC_DIR/PETSC_ARCH/testdir. Default is "tests"') 885e551db17SScott Kruger opts, extra_args = parser.parse_args() 88629921a8fSScott Kruger opts, extra_args = parser.parse_args() 88729921a8fSScott Kruger if extra_args: 88829921a8fSScott Kruger import sys 88929921a8fSScott Kruger sys.stderr.write('Unknown arguments: %s\n' % ' '.join(extra_args)) 89029921a8fSScott Kruger exit(1) 891e551db17SScott Kruger main(petsc_arch=opts.petsc_arch, output=opts.output, verbose=opts.verbose, 892e551db17SScott Kruger single_ex=opts.single_executable, srcdir=opts.srcdir, testdir=opts.testdir) 893