Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v29r5 (37229091)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 1050 of file BaseTest.py.

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

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

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

Definition at line 979 of file BaseTest.py.

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

Definition at line 1034 of file BaseTest.py.

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

Definition at line 1203 of file BaseTest.py.

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

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

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

Definition at line 1191 of file BaseTest.py.

1191 def PlatformIsNotSupported(self, context, result):
1192  platform = GetPlatform(self)
1193  unsupported = [re.compile(x) for x in [str(y).strip()
1194  for y in unsupported_platforms] if x]
1195  for p_re in unsupported:
1196  if p_re.search(platform):
1197  result.SetOutcome(result.UNTESTED)
1198  result[result.CAUSE] = 'Platform not supported.'
1199  return True
1200  return False
1201 
1202 
def GetPlatform(self)
Definition: BaseTest.py:1203
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1191
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 1046 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 932 of file BaseTest.py.

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 788 of file BaseTest.py.