All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
GaudiTesting.BaseTest Namespace Reference

Classes

class  BaseTest
 
class  Result
 
class  BasicOutputValidator
 
class  FilePreprocessor
 
class  FilePreprocessorSequence
 
class  LineSkipper
 
class  BlockSkipper
 
class  RegexpReplacer
 
class  LineSorter
 Special preprocessor sorting the list of strings (whitespace separated) that follow a signature on a single line. More...
 
class  ReferenceFileValidator
 

Functions

def sanitize_for_xml
 
def ROOT6WorkAroundEnabled
 
def RationalizePath
 
def which
 
def findTTreeSummaries
 
def cmpTreesDicts
 
def getCmpFailingValues
 
def _parseTTreeSummary
 
def parseHistosSummary
 
def findHistosSummaries
 
def PlatformIsNotSupported
 
def GetPlatform
 
def isWinPlatform
 

Variables

tuple maskPointers RegexpReplacer("0x[0-9a-fA-F]{4,16}","0x########")
 
tuple normalizeDate
 
tuple normalizeEOL FilePreprocessor()
 
tuple skipEmptyLines FilePreprocessor()
 
 normalizeExamples maskPointers+normalizeDate
 
tuple lineSkipper
 
tuple h_count_re re.compile(r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+(.*)")
 

Function Documentation

def GaudiTesting.BaseTest._parseTTreeSummary (   lines,
  pos 
)
private
Parse the TTree summary table in lines, starting from pos.
Returns a tuple with the dictionary with the digested informations and the
position of the first line after the summary.

Definition at line 913 of file BaseTest.py.

914 def _parseTTreeSummary(lines, pos):
915  """
916  Parse the TTree summary table in lines, starting from pos.
917  Returns a tuple with the dictionary with the digested informations and the
918  position of the first line after the summary.
919  """
920  result = {}
921  i = pos + 1 # first line is a sequence of '*'
922  count = len(lines)
923 
924  splitcols = lambda l: [ f.strip() for f in l.strip("*\n").split(':',2) ]
925  def parseblock(ll):
926  r = {}
927  cols = splitcols(ll[0])
928  r["Name"], r["Title"] = cols[1:]
929 
930  cols = splitcols(ll[1])
931  r["Entries"] = int(cols[1])
932 
933  sizes = cols[2].split()
934  r["Total size"] = int(sizes[2])
935  if sizes[-1] == "memory":
936  r["File size"] = 0
937  else:
938  r["File size"] = int(sizes[-1])
939 
940  cols = splitcols(ll[2])
941  sizes = cols[2].split()
942  if cols[0] == "Baskets":
943  r["Baskets"] = int(cols[1])
944  r["Basket size"] = int(sizes[2])
945  r["Compression"] = float(sizes[-1])
946  return r
947 
948  if i < (count - 3) and lines[i].startswith("*Tree"):
949  result = parseblock(lines[i:i+3])
950  result["Branches"] = {}
951  i += 4
952  while i < (count - 3) and lines[i].startswith("*Br"):
953  if i < (count - 2) and lines[i].startswith("*Branch "):
954  # skip branch header
955  i += 3
956  continue
957  branch = parseblock(lines[i:i+3])
958  result["Branches"][branch["Name"]] = branch
959  i += 4
960 
961  return (result, i)
def GaudiTesting.BaseTest.cmpTreesDicts (   reference,
  to_check,
  ignore = None 
)
    Check that all the keys in reference are in to_check too, with the same value.
    If the value is a dict, the function is called recursively. to_check can
    contain more keys than reference, that will not be tested.
    The function returns at the first difference found.

Definition at line 868 of file BaseTest.py.

869 def cmpTreesDicts(reference, to_check, ignore = None):
870  """
871  Check that all the keys in reference are in to_check too, with the same value.
872  If the value is a dict, the function is called recursively. to_check can
873  contain more keys than reference, that will not be tested.
874  The function returns at the first difference found.
875  """
876  fail_keys = []
877  # filter the keys in the reference dictionary
878  if ignore:
879  ignore_re = re.compile(ignore)
880  keys = [ key for key in reference if not ignore_re.match(key) ]
881  else:
882  keys = reference.keys()
883  # loop over the keys (not ignored) in the reference dictionary
884  for k in keys:
885  if k in to_check: # the key must be in the dictionary to_check
886  if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
887  # if both reference and to_check values are dictionaries, recurse
888  failed = fail_keys = cmpTreesDicts(reference[k], to_check[k], ignore)
889  else:
890  # compare the two values
891  failed = to_check[k] != reference[k]
892  else: # handle missing keys in the dictionary to check (i.e. failure)
893  to_check[k] = None
894  failed = True
895  if failed:
896  fail_keys.insert(0, k)
897  break # exit from the loop at the first failure
898  return fail_keys # return the list of keys bringing to the different values
def GaudiTesting.BaseTest.findHistosSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 1027 of file BaseTest.py.

1028 def findHistosSummaries(stdout):
1029  """
1030  Scan stdout to find ROOT TTree summaries and digest them.
1031  """
1032  outlines = stdout.splitlines()
1033  nlines = len(outlines) - 1
1034  summaries = {}
1035  global h_count_re
1036 
1037  pos = 0
1038  while pos < nlines:
1039  summ = {}
1040  # find first line of block:
1041  match = h_count_re.search(outlines[pos])
1042  while pos < nlines and not match:
1043  pos += 1
1044  match = h_count_re.search(outlines[pos])
1045  if match:
1046  summ, pos = parseHistosSummary(outlines, pos)
1047  summaries.update(summ)
1048  return summaries
def GaudiTesting.BaseTest.findTTreeSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 847 of file BaseTest.py.

848 def findTTreeSummaries(stdout):
849  """
850  Scan stdout to find ROOT TTree summaries and digest them.
851  """
852  stars = re.compile(r"^\*+$")
853  outlines = stdout.splitlines()
854  nlines = len(outlines)
855  trees = {}
856 
857  i = 0
858  while i < nlines: #loop over the output
859  # look for
860  while i < nlines and not stars.match(outlines[i]):
861  i += 1
862  if i < nlines:
863  tree, i = _parseTTreeSummary(outlines, i)
864  if tree:
865  trees[tree["Name"]] = tree
866 
867  return trees
def GaudiTesting.BaseTest.getCmpFailingValues (   reference,
  to_check,
  fail_path 
)

Definition at line 899 of file BaseTest.py.

900 def getCmpFailingValues(reference, to_check, fail_path):
901  c = to_check
902  r = reference
903  for k in fail_path:
904  c = c.get(k,None)
905  r = r.get(k,None)
906  if c is None or r is None:
907  break # one of the dictionaries is not deep enough
908  return (fail_path, r, c)
909 
# signature of the print-out of the histograms
def GaudiTesting.BaseTest.GetPlatform (   self)
    Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1059 of file BaseTest.py.

1060 def GetPlatform(self):
1061  """
1062  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1063  """
1064  arch = "None"
1065  # check architecture name
1066  if "CMTCONFIG" in os.environ:
1067  arch = os.environ["CMTCONFIG"]
1068  elif "SCRAM_ARCH" in os.environ:
1069  arch = os.environ["SCRAM_ARCH"]
1070  return arch
def GaudiTesting.BaseTest.isWinPlatform (   self)
    Return True if the current platform is Windows.

    This function was needed because of the change in the CMTCONFIG format,
    from win32_vc71_dbg to i686-winxp-vc9-dbg.

Definition at line 1071 of file BaseTest.py.

1072 def isWinPlatform(self):
1073  """
1074  Return True if the current platform is Windows.
1075 
1076  This function was needed because of the change in the CMTCONFIG format,
1077  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1078  """
1079  platform = GetPlatform(self)
1080  return "winxp" in platform or platform.startswith("win")
1081 
def GaudiTesting.BaseTest.parseHistosSummary (   lines,
  pos 
)
    Extract the histograms infos from the lines starting at pos.
    Returns the position of the first line after the summary block.

Definition at line 962 of file BaseTest.py.

963 def parseHistosSummary(lines, pos):
964  """
965  Extract the histograms infos from the lines starting at pos.
966  Returns the position of the first line after the summary block.
967  """
968  global h_count_re
969  h_table_head = re.compile(r'SUCCESS\s+List of booked (1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"')
970  h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
971 
972  nlines = len(lines)
973 
974  # decode header
975  m = h_count_re.search(lines[pos])
976  name = m.group(1).strip()
977  total = int(m.group(2))
978  header = {}
979  for k, v in [ x.split("=") for x in m.group(3).split() ]:
980  header[k] = int(v)
981  pos += 1
982  header["Total"] = total
983 
984  summ = {}
985  while pos < nlines:
986  m = h_table_head.search(lines[pos])
987  if m:
988  t, d = m.groups(1) # type and directory
989  t = t.replace(" profile", "Prof")
990  pos += 1
991  if pos < nlines:
992  l = lines[pos]
993  else:
994  l = ""
995  cont = {}
996  if l.startswith(" | ID"):
997  # table format
998  titles = [ x.strip() for x in l.split("|")][1:]
999  pos += 1
1000  while pos < nlines and lines[pos].startswith(" |"):
1001  l = lines[pos]
1002  values = [ x.strip() for x in l.split("|")][1:]
1003  hcont = {}
1004  for i in range(len(titles)):
1005  hcont[titles[i]] = values[i]
1006  cont[hcont["ID"]] = hcont
1007  pos += 1
1008  elif l.startswith(" ID="):
1009  while pos < nlines and lines[pos].startswith(" ID="):
1010  values = [ x.strip() for x in h_short_summ.search(lines[pos]).groups() ]
1011  cont[values[0]] = values
1012  pos += 1
1013  else: # not interpreted
1014  raise RuntimeError("Cannot understand line %d: '%s'" % (pos, l))
1015  if not d in summ:
1016  summ[d] = {}
1017  summ[d][t] = cont
1018  summ[d]["header"] = header
1019  else:
1020  break
1021  if not summ:
1022  # If the full table is not present, we use only the header
1023  summ[name] = {"header": header}
1024  return summ, pos
1025 
1026 
def GaudiTesting.BaseTest.PlatformIsNotSupported (   self,
  context,
  result 
)

Definition at line 1049 of file BaseTest.py.

1050 def PlatformIsNotSupported(self, context, result):
1051  platform = GetPlatform(self)
1052  unsupported = [ re.compile(x) for x in [ str(y).strip() for y in unsupported_platforms ] if x]
1053  for p_re in unsupported :
1054  if p_re.search(platform):
1055  result.SetOutcome(result.UNTESTED)
1056  result[result.CAUSE] = 'Platform not supported.'
1057  return True
1058  return False
def GaudiTesting.BaseTest.RationalizePath (   p)
Function used to normalize the used path

Definition at line 507 of file BaseTest.py.

508 def RationalizePath(p) :
509  """
510  Function used to normalize the used path
511  """
512  newPath = os.path.normpath(os.path.expandvars(p))
513  if os.path.exists(newPath) :
514  p = os.path.realpath(newPath)
515  return p
516 
def GaudiTesting.BaseTest.ROOT6WorkAroundEnabled (   id = None)

Definition at line 501 of file BaseTest.py.

502  def ROOT6WorkAroundEnabled(id=None):
503  # dummy implementation
504  return False
505 
506 #--------------------------------- TOOLS ---------------------------------#
def GaudiTesting.BaseTest.sanitize_for_xml (   data)
Take a string with invalid ASCII/UTF characters and quote them so that the
string can be used in an XML text.

>>> sanitize_for_xml('this is \x1b')
'this is [NON-XML-CHAR-0x1B]'

Definition at line 16 of file BaseTest.py.

16 
17 def sanitize_for_xml(data):
18  '''
19  Take a string with invalid ASCII/UTF characters and quote them so that the
20  string can be used in an XML text.
21 
22  >>> sanitize_for_xml('this is \x1b')
23  'this is [NON-XML-CHAR-0x1B]'
24  '''
25  bad_chars = re.compile(u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]')
26  def quote(match):
27  'helper function'
28  return ''.join('[NON-XML-CHAR-0x%2X]' % ord(c) for c in match.group())
29  return bad_chars.sub(quote, data)
30 
#-------------------------------------------------------------------------#
def GaudiTesting.BaseTest.which (   executable)
Locates an executable in the executables path ($PATH) and returns the full
path to it.  An application is looked for with or without the '.exe' suffix.
If the executable cannot be found, None is returned

Definition at line 517 of file BaseTest.py.

518 def which(executable):
519  """
520  Locates an executable in the executables path ($PATH) and returns the full
521  path to it. An application is looked for with or without the '.exe' suffix.
522  If the executable cannot be found, None is returned
523  """
524  if os.path.isabs(executable):
525  if not os.path.exists(executable):
526  if executable.endswith('.exe'):
527  if os.path.exists(executable[:-4]):
528  return executable[:-4]
529  else :
530  head,executable = os.path.split(executable)
531  else :
532  return executable
533  for d in os.environ.get("PATH").split(os.pathsep):
534  fullpath = os.path.join(d, executable)
535  if os.path.exists(fullpath):
536  return fullpath
537  if executable.endswith('.exe'):
538  return which(executable[:-4])
539  return None
540 
541 
542 
543 #-------------------------------------------------------------------------#
544 #----------------------------- Result Classe -----------------------------#
#-------------------------------------------------------------------------#

Variable Documentation

tuple GaudiTesting.BaseTest.h_count_re re.compile(r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+(.*)")

Definition at line 910 of file BaseTest.py.

tuple GaudiTesting.BaseTest.lineSkipper

Definition at line 754 of file BaseTest.py.

tuple GaudiTesting.BaseTest.maskPointers RegexpReplacer("0x[0-9a-fA-F]{4,16}","0x########")

Definition at line 709 of file BaseTest.py.

tuple GaudiTesting.BaseTest.normalizeDate
Initial value:
1 RegexpReplacer("[0-2]?[0-9]:[0-5][0-9]:[0-5][0-9] [0-9]{4}[-/][01][0-9][-/][0-3][0-9][ A-Z]*",
2  "00:00:00 1970-01-01")

Definition at line 710 of file BaseTest.py.

tuple GaudiTesting.BaseTest.normalizeEOL FilePreprocessor()

Definition at line 712 of file BaseTest.py.

tuple GaudiTesting.BaseTest.normalizeExamples maskPointers+normalizeDate

Definition at line 735 of file BaseTest.py.

tuple GaudiTesting.BaseTest.skipEmptyLines FilePreprocessor()

Definition at line 715 of file BaseTest.py.