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 Kruger 1429921a8fSScott Kruger 1529921a8fSScott KrugerExample language 1629921a8fSScott Kruger---------------- 1729921a8fSScott Kruger/*T 1829921a8fSScott Kruger Concepts: 1929921a8fSScott Kruger requires: moab 2029921a8fSScott KrugerT*/ 2129921a8fSScott Kruger 2229921a8fSScott Kruger 2329921a8fSScott Kruger 2429921a8fSScott Kruger/*TEST 2529921a8fSScott Kruger 26e53dc769SScott Kruger # This is equivalent to test: 27e53dc769SScott Kruger testset: 2829921a8fSScott 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 2929921a8fSScott Kruger 30e53dc769SScott Kruger testset: 3129921a8fSScott Kruger suffix: 2 3229921a8fSScott Kruger nsize: 2 3329921a8fSScott 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 3429921a8fSScott Kruger 35e53dc769SScott Kruger testset: 36e53dc769SScott Kruger suffix: 2 37e53dc769SScott Kruger nsize: 2 38e53dc769SScott 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 39e53dc769SScott Kruger test: 40e53dc769SScott Kruger 4129921a8fSScott KrugerTEST*/ 4229921a8fSScott Kruger 4329921a8fSScott Kruger""" 4429921a8fSScott Kruger 4529921a8fSScott Krugerimport os, re, glob, types 4629921a8fSScott Krugerfrom distutils.sysconfig import parse_makefile 4729921a8fSScott Krugerimport sys 4829921a8fSScott Krugerimport logging 4929921a8fSScott Krugersys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) 5029921a8fSScott Kruger 5129921a8fSScott Krugerimport inspect 5229921a8fSScott Krugerthisscriptdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) 5329921a8fSScott Krugermaintdir=os.path.join(os.path.join(os.path.dirname(thisscriptdir),'bin'),'maint') 5429921a8fSScott Krugersys.path.insert(0,maintdir) 5566db876fSScott Kruger# Don't print out trace when raise Exceptions 5666db876fSScott Krugersys.tracebacklimit = 0 5729921a8fSScott Kruger 5829921a8fSScott Kruger# These are special keys describing build 5929921a8fSScott Krugerbuildkeys="requires TODO SKIP depends".split() 6029921a8fSScott Kruger 61e53dc769SScott Krugeracceptedkeys="test nsize requires command suffix args filter filter_output localrunfiles comments TODO SKIP output_file".split() 6244776d8cSScott Krugerappendlist="args requires comments".split() 6368a9e459SScott Kruger 6468a9e459SScott Krugerimport re 6568a9e459SScott Kruger 6644776d8cSScott Krugerdef _stripIndent(block,srcfile,entireBlock=False,fileNums=[]): 6729921a8fSScott Kruger """ 6829921a8fSScott Kruger Go through and remove a level of indentation 6929921a8fSScott Kruger Also strip of trailing whitespace 7029921a8fSScott Kruger """ 7129921a8fSScott Kruger # The first entry should be test: but it might be indented. 7229921a8fSScott Kruger ext=os.path.splitext(srcfile)[1] 7344776d8cSScott Kruger stripstr=" " 7466db876fSScott Kruger if len(fileNums)>0: lineNum=fileNums[0]-1 758ccd5183SScott Kruger for lline in block.split("\n"): 7666db876fSScott Kruger if len(fileNums)>0: lineNum+=1 778ccd5183SScott Kruger line=lline[1:] if lline.startswith("!") else lline 7829921a8fSScott Kruger if not line.strip(): continue 79c4b80baaSScott Kruger if line.strip().startswith('#'): continue 8044776d8cSScott Kruger if entireBlock: 8144776d8cSScott Kruger var=line.split(":")[0].strip() 82e53dc769SScott Kruger if not (var=='test' or var=='testset'): 8366db876fSScott Kruger raise Exception("Formatting error: Cannot find test in file: "+srcfile+" at line: "+str(lineNum)+"\n") 8429921a8fSScott Kruger nspace=len(line)-len(line.lstrip(stripstr)) 8529921a8fSScott Kruger newline=line[nspace:] 8629921a8fSScott Kruger break 8729921a8fSScott Kruger 8829921a8fSScott Kruger # Strip off any indentation for the whole string and any trailing 8929921a8fSScott Kruger # whitespace for convenience 9029921a8fSScott Kruger newTestStr="\n" 9144776d8cSScott Kruger if len(fileNums)>0: lineNum=fileNums[0]-1 9244776d8cSScott Kruger firstPass=True 938ccd5183SScott Kruger for lline in block.split("\n"): 9444776d8cSScott Kruger if len(fileNums)>0: lineNum+=1 958ccd5183SScott Kruger line=lline[1:] if lline.startswith("!") else lline 9629921a8fSScott Kruger if not line.strip(): continue 97c4b80baaSScott Kruger if line.strip().startswith('#'): 98c4b80baaSScott Kruger newTestStr+=line+'\n' 99c4b80baaSScott Kruger else: 10029921a8fSScott Kruger newline=line[nspace:] 101c4b80baaSScott Kruger newTestStr+=newline.rstrip()+"\n" 10244776d8cSScott Kruger # Do some basic indentation checks 10344776d8cSScott Kruger if entireBlock: 10444776d8cSScott Kruger # Don't need to check comment lines 10544776d8cSScott Kruger if line.strip().startswith('#'): continue 10644776d8cSScott Kruger if not newline.startswith(" "): 10744776d8cSScott Kruger var=newline.split(":")[0].strip() 108e53dc769SScott Kruger if not (var=='test' or var=='testset'): 10944776d8cSScott Kruger err="Formatting error in file "+srcfile+" at line: " +line+"\n" 11044776d8cSScott Kruger if len(fileNums)>0: 11144776d8cSScott Kruger raise Exception(err+"Check indentation at line number: "+str(lineNum)) 11244776d8cSScott Kruger else: 11344776d8cSScott Kruger raise Exception(err) 11444776d8cSScott Kruger else: 11544776d8cSScott Kruger var=line.split(":")[0].strip() 116e53dc769SScott Kruger if var=='test' or var=='testset': 11744776d8cSScott Kruger subnspace=len(line)-len(line.lstrip(stripstr)) 11844776d8cSScott Kruger if firstPass: 11944776d8cSScott Kruger firstsubnspace=subnspace 12044776d8cSScott Kruger firstPass=False 12144776d8cSScott Kruger else: 12244776d8cSScott Kruger if firstsubnspace!=subnspace: 12344776d8cSScott Kruger err="Formatting subtest error in file "+srcfile+" at line: " +line+"\n" 12444776d8cSScott Kruger if len(fileNums)>0: 12544776d8cSScott Kruger raise Exception(err+"Check indentation at line number: "+str(lineNum)) 12644776d8cSScott Kruger else: 12744776d8cSScott Kruger raise Exception(err) 12844776d8cSScott Kruger 12929921a8fSScott Kruger 13029921a8fSScott Kruger return newTestStr 13129921a8fSScott Kruger 132aae9f2d9SScott Krugerdef parseLoopArgs(varset): 13344776d8cSScott Kruger """ 134aae9f2d9SScott Kruger Given: String containing loop variables 135aae9f2d9SScott Kruger Return: tuple containing separate/shared and string of loop vars 13644776d8cSScott Kruger """ 137aae9f2d9SScott Kruger keynm=varset.split("{{")[0].strip() 138aae9f2d9SScott Kruger if not keynm.strip(): keynm='nsize' 139aae9f2d9SScott Kruger lvars=varset.split('{{')[1].split('}')[0] 140aae9f2d9SScott Kruger suffx=varset.split('{{')[1].split('}')[1] 141aae9f2d9SScott Kruger ftype='separate' if suffx.startswith('separate') else 'shared' 142aae9f2d9SScott Kruger return keynm,lvars,ftype 14344776d8cSScott Kruger 144e53dc769SScott Krugerdef _getSeparateTestvars(testDict): 145e53dc769SScott Kruger """ 146e53dc769SScott Kruger Given: dictionary that may have 147e53dc769SScott Kruger Return: Variables that cause a test split 148e53dc769SScott Kruger """ 149e53dc769SScott Kruger vals=None 150e53dc769SScott Kruger sepvars=[] 151e53dc769SScott Kruger # Check nsize 152e53dc769SScott Kruger if testDict.has_key('nsize'): 153e53dc769SScott Kruger varset=testDict['nsize'] 154aae9f2d9SScott Kruger if '{{' in varset: 155aae9f2d9SScott Kruger keynm,lvars,ftype=parseLoopArgs(varset) 156aae9f2d9SScott Kruger if ftype=='separate': sepvars.append(keynm) 157e53dc769SScott Kruger 158e53dc769SScott Kruger # Now check args 159e53dc769SScott Kruger if not testDict.has_key('args'): return sepvars 160e53dc769SScott Kruger for varset in re.split('-(?=[a-zA-Z])',testDict['args']): 161e53dc769SScott Kruger if not varset.strip(): continue 162aae9f2d9SScott Kruger if '{{' in varset: 163e53dc769SScott Kruger # Assuming only one for loop per var specification 164aae9f2d9SScott Kruger keynm,lvars,ftype=parseLoopArgs(varset) 165aae9f2d9SScott Kruger if ftype=='separate': sepvars.append(keynm) 166e53dc769SScott Kruger 167e53dc769SScott Kruger return sepvars 168e53dc769SScott Kruger 16944776d8cSScott Krugerdef _getVarVals(findvar,testDict): 17044776d8cSScott Kruger """ 17144776d8cSScott Kruger Given: variable that is either nsize or in args 17244776d8cSScott Kruger Return: Values to loop over 17344776d8cSScott Kruger """ 17444776d8cSScott Kruger vals=None 17544776d8cSScott Kruger newargs='' 17644776d8cSScott Kruger if findvar=='nsize': 177e53dc769SScott Kruger varset=testDict[findvar] 178aae9f2d9SScott Kruger keynm,vals,ftype=parseLoopArgs('nsize '+varset) 17944776d8cSScott Kruger else: 18044776d8cSScott Kruger varlist=[] 18144776d8cSScott Kruger for varset in re.split('-(?=[a-zA-Z])',testDict['args']): 18244776d8cSScott Kruger if not varset.strip(): continue 183aae9f2d9SScott Kruger if '{{' in varset: 184aae9f2d9SScott Kruger keyvar,vals,ftype=parseLoopArgs(varset) 18544776d8cSScott Kruger if keyvar!=findvar: 1860bcc1aabSScott Kruger newargs+="-"+varset.strip()+" " 18744776d8cSScott Kruger continue 1880bcc1aabSScott Kruger else: 1890bcc1aabSScott Kruger newargs+="-"+varset.strip()+" " 19044776d8cSScott Kruger 19144776d8cSScott Kruger if not vals: raise StandardError("Could not find separate_testvar: "+findvar) 19244776d8cSScott Kruger return vals,newargs 19344776d8cSScott Kruger 19444776d8cSScott Krugerdef genTestsSeparateTestvars(intests,indicts): 19544776d8cSScott Kruger """ 196e53dc769SScott Kruger Given: testname, sdict with 'separate_testvars 19744776d8cSScott Kruger Return: testnames,sdicts: List of generated tests 19844776d8cSScott Kruger """ 19944776d8cSScott Kruger testnames=[]; sdicts=[] 20044776d8cSScott Kruger for i in range(len(intests)): 20144776d8cSScott Kruger testname=intests[i]; sdict=indicts[i]; i+=1 202e53dc769SScott Kruger separate_testvars=_getSeparateTestvars(sdict) 203e53dc769SScott Kruger if len(separate_testvars)>0: 204e53dc769SScott Kruger for kvar in separate_testvars: 20544776d8cSScott Kruger kvals,newargs=_getVarVals(kvar,sdict) 20644776d8cSScott Kruger # No errors means we are good to go 20744776d8cSScott Kruger for val in kvals.split(): 20844776d8cSScott Kruger kvardict=sdict.copy() 20944776d8cSScott Kruger gensuffix="_"+kvar+"-"+val 21044776d8cSScott Kruger newtestnm=testname+gensuffix 2110bcc1aabSScott Kruger if sdict.has_key('suffix'): 21244776d8cSScott Kruger kvardict['suffix']=sdict['suffix']+gensuffix 2130bcc1aabSScott Kruger else: 2140bcc1aabSScott Kruger kvardict['suffix']=gensuffix 21544776d8cSScott Kruger if kvar=='nsize': 21644776d8cSScott Kruger kvardict[kvar]=val 21744776d8cSScott Kruger else: 21844776d8cSScott Kruger kvardict['args']=newargs+"-"+kvar+" "+val 21944776d8cSScott Kruger testnames.append(newtestnm) 22044776d8cSScott Kruger sdicts.append(kvardict) 22144776d8cSScott Kruger else: 22244776d8cSScott Kruger testnames.append(testname) 22344776d8cSScott Kruger sdicts.append(sdict) 22444776d8cSScott Kruger return testnames,sdicts 22544776d8cSScott Kruger 22644776d8cSScott Krugerdef genTestsSubtestSuffix(testnames,sdicts): 22744776d8cSScott Kruger """ 22844776d8cSScott Kruger Given: testname, sdict with separate_testvars 22944776d8cSScott Kruger Return: testnames,sdicts: List of generated tests 23044776d8cSScott Kruger """ 23144776d8cSScott Kruger tnms=[]; sdcts=[] 23244776d8cSScott Kruger for i in range(len(testnames)): 23344776d8cSScott Kruger testname=testnames[i] 23444776d8cSScott Kruger rmsubtests=[]; keepSubtests=False 23544776d8cSScott Kruger if sdicts[i].has_key('subtests'): 23644776d8cSScott Kruger for stest in sdicts[i]["subtests"]: 23744776d8cSScott Kruger if sdicts[i][stest].has_key('suffix'): 23844776d8cSScott Kruger rmsubtests.append(stest) 23944776d8cSScott Kruger gensuffix="_"+sdicts[i][stest]['suffix'] 24044776d8cSScott Kruger newtestnm=testname+gensuffix 24144776d8cSScott Kruger tnms.append(newtestnm) 24244776d8cSScott Kruger newsdict=sdicts[i].copy() 24344776d8cSScott Kruger del newsdict['subtests'] 24444776d8cSScott Kruger # Have to hand update 24544776d8cSScott Kruger # Append 24644776d8cSScott Kruger for kup in appendlist: 24744776d8cSScott Kruger if sdicts[i][stest].has_key(kup): 24844776d8cSScott Kruger if sdicts[i].has_key(kup): 24944776d8cSScott Kruger newsdict[kup]=sdicts[i][kup]+" "+sdicts[i][stest][kup] 25044776d8cSScott Kruger else: 25144776d8cSScott Kruger newsdict[kup]=sdicts[i][stest][kup] 25244776d8cSScott Kruger # Promote 25344776d8cSScott Kruger for kup in acceptedkeys: 25444776d8cSScott Kruger if kup in appendlist: continue 25544776d8cSScott Kruger if sdicts[i][stest].has_key(kup): 25644776d8cSScott Kruger newsdict[kup]=sdicts[i][stest][kup] 25744776d8cSScott Kruger # Cleanup 25844776d8cSScott Kruger for st in sdicts[i]["subtests"]: del newsdict[st] 25944776d8cSScott Kruger sdcts.append(newsdict) 26044776d8cSScott Kruger else: 26144776d8cSScott Kruger keepSubtests=True 26244776d8cSScott Kruger else: 26344776d8cSScott Kruger tnms.append(testnames[i]) 26444776d8cSScott Kruger sdcts.append(sdicts[i]) 2650bcc1aabSScott Kruger # If a subtest without a suffix exists, then save it 26644776d8cSScott Kruger if keepSubtests: 26744776d8cSScott Kruger tnms.append(testnames[i]) 2680bcc1aabSScott Kruger newsdict=sdicts[i].copy() 2690bcc1aabSScott Kruger # Prune the tests to prepare for keeping 2700bcc1aabSScott Kruger for rmtest in rmsubtests: 2710bcc1aabSScott Kruger newsdict['subtests'].remove(rmtest) 2720bcc1aabSScott Kruger del newsdict[rmtest] 2730bcc1aabSScott Kruger sdcts.append(newsdict) 27444776d8cSScott Kruger i+=1 27544776d8cSScott Kruger return tnms,sdcts 27644776d8cSScott Kruger 27744776d8cSScott Krugerdef splitTests(testname,sdict): 27844776d8cSScott Kruger """ 27944776d8cSScott Kruger Given: testname and YAML-generated dictionary 28044776d8cSScott Kruger Return: list of names and dictionaries corresponding to each test 28144776d8cSScott Kruger given that the YAML language allows for multiple tests 28244776d8cSScott Kruger """ 28344776d8cSScott Kruger 28444776d8cSScott Kruger # Order: Parent sep_tv, subtests suffix, subtests sep_tv 28544776d8cSScott Kruger testnames,sdicts=genTestsSeparateTestvars([testname],[sdict]) 28644776d8cSScott Kruger testnames,sdicts=genTestsSubtestSuffix(testnames,sdicts) 28744776d8cSScott Kruger testnames,sdicts=genTestsSeparateTestvars(testnames,sdicts) 28844776d8cSScott Kruger 28944776d8cSScott Kruger # Because I am altering the list, I do this in passes. Inelegant 29044776d8cSScott Kruger 29144776d8cSScott Kruger return testnames, sdicts 29244776d8cSScott Kruger 2936cecdbdcSScott Krugerdef parseTest(testStr,srcfile,verbosity): 29429921a8fSScott Kruger """ 29529921a8fSScott Kruger This parses an individual test 29629921a8fSScott Kruger YAML is hierarchial so should use a state machine in the general case, 29753f2a965SBarry Smith but in practice we only support two levels of test: 29829921a8fSScott Kruger """ 29929921a8fSScott Kruger basename=os.path.basename(srcfile) 30029921a8fSScott Kruger # Handle the new at the begininng 30129921a8fSScott Kruger bn=re.sub("new_","",basename) 30229921a8fSScott Kruger # This is the default 30329921a8fSScott Kruger testname="run"+os.path.splitext(bn)[0] 30429921a8fSScott Kruger 30529921a8fSScott Kruger # Tests that have default everything (so empty effectively) 30629921a8fSScott Kruger if len(testStr)==0: return testname, {} 30729921a8fSScott Kruger 30829921a8fSScott Kruger striptest=_stripIndent(testStr,srcfile) 30929921a8fSScott Kruger 31029921a8fSScott Kruger # go through and parse 31129921a8fSScott Kruger subtestnum=0 31229921a8fSScott Kruger subdict={} 31368a9e459SScott Kruger comments=[] 31468a9e459SScott Kruger indentlevel=0 31568a9e459SScott Kruger for ln in striptest.split("\n"): 316c4b80baaSScott Kruger line=ln.split('#')[0].rstrip() 3176cecdbdcSScott Kruger if verbosity>2: print line 3180bcc1aabSScott Kruger comment=("" if len(ln.split("#"))>0 else " ".join(ln.split("#")[1:]).strip()) 31968a9e459SScott Kruger if comment: comments.append(comment) 32029921a8fSScott Kruger if not line.strip(): continue 32144776d8cSScott Kruger lsplit=line.split(':') 32244776d8cSScott Kruger if len(lsplit)==0: raise Exception("Missing : in line: "+line) 32344776d8cSScott Kruger indentcount=lsplit[0].count(" ") 32444776d8cSScott Kruger var=lsplit[0].strip() 32540ae0433SScott Kruger val=line[line.find(':')+1:].strip() 32644776d8cSScott Kruger if not var in acceptedkeys: raise Exception("Not a defined key: "+var+" from: "+line) 32729921a8fSScott Kruger # Start by seeing if we are in a subtest 32829921a8fSScott Kruger if line.startswith(" "): 329c0658d2aSScott Kruger subdict[subtestname][var]=val 33068a9e459SScott Kruger if not indentlevel: indentlevel=indentcount 33168a9e459SScott Kruger #if indentlevel!=indentcount: print "Error in indentation:", ln 33229921a8fSScott Kruger # Determine subtest name and make dict 33329921a8fSScott Kruger elif var=="test": 33429921a8fSScott Kruger subtestname="test"+str(subtestnum) 33529921a8fSScott Kruger subdict[subtestname]={} 33629921a8fSScott Kruger if not subdict.has_key("subtests"): subdict["subtests"]=[] 33729921a8fSScott Kruger subdict["subtests"].append(subtestname) 33829921a8fSScott Kruger subtestnum=subtestnum+1 33968a9e459SScott Kruger # The rest are easy 34029921a8fSScott Kruger else: 34144776d8cSScott Kruger # For convenience, it is sometimes convenient to list twice 34244776d8cSScott Kruger if subdict.has_key(var): 34344776d8cSScott Kruger if var in appendlist: 34444776d8cSScott Kruger subdict[var]+=" "+val 34544776d8cSScott Kruger else: 34644776d8cSScott Kruger raise Exception(var+" entered twice: "+line) 34744776d8cSScott Kruger else: 348c0658d2aSScott Kruger subdict[var]=val 34929921a8fSScott Kruger if var=="suffix": 35029921a8fSScott Kruger if len(val)>0: 35129921a8fSScott Kruger testname=testname+"_"+val 35229921a8fSScott Kruger 35368a9e459SScott Kruger if len(comments): subdict['comments']="\n".join(comments).lstrip("\n") 35444776d8cSScott Kruger # A test block can create multiple tests. This does 35544776d8cSScott Kruger # that logic 35644776d8cSScott Kruger testnames,subdicts=splitTests(testname,subdict) 35744776d8cSScott Kruger return testnames,subdicts 35829921a8fSScott Kruger 3596cecdbdcSScott Krugerdef parseTests(testStr,srcfile,fileNums,verbosity): 36029921a8fSScott Kruger """ 36129921a8fSScott Kruger Parse the yaml string describing tests and return 36229921a8fSScott Kruger a dictionary with the info in the form of: 36329921a8fSScott Kruger testDict[test][subtest] 36429921a8fSScott Kruger This is an inelegant parser as we do not wish to 36529921a8fSScott Kruger introduce a new dependency by bringing in pyyaml. 36629921a8fSScott Kruger The advantage is that validation can be done as 36729921a8fSScott Kruger it is parsed (e.g., 'test' is the only top-level node) 36829921a8fSScott Kruger """ 36929921a8fSScott Kruger 37029921a8fSScott Kruger testDict={} 37129921a8fSScott Kruger 37229921a8fSScott Kruger # The first entry should be test: but it might be indented. 37344776d8cSScott Kruger newTestStr=_stripIndent(testStr,srcfile,entireBlock=True,fileNums=fileNums) 3746cecdbdcSScott Kruger if verbosity>2: print srcfile 37529921a8fSScott Kruger 37629921a8fSScott Kruger # Now go through each test. First elem in split is blank 377e53dc769SScott Kruger for test in re.split("\ntest(?:set)?:",newTestStr)[1:]: 3786cecdbdcSScott Kruger testnames,subdicts=parseTest(test,srcfile,verbosity) 37944776d8cSScott Kruger for i in range(len(testnames)): 38044776d8cSScott Kruger if testDict.has_key(testnames[i]): 381*1acf9037SMatthew G. Knepley raise RuntimeError("Multiple test names specified: "+testnames[i]+" in file: "+srcfile) 38244776d8cSScott Kruger testDict[testnames[i]]=subdicts[i] 38329921a8fSScott Kruger 38429921a8fSScott Kruger return testDict 38529921a8fSScott Kruger 3866cecdbdcSScott Krugerdef parseTestFile(srcfile,verbosity): 38729921a8fSScott Kruger """ 38829921a8fSScott Kruger Parse single example files and return dictionary of the form: 38929921a8fSScott Kruger testDict[srcfile][test][subtest] 39029921a8fSScott Kruger """ 39129921a8fSScott Kruger debug=False 39229921a8fSScott Kruger curdir=os.path.realpath(os.path.curdir) 39329921a8fSScott Kruger basedir=os.path.dirname(os.path.realpath(srcfile)) 39429921a8fSScott Kruger basename=os.path.basename(srcfile) 39529921a8fSScott Kruger os.chdir(basedir) 39629921a8fSScott Kruger 39729921a8fSScott Kruger testDict={} 39829921a8fSScott Kruger sh=open(srcfile,"r"); fileStr=sh.read(); sh.close() 39929921a8fSScott Kruger 40029921a8fSScott Kruger ## Start with doing the tests 40129921a8fSScott Kruger # 40229921a8fSScott Kruger fsplit=fileStr.split("/*TEST\n")[1:] 40329921a8fSScott Kruger if len(fsplit)==0: 40429921a8fSScott Kruger if debug: print "No test found in: "+srcfile 40529921a8fSScott Kruger return {} 40644776d8cSScott Kruger fstart=len(fileStr.split("/*TEST\n")[0].split("\n"))+1 40729921a8fSScott Kruger # Allow for multiple "/*TEST" blocks even though it really should be 4086f029658SMatthew G. Knepley # one 40929921a8fSScott Kruger srcTests=[] 41029921a8fSScott Kruger for t in fsplit: srcTests.append(t.split("TEST*/")[0]) 41129921a8fSScott Kruger testString=" ".join(srcTests) 41229921a8fSScott Kruger if len(testString.strip())==0: 41329921a8fSScott Kruger print "No test found in: "+srcfile 41429921a8fSScott Kruger return {} 41544776d8cSScott Kruger flen=len(testString.split("\n")) 41644776d8cSScott Kruger fend=fstart+flen-1 41744776d8cSScott Kruger fileNums=range(fstart,fend) 4186cecdbdcSScott Kruger testDict[basename]=parseTests(testString,srcfile,fileNums,verbosity) 41929921a8fSScott Kruger 42029921a8fSScott Kruger ## Check and see if we have build reuqirements 42129921a8fSScott Kruger # 42229921a8fSScott Kruger if "/*T\n" in fileStr or "/*T " in fileStr: 42329921a8fSScott Kruger # The file info is already here and need to append 42429921a8fSScott Kruger Part1=fileStr.split("T*/")[0] 42529921a8fSScott Kruger fileInfo=Part1.split("/*T")[1] 42629921a8fSScott Kruger for bkey in buildkeys: 42729921a8fSScott Kruger if bkey+":" in fileInfo: 42829921a8fSScott Kruger testDict[basename][bkey]=fileInfo.split(bkey+":")[1].split("\n")[0].strip() 42929921a8fSScott Kruger 43029921a8fSScott Kruger os.chdir(curdir) 43129921a8fSScott Kruger return testDict 43229921a8fSScott Kruger 4336cecdbdcSScott Krugerdef parseTestDir(directory,verbosity): 43429921a8fSScott Kruger """ 43529921a8fSScott Kruger Parse single example files and return dictionary of the form: 43629921a8fSScott Kruger testDict[srcfile][test][subtest] 43729921a8fSScott Kruger """ 43829921a8fSScott Kruger curdir=os.path.realpath(os.path.curdir) 43929921a8fSScott Kruger basedir=os.path.realpath(directory) 44029921a8fSScott Kruger os.chdir(basedir) 44129921a8fSScott Kruger 44229921a8fSScott Kruger tDict={} 44329921a8fSScott Kruger for test_file in glob.glob("new_ex*.*"): 4446cecdbdcSScott Kruger tDict.update(parseTestFile(test_file,verbosity)) 44529921a8fSScott Kruger 44629921a8fSScott Kruger os.chdir(curdir) 44729921a8fSScott Kruger return tDict 44829921a8fSScott Kruger 44929921a8fSScott Krugerdef printExParseDict(rDict): 45029921a8fSScott Kruger """ 45129921a8fSScott Kruger This is useful for debugging 45229921a8fSScott Kruger """ 45329921a8fSScott Kruger indent=" " 45429921a8fSScott Kruger for sfile in rDict: 45544776d8cSScott Kruger print sfile 45644776d8cSScott Kruger sortkeys=rDict[sfile].keys() 45744776d8cSScott Kruger sortkeys.sort() 45844776d8cSScott Kruger for runex in sortkeys: 45929921a8fSScott Kruger print indent+runex 46029921a8fSScott Kruger if type(rDict[sfile][runex])==types.StringType: 46129921a8fSScott Kruger print indent*2+rDict[sfile][runex] 46229921a8fSScott Kruger else: 46329921a8fSScott Kruger for var in rDict[sfile][runex]: 46444776d8cSScott Kruger if var.startswith("test"): continue 46544776d8cSScott Kruger print indent*2+var+": "+str(rDict[sfile][runex][var]) 46644776d8cSScott Kruger if rDict[sfile][runex].has_key('subtests'): 46744776d8cSScott Kruger for var in rDict[sfile][runex]['subtests']: 46829921a8fSScott Kruger print indent*2+var 46929921a8fSScott Kruger for var2 in rDict[sfile][runex][var]: 47029921a8fSScott Kruger print indent*3+var2+": "+str(rDict[sfile][runex][var][var2]) 47144776d8cSScott Kruger print "\n" 47229921a8fSScott Kruger return 47329921a8fSScott Kruger 47429921a8fSScott Krugerdef main(directory='',test_file='',verbosity=0): 47529921a8fSScott Kruger 47629921a8fSScott Kruger if directory: 4776cecdbdcSScott Kruger tDict=parseTestDir(directory,verbosity) 47829921a8fSScott Kruger else: 4796cecdbdcSScott Kruger tDict=parseTestFile(test_file,verbosity) 48029921a8fSScott Kruger if verbosity>0: printExParseDict(tDict) 48129921a8fSScott Kruger 48229921a8fSScott Kruger return 48329921a8fSScott Kruger 48429921a8fSScott Krugerif __name__ == '__main__': 48529921a8fSScott Kruger import optparse 48629921a8fSScott Kruger parser = optparse.OptionParser() 48729921a8fSScott Kruger parser.add_option('-d', '--directory', dest='directory', 48829921a8fSScott Kruger default="", help='Directory containing files to parse') 48929921a8fSScott Kruger parser.add_option('-t', '--test_file', dest='test_file', 49029921a8fSScott Kruger default="", help='Test file, e.g., ex1.c, to parse') 49129921a8fSScott Kruger parser.add_option('-v', '--verbosity', dest='verbosity', 49229921a8fSScott Kruger help='Verbosity of output by level: 1, 2, or 3', default=0) 49329921a8fSScott Kruger opts, extra_args = parser.parse_args() 49429921a8fSScott Kruger 49529921a8fSScott Kruger if extra_args: 49629921a8fSScott Kruger import sys 49729921a8fSScott Kruger sys.stderr.write('Unknown arguments: %s\n' % ' '.join(extra_args)) 49829921a8fSScott Kruger exit(1) 49929921a8fSScott Kruger if not opts.test_file and not opts.directory: 50029921a8fSScott Kruger print "test file or directory is required" 50129921a8fSScott Kruger parser.print_usage() 50229921a8fSScott Kruger sys.exit() 50329921a8fSScott Kruger 50429921a8fSScott Kruger # Need verbosity to be an integer 50529921a8fSScott Kruger try: 50629921a8fSScott Kruger verbosity=int(opts.verbosity) 50729921a8fSScott Kruger except: 50829921a8fSScott Kruger raise Exception("Error: Verbosity must be integer") 50929921a8fSScott Kruger 51029921a8fSScott Kruger main(directory=opts.directory,test_file=opts.test_file,verbosity=verbosity) 511