xref: /petsc/config/testparse.py (revision 0bcc1aab402c034f43f23ccecdc4318bdc42ee58)
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