129921a8fSScott Kruger#!/usr/bin/env python 229921a8fSScott Kruger""" 329921a8fSScott KrugerParse the test file and return a dictionary. 429921a8fSScott Kruger 529921a8fSScott KrugerQuick usage:: 629921a8fSScott Kruger 729921a8fSScott Kruger bin/maint/testparse.py -t src/ksp/ksp/examples/tutorials/ex1.c 829921a8fSScott Kruger 929921a8fSScott KrugerFrom the command line, it prints out the dictionary. 1029921a8fSScott KrugerThis is meant to be used by other scripts, but it is 1129921a8fSScott Krugeruseful to debug individual files. 1229921a8fSScott Kruger 1329921a8fSScott KrugerExample language 1429921a8fSScott Kruger---------------- 1529921a8fSScott Kruger 1629921a8fSScott Kruger/*TEST 17aec507c4SScott Kruger build: 18aec507c4SScott Kruger requires: moab 19e53dc769SScott Kruger # This is equivalent to test: 20e53dc769SScott Kruger testset: 2129921a8fSScott Kruger args: -pc_type mg -ksp_type fgmres -da_refine 2 -ksp_monitor_short -mg_levels_ksp_monitor_short -mg_levels_ksp_norm_type unpreconditioned -ksp_view -pc_mg_type full 2229921a8fSScott Kruger 23e53dc769SScott Kruger testset: 2429921a8fSScott Kruger suffix: 2 2529921a8fSScott Kruger nsize: 2 2629921a8fSScott Kruger args: -pc_type mg -ksp_type fgmres -da_refine 2 -ksp_monitor_short -mg_levels_ksp_monitor_short -mg_levels_ksp_norm_type unpreconditioned -ksp_view -pc_mg_type full 2729921a8fSScott Kruger 28e53dc769SScott Kruger testset: 29e53dc769SScott Kruger suffix: 2 30e53dc769SScott Kruger nsize: 2 31e53dc769SScott Kruger args: -pc_type mg -ksp_type fgmres -da_refine 2 -ksp_monitor_short -mg_levels_ksp_monitor_short -mg_levels_ksp_norm_type unpreconditioned -ksp_view -pc_mg_type full 32e53dc769SScott Kruger test: 33e53dc769SScott Kruger 3429921a8fSScott KrugerTEST*/ 3529921a8fSScott Kruger 3629921a8fSScott Kruger""" 3729921a8fSScott Kruger 3829921a8fSScott Krugerimport os, re, glob, types 3929921a8fSScott Krugerfrom distutils.sysconfig import parse_makefile 4029921a8fSScott Krugerimport sys 4129921a8fSScott Krugerimport logging 4229921a8fSScott Krugersys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) 4329921a8fSScott Kruger 4429921a8fSScott Krugerimport inspect 4529921a8fSScott Krugerthisscriptdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) 4629921a8fSScott Krugermaintdir=os.path.join(os.path.join(os.path.dirname(thisscriptdir),'bin'),'maint') 4729921a8fSScott Krugersys.path.insert(0,maintdir) 4866db876fSScott Kruger# Don't print out trace when raise Exceptions 4966db876fSScott Krugersys.tracebacklimit = 0 5029921a8fSScott Kruger 5129921a8fSScott Kruger# These are special keys describing build 5229921a8fSScott Krugerbuildkeys="requires TODO SKIP depends".split() 5329921a8fSScott Kruger 540a091e3eSScott Krugeracceptedkeys="test nsize requires command suffix args filter filter_output localrunfiles comments TODO SKIP output_file timeoutfactor".split() 5544776d8cSScott Krugerappendlist="args requires comments".split() 5668a9e459SScott Kruger 5768a9e459SScott Krugerimport re 5868a9e459SScott Kruger 5944776d8cSScott Krugerdef _stripIndent(block,srcfile,entireBlock=False,fileNums=[]): 6029921a8fSScott Kruger """ 6129921a8fSScott Kruger Go through and remove a level of indentation 6229921a8fSScott Kruger Also strip of trailing whitespace 6329921a8fSScott Kruger """ 6429921a8fSScott Kruger # The first entry should be test: but it might be indented. 6529921a8fSScott Kruger ext=os.path.splitext(srcfile)[1] 6644776d8cSScott Kruger stripstr=" " 6766db876fSScott Kruger if len(fileNums)>0: lineNum=fileNums[0]-1 688ccd5183SScott Kruger for lline in block.split("\n"): 6966db876fSScott Kruger if len(fileNums)>0: lineNum+=1 708ccd5183SScott Kruger line=lline[1:] if lline.startswith("!") else lline 7129921a8fSScott Kruger if not line.strip(): continue 72c4b80baaSScott Kruger if line.strip().startswith('#'): continue 7344776d8cSScott Kruger if entireBlock: 7444776d8cSScott Kruger var=line.split(":")[0].strip() 75aec507c4SScott Kruger if not var in ['test','testset','build']: 7666db876fSScott Kruger raise Exception("Formatting error: Cannot find test in file: "+srcfile+" at line: "+str(lineNum)+"\n") 7729921a8fSScott Kruger nspace=len(line)-len(line.lstrip(stripstr)) 7829921a8fSScott Kruger newline=line[nspace:] 7929921a8fSScott Kruger break 8029921a8fSScott Kruger 8129921a8fSScott Kruger # Strip off any indentation for the whole string and any trailing 8229921a8fSScott Kruger # whitespace for convenience 8329921a8fSScott Kruger newTestStr="\n" 8444776d8cSScott Kruger if len(fileNums)>0: lineNum=fileNums[0]-1 8544776d8cSScott Kruger firstPass=True 868ccd5183SScott Kruger for lline in block.split("\n"): 8744776d8cSScott Kruger if len(fileNums)>0: lineNum+=1 888ccd5183SScott Kruger line=lline[1:] if lline.startswith("!") else lline 8929921a8fSScott Kruger if not line.strip(): continue 90c4b80baaSScott Kruger if line.strip().startswith('#'): 91c4b80baaSScott Kruger newTestStr+=line+'\n' 92c4b80baaSScott Kruger else: 9329921a8fSScott Kruger newline=line[nspace:] 94c4b80baaSScott Kruger newTestStr+=newline.rstrip()+"\n" 9544776d8cSScott Kruger # Do some basic indentation checks 9644776d8cSScott Kruger if entireBlock: 9744776d8cSScott Kruger # Don't need to check comment lines 9844776d8cSScott Kruger if line.strip().startswith('#'): continue 9944776d8cSScott Kruger if not newline.startswith(" "): 10044776d8cSScott Kruger var=newline.split(":")[0].strip() 101aec507c4SScott Kruger if not var in ['test','testset','build']: 10244776d8cSScott Kruger err="Formatting error in file "+srcfile+" at line: " +line+"\n" 10344776d8cSScott Kruger if len(fileNums)>0: 10444776d8cSScott Kruger raise Exception(err+"Check indentation at line number: "+str(lineNum)) 10544776d8cSScott Kruger else: 10644776d8cSScott Kruger raise Exception(err) 10744776d8cSScott Kruger else: 10844776d8cSScott Kruger var=line.split(":")[0].strip() 109aec507c4SScott Kruger if var in ['test','testset','build']: 11044776d8cSScott Kruger subnspace=len(line)-len(line.lstrip(stripstr)) 11144776d8cSScott Kruger if firstPass: 11244776d8cSScott Kruger firstsubnspace=subnspace 11344776d8cSScott Kruger firstPass=False 11444776d8cSScott Kruger else: 11544776d8cSScott Kruger if firstsubnspace!=subnspace: 11644776d8cSScott Kruger err="Formatting subtest error in file "+srcfile+" at line: " +line+"\n" 11744776d8cSScott Kruger if len(fileNums)>0: 11844776d8cSScott Kruger raise Exception(err+"Check indentation at line number: "+str(lineNum)) 11944776d8cSScott Kruger else: 12044776d8cSScott Kruger raise Exception(err) 12144776d8cSScott Kruger 12229921a8fSScott Kruger 12329921a8fSScott Kruger return newTestStr 12429921a8fSScott Kruger 125aae9f2d9SScott Krugerdef parseLoopArgs(varset): 12644776d8cSScott Kruger """ 127aae9f2d9SScott Kruger Given: String containing loop variables 128aae9f2d9SScott Kruger Return: tuple containing separate/shared and string of loop vars 12944776d8cSScott Kruger """ 130aae9f2d9SScott Kruger keynm=varset.split("{{")[0].strip() 131aae9f2d9SScott Kruger if not keynm.strip(): keynm='nsize' 132aae9f2d9SScott Kruger lvars=varset.split('{{')[1].split('}')[0] 133aae9f2d9SScott Kruger suffx=varset.split('{{')[1].split('}')[1] 134aae9f2d9SScott Kruger ftype='separate' if suffx.startswith('separate') else 'shared' 135aae9f2d9SScott Kruger return keynm,lvars,ftype 13644776d8cSScott Kruger 137e53dc769SScott Krugerdef _getSeparateTestvars(testDict): 138e53dc769SScott Kruger """ 139e53dc769SScott Kruger Given: dictionary that may have 140e53dc769SScott Kruger Return: Variables that cause a test split 141e53dc769SScott Kruger """ 142e53dc769SScott Kruger vals=None 143e53dc769SScott Kruger sepvars=[] 144e53dc769SScott Kruger # Check nsize 145e53dc769SScott Kruger if testDict.has_key('nsize'): 146e53dc769SScott Kruger varset=testDict['nsize'] 147aae9f2d9SScott Kruger if '{{' in varset: 148aae9f2d9SScott Kruger keynm,lvars,ftype=parseLoopArgs(varset) 149aae9f2d9SScott Kruger if ftype=='separate': sepvars.append(keynm) 150e53dc769SScott Kruger 151e53dc769SScott Kruger # Now check args 152e53dc769SScott Kruger if not testDict.has_key('args'): return sepvars 153e53dc769SScott Kruger for varset in re.split('-(?=[a-zA-Z])',testDict['args']): 154e53dc769SScott Kruger if not varset.strip(): continue 155aae9f2d9SScott Kruger if '{{' in varset: 156e53dc769SScott Kruger # Assuming only one for loop per var specification 157aae9f2d9SScott Kruger keynm,lvars,ftype=parseLoopArgs(varset) 158aae9f2d9SScott Kruger if ftype=='separate': sepvars.append(keynm) 159e53dc769SScott Kruger 160e53dc769SScott Kruger return sepvars 161e53dc769SScott Kruger 16244776d8cSScott Krugerdef _getVarVals(findvar,testDict): 16344776d8cSScott Kruger """ 16444776d8cSScott Kruger Given: variable that is either nsize or in args 16544776d8cSScott Kruger Return: Values to loop over 16644776d8cSScott Kruger """ 16744776d8cSScott Kruger vals=None 16844776d8cSScott Kruger newargs='' 16944776d8cSScott Kruger if findvar=='nsize': 170e53dc769SScott Kruger varset=testDict[findvar] 171aae9f2d9SScott Kruger keynm,vals,ftype=parseLoopArgs('nsize '+varset) 17244776d8cSScott Kruger else: 17344776d8cSScott Kruger varlist=[] 17444776d8cSScott Kruger for varset in re.split('-(?=[a-zA-Z])',testDict['args']): 17544776d8cSScott Kruger if not varset.strip(): continue 176aae9f2d9SScott Kruger if '{{' in varset: 177aae9f2d9SScott Kruger keyvar,vals,ftype=parseLoopArgs(varset) 17844776d8cSScott Kruger if keyvar!=findvar: 1790bcc1aabSScott Kruger newargs+="-"+varset.strip()+" " 18044776d8cSScott Kruger continue 1810bcc1aabSScott Kruger else: 1820bcc1aabSScott Kruger newargs+="-"+varset.strip()+" " 18344776d8cSScott Kruger 18444776d8cSScott Kruger if not vals: raise StandardError("Could not find separate_testvar: "+findvar) 18544776d8cSScott Kruger return vals,newargs 18644776d8cSScott Kruger 18744776d8cSScott Krugerdef genTestsSeparateTestvars(intests,indicts): 18844776d8cSScott Kruger """ 189e53dc769SScott Kruger Given: testname, sdict with 'separate_testvars 19044776d8cSScott Kruger Return: testnames,sdicts: List of generated tests 19144776d8cSScott Kruger """ 19244776d8cSScott Kruger testnames=[]; sdicts=[] 19344776d8cSScott Kruger for i in range(len(intests)): 19444776d8cSScott Kruger testname=intests[i]; sdict=indicts[i]; i+=1 195e53dc769SScott Kruger separate_testvars=_getSeparateTestvars(sdict) 196e53dc769SScott Kruger if len(separate_testvars)>0: 197e53dc769SScott Kruger for kvar in separate_testvars: 19844776d8cSScott Kruger kvals,newargs=_getVarVals(kvar,sdict) 19944776d8cSScott Kruger # No errors means we are good to go 20044776d8cSScott Kruger for val in kvals.split(): 20144776d8cSScott Kruger kvardict=sdict.copy() 20244776d8cSScott Kruger gensuffix="_"+kvar+"-"+val 20344776d8cSScott Kruger newtestnm=testname+gensuffix 2040bcc1aabSScott Kruger if sdict.has_key('suffix'): 20544776d8cSScott Kruger kvardict['suffix']=sdict['suffix']+gensuffix 2060bcc1aabSScott Kruger else: 2070bcc1aabSScott Kruger kvardict['suffix']=gensuffix 20844776d8cSScott Kruger if kvar=='nsize': 20944776d8cSScott Kruger kvardict[kvar]=val 21044776d8cSScott Kruger else: 21144776d8cSScott Kruger kvardict['args']=newargs+"-"+kvar+" "+val 21244776d8cSScott Kruger testnames.append(newtestnm) 21344776d8cSScott Kruger sdicts.append(kvardict) 21444776d8cSScott Kruger else: 21544776d8cSScott Kruger testnames.append(testname) 21644776d8cSScott Kruger sdicts.append(sdict) 21744776d8cSScott Kruger return testnames,sdicts 21844776d8cSScott Kruger 21944776d8cSScott Krugerdef genTestsSubtestSuffix(testnames,sdicts): 22044776d8cSScott Kruger """ 22144776d8cSScott Kruger Given: testname, sdict with separate_testvars 22244776d8cSScott Kruger Return: testnames,sdicts: List of generated tests 22344776d8cSScott Kruger """ 22444776d8cSScott Kruger tnms=[]; sdcts=[] 22544776d8cSScott Kruger for i in range(len(testnames)): 22644776d8cSScott Kruger testname=testnames[i] 22744776d8cSScott Kruger rmsubtests=[]; keepSubtests=False 22844776d8cSScott Kruger if sdicts[i].has_key('subtests'): 22944776d8cSScott Kruger for stest in sdicts[i]["subtests"]: 23044776d8cSScott Kruger if sdicts[i][stest].has_key('suffix'): 23144776d8cSScott Kruger rmsubtests.append(stest) 23244776d8cSScott Kruger gensuffix="_"+sdicts[i][stest]['suffix'] 23344776d8cSScott Kruger newtestnm=testname+gensuffix 23444776d8cSScott Kruger tnms.append(newtestnm) 23544776d8cSScott Kruger newsdict=sdicts[i].copy() 23644776d8cSScott Kruger del newsdict['subtests'] 23744776d8cSScott Kruger # Have to hand update 23844776d8cSScott Kruger # Append 23944776d8cSScott Kruger for kup in appendlist: 24044776d8cSScott Kruger if sdicts[i][stest].has_key(kup): 24144776d8cSScott Kruger if sdicts[i].has_key(kup): 24244776d8cSScott Kruger newsdict[kup]=sdicts[i][kup]+" "+sdicts[i][stest][kup] 24344776d8cSScott Kruger else: 24444776d8cSScott Kruger newsdict[kup]=sdicts[i][stest][kup] 24544776d8cSScott Kruger # Promote 24644776d8cSScott Kruger for kup in acceptedkeys: 24744776d8cSScott Kruger if kup in appendlist: continue 24844776d8cSScott Kruger if sdicts[i][stest].has_key(kup): 24944776d8cSScott Kruger newsdict[kup]=sdicts[i][stest][kup] 25044776d8cSScott Kruger # Cleanup 25144776d8cSScott Kruger for st in sdicts[i]["subtests"]: del newsdict[st] 25244776d8cSScott Kruger sdcts.append(newsdict) 25344776d8cSScott Kruger else: 25444776d8cSScott Kruger keepSubtests=True 25544776d8cSScott Kruger else: 25644776d8cSScott Kruger tnms.append(testnames[i]) 25744776d8cSScott Kruger sdcts.append(sdicts[i]) 2580bcc1aabSScott Kruger # If a subtest without a suffix exists, then save it 25944776d8cSScott Kruger if keepSubtests: 26044776d8cSScott Kruger tnms.append(testnames[i]) 2610bcc1aabSScott Kruger newsdict=sdicts[i].copy() 2620bcc1aabSScott Kruger # Prune the tests to prepare for keeping 2630bcc1aabSScott Kruger for rmtest in rmsubtests: 2640bcc1aabSScott Kruger newsdict['subtests'].remove(rmtest) 2650bcc1aabSScott Kruger del newsdict[rmtest] 2660bcc1aabSScott Kruger sdcts.append(newsdict) 26744776d8cSScott Kruger i+=1 26844776d8cSScott Kruger return tnms,sdcts 26944776d8cSScott Kruger 27044776d8cSScott Krugerdef splitTests(testname,sdict): 27144776d8cSScott Kruger """ 27244776d8cSScott Kruger Given: testname and YAML-generated dictionary 27344776d8cSScott Kruger Return: list of names and dictionaries corresponding to each test 27444776d8cSScott Kruger given that the YAML language allows for multiple tests 27544776d8cSScott Kruger """ 27644776d8cSScott Kruger 27744776d8cSScott Kruger # Order: Parent sep_tv, subtests suffix, subtests sep_tv 27844776d8cSScott Kruger testnames,sdicts=genTestsSeparateTestvars([testname],[sdict]) 27944776d8cSScott Kruger testnames,sdicts=genTestsSubtestSuffix(testnames,sdicts) 28044776d8cSScott Kruger testnames,sdicts=genTestsSeparateTestvars(testnames,sdicts) 28144776d8cSScott Kruger 28244776d8cSScott Kruger # Because I am altering the list, I do this in passes. Inelegant 28344776d8cSScott Kruger 28444776d8cSScott Kruger return testnames, sdicts 28544776d8cSScott Kruger 2866cecdbdcSScott Krugerdef parseTest(testStr,srcfile,verbosity): 28729921a8fSScott Kruger """ 28829921a8fSScott Kruger This parses an individual test 28929921a8fSScott Kruger YAML is hierarchial so should use a state machine in the general case, 29053f2a965SBarry Smith but in practice we only support two levels of test: 29129921a8fSScott Kruger """ 29229921a8fSScott Kruger basename=os.path.basename(srcfile) 29329921a8fSScott Kruger # Handle the new at the begininng 29429921a8fSScott Kruger bn=re.sub("new_","",basename) 29529921a8fSScott Kruger # This is the default 29629921a8fSScott Kruger testname="run"+os.path.splitext(bn)[0] 29729921a8fSScott Kruger 29829921a8fSScott Kruger # Tests that have default everything (so empty effectively) 29929921a8fSScott Kruger if len(testStr)==0: return testname, {} 30029921a8fSScott Kruger 30129921a8fSScott Kruger striptest=_stripIndent(testStr,srcfile) 30229921a8fSScott Kruger 30329921a8fSScott Kruger # go through and parse 30429921a8fSScott Kruger subtestnum=0 30529921a8fSScott Kruger subdict={} 30668a9e459SScott Kruger comments=[] 30768a9e459SScott Kruger indentlevel=0 30868a9e459SScott Kruger for ln in striptest.split("\n"): 309c4b80baaSScott Kruger line=ln.split('#')[0].rstrip() 3106cecdbdcSScott Kruger if verbosity>2: print line 3110bcc1aabSScott Kruger comment=("" if len(ln.split("#"))>0 else " ".join(ln.split("#")[1:]).strip()) 31268a9e459SScott Kruger if comment: comments.append(comment) 31329921a8fSScott Kruger if not line.strip(): continue 31444776d8cSScott Kruger lsplit=line.split(':') 31544776d8cSScott Kruger if len(lsplit)==0: raise Exception("Missing : in line: "+line) 31644776d8cSScott Kruger indentcount=lsplit[0].count(" ") 31744776d8cSScott Kruger var=lsplit[0].strip() 31840ae0433SScott Kruger val=line[line.find(':')+1:].strip() 31944776d8cSScott Kruger if not var in acceptedkeys: raise Exception("Not a defined key: "+var+" from: "+line) 32029921a8fSScott Kruger # Start by seeing if we are in a subtest 32129921a8fSScott Kruger if line.startswith(" "): 322c0658d2aSScott Kruger subdict[subtestname][var]=val 32368a9e459SScott Kruger if not indentlevel: indentlevel=indentcount 32468a9e459SScott Kruger #if indentlevel!=indentcount: print "Error in indentation:", ln 32529921a8fSScott Kruger # Determine subtest name and make dict 32629921a8fSScott Kruger elif var=="test": 32729921a8fSScott Kruger subtestname="test"+str(subtestnum) 32829921a8fSScott Kruger subdict[subtestname]={} 32929921a8fSScott Kruger if not subdict.has_key("subtests"): subdict["subtests"]=[] 33029921a8fSScott Kruger subdict["subtests"].append(subtestname) 33129921a8fSScott Kruger subtestnum=subtestnum+1 33268a9e459SScott Kruger # The rest are easy 33329921a8fSScott Kruger else: 33444776d8cSScott Kruger # For convenience, it is sometimes convenient to list twice 33544776d8cSScott Kruger if subdict.has_key(var): 33644776d8cSScott Kruger if var in appendlist: 33744776d8cSScott Kruger subdict[var]+=" "+val 33844776d8cSScott Kruger else: 33944776d8cSScott Kruger raise Exception(var+" entered twice: "+line) 34044776d8cSScott Kruger else: 341c0658d2aSScott Kruger subdict[var]=val 34229921a8fSScott Kruger if var=="suffix": 34329921a8fSScott Kruger if len(val)>0: 34429921a8fSScott Kruger testname=testname+"_"+val 34529921a8fSScott Kruger 34668a9e459SScott Kruger if len(comments): subdict['comments']="\n".join(comments).lstrip("\n") 34744776d8cSScott Kruger # A test block can create multiple tests. This does 34844776d8cSScott Kruger # that logic 34944776d8cSScott Kruger testnames,subdicts=splitTests(testname,subdict) 35044776d8cSScott Kruger return testnames,subdicts 35129921a8fSScott Kruger 3526cecdbdcSScott Krugerdef parseTests(testStr,srcfile,fileNums,verbosity): 35329921a8fSScott Kruger """ 35429921a8fSScott Kruger Parse the yaml string describing tests and return 35529921a8fSScott Kruger a dictionary with the info in the form of: 35629921a8fSScott Kruger testDict[test][subtest] 35729921a8fSScott Kruger This is an inelegant parser as we do not wish to 35829921a8fSScott Kruger introduce a new dependency by bringing in pyyaml. 35929921a8fSScott Kruger The advantage is that validation can be done as 36029921a8fSScott Kruger it is parsed (e.g., 'test' is the only top-level node) 36129921a8fSScott Kruger """ 36229921a8fSScott Kruger 36329921a8fSScott Kruger testDict={} 36429921a8fSScott Kruger 36529921a8fSScott Kruger # The first entry should be test: but it might be indented. 36644776d8cSScott Kruger newTestStr=_stripIndent(testStr,srcfile,entireBlock=True,fileNums=fileNums) 3676cecdbdcSScott Kruger if verbosity>2: print srcfile 36829921a8fSScott Kruger 369aec507c4SScott Kruger ## Check and see if we have build reuqirements 370aec507c4SScott Kruger if "\nbuild:" in newTestStr: 371aec507c4SScott Kruger testDict['build']={} 372aec507c4SScott Kruger # The file info is already here and need to append 373aec507c4SScott Kruger Part1=newTestStr.split("build:")[1] 374aec507c4SScott Kruger fileInfo=re.split("\ntest(?:set)?:",newTestStr)[0] 375aec507c4SScott Kruger for bkey in buildkeys: 376aec507c4SScott Kruger if bkey+":" in fileInfo: 377aec507c4SScott Kruger testDict['build'][bkey]=fileInfo.split(bkey+":")[1].split("\n")[0].strip() 378aec507c4SScott Kruger #if verbosity>1: bkey+": "+testDict['build'][bkey] 379aec507c4SScott Kruger 38029921a8fSScott Kruger # Now go through each test. First elem in split is blank 381e53dc769SScott Kruger for test in re.split("\ntest(?:set)?:",newTestStr)[1:]: 3826cecdbdcSScott Kruger testnames,subdicts=parseTest(test,srcfile,verbosity) 38344776d8cSScott Kruger for i in range(len(testnames)): 38444776d8cSScott Kruger if testDict.has_key(testnames[i]): 3851acf9037SMatthew G. Knepley raise RuntimeError("Multiple test names specified: "+testnames[i]+" in file: "+srcfile) 38644776d8cSScott Kruger testDict[testnames[i]]=subdicts[i] 38729921a8fSScott Kruger 38829921a8fSScott Kruger return testDict 38929921a8fSScott Kruger 3906cecdbdcSScott Krugerdef parseTestFile(srcfile,verbosity): 39129921a8fSScott Kruger """ 39229921a8fSScott Kruger Parse single example files and return dictionary of the form: 39329921a8fSScott Kruger testDict[srcfile][test][subtest] 39429921a8fSScott Kruger """ 39529921a8fSScott Kruger debug=False 39629921a8fSScott Kruger curdir=os.path.realpath(os.path.curdir) 39729921a8fSScott Kruger basedir=os.path.dirname(os.path.realpath(srcfile)) 39829921a8fSScott Kruger basename=os.path.basename(srcfile) 39929921a8fSScott Kruger os.chdir(basedir) 40029921a8fSScott Kruger 40129921a8fSScott Kruger testDict={} 40229921a8fSScott Kruger sh=open(srcfile,"r"); fileStr=sh.read(); sh.close() 40329921a8fSScott Kruger 40429921a8fSScott Kruger ## Start with doing the tests 40529921a8fSScott Kruger # 40629921a8fSScott Kruger fsplit=fileStr.split("/*TEST\n")[1:] 40729921a8fSScott Kruger if len(fsplit)==0: 40829921a8fSScott Kruger if debug: print "No test found in: "+srcfile 40929921a8fSScott Kruger return {} 41044776d8cSScott Kruger fstart=len(fileStr.split("/*TEST\n")[0].split("\n"))+1 41129921a8fSScott Kruger # Allow for multiple "/*TEST" blocks even though it really should be 4126f029658SMatthew G. Knepley # one 41329921a8fSScott Kruger srcTests=[] 41429921a8fSScott Kruger for t in fsplit: srcTests.append(t.split("TEST*/")[0]) 41529921a8fSScott Kruger testString=" ".join(srcTests) 41629921a8fSScott Kruger if len(testString.strip())==0: 41729921a8fSScott Kruger print "No test found in: "+srcfile 41829921a8fSScott Kruger return {} 41944776d8cSScott Kruger flen=len(testString.split("\n")) 42044776d8cSScott Kruger fend=fstart+flen-1 42144776d8cSScott Kruger fileNums=range(fstart,fend) 4226cecdbdcSScott Kruger testDict[basename]=parseTests(testString,srcfile,fileNums,verbosity) 423aec507c4SScott Kruger # Massage dictionary for build requirements 424aec507c4SScott Kruger if 'build' in testDict[basename]: 425aec507c4SScott Kruger testDict[basename].update(testDict[basename]['build']) 426aec507c4SScott Kruger del testDict[basename]['build'] 42729921a8fSScott Kruger 42829921a8fSScott Kruger 42929921a8fSScott Kruger os.chdir(curdir) 43029921a8fSScott Kruger return testDict 43129921a8fSScott Kruger 4326cecdbdcSScott Krugerdef parseTestDir(directory,verbosity): 43329921a8fSScott Kruger """ 43429921a8fSScott Kruger Parse single example files and return dictionary of the form: 43529921a8fSScott Kruger testDict[srcfile][test][subtest] 43629921a8fSScott Kruger """ 43729921a8fSScott Kruger curdir=os.path.realpath(os.path.curdir) 43829921a8fSScott Kruger basedir=os.path.realpath(directory) 43929921a8fSScott Kruger os.chdir(basedir) 44029921a8fSScott Kruger 44129921a8fSScott Kruger tDict={} 442*09a6cbfcSBernhard M. Wiedemann for test_file in sorted(glob.glob("new_ex*.*")): 4436cecdbdcSScott Kruger tDict.update(parseTestFile(test_file,verbosity)) 44429921a8fSScott Kruger 44529921a8fSScott Kruger os.chdir(curdir) 44629921a8fSScott Kruger return tDict 44729921a8fSScott Kruger 44829921a8fSScott Krugerdef printExParseDict(rDict): 44929921a8fSScott Kruger """ 45029921a8fSScott Kruger This is useful for debugging 45129921a8fSScott Kruger """ 45229921a8fSScott Kruger indent=" " 45329921a8fSScott Kruger for sfile in rDict: 45444776d8cSScott Kruger print sfile 45544776d8cSScott Kruger sortkeys=rDict[sfile].keys() 45644776d8cSScott Kruger sortkeys.sort() 45744776d8cSScott Kruger for runex in sortkeys: 45829921a8fSScott Kruger print indent+runex 45929921a8fSScott Kruger if type(rDict[sfile][runex])==types.StringType: 46029921a8fSScott Kruger print indent*2+rDict[sfile][runex] 46129921a8fSScott Kruger else: 46229921a8fSScott Kruger for var in rDict[sfile][runex]: 46344776d8cSScott Kruger if var.startswith("test"): continue 46444776d8cSScott Kruger print indent*2+var+": "+str(rDict[sfile][runex][var]) 46544776d8cSScott Kruger if rDict[sfile][runex].has_key('subtests'): 46644776d8cSScott Kruger for var in rDict[sfile][runex]['subtests']: 46729921a8fSScott Kruger print indent*2+var 46829921a8fSScott Kruger for var2 in rDict[sfile][runex][var]: 46929921a8fSScott Kruger print indent*3+var2+": "+str(rDict[sfile][runex][var][var2]) 47044776d8cSScott Kruger print "\n" 47129921a8fSScott Kruger return 47229921a8fSScott Kruger 47329921a8fSScott Krugerdef main(directory='',test_file='',verbosity=0): 47429921a8fSScott Kruger 47529921a8fSScott Kruger if directory: 4766cecdbdcSScott Kruger tDict=parseTestDir(directory,verbosity) 47729921a8fSScott Kruger else: 4786cecdbdcSScott Kruger tDict=parseTestFile(test_file,verbosity) 47929921a8fSScott Kruger if verbosity>0: printExParseDict(tDict) 48029921a8fSScott Kruger 48129921a8fSScott Kruger return 48229921a8fSScott Kruger 48329921a8fSScott Krugerif __name__ == '__main__': 48429921a8fSScott Kruger import optparse 48529921a8fSScott Kruger parser = optparse.OptionParser() 48629921a8fSScott Kruger parser.add_option('-d', '--directory', dest='directory', 48729921a8fSScott Kruger default="", help='Directory containing files to parse') 48829921a8fSScott Kruger parser.add_option('-t', '--test_file', dest='test_file', 48929921a8fSScott Kruger default="", help='Test file, e.g., ex1.c, to parse') 49029921a8fSScott Kruger parser.add_option('-v', '--verbosity', dest='verbosity', 49129921a8fSScott Kruger help='Verbosity of output by level: 1, 2, or 3', default=0) 49229921a8fSScott Kruger opts, extra_args = parser.parse_args() 49329921a8fSScott Kruger 49429921a8fSScott Kruger if extra_args: 49529921a8fSScott Kruger import sys 49629921a8fSScott Kruger sys.stderr.write('Unknown arguments: %s\n' % ' '.join(extra_args)) 49729921a8fSScott Kruger exit(1) 49829921a8fSScott Kruger if not opts.test_file and not opts.directory: 49929921a8fSScott Kruger print "test file or directory is required" 50029921a8fSScott Kruger parser.print_usage() 50129921a8fSScott Kruger sys.exit() 50229921a8fSScott Kruger 50329921a8fSScott Kruger # Need verbosity to be an integer 50429921a8fSScott Kruger try: 50529921a8fSScott Kruger verbosity=int(opts.verbosity) 50629921a8fSScott Kruger except: 50729921a8fSScott Kruger raise Exception("Error: Verbosity must be integer") 50829921a8fSScott Kruger 50929921a8fSScott Kruger main(directory=opts.directory,test_file=opts.test_file,verbosity=verbosity) 510