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 5244776d8cSScott Krugeracceptedkeys="test nsize requires command suffix args separate_testvars filter filter_output localrunfiles comments TODO SKIP output_file".split() 5344776d8cSScott Krugerappendlist="args requires comments".split() 5468a9e459SScott Kruger 5568a9e459SScott Krugerimport re 5668a9e459SScott Kruger 5744776d8cSScott 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] 6444776d8cSScott 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 6944776d8cSScott Kruger if entireBlock: 7044776d8cSScott Kruger var=line.split(":")[0].strip() 7144776d8cSScott Kruger if not var=='test': 7244776d8cSScott 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" 8044776d8cSScott Kruger if len(fileNums)>0: lineNum=fileNums[0]-1 8144776d8cSScott Kruger firstPass=True 828ccd5183SScott Kruger for lline in block.split("\n"): 8344776d8cSScott 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" 9144776d8cSScott Kruger # Do some basic indentation checks 9244776d8cSScott Kruger if entireBlock: 9344776d8cSScott Kruger # Don't need to check comment lines 9444776d8cSScott Kruger if line.strip().startswith('#'): continue 9544776d8cSScott Kruger if not newline.startswith(" "): 9644776d8cSScott Kruger var=newline.split(":")[0].strip() 9744776d8cSScott Kruger if not var=='test': 9844776d8cSScott Kruger err="Formatting error in file "+srcfile+" at line: " +line+"\n" 9944776d8cSScott Kruger if len(fileNums)>0: 10044776d8cSScott Kruger raise Exception(err+"Check indentation at line number: "+str(lineNum)) 10144776d8cSScott Kruger else: 10244776d8cSScott Kruger raise Exception(err) 10344776d8cSScott Kruger else: 10444776d8cSScott Kruger var=line.split(":")[0].strip() 10544776d8cSScott Kruger if var=='test': 10644776d8cSScott Kruger subnspace=len(line)-len(line.lstrip(stripstr)) 10744776d8cSScott Kruger if firstPass: 10844776d8cSScott Kruger firstsubnspace=subnspace 10944776d8cSScott Kruger firstPass=False 11044776d8cSScott Kruger else: 11144776d8cSScott Kruger if firstsubnspace!=subnspace: 11244776d8cSScott Kruger err="Formatting subtest error in file "+srcfile+" at line: " +line+"\n" 11344776d8cSScott Kruger if len(fileNums)>0: 11444776d8cSScott Kruger raise Exception(err+"Check indentation at line number: "+str(lineNum)) 11544776d8cSScott Kruger else: 11644776d8cSScott Kruger raise Exception(err) 11744776d8cSScott Kruger 11829921a8fSScott Kruger 11929921a8fSScott Kruger return newTestStr 12029921a8fSScott Kruger 12144776d8cSScott Krugerdef _getNewArgs(kvar,val,argStr): 12244776d8cSScott Kruger """ 12344776d8cSScott Kruger Given: String containing arguments 12444776d8cSScott Kruger Return: String without the value in it 12544776d8cSScott Kruger """ 12644776d8cSScott Kruger return newTestStr 12744776d8cSScott Kruger 12844776d8cSScott Krugerdef _getVarVals(findvar,testDict): 12944776d8cSScott Kruger """ 13044776d8cSScott Kruger Given: variable that is either nsize or in args 13144776d8cSScott Kruger Return: Values to loop over 13244776d8cSScott Kruger """ 13344776d8cSScott Kruger vals=None 13444776d8cSScott Kruger newargs='' 13544776d8cSScott Kruger if findvar=='nsize': 13644776d8cSScott Kruger vals=testDict[findvar] 13744776d8cSScott Kruger else: 13844776d8cSScott Kruger varlist=[] 13944776d8cSScott Kruger for varset in re.split('-(?=[a-zA-Z])',testDict['args']): 14044776d8cSScott Kruger if not varset.strip(): continue 14144776d8cSScott Kruger if len(re.findall('{{(.*?)}}',varset))>0: 14244776d8cSScott Kruger # Assuming only one for loop per var specification 14344776d8cSScott Kruger keyvar=varset.split("{{")[0].strip() 14444776d8cSScott Kruger if keyvar!=findvar: 145*0bcc1aabSScott Kruger newargs+="-"+varset.strip()+" " 14644776d8cSScott Kruger continue 14744776d8cSScott Kruger vals=re.findall('{{(.*?)}}',varset)[0] 148*0bcc1aabSScott Kruger else: 149*0bcc1aabSScott Kruger newargs+="-"+varset.strip()+" " 15044776d8cSScott Kruger 15144776d8cSScott Kruger if not vals: raise StandardError("Could not find separate_testvar: "+findvar) 15244776d8cSScott Kruger return vals,newargs 15344776d8cSScott Kruger 15444776d8cSScott Krugerdef genTestsSeparateTestvars(intests,indicts): 15544776d8cSScott Kruger """ 15644776d8cSScott Kruger Given: testname, sdict with separate_testvars 15744776d8cSScott Kruger Return: testnames,sdicts: List of generated tests 15844776d8cSScott Kruger """ 15944776d8cSScott Kruger testnames=[]; sdicts=[] 16044776d8cSScott Kruger for i in range(len(intests)): 16144776d8cSScott Kruger testname=intests[i]; sdict=indicts[i]; i+=1 16244776d8cSScott Kruger if sdict.has_key('separate_testvars'): 16344776d8cSScott Kruger for kvar in sdict['separate_testvars'].split(): 16444776d8cSScott Kruger kvals,newargs=_getVarVals(kvar,sdict) 16544776d8cSScott Kruger # No errors means we are good to go 16644776d8cSScott Kruger for val in kvals.split(): 16744776d8cSScott Kruger kvardict=sdict.copy() 16844776d8cSScott Kruger del kvardict['separate_testvars'] 16944776d8cSScott Kruger gensuffix="_"+kvar+"-"+val 17044776d8cSScott Kruger newtestnm=testname+gensuffix 171*0bcc1aabSScott Kruger if sdict.has_key('suffix'): 17244776d8cSScott Kruger kvardict['suffix']=sdict['suffix']+gensuffix 173*0bcc1aabSScott Kruger else: 174*0bcc1aabSScott Kruger kvardict['suffix']=gensuffix 17544776d8cSScott Kruger if kvar=='nsize': 17644776d8cSScott Kruger kvardict[kvar]=val 17744776d8cSScott Kruger else: 17844776d8cSScott Kruger kvardict['args']=newargs+"-"+kvar+" "+val 17944776d8cSScott Kruger testnames.append(newtestnm) 18044776d8cSScott Kruger sdicts.append(kvardict) 18144776d8cSScott Kruger else: 18244776d8cSScott Kruger testnames.append(testname) 18344776d8cSScott Kruger sdicts.append(sdict) 18444776d8cSScott Kruger return testnames,sdicts 18544776d8cSScott Kruger 18644776d8cSScott Krugerdef genTestsSubtestSuffix(testnames,sdicts): 18744776d8cSScott Kruger """ 18844776d8cSScott Kruger Given: testname, sdict with separate_testvars 18944776d8cSScott Kruger Return: testnames,sdicts: List of generated tests 19044776d8cSScott Kruger """ 19144776d8cSScott Kruger tnms=[]; sdcts=[] 19244776d8cSScott Kruger for i in range(len(testnames)): 19344776d8cSScott Kruger testname=testnames[i] 19444776d8cSScott Kruger rmsubtests=[]; keepSubtests=False 19544776d8cSScott Kruger if sdicts[i].has_key('subtests'): 19644776d8cSScott Kruger for stest in sdicts[i]["subtests"]: 19744776d8cSScott Kruger if sdicts[i][stest].has_key('suffix'): 19844776d8cSScott Kruger rmsubtests.append(stest) 19944776d8cSScott Kruger gensuffix="_"+sdicts[i][stest]['suffix'] 20044776d8cSScott Kruger newtestnm=testname+gensuffix 20144776d8cSScott Kruger tnms.append(newtestnm) 20244776d8cSScott Kruger newsdict=sdicts[i].copy() 20344776d8cSScott Kruger del newsdict['subtests'] 20444776d8cSScott Kruger # Have to hand update 20544776d8cSScott Kruger # Append 20644776d8cSScott Kruger for kup in appendlist: 20744776d8cSScott Kruger if sdicts[i][stest].has_key(kup): 20844776d8cSScott Kruger if sdicts[i].has_key(kup): 20944776d8cSScott Kruger newsdict[kup]=sdicts[i][kup]+" "+sdicts[i][stest][kup] 21044776d8cSScott Kruger else: 21144776d8cSScott Kruger newsdict[kup]=sdicts[i][stest][kup] 21244776d8cSScott Kruger # Promote 21344776d8cSScott Kruger for kup in acceptedkeys: 21444776d8cSScott Kruger if kup in appendlist: continue 21544776d8cSScott Kruger if sdicts[i][stest].has_key(kup): 21644776d8cSScott Kruger newsdict[kup]=sdicts[i][stest][kup] 21744776d8cSScott Kruger # Cleanup 21844776d8cSScott Kruger for st in sdicts[i]["subtests"]: del newsdict[st] 21944776d8cSScott Kruger sdcts.append(newsdict) 22044776d8cSScott Kruger else: 22144776d8cSScott Kruger keepSubtests=True 22244776d8cSScott Kruger else: 22344776d8cSScott Kruger tnms.append(testnames[i]) 22444776d8cSScott Kruger sdcts.append(sdicts[i]) 225*0bcc1aabSScott Kruger # If a subtest without a suffix exists, then save it 22644776d8cSScott Kruger if keepSubtests: 22744776d8cSScott Kruger tnms.append(testnames[i]) 228*0bcc1aabSScott Kruger newsdict=sdicts[i].copy() 229*0bcc1aabSScott Kruger # Prune the tests to prepare for keeping 230*0bcc1aabSScott Kruger for rmtest in rmsubtests: 231*0bcc1aabSScott Kruger newsdict['subtests'].remove(rmtest) 232*0bcc1aabSScott Kruger del newsdict[rmtest] 233*0bcc1aabSScott Kruger sdcts.append(newsdict) 23444776d8cSScott Kruger i+=1 23544776d8cSScott Kruger return tnms,sdcts 23644776d8cSScott Kruger 23744776d8cSScott Krugerdef splitTests(testname,sdict): 23844776d8cSScott Kruger """ 23944776d8cSScott Kruger Given: testname and YAML-generated dictionary 24044776d8cSScott Kruger Return: list of names and dictionaries corresponding to each test 24144776d8cSScott Kruger given that the YAML language allows for multiple tests 24244776d8cSScott Kruger """ 24344776d8cSScott Kruger 24444776d8cSScott Kruger # Order: Parent sep_tv, subtests suffix, subtests sep_tv 24544776d8cSScott Kruger testnames,sdicts=genTestsSeparateTestvars([testname],[sdict]) 24644776d8cSScott Kruger testnames,sdicts=genTestsSubtestSuffix(testnames,sdicts) 24744776d8cSScott Kruger testnames,sdicts=genTestsSeparateTestvars(testnames,sdicts) 24844776d8cSScott Kruger 24944776d8cSScott Kruger # Because I am altering the list, I do this in passes. Inelegant 25044776d8cSScott Kruger 25144776d8cSScott Kruger return testnames, sdicts 25244776d8cSScott Kruger 2536cecdbdcSScott Krugerdef parseTest(testStr,srcfile,verbosity): 25429921a8fSScott Kruger """ 25529921a8fSScott Kruger This parses an individual test 25629921a8fSScott Kruger YAML is hierarchial so should use a state machine in the general case, 25753f2a965SBarry Smith but in practice we only support two levels of test: 25829921a8fSScott Kruger """ 25929921a8fSScott Kruger basename=os.path.basename(srcfile) 26029921a8fSScott Kruger # Handle the new at the begininng 26129921a8fSScott Kruger bn=re.sub("new_","",basename) 26229921a8fSScott Kruger # This is the default 26329921a8fSScott Kruger testname="run"+os.path.splitext(bn)[0] 26429921a8fSScott Kruger 26529921a8fSScott Kruger # Tests that have default everything (so empty effectively) 26629921a8fSScott Kruger if len(testStr)==0: return testname, {} 26729921a8fSScott Kruger 26829921a8fSScott Kruger striptest=_stripIndent(testStr,srcfile) 26929921a8fSScott Kruger 27029921a8fSScott Kruger # go through and parse 27129921a8fSScott Kruger subtestnum=0 27229921a8fSScott Kruger subdict={} 27368a9e459SScott Kruger comments=[] 27468a9e459SScott Kruger indentlevel=0 27568a9e459SScott Kruger for ln in striptest.split("\n"): 276c4b80baaSScott Kruger line=ln.split('#')[0].rstrip() 2776cecdbdcSScott Kruger if verbosity>2: print line 278*0bcc1aabSScott Kruger comment=("" if len(ln.split("#"))>0 else " ".join(ln.split("#")[1:]).strip()) 27968a9e459SScott Kruger if comment: comments.append(comment) 28029921a8fSScott Kruger if not line.strip(): continue 28144776d8cSScott Kruger lsplit=line.split(':') 28244776d8cSScott Kruger if len(lsplit)==0: raise Exception("Missing : in line: "+line) 28344776d8cSScott Kruger indentcount=lsplit[0].count(" ") 28444776d8cSScott Kruger var=lsplit[0].strip() 28544776d8cSScott Kruger val=lsplit[1].strip() 28644776d8cSScott Kruger if not var in acceptedkeys: raise Exception("Not a defined key: "+var+" from: "+line) 28729921a8fSScott Kruger # Start by seeing if we are in a subtest 28829921a8fSScott Kruger if line.startswith(" "): 289c0658d2aSScott Kruger subdict[subtestname][var]=val 29068a9e459SScott Kruger if not indentlevel: indentlevel=indentcount 29168a9e459SScott Kruger #if indentlevel!=indentcount: print "Error in indentation:", ln 29229921a8fSScott Kruger # Determine subtest name and make dict 29329921a8fSScott Kruger elif var=="test": 29429921a8fSScott Kruger subtestname="test"+str(subtestnum) 29529921a8fSScott Kruger subdict[subtestname]={} 29629921a8fSScott Kruger if not subdict.has_key("subtests"): subdict["subtests"]=[] 29729921a8fSScott Kruger subdict["subtests"].append(subtestname) 29829921a8fSScott Kruger subtestnum=subtestnum+1 29968a9e459SScott Kruger # The rest are easy 30029921a8fSScott Kruger else: 30144776d8cSScott Kruger # For convenience, it is sometimes convenient to list twice 30244776d8cSScott Kruger if subdict.has_key(var): 30344776d8cSScott Kruger if var in appendlist: 30444776d8cSScott Kruger subdict[var]+=" "+val 30544776d8cSScott Kruger else: 30644776d8cSScott Kruger raise Exception(var+" entered twice: "+line) 30744776d8cSScott Kruger else: 308c0658d2aSScott Kruger subdict[var]=val 30929921a8fSScott Kruger if var=="suffix": 31029921a8fSScott Kruger if len(val)>0: 31129921a8fSScott Kruger testname=testname+"_"+val 31229921a8fSScott Kruger 31368a9e459SScott Kruger if len(comments): subdict['comments']="\n".join(comments).lstrip("\n") 31444776d8cSScott Kruger # A test block can create multiple tests. This does 31544776d8cSScott Kruger # that logic 31644776d8cSScott Kruger testnames,subdicts=splitTests(testname,subdict) 31744776d8cSScott Kruger return testnames,subdicts 31829921a8fSScott Kruger 3196cecdbdcSScott Krugerdef parseTests(testStr,srcfile,fileNums,verbosity): 32029921a8fSScott Kruger """ 32129921a8fSScott Kruger Parse the yaml string describing tests and return 32229921a8fSScott Kruger a dictionary with the info in the form of: 32329921a8fSScott Kruger testDict[test][subtest] 32429921a8fSScott Kruger This is an inelegant parser as we do not wish to 32529921a8fSScott Kruger introduce a new dependency by bringing in pyyaml. 32629921a8fSScott Kruger The advantage is that validation can be done as 32729921a8fSScott Kruger it is parsed (e.g., 'test' is the only top-level node) 32829921a8fSScott Kruger """ 32929921a8fSScott Kruger 33029921a8fSScott Kruger testDict={} 33129921a8fSScott Kruger 33229921a8fSScott Kruger # The first entry should be test: but it might be indented. 33344776d8cSScott Kruger newTestStr=_stripIndent(testStr,srcfile,entireBlock=True,fileNums=fileNums) 3346cecdbdcSScott Kruger if verbosity>2: print srcfile 33529921a8fSScott Kruger 33629921a8fSScott Kruger # Now go through each test. First elem in split is blank 337c4b80baaSScott Kruger for test in newTestStr.split("\ntest:")[1:]: 3386cecdbdcSScott Kruger testnames,subdicts=parseTest(test,srcfile,verbosity) 33944776d8cSScott Kruger for i in range(len(testnames)): 34044776d8cSScott Kruger if testDict.has_key(testnames[i]): 34144776d8cSScott Kruger raise Error("Multiple test names specified: "+testname+" in file: "+srcfile) 34244776d8cSScott Kruger testDict[testnames[i]]=subdicts[i] 34329921a8fSScott Kruger 34429921a8fSScott Kruger return testDict 34529921a8fSScott Kruger 3466cecdbdcSScott Krugerdef parseTestFile(srcfile,verbosity): 34729921a8fSScott Kruger """ 34829921a8fSScott Kruger Parse single example files and return dictionary of the form: 34929921a8fSScott Kruger testDict[srcfile][test][subtest] 35029921a8fSScott Kruger """ 35129921a8fSScott Kruger debug=False 35229921a8fSScott Kruger curdir=os.path.realpath(os.path.curdir) 35329921a8fSScott Kruger basedir=os.path.dirname(os.path.realpath(srcfile)) 35429921a8fSScott Kruger basename=os.path.basename(srcfile) 35529921a8fSScott Kruger os.chdir(basedir) 35629921a8fSScott Kruger 35729921a8fSScott Kruger testDict={} 35829921a8fSScott Kruger sh=open(srcfile,"r"); fileStr=sh.read(); sh.close() 35929921a8fSScott Kruger 36029921a8fSScott Kruger ## Start with doing the tests 36129921a8fSScott Kruger # 36229921a8fSScott Kruger fsplit=fileStr.split("/*TEST\n")[1:] 36329921a8fSScott Kruger if len(fsplit)==0: 36429921a8fSScott Kruger if debug: print "No test found in: "+srcfile 36529921a8fSScott Kruger return {} 36644776d8cSScott Kruger fstart=len(fileStr.split("/*TEST\n")[0].split("\n"))+1 36729921a8fSScott Kruger # Allow for multiple "/*TEST" blocks even though it really should be 36829921a8fSScott Kruger # on 36929921a8fSScott Kruger srcTests=[] 37029921a8fSScott Kruger for t in fsplit: srcTests.append(t.split("TEST*/")[0]) 37129921a8fSScott Kruger testString=" ".join(srcTests) 37229921a8fSScott Kruger if len(testString.strip())==0: 37329921a8fSScott Kruger print "No test found in: "+srcfile 37429921a8fSScott Kruger return {} 37544776d8cSScott Kruger flen=len(testString.split("\n")) 37644776d8cSScott Kruger fend=fstart+flen-1 37744776d8cSScott Kruger fileNums=range(fstart,fend) 3786cecdbdcSScott Kruger testDict[basename]=parseTests(testString,srcfile,fileNums,verbosity) 37929921a8fSScott Kruger 38029921a8fSScott Kruger ## Check and see if we have build reuqirements 38129921a8fSScott Kruger # 38229921a8fSScott Kruger if "/*T\n" in fileStr or "/*T " in fileStr: 38329921a8fSScott Kruger # The file info is already here and need to append 38429921a8fSScott Kruger Part1=fileStr.split("T*/")[0] 38529921a8fSScott Kruger fileInfo=Part1.split("/*T")[1] 38629921a8fSScott Kruger for bkey in buildkeys: 38729921a8fSScott Kruger if bkey+":" in fileInfo: 38829921a8fSScott Kruger testDict[basename][bkey]=fileInfo.split(bkey+":")[1].split("\n")[0].strip() 38929921a8fSScott Kruger 39029921a8fSScott Kruger os.chdir(curdir) 39129921a8fSScott Kruger return testDict 39229921a8fSScott Kruger 3936cecdbdcSScott Krugerdef parseTestDir(directory,verbosity): 39429921a8fSScott Kruger """ 39529921a8fSScott Kruger Parse single example files and return dictionary of the form: 39629921a8fSScott Kruger testDict[srcfile][test][subtest] 39729921a8fSScott Kruger """ 39829921a8fSScott Kruger curdir=os.path.realpath(os.path.curdir) 39929921a8fSScott Kruger basedir=os.path.realpath(directory) 40029921a8fSScott Kruger os.chdir(basedir) 40129921a8fSScott Kruger 40229921a8fSScott Kruger tDict={} 40329921a8fSScott Kruger for test_file in glob.glob("new_ex*.*"): 4046cecdbdcSScott Kruger tDict.update(parseTestFile(test_file,verbosity)) 40529921a8fSScott Kruger 40629921a8fSScott Kruger os.chdir(curdir) 40729921a8fSScott Kruger return tDict 40829921a8fSScott Kruger 40929921a8fSScott Krugerdef printExParseDict(rDict): 41029921a8fSScott Kruger """ 41129921a8fSScott Kruger This is useful for debugging 41229921a8fSScott Kruger """ 41329921a8fSScott Kruger indent=" " 41429921a8fSScott Kruger for sfile in rDict: 41544776d8cSScott Kruger print sfile 41644776d8cSScott Kruger sortkeys=rDict[sfile].keys() 41744776d8cSScott Kruger sortkeys.sort() 41844776d8cSScott Kruger for runex in sortkeys: 41929921a8fSScott Kruger print indent+runex 42029921a8fSScott Kruger if type(rDict[sfile][runex])==types.StringType: 42129921a8fSScott Kruger print indent*2+rDict[sfile][runex] 42229921a8fSScott Kruger else: 42329921a8fSScott Kruger for var in rDict[sfile][runex]: 42444776d8cSScott Kruger if var.startswith("test"): continue 42544776d8cSScott Kruger print indent*2+var+": "+str(rDict[sfile][runex][var]) 42644776d8cSScott Kruger if rDict[sfile][runex].has_key('subtests'): 42744776d8cSScott Kruger for var in rDict[sfile][runex]['subtests']: 42829921a8fSScott Kruger print indent*2+var 42929921a8fSScott Kruger for var2 in rDict[sfile][runex][var]: 43029921a8fSScott Kruger print indent*3+var2+": "+str(rDict[sfile][runex][var][var2]) 43144776d8cSScott Kruger print "\n" 43229921a8fSScott Kruger return 43329921a8fSScott Kruger 43429921a8fSScott Krugerdef main(directory='',test_file='',verbosity=0): 43529921a8fSScott Kruger 43629921a8fSScott Kruger if directory: 4376cecdbdcSScott Kruger tDict=parseTestDir(directory,verbosity) 43829921a8fSScott Kruger else: 4396cecdbdcSScott Kruger tDict=parseTestFile(test_file,verbosity) 44029921a8fSScott Kruger if verbosity>0: printExParseDict(tDict) 44129921a8fSScott Kruger 44229921a8fSScott Kruger return 44329921a8fSScott Kruger 44429921a8fSScott Krugerif __name__ == '__main__': 44529921a8fSScott Kruger import optparse 44629921a8fSScott Kruger parser = optparse.OptionParser() 44729921a8fSScott Kruger parser.add_option('-d', '--directory', dest='directory', 44829921a8fSScott Kruger default="", help='Directory containing files to parse') 44929921a8fSScott Kruger parser.add_option('-t', '--test_file', dest='test_file', 45029921a8fSScott Kruger default="", help='Test file, e.g., ex1.c, to parse') 45129921a8fSScott Kruger parser.add_option('-v', '--verbosity', dest='verbosity', 45229921a8fSScott Kruger help='Verbosity of output by level: 1, 2, or 3', default=0) 45329921a8fSScott Kruger opts, extra_args = parser.parse_args() 45429921a8fSScott Kruger 45529921a8fSScott Kruger if extra_args: 45629921a8fSScott Kruger import sys 45729921a8fSScott Kruger sys.stderr.write('Unknown arguments: %s\n' % ' '.join(extra_args)) 45829921a8fSScott Kruger exit(1) 45929921a8fSScott Kruger if not opts.test_file and not opts.directory: 46029921a8fSScott Kruger print "test file or directory is required" 46129921a8fSScott Kruger parser.print_usage() 46229921a8fSScott Kruger sys.exit() 46329921a8fSScott Kruger 46429921a8fSScott Kruger # Need verbosity to be an integer 46529921a8fSScott Kruger try: 46629921a8fSScott Kruger verbosity=int(opts.verbosity) 46729921a8fSScott Kruger except: 46829921a8fSScott Kruger raise Exception("Error: Verbosity must be integer") 46929921a8fSScott Kruger 47029921a8fSScott Kruger main(directory=opts.directory,test_file=opts.test_file,verbosity=verbosity) 471