The Gaudi Framework  v29r0 (ff2e7097)
GaudiTesting.BaseTest Namespace Reference

Classes

class  BaseTest
 
class  BasicOutputValidator
 
class  BlockSkipper
 
class  FilePreprocessor
 
class  FilePreprocessorSequence
 
class  LineSkipper
 
class  LineSorter
 
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
 

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

1048 def _parseTTreeSummary(lines, pos):
1049  """
1050  Parse the TTree summary table in lines, starting from pos.
1051  Returns a tuple with the dictionary with the digested informations and the
1052  position of the first line after the summary.
1053  """
1054  result = {}
1055  i = pos + 1 # first line is a sequence of '*'
1056  count = len(lines)
1057 
1058  def splitcols(l): return [f.strip() for f in l.strip("*\n").split(':', 2)]
1059 
1060  def parseblock(ll):
1061  r = {}
1062  cols = splitcols(ll[0])
1063  r["Name"], r["Title"] = cols[1:]
1064 
1065  cols = splitcols(ll[1])
1066  r["Entries"] = int(cols[1])
1067 
1068  sizes = cols[2].split()
1069  r["Total size"] = int(sizes[2])
1070  if sizes[-1] == "memory":
1071  r["File size"] = 0
1072  else:
1073  r["File size"] = int(sizes[-1])
1074 
1075  cols = splitcols(ll[2])
1076  sizes = cols[2].split()
1077  if cols[0] == "Baskets":
1078  r["Baskets"] = int(cols[1])
1079  r["Basket size"] = int(sizes[2])
1080  r["Compression"] = float(sizes[-1])
1081  return r
1082 
1083  if i < (count - 3) and lines[i].startswith("*Tree"):
1084  result = parseblock(lines[i:i + 3])
1085  result["Branches"] = {}
1086  i += 4
1087  while i < (count - 3) and lines[i].startswith("*Br"):
1088  if i < (count - 2) and lines[i].startswith("*Branch "):
1089  # skip branch header
1090  i += 3
1091  continue
1092  branch = parseblock(lines[i:i + 3])
1093  result["Branches"][branch["Name"]] = branch
1094  i += 4
1095 
1096  return (result, i)
1097 
1098 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:1048
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 999 of file BaseTest.py.

999 def cmpTreesDicts(reference, to_check, ignore=None):
1000  """
1001  Check that all the keys in reference are in to_check too, with the same value.
1002  If the value is a dict, the function is called recursively. to_check can
1003  contain more keys than reference, that will not be tested.
1004  The function returns at the first difference found.
1005  """
1006  fail_keys = []
1007  # filter the keys in the reference dictionary
1008  if ignore:
1009  ignore_re = re.compile(ignore)
1010  keys = [key for key in reference if not ignore_re.match(key)]
1011  else:
1012  keys = reference.keys()
1013  # loop over the keys (not ignored) in the reference dictionary
1014  for k in keys:
1015  if k in to_check: # the key must be in the dictionary to_check
1016  if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
1017  # if both reference and to_check values are dictionaries, recurse
1018  failed = fail_keys = cmpTreesDicts(
1019  reference[k], to_check[k], ignore)
1020  else:
1021  # compare the two values
1022  failed = to_check[k] != reference[k]
1023  else: # handle missing keys in the dictionary to check (i.e. failure)
1024  to_check[k] = None
1025  failed = True
1026  if failed:
1027  fail_keys.insert(0, k)
1028  break # exit from the loop at the first failure
1029  return fail_keys # return the list of keys bringing to the different values
1030 
1031 
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: BaseTest.py:999
def GaudiTesting.BaseTest.dumpProcs (   name)
helper to debug GAUDI-1084, dump the list of processes

Definition at line 34 of file BaseTest.py.

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

Definition at line 1166 of file BaseTest.py.

1167  """
1168  Scan stdout to find ROOT TTree summaries and digest them.
1169  """
1170  outlines = stdout.splitlines()
1171  nlines = len(outlines) - 1
1172  summaries = {}
1173  global h_count_re
1174 
1175  pos = 0
1176  while pos < nlines:
1177  summ = {}
1178  # find first line of block:
1179  match = h_count_re.search(outlines[pos])
1180  while pos < nlines and not match:
1181  pos += 1
1182  match = h_count_re.search(outlines[pos])
1183  if match:
1184  summ, pos = parseHistosSummary(outlines, pos)
1185  summaries.update(summ)
1186  return summaries
1187 
1188 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1166
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1099
def GaudiTesting.BaseTest.findTTreeSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 977 of file BaseTest.py.

977 def findTTreeSummaries(stdout):
978  """
979  Scan stdout to find ROOT TTree summaries and digest them.
980  """
981  stars = re.compile(r"^\*+$")
982  outlines = stdout.splitlines()
983  nlines = len(outlines)
984  trees = {}
985 
986  i = 0
987  while i < nlines: # loop over the output
988  # look for
989  while i < nlines and not stars.match(outlines[i]):
990  i += 1
991  if i < nlines:
992  tree, i = _parseTTreeSummary(outlines, i)
993  if tree:
994  trees[tree["Name"]] = tree
995 
996  return trees
997 
998 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:1048
def findTTreeSummaries(stdout)
Definition: BaseTest.py:977
def GaudiTesting.BaseTest.getCmpFailingValues (   reference,
  to_check,
  fail_path 
)

Definition at line 1032 of file BaseTest.py.

1032 def getCmpFailingValues(reference, to_check, fail_path):
1033  c = to_check
1034  r = reference
1035  for k in fail_path:
1036  c = c.get(k, None)
1037  r = r.get(k, None)
1038  if c is None or r is None:
1039  break # one of the dictionaries is not deep enough
1040  return (fail_path, r, c)
1041 
1042 
1043 # signature of the print-out of the histograms
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:1032
def GaudiTesting.BaseTest.GetPlatform (   self)
    Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1201 of file BaseTest.py.

1201 def GetPlatform(self):
1202  """
1203  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1204  """
1205  arch = "None"
1206  # check architecture name
1207  if "BINARY_TAG" in os.environ:
1208  arch = os.environ["BINARY_TAG"]
1209  elif "CMTCONFIG" in os.environ:
1210  arch = os.environ["CMTCONFIG"]
1211  elif "SCRAM_ARCH" in os.environ:
1212  arch = os.environ["SCRAM_ARCH"]
1213  return arch
1214 
1215 
def GetPlatform(self)
Definition: BaseTest.py:1201
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 1216 of file BaseTest.py.

1216 def isWinPlatform(self):
1217  """
1218  Return True if the current platform is Windows.
1219 
1220  This function was needed because of the change in the CMTCONFIG format,
1221  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1222  """
1223  platform = GetPlatform(self)
1224  return "winxp" in platform or platform.startswith("win")
1225 
def GetPlatform(self)
Definition: BaseTest.py:1201
def isWinPlatform(self)
Definition: BaseTest.py:1216
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 43 of file BaseTest.py.

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

1099 def parseHistosSummary(lines, pos):
1100  """
1101  Extract the histograms infos from the lines starting at pos.
1102  Returns the position of the first line after the summary block.
1103  """
1104  global h_count_re
1105  h_table_head = re.compile(
1106  r'SUCCESS\s+List of booked (1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"')
1107  h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
1108 
1109  nlines = len(lines)
1110 
1111  # decode header
1112  m = h_count_re.search(lines[pos])
1113  name = m.group(1).strip()
1114  total = int(m.group(2))
1115  header = {}
1116  for k, v in [x.split("=") for x in m.group(3).split()]:
1117  header[k] = int(v)
1118  pos += 1
1119  header["Total"] = total
1120 
1121  summ = {}
1122  while pos < nlines:
1123  m = h_table_head.search(lines[pos])
1124  if m:
1125  t, d = m.groups(1) # type and directory
1126  t = t.replace(" profile", "Prof")
1127  pos += 1
1128  if pos < nlines:
1129  l = lines[pos]
1130  else:
1131  l = ""
1132  cont = {}
1133  if l.startswith(" | ID"):
1134  # table format
1135  titles = [x.strip() for x in l.split("|")][1:]
1136  pos += 1
1137  while pos < nlines and lines[pos].startswith(" |"):
1138  l = lines[pos]
1139  values = [x.strip() for x in l.split("|")][1:]
1140  hcont = {}
1141  for i in range(len(titles)):
1142  hcont[titles[i]] = values[i]
1143  cont[hcont["ID"]] = hcont
1144  pos += 1
1145  elif l.startswith(" ID="):
1146  while pos < nlines and lines[pos].startswith(" ID="):
1147  values = [x.strip()
1148  for x in h_short_summ.search(lines[pos]).groups()]
1149  cont[values[0]] = values
1150  pos += 1
1151  else: # not interpreted
1152  raise RuntimeError(
1153  "Cannot understand line %d: '%s'" % (pos, l))
1154  if not d in summ:
1155  summ[d] = {}
1156  summ[d][t] = cont
1157  summ[d]["header"] = header
1158  else:
1159  break
1160  if not summ:
1161  # If the full table is not present, we use only the header
1162  summ[name] = {"header": header}
1163  return summ, pos
1164 
1165 
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1099
def GaudiTesting.BaseTest.PlatformIsNotSupported (   self,
  context,
  result 
)

Definition at line 1189 of file BaseTest.py.

1189 def PlatformIsNotSupported(self, context, result):
1190  platform = GetPlatform(self)
1191  unsupported = [re.compile(x) for x in [str(y).strip()
1192  for y in unsupported_platforms] if x]
1193  for p_re in unsupported:
1194  if p_re.search(platform):
1195  result.SetOutcome(result.UNTESTED)
1196  result[result.CAUSE] = 'Platform not supported.'
1197  return True
1198  return False
1199 
1200 
def GetPlatform(self)
Definition: BaseTest.py:1201
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1189
def GaudiTesting.BaseTest.RationalizePath (   p)
Function used to normalize the used path

Definition at line 560 of file BaseTest.py.

561  """
562  Function used to normalize the used path
563  """
564  newPath = os.path.normpath(os.path.expandvars(p))
565  if os.path.exists(newPath):
566  p = os.path.realpath(newPath)
567  return p
568 
569 
def GaudiTesting.BaseTest.ROOT6WorkAroundEnabled (   id = None)

Definition at line 553 of file BaseTest.py.

554  # dummy implementation
555  return False
556 
557 #--------------------------------- TOOLS ---------------------------------#
558 
559 
def ROOT6WorkAroundEnabled(id=None)
Definition: BaseTest.py:553
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 17 of file BaseTest.py.

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(
26  u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]')
27 
28  def quote(match):
29  'helper function'
30  return ''.join('[NON-XML-CHAR-0x%2X]' % ord(c) for c in match.group())
31  return bad_chars.sub(quote, data)
32 
33 
def sanitize_for_xml(data)
Definition: BaseTest.py:17
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 570 of file BaseTest.py.

570 def which(executable):
571  """
572  Locates an executable in the executables path ($PATH) and returns the full
573  path to it. An application is looked for with or without the '.exe' suffix.
574  If the executable cannot be found, None is returned
575  """
576  if os.path.isabs(executable):
577  if not os.path.exists(executable):
578  if executable.endswith('.exe'):
579  if os.path.exists(executable[:-4]):
580  return executable[:-4]
581  else:
582  head, executable = os.path.split(executable)
583  else:
584  return executable
585  for d in os.environ.get("PATH").split(os.pathsep):
586  fullpath = os.path.join(d, executable)
587  if os.path.exists(fullpath):
588  return fullpath
589  if executable.endswith('.exe'):
590  return which(executable[:-4])
591  return None
592 
593 
594 
595 #-------------------------------------------------------------------------#
596 #----------------------------- Result Classe -----------------------------#
597 #-------------------------------------------------------------------------#
def which(executable)
Definition: BaseTest.py:570

Variable Documentation

GaudiTesting.BaseTest.__processLine__
private

Definition at line 786 of file BaseTest.py.

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

Definition at line 1044 of file BaseTest.py.

GaudiTesting.BaseTest.lineSkipper

Definition at line 860 of file BaseTest.py.

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

Definition at line 782 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 783 of file BaseTest.py.

GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 785 of file BaseTest.py.

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers+normalizeDate

Definition at line 836 of file BaseTest.py.

GaudiTesting.BaseTest.regexps

Definition at line 930 of file BaseTest.py.

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 788 of file BaseTest.py.