The Gaudi Framework  v30r0 (c919700c)
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 1071 of file BaseTest.py.

1071 def _parseTTreeSummary(lines, pos):
1072  """
1073  Parse the TTree summary table in lines, starting from pos.
1074  Returns a tuple with the dictionary with the digested informations and the
1075  position of the first line after the summary.
1076  """
1077  result = {}
1078  i = pos + 1 # first line is a sequence of '*'
1079  count = len(lines)
1080 
1081  def splitcols(l): return [f.strip() for f in l.strip("*\n").split(':', 2)]
1082 
1083  def parseblock(ll):
1084  r = {}
1085  cols = splitcols(ll[0])
1086  r["Name"], r["Title"] = cols[1:]
1087 
1088  cols = splitcols(ll[1])
1089  r["Entries"] = int(cols[1])
1090 
1091  sizes = cols[2].split()
1092  r["Total size"] = int(sizes[2])
1093  if sizes[-1] == "memory":
1094  r["File size"] = 0
1095  else:
1096  r["File size"] = int(sizes[-1])
1097 
1098  cols = splitcols(ll[2])
1099  sizes = cols[2].split()
1100  if cols[0] == "Baskets":
1101  r["Baskets"] = int(cols[1])
1102  r["Basket size"] = int(sizes[2])
1103  r["Compression"] = float(sizes[-1])
1104  return r
1105 
1106  if i < (count - 3) and lines[i].startswith("*Tree"):
1107  result = parseblock(lines[i:i + 3])
1108  result["Branches"] = {}
1109  i += 4
1110  while i < (count - 3) and lines[i].startswith("*Br"):
1111  if i < (count - 2) and lines[i].startswith("*Branch "):
1112  # skip branch header
1113  i += 3
1114  continue
1115  branch = parseblock(lines[i:i + 3])
1116  result["Branches"][branch["Name"]] = branch
1117  i += 4
1118 
1119  return (result, i)
1120 
1121 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:1071
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 1021 of file BaseTest.py.

1021 def cmpTreesDicts(reference, to_check, ignore=None):
1022  """
1023  Check that all the keys in reference are in to_check too, with the same value.
1024  If the value is a dict, the function is called recursively. to_check can
1025  contain more keys than reference, that will not be tested.
1026  The function returns at the first difference found.
1027  """
1028  fail_keys = []
1029  # filter the keys in the reference dictionary
1030  if ignore:
1031  ignore_re = re.compile(ignore)
1032  keys = [key for key in reference if not ignore_re.match(key)]
1033  else:
1034  keys = reference.keys()
1035  # loop over the keys (not ignored) in the reference dictionary
1036  for k in keys:
1037  if k in to_check: # the key must be in the dictionary to_check
1038  if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
1039  # if both reference and to_check values are dictionaries,
1040  # recurse
1041  failed = fail_keys = cmpTreesDicts(
1042  reference[k], to_check[k], ignore)
1043  else:
1044  # compare the two values
1045  failed = to_check[k] != reference[k]
1046  else: # handle missing keys in the dictionary to check (i.e. failure)
1047  to_check[k] = None
1048  failed = True
1049  if failed:
1050  fail_keys.insert(0, k)
1051  break # exit from the loop at the first failure
1052  return fail_keys # return the list of keys bringing to the different values
1053 
1054 
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: BaseTest.py:1021
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 1189 of file BaseTest.py.

1190  """
1191  Scan stdout to find ROOT TTree summaries and digest them.
1192  """
1193  outlines = stdout.splitlines()
1194  nlines = len(outlines) - 1
1195  summaries = {}
1196  global h_count_re
1197 
1198  pos = 0
1199  while pos < nlines:
1200  summ = {}
1201  # find first line of block:
1202  match = h_count_re.search(outlines[pos])
1203  while pos < nlines and not match:
1204  pos += 1
1205  match = h_count_re.search(outlines[pos])
1206  if match:
1207  summ, pos = parseHistosSummary(outlines, pos)
1208  summaries.update(summ)
1209  return summaries
1210 
1211 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1189
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1122
def GaudiTesting.BaseTest.findTTreeSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 999 of file BaseTest.py.

999 def findTTreeSummaries(stdout):
1000  """
1001  Scan stdout to find ROOT TTree summaries and digest them.
1002  """
1003  stars = re.compile(r"^\*+$")
1004  outlines = stdout.splitlines()
1005  nlines = len(outlines)
1006  trees = {}
1007 
1008  i = 0
1009  while i < nlines: # loop over the output
1010  # look for
1011  while i < nlines and not stars.match(outlines[i]):
1012  i += 1
1013  if i < nlines:
1014  tree, i = _parseTTreeSummary(outlines, i)
1015  if tree:
1016  trees[tree["Name"]] = tree
1017 
1018  return trees
1019 
1020 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:1071
def findTTreeSummaries(stdout)
Definition: BaseTest.py:999
def GaudiTesting.BaseTest.getCmpFailingValues (   reference,
  to_check,
  fail_path 
)

Definition at line 1055 of file BaseTest.py.

1055 def getCmpFailingValues(reference, to_check, fail_path):
1056  c = to_check
1057  r = reference
1058  for k in fail_path:
1059  c = c.get(k, None)
1060  r = r.get(k, None)
1061  if c is None or r is None:
1062  break # one of the dictionaries is not deep enough
1063  return (fail_path, r, c)
1064 
1065 
1066 # signature of the print-out of the histograms
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:1055
def GaudiTesting.BaseTest.GetPlatform (   self)
    Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1224 of file BaseTest.py.

1224 def GetPlatform(self):
1225  """
1226  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1227  """
1228  arch = "None"
1229  # check architecture name
1230  if "BINARY_TAG" in os.environ:
1231  arch = os.environ["BINARY_TAG"]
1232  elif "CMTCONFIG" in os.environ:
1233  arch = os.environ["CMTCONFIG"]
1234  elif "SCRAM_ARCH" in os.environ:
1235  arch = os.environ["SCRAM_ARCH"]
1236  return arch
1237 
1238 
def GetPlatform(self)
Definition: BaseTest.py:1224
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 1239 of file BaseTest.py.

1239 def isWinPlatform(self):
1240  """
1241  Return True if the current platform is Windows.
1242 
1243  This function was needed because of the change in the CMTCONFIG format,
1244  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1245  """
1246  platform = GetPlatform(self)
1247  return "winxp" in platform or platform.startswith("win")
1248 
def GetPlatform(self)
Definition: BaseTest.py:1224
def isWinPlatform(self)
Definition: BaseTest.py:1239
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 1122 of file BaseTest.py.

1122 def parseHistosSummary(lines, pos):
1123  """
1124  Extract the histograms infos from the lines starting at pos.
1125  Returns the position of the first line after the summary block.
1126  """
1127  global h_count_re
1128  h_table_head = re.compile(
1129  r'SUCCESS\s+List of booked (1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"')
1130  h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
1131 
1132  nlines = len(lines)
1133 
1134  # decode header
1135  m = h_count_re.search(lines[pos])
1136  name = m.group(1).strip()
1137  total = int(m.group(2))
1138  header = {}
1139  for k, v in [x.split("=") for x in m.group(3).split()]:
1140  header[k] = int(v)
1141  pos += 1
1142  header["Total"] = total
1143 
1144  summ = {}
1145  while pos < nlines:
1146  m = h_table_head.search(lines[pos])
1147  if m:
1148  t, d = m.groups(1) # type and directory
1149  t = t.replace(" profile", "Prof")
1150  pos += 1
1151  if pos < nlines:
1152  l = lines[pos]
1153  else:
1154  l = ""
1155  cont = {}
1156  if l.startswith(" | ID"):
1157  # table format
1158  titles = [x.strip() for x in l.split("|")][1:]
1159  pos += 1
1160  while pos < nlines and lines[pos].startswith(" |"):
1161  l = lines[pos]
1162  values = [x.strip() for x in l.split("|")][1:]
1163  hcont = {}
1164  for i in range(len(titles)):
1165  hcont[titles[i]] = values[i]
1166  cont[hcont["ID"]] = hcont
1167  pos += 1
1168  elif l.startswith(" ID="):
1169  while pos < nlines and lines[pos].startswith(" ID="):
1170  values = [x.strip()
1171  for x in h_short_summ.search(lines[pos]).groups()]
1172  cont[values[0]] = values
1173  pos += 1
1174  else: # not interpreted
1175  raise RuntimeError(
1176  "Cannot understand line %d: '%s'" % (pos, l))
1177  if not d in summ:
1178  summ[d] = {}
1179  summ[d][t] = cont
1180  summ[d]["header"] = header
1181  else:
1182  break
1183  if not summ:
1184  # If the full table is not present, we use only the header
1185  summ[name] = {"header": header}
1186  return summ, pos
1187 
1188 
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1122
def GaudiTesting.BaseTest.PlatformIsNotSupported (   self,
  context,
  result 
)

Definition at line 1212 of file BaseTest.py.

1212 def PlatformIsNotSupported(self, context, result):
1213  platform = GetPlatform(self)
1214  unsupported = [re.compile(x) for x in [str(y).strip()
1215  for y in unsupported_platforms] if x]
1216  for p_re in unsupported:
1217  if p_re.search(platform):
1218  result.SetOutcome(result.UNTESTED)
1219  result[result.CAUSE] = 'Platform not supported.'
1220  return True
1221  return False
1222 
1223 
def GetPlatform(self)
Definition: BaseTest.py:1224
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1212
def GaudiTesting.BaseTest.RationalizePath (   p)
Function used to normalize the used path

Definition at line 561 of file BaseTest.py.

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

Definition at line 554 of file BaseTest.py.

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

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

Variable Documentation

GaudiTesting.BaseTest.__processLine__
private

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

GaudiTesting.BaseTest.lineSkipper

Definition at line 872 of file BaseTest.py.

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

Definition at line 790 of file BaseTest.py.

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

Definition at line 791 of file BaseTest.py.

GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 794 of file BaseTest.py.

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers+normalizeDate

Definition at line 847 of file BaseTest.py.

GaudiTesting.BaseTest.regexps

Definition at line 951 of file BaseTest.py.

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 797 of file BaseTest.py.