The Gaudi Framework  v28r3 (cc1cf868)
GaudiTesting.BaseTest Namespace Reference

Classes

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

Functions

def sanitize_for_xml (data)
 
def dumpProcs (name)
 
def kill_tree (ppid, sig)
 
def ROOT6WorkAroundEnabled (id=None)
 
def RationalizePath (p)
 
def which (executable)
 
def findTTreeSummaries (stdout)
 
def cmpTreesDicts (reference, to_check, ignore=None)
 
def getCmpFailingValues (reference, to_check, fail_path)
 
def _parseTTreeSummary (lines, pos)
 
def parseHistosSummary (lines, pos)
 
def findHistosSummaries (stdout)
 
def PlatformIsNotSupported (self, context, result)
 
def GetPlatform (self)
 
def isWinPlatform (self)
 

Variables

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

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 970 of file BaseTest.py.

970 def _parseTTreeSummary(lines, pos):
971  """
972  Parse the TTree summary table in lines, starting from pos.
973  Returns a tuple with the dictionary with the digested informations and the
974  position of the first line after the summary.
975  """
976  result = {}
977  i = pos + 1 # first line is a sequence of '*'
978  count = len(lines)
979 
980  splitcols = lambda l: [ f.strip() for f in l.strip("*\n").split(':',2) ]
981  def parseblock(ll):
982  r = {}
983  cols = splitcols(ll[0])
984  r["Name"], r["Title"] = cols[1:]
985 
986  cols = splitcols(ll[1])
987  r["Entries"] = int(cols[1])
988 
989  sizes = cols[2].split()
990  r["Total size"] = int(sizes[2])
991  if sizes[-1] == "memory":
992  r["File size"] = 0
993  else:
994  r["File size"] = int(sizes[-1])
995 
996  cols = splitcols(ll[2])
997  sizes = cols[2].split()
998  if cols[0] == "Baskets":
999  r["Baskets"] = int(cols[1])
1000  r["Basket size"] = int(sizes[2])
1001  r["Compression"] = float(sizes[-1])
1002  return r
1003 
1004  if i < (count - 3) and lines[i].startswith("*Tree"):
1005  result = parseblock(lines[i:i+3])
1006  result["Branches"] = {}
1007  i += 4
1008  while i < (count - 3) and lines[i].startswith("*Br"):
1009  if i < (count - 2) and lines[i].startswith("*Branch "):
1010  # skip branch header
1011  i += 3
1012  continue
1013  branch = parseblock(lines[i:i+3])
1014  result["Branches"][branch["Name"]] = branch
1015  i += 4
1016 
1017  return (result, i)
1018 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:970
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 925 of file BaseTest.py.

925 def cmpTreesDicts(reference, to_check, ignore = None):
926  """
927  Check that all the keys in reference are in to_check too, with the same value.
928  If the value is a dict, the function is called recursively. to_check can
929  contain more keys than reference, that will not be tested.
930  The function returns at the first difference found.
931  """
932  fail_keys = []
933  # filter the keys in the reference dictionary
934  if ignore:
935  ignore_re = re.compile(ignore)
936  keys = [ key for key in reference if not ignore_re.match(key) ]
937  else:
938  keys = reference.keys()
939  # loop over the keys (not ignored) in the reference dictionary
940  for k in keys:
941  if k in to_check: # the key must be in the dictionary to_check
942  if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
943  # if both reference and to_check values are dictionaries, recurse
944  failed = fail_keys = cmpTreesDicts(reference[k], to_check[k], ignore)
945  else:
946  # compare the two values
947  failed = to_check[k] != reference[k]
948  else: # handle missing keys in the dictionary to check (i.e. failure)
949  to_check[k] = None
950  failed = True
951  if failed:
952  fail_keys.insert(0, k)
953  break # exit from the loop at the first failure
954  return fail_keys # return the list of keys bringing to the different values
955 
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: BaseTest.py:925
def GaudiTesting.BaseTest.dumpProcs (   name)
helper to debug GAUDI-1084, dump the list of processes

Definition at line 30 of file BaseTest.py.

30 def dumpProcs(name):
31  '''helper to debug GAUDI-1084, dump the list of processes'''
32  from getpass import getuser
33  if 'WORKSPACE' in os.environ:
34  p = Popen(['ps', '-fH', '-U', getuser()], stdout=PIPE)
35  with open(os.path.join(os.environ['WORKSPACE'], name), 'w') as f:
36  f.write(p.communicate()[0])
37 
def dumpProcs(name)
Definition: BaseTest.py:30
def GaudiTesting.BaseTest.findHistosSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 1084 of file BaseTest.py.

1085  """
1086  Scan stdout to find ROOT TTree summaries and digest them.
1087  """
1088  outlines = stdout.splitlines()
1089  nlines = len(outlines) - 1
1090  summaries = {}
1091  global h_count_re
1092 
1093  pos = 0
1094  while pos < nlines:
1095  summ = {}
1096  # find first line of block:
1097  match = h_count_re.search(outlines[pos])
1098  while pos < nlines and not match:
1099  pos += 1
1100  match = h_count_re.search(outlines[pos])
1101  if match:
1102  summ, pos = parseHistosSummary(outlines, pos)
1103  summaries.update(summ)
1104  return summaries
1105 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1084
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1019
def GaudiTesting.BaseTest.findTTreeSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 904 of file BaseTest.py.

904 def findTTreeSummaries(stdout):
905  """
906  Scan stdout to find ROOT TTree summaries and digest them.
907  """
908  stars = re.compile(r"^\*+$")
909  outlines = stdout.splitlines()
910  nlines = len(outlines)
911  trees = {}
912 
913  i = 0
914  while i < nlines: #loop over the output
915  # look for
916  while i < nlines and not stars.match(outlines[i]):
917  i += 1
918  if i < nlines:
919  tree, i = _parseTTreeSummary(outlines, i)
920  if tree:
921  trees[tree["Name"]] = tree
922 
923  return trees
924 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:970
def findTTreeSummaries(stdout)
Definition: BaseTest.py:904
def GaudiTesting.BaseTest.getCmpFailingValues (   reference,
  to_check,
  fail_path 
)

Definition at line 956 of file BaseTest.py.

956 def getCmpFailingValues(reference, to_check, fail_path):
957  c = to_check
958  r = reference
959  for k in fail_path:
960  c = c.get(k,None)
961  r = r.get(k,None)
962  if c is None or r is None:
963  break # one of the dictionaries is not deep enough
964  return (fail_path, r, c)
965 
966 # signature of the print-out of the histograms
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:956
def GaudiTesting.BaseTest.GetPlatform (   self)
    Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1116 of file BaseTest.py.

1116 def GetPlatform(self):
1117  """
1118  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1119  """
1120  arch = "None"
1121  # check architecture name
1122  if "BINARY_TAG" in os.environ:
1123  arch = os.environ["BINARY_TAG"]
1124  elif "CMTCONFIG" in os.environ:
1125  arch = os.environ["CMTCONFIG"]
1126  elif "SCRAM_ARCH" in os.environ:
1127  arch = os.environ["SCRAM_ARCH"]
1128  return arch
1129 
def GetPlatform(self)
Definition: BaseTest.py:1116
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 1130 of file BaseTest.py.

1130 def isWinPlatform(self):
1131  """
1132  Return True if the current platform is Windows.
1133 
1134  This function was needed because of the change in the CMTCONFIG format,
1135  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1136  """
1137  platform = GetPlatform(self)
1138  return "winxp" in platform or platform.startswith("win")
1139 
def GetPlatform(self)
Definition: BaseTest.py:1116
def isWinPlatform(self)
Definition: BaseTest.py:1130
def GaudiTesting.BaseTest.kill_tree (   ppid,
  sig 
)
Send a signal to a process and all its child processes (starting from the
leaves).

Definition at line 38 of file BaseTest.py.

38 def kill_tree(ppid, sig):
39  '''
40  Send a signal to a process and all its child processes (starting from the
41  leaves).
42  '''
43  log = logging.getLogger('kill_tree')
44  ps_cmd = ['ps', '--no-headers', '-o', 'pid', '--ppid', str(ppid)]
45  get_children = Popen(ps_cmd, stdout=PIPE, stderr=PIPE)
46  children = map(int, get_children.communicate()[0].split())
47  for child in children:
48  kill_tree(child, sig)
49  try:
50  log.debug('killing process %d', ppid)
51  os.kill(ppid, sig)
52  except OSError, err:
53  if err.errno != 3: # No such process
54  raise
55  log.debug('no such process %d', ppid)
56 
57 #-------------------------------------------------------------------------#
struct GAUDI_API map
Parametrisation class for map-like implementation.
def kill_tree(ppid, sig)
Definition: BaseTest.py:38
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 1019 of file BaseTest.py.

1019 def parseHistosSummary(lines, pos):
1020  """
1021  Extract the histograms infos from the lines starting at pos.
1022  Returns the position of the first line after the summary block.
1023  """
1024  global h_count_re
1025  h_table_head = re.compile(r'SUCCESS\s+List of booked (1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"')
1026  h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
1027 
1028  nlines = len(lines)
1029 
1030  # decode header
1031  m = h_count_re.search(lines[pos])
1032  name = m.group(1).strip()
1033  total = int(m.group(2))
1034  header = {}
1035  for k, v in [ x.split("=") for x in m.group(3).split() ]:
1036  header[k] = int(v)
1037  pos += 1
1038  header["Total"] = total
1039 
1040  summ = {}
1041  while pos < nlines:
1042  m = h_table_head.search(lines[pos])
1043  if m:
1044  t, d = m.groups(1) # type and directory
1045  t = t.replace(" profile", "Prof")
1046  pos += 1
1047  if pos < nlines:
1048  l = lines[pos]
1049  else:
1050  l = ""
1051  cont = {}
1052  if l.startswith(" | ID"):
1053  # table format
1054  titles = [ x.strip() for x in l.split("|")][1:]
1055  pos += 1
1056  while pos < nlines and lines[pos].startswith(" |"):
1057  l = lines[pos]
1058  values = [ x.strip() for x in l.split("|")][1:]
1059  hcont = {}
1060  for i in range(len(titles)):
1061  hcont[titles[i]] = values[i]
1062  cont[hcont["ID"]] = hcont
1063  pos += 1
1064  elif l.startswith(" ID="):
1065  while pos < nlines and lines[pos].startswith(" ID="):
1066  values = [ x.strip() for x in h_short_summ.search(lines[pos]).groups() ]
1067  cont[values[0]] = values
1068  pos += 1
1069  else: # not interpreted
1070  raise RuntimeError("Cannot understand line %d: '%s'" % (pos, l))
1071  if not d in summ:
1072  summ[d] = {}
1073  summ[d][t] = cont
1074  summ[d]["header"] = header
1075  else:
1076  break
1077  if not summ:
1078  # If the full table is not present, we use only the header
1079  summ[name] = {"header": header}
1080  return summ, pos
1081 
1082 
1083 
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1019
def GaudiTesting.BaseTest.PlatformIsNotSupported (   self,
  context,
  result 
)

Definition at line 1106 of file BaseTest.py.

1106 def PlatformIsNotSupported(self, context, result):
1107  platform = GetPlatform(self)
1108  unsupported = [ re.compile(x) for x in [ str(y).strip() for y in unsupported_platforms ] if x]
1109  for p_re in unsupported :
1110  if p_re.search(platform):
1111  result.SetOutcome(result.UNTESTED)
1112  result[result.CAUSE] = 'Platform not supported.'
1113  return True
1114  return False
1115 
def GetPlatform(self)
Definition: BaseTest.py:1116
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1106
def GaudiTesting.BaseTest.RationalizePath (   p)
Function used to normalize the used path

Definition at line 525 of file BaseTest.py.

526  """
527  Function used to normalize the used path
528  """
529  newPath = os.path.normpath(os.path.expandvars(p))
530  if os.path.exists(newPath) :
531  p = os.path.realpath(newPath)
532  return p
533 
534 
def GaudiTesting.BaseTest.ROOT6WorkAroundEnabled (   id = None)

Definition at line 519 of file BaseTest.py.

520  # dummy implementation
521  return False
522 
523 #--------------------------------- TOOLS ---------------------------------#
524 
def ROOT6WorkAroundEnabled(id=None)
Definition: BaseTest.py:519
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 def sanitize_for_xml(data):
17  '''
18  Take a string with invalid ASCII/UTF characters and quote them so that the
19  string can be used in an XML text.
20 
21  >>> sanitize_for_xml('this is \x1b')
22  'this is [NON-XML-CHAR-0x1B]'
23  '''
24  bad_chars = re.compile(u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]')
25  def quote(match):
26  'helper function'
27  return ''.join('[NON-XML-CHAR-0x%2X]' % ord(c) for c in match.group())
28  return bad_chars.sub(quote, data)
29 
def sanitize_for_xml(data)
Definition: BaseTest.py:16
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 535 of file BaseTest.py.

535 def which(executable):
536  """
537  Locates an executable in the executables path ($PATH) and returns the full
538  path to it. An application is looked for with or without the '.exe' suffix.
539  If the executable cannot be found, None is returned
540  """
541  if os.path.isabs(executable):
542  if not os.path.exists(executable):
543  if executable.endswith('.exe'):
544  if os.path.exists(executable[:-4]):
545  return executable[:-4]
546  else :
547  head,executable = os.path.split(executable)
548  else :
549  return executable
550  for d in os.environ.get("PATH").split(os.pathsep):
551  fullpath = os.path.join(d, executable)
552  if os.path.exists(fullpath):
553  return fullpath
554  if executable.endswith('.exe'):
555  return which(executable[:-4])
556  return None
557 
558 
559 
560 #-------------------------------------------------------------------------#
561 #----------------------------- Result Classe -----------------------------#
562 #-------------------------------------------------------------------------#
def which(executable)
Definition: BaseTest.py:535

Variable Documentation

GaudiTesting.BaseTest.__processLine__
private

Definition at line 734 of file BaseTest.py.

GaudiTesting.BaseTest.h_count_re = re.compile(r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+([\s\w=-]*)")

Definition at line 967 of file BaseTest.py.

GaudiTesting.BaseTest.lineSkipper

Definition at line 797 of file BaseTest.py.

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

Definition at line 730 of file BaseTest.py.

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 731 of file BaseTest.py.

GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 733 of file BaseTest.py.

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers+normalizeDate

Definition at line 777 of file BaseTest.py.

GaudiTesting.BaseTest.regexps

Definition at line 860 of file BaseTest.py.

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 736 of file BaseTest.py.