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 2629921a8fSScott Kruger test: 2729921a8fSScott 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 2829921a8fSScott Kruger 2929921a8fSScott Kruger test: 3029921a8fSScott Kruger suffix: 2 3129921a8fSScott Kruger nsize: 2 3229921a8fSScott 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 3329921a8fSScott 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) 4829921a8fSScott Kruger 4929921a8fSScott Kruger# These are special keys describing build 5029921a8fSScott Krugerbuildkeys="requires TODO SKIP depends".split() 5129921a8fSScott Kruger 52*44776d8cSScott Krugeracceptedkeys="test nsize requires command suffix args separate_testvars filter filter_output localrunfiles comments TODO SKIP output_file".split() 53*44776d8cSScott Krugerappendlist="args requires comments".split() 5468a9e459SScott Kruger 5568a9e459SScott Krugerimport re 5668a9e459SScott Kruger 57*44776d8cSScott Krugerdef _stripIndent(block,srcfile,entireBlock=False,fileNums=[]): 5829921a8fSScott Kruger """ 5929921a8fSScott Kruger Go through and remove a level of indentation 6029921a8fSScott Kruger Also strip of trailing whitespace 6129921a8fSScott Kruger """ 6229921a8fSScott Kruger # The first entry should be test: but it might be indented. 6329921a8fSScott Kruger ext=os.path.splitext(srcfile)[1] 64*44776d8cSScott Kruger stripstr=" " 658ccd5183SScott Kruger for lline in block.split("\n"): 668ccd5183SScott Kruger line=lline[1:] if lline.startswith("!") else lline 6729921a8fSScott Kruger if not line.strip(): continue 68c4b80baaSScott Kruger if line.strip().startswith('#'): continue 69*44776d8cSScott Kruger if entireBlock: 70*44776d8cSScott Kruger var=line.split(":")[0].strip() 71*44776d8cSScott Kruger if not var=='test': 72*44776d8cSScott Kruger raise Exception("Formatting error in finding test in file: "+srcfile+"\n") 7329921a8fSScott Kruger nspace=len(line)-len(line.lstrip(stripstr)) 7429921a8fSScott Kruger newline=line[nspace:] 7529921a8fSScott Kruger break 7629921a8fSScott Kruger 7729921a8fSScott Kruger # Strip off any indentation for the whole string and any trailing 7829921a8fSScott Kruger # whitespace for convenience 7929921a8fSScott Kruger newTestStr="\n" 80*44776d8cSScott Kruger if len(fileNums)>0: lineNum=fileNums[0]-1 81*44776d8cSScott Kruger firstPass=True 828ccd5183SScott Kruger for lline in block.split("\n"): 83*44776d8cSScott Kruger if len(fileNums)>0: lineNum+=1 848ccd5183SScott Kruger line=lline[1:] if lline.startswith("!") else lline 8529921a8fSScott Kruger if not line.strip(): continue 86c4b80baaSScott Kruger if line.strip().startswith('#'): 87c4b80baaSScott Kruger newTestStr+=line+'\n' 88c4b80baaSScott Kruger else: 8929921a8fSScott Kruger newline=line[nspace:] 90c4b80baaSScott Kruger newTestStr+=newline.rstrip()+"\n" 91*44776d8cSScott Kruger # Do some basic indentation checks 92*44776d8cSScott Kruger if entireBlock: 93*44776d8cSScott Kruger # Don't need to check comment lines 94*44776d8cSScott Kruger if line.strip().startswith('#'): continue 95*44776d8cSScott Kruger if not newline.startswith(" "): 96*44776d8cSScott Kruger var=newline.split(":")[0].strip() 97*44776d8cSScott Kruger if not var=='test': 98*44776d8cSScott Kruger err="Formatting error in file "+srcfile+" at line: " +line+"\n" 99*44776d8cSScott Kruger if len(fileNums)>0: 100*44776d8cSScott Kruger raise Exception(err+"Check indentation at line number: "+str(lineNum)) 101*44776d8cSScott Kruger else: 102*44776d8cSScott Kruger raise Exception(err) 103*44776d8cSScott Kruger else: 104*44776d8cSScott Kruger var=line.split(":")[0].strip() 105*44776d8cSScott Kruger if var=='test': 106*44776d8cSScott Kruger subnspace=len(line)-len(line.lstrip(stripstr)) 107*44776d8cSScott Kruger if firstPass: 108*44776d8cSScott Kruger firstsubnspace=subnspace 109*44776d8cSScott Kruger firstPass=False 110*44776d8cSScott Kruger else: 111*44776d8cSScott Kruger if firstsubnspace!=subnspace: 112*44776d8cSScott Kruger err="Formatting subtest error in file "+srcfile+" at line: " +line+"\n" 113*44776d8cSScott Kruger if len(fileNums)>0: 114*44776d8cSScott Kruger raise Exception(err+"Check indentation at line number: "+str(lineNum)) 115*44776d8cSScott Kruger else: 116*44776d8cSScott Kruger raise Exception(err) 117*44776d8cSScott Kruger 11829921a8fSScott Kruger 11929921a8fSScott Kruger return newTestStr 12029921a8fSScott Kruger 121*44776d8cSScott Krugerdef _getNewArgs(kvar,val,argStr): 122*44776d8cSScott Kruger """ 123*44776d8cSScott Kruger Given: String containing arguments 124*44776d8cSScott Kruger Return: String without the value in it 125*44776d8cSScott Kruger """ 126*44776d8cSScott Kruger return newTestStr 127*44776d8cSScott Kruger 128*44776d8cSScott Krugerdef _getVarVals(findvar,testDict): 129*44776d8cSScott Kruger """ 130*44776d8cSScott Kruger Given: variable that is either nsize or in args 131*44776d8cSScott Kruger Return: Values to loop over 132*44776d8cSScott Kruger """ 133*44776d8cSScott Kruger vals=None 134*44776d8cSScott Kruger newargs='' 135*44776d8cSScott Kruger if findvar=='nsize': 136*44776d8cSScott Kruger vals=testDict[findvar] 137*44776d8cSScott Kruger else: 138*44776d8cSScott Kruger varlist=[] 139*44776d8cSScott Kruger for varset in re.split('-(?=[a-zA-Z])',testDict['args']): 140*44776d8cSScott Kruger if not varset.strip(): continue 141*44776d8cSScott Kruger if len(re.findall('{{(.*?)}}',varset))>0: 142*44776d8cSScott Kruger # Assuming only one for loop per var specification 143*44776d8cSScott Kruger keyvar=varset.split("{{")[0].strip() 144*44776d8cSScott Kruger if keyvar!=findvar: 145*44776d8cSScott Kruger newargs+="-"+varset+" " 146*44776d8cSScott Kruger continue 147*44776d8cSScott Kruger vals=re.findall('{{(.*?)}}',varset)[0] 148*44776d8cSScott Kruger 149*44776d8cSScott Kruger if not vals: raise StandardError("Could not find separate_testvar: "+findvar) 150*44776d8cSScott Kruger return vals,newargs 151*44776d8cSScott Kruger 152*44776d8cSScott Krugerdef genTestsSeparateTestvars(intests,indicts): 153*44776d8cSScott Kruger """ 154*44776d8cSScott Kruger Given: testname, sdict with separate_testvars 155*44776d8cSScott Kruger Return: testnames,sdicts: List of generated tests 156*44776d8cSScott Kruger """ 157*44776d8cSScott Kruger testnames=[]; sdicts=[] 158*44776d8cSScott Kruger for i in range(len(intests)): 159*44776d8cSScott Kruger testname=intests[i]; sdict=indicts[i]; i+=1 160*44776d8cSScott Kruger if sdict.has_key('separate_testvars'): 161*44776d8cSScott Kruger for kvar in sdict['separate_testvars'].split(): 162*44776d8cSScott Kruger kvals,newargs=_getVarVals(kvar,sdict) 163*44776d8cSScott Kruger # No errors means we are good to go 164*44776d8cSScott Kruger for val in kvals.split(): 165*44776d8cSScott Kruger kvardict=sdict.copy() 166*44776d8cSScott Kruger del kvardict['separate_testvars'] 167*44776d8cSScott Kruger gensuffix="_"+kvar+"-"+val 168*44776d8cSScott Kruger newtestnm=testname+gensuffix 169*44776d8cSScott Kruger kvardict['suffix']=sdict['suffix']+gensuffix 170*44776d8cSScott Kruger if kvar=='nsize': 171*44776d8cSScott Kruger kvardict[kvar]=val 172*44776d8cSScott Kruger else: 173*44776d8cSScott Kruger kvardict['args']=newargs+"-"+kvar+" "+val 174*44776d8cSScott Kruger testnames.append(newtestnm) 175*44776d8cSScott Kruger sdicts.append(kvardict) 176*44776d8cSScott Kruger else: 177*44776d8cSScott Kruger testnames.append(testname) 178*44776d8cSScott Kruger sdicts.append(sdict) 179*44776d8cSScott Kruger return testnames,sdicts 180*44776d8cSScott Kruger 181*44776d8cSScott Krugerdef genTestsSubtestSuffix(testnames,sdicts): 182*44776d8cSScott Kruger """ 183*44776d8cSScott Kruger Given: testname, sdict with separate_testvars 184*44776d8cSScott Kruger Return: testnames,sdicts: List of generated tests 185*44776d8cSScott Kruger """ 186*44776d8cSScott Kruger tnms=[]; sdcts=[] 187*44776d8cSScott Kruger for i in range(len(testnames)): 188*44776d8cSScott Kruger testname=testnames[i] 189*44776d8cSScott Kruger rmsubtests=[]; keepSubtests=False 190*44776d8cSScott Kruger if sdicts[i].has_key('subtests'): 191*44776d8cSScott Kruger for stest in sdicts[i]["subtests"]: 192*44776d8cSScott Kruger if sdicts[i][stest].has_key('suffix'): 193*44776d8cSScott Kruger rmsubtests.append(stest) 194*44776d8cSScott Kruger gensuffix="_"+sdicts[i][stest]['suffix'] 195*44776d8cSScott Kruger newtestnm=testname+gensuffix 196*44776d8cSScott Kruger tnms.append(newtestnm) 197*44776d8cSScott Kruger newsdict=sdicts[i].copy() 198*44776d8cSScott Kruger del newsdict['subtests'] 199*44776d8cSScott Kruger # Have to hand update 200*44776d8cSScott Kruger # Append 201*44776d8cSScott Kruger for kup in appendlist: 202*44776d8cSScott Kruger if sdicts[i][stest].has_key(kup): 203*44776d8cSScott Kruger if sdicts[i].has_key(kup): 204*44776d8cSScott Kruger newsdict[kup]=sdicts[i][kup]+" "+sdicts[i][stest][kup] 205*44776d8cSScott Kruger else: 206*44776d8cSScott Kruger newsdict[kup]=sdicts[i][stest][kup] 207*44776d8cSScott Kruger # Promote 208*44776d8cSScott Kruger for kup in acceptedkeys: 209*44776d8cSScott Kruger if kup in appendlist: continue 210*44776d8cSScott Kruger if sdicts[i][stest].has_key(kup): 211*44776d8cSScott Kruger newsdict[kup]=sdicts[i][stest][kup] 212*44776d8cSScott Kruger # Cleanup 213*44776d8cSScott Kruger for st in sdicts[i]["subtests"]: del newsdict[st] 214*44776d8cSScott Kruger sdcts.append(newsdict) 215*44776d8cSScott Kruger else: 216*44776d8cSScott Kruger keepSubtests=True 217*44776d8cSScott Kruger else: 218*44776d8cSScott Kruger tnms.append(testnames[i]) 219*44776d8cSScott Kruger sdcts.append(sdicts[i]) 220*44776d8cSScott Kruger # Prune the tests to prepare for keeping 221*44776d8cSScott Kruger for rmtest in rmsubtests: 222*44776d8cSScott Kruger sdicts[i]['subtests'].remove(rmtest) 223*44776d8cSScott Kruger del sdicts[i][rmtest] 224*44776d8cSScott Kruger # If we are keeping any tests, then append 225*44776d8cSScott Kruger if keepSubtests: 226*44776d8cSScott Kruger tnms.append(testnames[i]) 227*44776d8cSScott Kruger sdcts.append(sdicts[i]) 228*44776d8cSScott Kruger i+=1 229*44776d8cSScott Kruger return tnms,sdcts 230*44776d8cSScott Kruger 231*44776d8cSScott Krugerdef splitTests(testname,sdict): 232*44776d8cSScott Kruger """ 233*44776d8cSScott Kruger Given: testname and YAML-generated dictionary 234*44776d8cSScott Kruger Return: list of names and dictionaries corresponding to each test 235*44776d8cSScott Kruger given that the YAML language allows for multiple tests 236*44776d8cSScott Kruger """ 237*44776d8cSScott Kruger 238*44776d8cSScott Kruger # Order: Parent sep_tv, subtests suffix, subtests sep_tv 239*44776d8cSScott Kruger testnames,sdicts=genTestsSeparateTestvars([testname],[sdict]) 240*44776d8cSScott Kruger testnames,sdicts=genTestsSubtestSuffix(testnames,sdicts) 241*44776d8cSScott Kruger testnames,sdicts=genTestsSeparateTestvars(testnames,sdicts) 242*44776d8cSScott Kruger 243*44776d8cSScott Kruger # Because I am altering the list, I do this in passes. Inelegant 244*44776d8cSScott Kruger 245*44776d8cSScott Kruger return testnames, sdicts 246*44776d8cSScott Kruger 24729921a8fSScott Krugerdef parseTest(testStr,srcfile): 24829921a8fSScott Kruger """ 24929921a8fSScott Kruger This parses an individual test 25029921a8fSScott Kruger YAML is hierarchial so should use a state machine in the general case, 25153f2a965SBarry Smith but in practice we only support two levels of test: 25229921a8fSScott Kruger """ 25329921a8fSScott Kruger basename=os.path.basename(srcfile) 25429921a8fSScott Kruger # Handle the new at the begininng 25529921a8fSScott Kruger bn=re.sub("new_","",basename) 25629921a8fSScott Kruger # This is the default 25729921a8fSScott Kruger testname="run"+os.path.splitext(bn)[0] 25829921a8fSScott Kruger 25929921a8fSScott Kruger # Tests that have default everything (so empty effectively) 26029921a8fSScott Kruger if len(testStr)==0: return testname, {} 26129921a8fSScott Kruger 26229921a8fSScott Kruger striptest=_stripIndent(testStr,srcfile) 26329921a8fSScott Kruger 26429921a8fSScott Kruger # go through and parse 26529921a8fSScott Kruger subtestnum=0 26629921a8fSScott Kruger subdict={} 26768a9e459SScott Kruger comments=[] 26868a9e459SScott Kruger indentlevel=0 26968a9e459SScott Kruger for ln in striptest.split("\n"): 270c4b80baaSScott Kruger line=ln.split('#')[0].rstrip() 27168a9e459SScott Kruger comment=("" if len(ln.split("#"))==1 else " ".join(ln.split("#")[1:]).strip()) 27268a9e459SScott Kruger if comment: comments.append(comment) 27329921a8fSScott Kruger if not line.strip(): continue 274*44776d8cSScott Kruger lsplit=line.split(':') 275*44776d8cSScott Kruger if len(lsplit)==0: raise Exception("Missing : in line: "+line) 276*44776d8cSScott Kruger indentcount=lsplit[0].count(" ") 277*44776d8cSScott Kruger var=lsplit[0].strip() 278*44776d8cSScott Kruger val=lsplit[1].strip() 279*44776d8cSScott Kruger if not var in acceptedkeys: raise Exception("Not a defined key: "+var+" from: "+line) 28029921a8fSScott Kruger # Start by seeing if we are in a subtest 28129921a8fSScott Kruger if line.startswith(" "): 282c0658d2aSScott Kruger subdict[subtestname][var]=val 28368a9e459SScott Kruger if not indentlevel: indentlevel=indentcount 28468a9e459SScott Kruger #if indentlevel!=indentcount: print "Error in indentation:", ln 28529921a8fSScott Kruger # Determine subtest name and make dict 28629921a8fSScott Kruger elif var=="test": 28729921a8fSScott Kruger subtestname="test"+str(subtestnum) 28829921a8fSScott Kruger subdict[subtestname]={} 28929921a8fSScott Kruger if not subdict.has_key("subtests"): subdict["subtests"]=[] 29029921a8fSScott Kruger subdict["subtests"].append(subtestname) 29129921a8fSScott Kruger subtestnum=subtestnum+1 29268a9e459SScott Kruger # The rest are easy 29329921a8fSScott Kruger else: 294*44776d8cSScott Kruger # For convenience, it is sometimes convenient to list twice 295*44776d8cSScott Kruger if subdict.has_key(var): 296*44776d8cSScott Kruger if var in appendlist: 297*44776d8cSScott Kruger subdict[var]+=" "+val 298*44776d8cSScott Kruger else: 299*44776d8cSScott Kruger raise Exception(var+" entered twice: "+line) 300*44776d8cSScott Kruger else: 301c0658d2aSScott Kruger subdict[var]=val 30229921a8fSScott Kruger if var=="suffix": 30329921a8fSScott Kruger if len(val)>0: 30429921a8fSScott Kruger testname=testname+"_"+val 30529921a8fSScott Kruger 30668a9e459SScott Kruger if len(comments): subdict['comments']="\n".join(comments).lstrip("\n") 307*44776d8cSScott Kruger # A test block can create multiple tests. This does 308*44776d8cSScott Kruger # that logic 309*44776d8cSScott Kruger testnames,subdicts=splitTests(testname,subdict) 310*44776d8cSScott Kruger return testnames,subdicts 31129921a8fSScott Kruger 312*44776d8cSScott Krugerdef parseTests(testStr,srcfile,fileNums): 31329921a8fSScott Kruger """ 31429921a8fSScott Kruger Parse the yaml string describing tests and return 31529921a8fSScott Kruger a dictionary with the info in the form of: 31629921a8fSScott Kruger testDict[test][subtest] 31729921a8fSScott Kruger This is an inelegant parser as we do not wish to 31829921a8fSScott Kruger introduce a new dependency by bringing in pyyaml. 31929921a8fSScott Kruger The advantage is that validation can be done as 32029921a8fSScott Kruger it is parsed (e.g., 'test' is the only top-level node) 32129921a8fSScott Kruger """ 32229921a8fSScott Kruger 32329921a8fSScott Kruger testDict={} 32429921a8fSScott Kruger 32529921a8fSScott Kruger # The first entry should be test: but it might be indented. 326*44776d8cSScott Kruger newTestStr=_stripIndent(testStr,srcfile,entireBlock=True,fileNums=fileNums) 32729921a8fSScott Kruger 32829921a8fSScott Kruger # Now go through each test. First elem in split is blank 329c4b80baaSScott Kruger for test in newTestStr.split("\ntest:")[1:]: 330*44776d8cSScott Kruger testnames,subdicts=parseTest(test,srcfile) 331*44776d8cSScott Kruger for i in range(len(testnames)): 332*44776d8cSScott Kruger if testDict.has_key(testnames[i]): 333*44776d8cSScott Kruger raise Error("Multiple test names specified: "+testname+" in file: "+srcfile) 334*44776d8cSScott Kruger testDict[testnames[i]]=subdicts[i] 33529921a8fSScott Kruger 33629921a8fSScott Kruger return testDict 33729921a8fSScott Kruger 33829921a8fSScott Krugerdef parseTestFile(srcfile): 33929921a8fSScott Kruger """ 34029921a8fSScott Kruger Parse single example files and return dictionary of the form: 34129921a8fSScott Kruger testDict[srcfile][test][subtest] 34229921a8fSScott Kruger """ 34329921a8fSScott Kruger debug=False 34429921a8fSScott Kruger curdir=os.path.realpath(os.path.curdir) 34529921a8fSScott Kruger basedir=os.path.dirname(os.path.realpath(srcfile)) 34629921a8fSScott Kruger basename=os.path.basename(srcfile) 34729921a8fSScott Kruger os.chdir(basedir) 34829921a8fSScott Kruger 34929921a8fSScott Kruger testDict={} 35029921a8fSScott Kruger sh=open(srcfile,"r"); fileStr=sh.read(); sh.close() 35129921a8fSScott Kruger 35229921a8fSScott Kruger ## Start with doing the tests 35329921a8fSScott Kruger # 35429921a8fSScott Kruger fsplit=fileStr.split("/*TEST\n")[1:] 35529921a8fSScott Kruger if len(fsplit)==0: 35629921a8fSScott Kruger if debug: print "No test found in: "+srcfile 35729921a8fSScott Kruger return {} 358*44776d8cSScott Kruger fstart=len(fileStr.split("/*TEST\n")[0].split("\n"))+1 35929921a8fSScott Kruger # Allow for multiple "/*TEST" blocks even though it really should be 36029921a8fSScott Kruger # on 36129921a8fSScott Kruger srcTests=[] 36229921a8fSScott Kruger for t in fsplit: srcTests.append(t.split("TEST*/")[0]) 36329921a8fSScott Kruger testString=" ".join(srcTests) 36429921a8fSScott Kruger if len(testString.strip())==0: 36529921a8fSScott Kruger print "No test found in: "+srcfile 36629921a8fSScott Kruger return {} 367*44776d8cSScott Kruger flen=len(testString.split("\n")) 368*44776d8cSScott Kruger fend=fstart+flen-1 369*44776d8cSScott Kruger fileNums=range(fstart,fend) 370*44776d8cSScott Kruger testDict[basename]=parseTests(testString,srcfile,fileNums) 37129921a8fSScott Kruger 37229921a8fSScott Kruger ## Check and see if we have build reuqirements 37329921a8fSScott Kruger # 37429921a8fSScott Kruger if "/*T\n" in fileStr or "/*T " in fileStr: 37529921a8fSScott Kruger # The file info is already here and need to append 37629921a8fSScott Kruger Part1=fileStr.split("T*/")[0] 37729921a8fSScott Kruger fileInfo=Part1.split("/*T")[1] 37829921a8fSScott Kruger for bkey in buildkeys: 37929921a8fSScott Kruger if bkey+":" in fileInfo: 38029921a8fSScott Kruger testDict[basename][bkey]=fileInfo.split(bkey+":")[1].split("\n")[0].strip() 38129921a8fSScott Kruger 38229921a8fSScott Kruger os.chdir(curdir) 38329921a8fSScott Kruger return testDict 38429921a8fSScott Kruger 38529921a8fSScott Krugerdef parseTestDir(directory): 38629921a8fSScott Kruger """ 38729921a8fSScott Kruger Parse single example files and return dictionary of the form: 38829921a8fSScott Kruger testDict[srcfile][test][subtest] 38929921a8fSScott Kruger """ 39029921a8fSScott Kruger curdir=os.path.realpath(os.path.curdir) 39129921a8fSScott Kruger basedir=os.path.realpath(directory) 39229921a8fSScott Kruger os.chdir(basedir) 39329921a8fSScott Kruger 39429921a8fSScott Kruger tDict={} 39529921a8fSScott Kruger for test_file in glob.glob("new_ex*.*"): 39629921a8fSScott Kruger tDict.update(parseTestFile(test_file)) 39729921a8fSScott Kruger 39829921a8fSScott Kruger os.chdir(curdir) 39929921a8fSScott Kruger return tDict 40029921a8fSScott Kruger 40129921a8fSScott Krugerdef printExParseDict(rDict): 40229921a8fSScott Kruger """ 40329921a8fSScott Kruger This is useful for debugging 40429921a8fSScott Kruger """ 40529921a8fSScott Kruger indent=" " 40629921a8fSScott Kruger for sfile in rDict: 407*44776d8cSScott Kruger print sfile 408*44776d8cSScott Kruger sortkeys=rDict[sfile].keys() 409*44776d8cSScott Kruger sortkeys.sort() 410*44776d8cSScott Kruger for runex in sortkeys: 41129921a8fSScott Kruger print indent+runex 41229921a8fSScott Kruger if type(rDict[sfile][runex])==types.StringType: 41329921a8fSScott Kruger print indent*2+rDict[sfile][runex] 41429921a8fSScott Kruger else: 41529921a8fSScott Kruger for var in rDict[sfile][runex]: 416*44776d8cSScott Kruger if var.startswith("test"): continue 417*44776d8cSScott Kruger print indent*2+var+": "+str(rDict[sfile][runex][var]) 418*44776d8cSScott Kruger if rDict[sfile][runex].has_key('subtests'): 419*44776d8cSScott Kruger for var in rDict[sfile][runex]['subtests']: 42029921a8fSScott Kruger print indent*2+var 42129921a8fSScott Kruger for var2 in rDict[sfile][runex][var]: 42229921a8fSScott Kruger print indent*3+var2+": "+str(rDict[sfile][runex][var][var2]) 423*44776d8cSScott Kruger print "\n" 42429921a8fSScott Kruger return 42529921a8fSScott Kruger 42629921a8fSScott Krugerdef main(directory='',test_file='',verbosity=0): 42729921a8fSScott Kruger 42829921a8fSScott Kruger if directory: 42929921a8fSScott Kruger tDict=parseTestDir(directory) 43029921a8fSScott Kruger else: 43129921a8fSScott Kruger tDict=parseTestFile(test_file) 43229921a8fSScott Kruger if verbosity>0: printExParseDict(tDict) 43329921a8fSScott Kruger 43429921a8fSScott Kruger return 43529921a8fSScott Kruger 43629921a8fSScott Krugerif __name__ == '__main__': 43729921a8fSScott Kruger import optparse 43829921a8fSScott Kruger parser = optparse.OptionParser() 43929921a8fSScott Kruger parser.add_option('-d', '--directory', dest='directory', 44029921a8fSScott Kruger default="", help='Directory containing files to parse') 44129921a8fSScott Kruger parser.add_option('-t', '--test_file', dest='test_file', 44229921a8fSScott Kruger default="", help='Test file, e.g., ex1.c, to parse') 44329921a8fSScott Kruger parser.add_option('-v', '--verbosity', dest='verbosity', 44429921a8fSScott Kruger help='Verbosity of output by level: 1, 2, or 3', default=0) 44529921a8fSScott Kruger opts, extra_args = parser.parse_args() 44629921a8fSScott Kruger 44729921a8fSScott Kruger if extra_args: 44829921a8fSScott Kruger import sys 44929921a8fSScott Kruger sys.stderr.write('Unknown arguments: %s\n' % ' '.join(extra_args)) 45029921a8fSScott Kruger exit(1) 45129921a8fSScott Kruger if not opts.test_file and not opts.directory: 45229921a8fSScott Kruger print "test file or directory is required" 45329921a8fSScott Kruger parser.print_usage() 45429921a8fSScott Kruger sys.exit() 45529921a8fSScott Kruger 45629921a8fSScott Kruger # Need verbosity to be an integer 45729921a8fSScott Kruger try: 45829921a8fSScott Kruger verbosity=int(opts.verbosity) 45929921a8fSScott Kruger except: 46029921a8fSScott Kruger raise Exception("Error: Verbosity must be integer") 46129921a8fSScott Kruger 46229921a8fSScott Kruger main(directory=opts.directory,test_file=opts.test_file,verbosity=verbosity) 463