The Gaudi Framework  v30r3 (a5ef0a68)
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 1072 of file BaseTest.py.

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

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

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

Definition at line 1000 of file BaseTest.py.

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

Definition at line 1056 of file BaseTest.py.

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

Definition at line 1225 of file BaseTest.py.

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

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

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

Definition at line 1213 of file BaseTest.py.

1213 def PlatformIsNotSupported(self, context, result):
1214  platform = GetPlatform(self)
1215  unsupported = [re.compile(x) for x in [str(y).strip()
1216  for y in unsupported_platforms] if x]
1217  for p_re in unsupported:
1218  if p_re.search(platform):
1219  result.SetOutcome(result.UNTESTED)
1220  result[result.CAUSE] = 'Platform not supported.'
1221  return True
1222  return False
1223 
1224 
def GetPlatform(self)
Definition: BaseTest.py:1225
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1213
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 1068 of file BaseTest.py.

GaudiTesting.BaseTest.lineSkipper

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

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 797 of file BaseTest.py.