The Gaudi Framework  v36r1 (3e2fb5a8)
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 _new_backslashreplace_errors (exc)
 
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 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

◆ _new_backslashreplace_errors()

def GaudiTesting.BaseTest._new_backslashreplace_errors (   exc)
private

Definition at line 38 of file BaseTest.py.

39  if isinstance(exc, UnicodeDecodeError):
40  code = hex(ord(exc.object[exc.start]))
41  return (u'\\' + code[1:], exc.start + 1)
42  else:
43  return backslashreplace_errors(exc)
44 

◆ _parseTTreeSummary()

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

1191 def _parseTTreeSummary(lines, pos):
1192  """
1193  Parse the TTree summary table in lines, starting from pos.
1194  Returns a tuple with the dictionary with the digested informations and the
1195  position of the first line after the summary.
1196  """
1197  result = {}
1198  i = pos + 1 # first line is a sequence of '*'
1199  count = len(lines)
1200 
1201  def splitcols(l):
1202  return [f.strip() for f in l.strip("*\n").split(':', 2)]
1203 
1204  def parseblock(ll):
1205  r = {}
1206  cols = splitcols(ll[0])
1207  r["Name"], r["Title"] = cols[1:]
1208 
1209  cols = splitcols(ll[1])
1210  r["Entries"] = int(cols[1])
1211 
1212  sizes = cols[2].split()
1213  r["Total size"] = int(sizes[2])
1214  if sizes[-1] == "memory":
1215  r["File size"] = 0
1216  else:
1217  r["File size"] = int(sizes[-1])
1218 
1219  cols = splitcols(ll[2])
1220  sizes = cols[2].split()
1221  if cols[0] == "Baskets":
1222  r["Baskets"] = int(cols[1])
1223  r["Basket size"] = int(sizes[2])
1224  r["Compression"] = float(sizes[-1])
1225  return r
1226 
1227  if i < (count - 3) and lines[i].startswith("*Tree"):
1228  result = parseblock(lines[i:i + 3])
1229  result["Branches"] = {}
1230  i += 4
1231  while i < (count - 3) and lines[i].startswith("*Br"):
1232  if i < (count - 2) and lines[i].startswith("*Branch "):
1233  # skip branch header
1234  i += 3
1235  continue
1236  branch = parseblock(lines[i:i + 3])
1237  result["Branches"][branch["Name"]] = branch
1238  i += 4
1239 
1240  return (result, i)
1241 
1242 

◆ cmpTreesDicts()

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

1141 def cmpTreesDicts(reference, to_check, ignore=None):
1142  """
1143  Check that all the keys in reference are in to_check too, with the same value.
1144  If the value is a dict, the function is called recursively. to_check can
1145  contain more keys than reference, that will not be tested.
1146  The function returns at the first difference found.
1147  """
1148  fail_keys = []
1149  # filter the keys in the reference dictionary
1150  if ignore:
1151  ignore_re = re.compile(ignore)
1152  keys = [key for key in reference if not ignore_re.match(key)]
1153  else:
1154  keys = reference.keys()
1155  # loop over the keys (not ignored) in the reference dictionary
1156  for k in keys:
1157  if k in to_check: # the key must be in the dictionary to_check
1158  if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
1159  # if both reference and to_check values are dictionaries,
1160  # recurse
1161  failed = fail_keys = cmpTreesDicts(reference[k], to_check[k],
1162  ignore)
1163  else:
1164  # compare the two values
1165  failed = to_check[k] != reference[k]
1166  else: # handle missing keys in the dictionary to check (i.e. failure)
1167  to_check[k] = None
1168  failed = True
1169  if failed:
1170  fail_keys.insert(0, k)
1171  break # exit from the loop at the first failure
1172  return fail_keys # return the list of keys bringing to the different values
1173 
1174 

◆ dumpProcs()

def GaudiTesting.BaseTest.dumpProcs (   name)
helper to debug GAUDI-1084, dump the list of processes

Definition at line 69 of file BaseTest.py.

69 def dumpProcs(name):
70  '''helper to debug GAUDI-1084, dump the list of processes'''
71  from getpass import getuser
72  if 'WORKSPACE' in os.environ:
73  p = Popen(['ps', '-fH', '-U', getuser()], stdout=PIPE)
74  with open(os.path.join(os.environ['WORKSPACE'], name), 'wb') as f:
75  f.write(p.communicate()[0])
76 
77 

◆ findHistosSummaries()

def GaudiTesting.BaseTest.findHistosSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 1313 of file BaseTest.py.

1313 def findHistosSummaries(stdout):
1314  """
1315  Scan stdout to find ROOT TTree summaries and digest them.
1316  """
1317  outlines = stdout.splitlines()
1318  nlines = len(outlines) - 1
1319  summaries = {}
1320  global h_count_re
1321 
1322  pos = 0
1323  while pos < nlines:
1324  summ = {}
1325  # find first line of block:
1326  match = h_count_re.search(outlines[pos])
1327  while pos < nlines and not match:
1328  pos += 1
1329  match = h_count_re.search(outlines[pos])
1330  if match:
1331  summ, pos = parseHistosSummary(outlines, pos)
1332  summaries.update(summ)
1333  return summaries
1334 
1335 

◆ findTTreeSummaries()

def GaudiTesting.BaseTest.findTTreeSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 1119 of file BaseTest.py.

1119 def findTTreeSummaries(stdout):
1120  """
1121  Scan stdout to find ROOT TTree summaries and digest them.
1122  """
1123  stars = re.compile(r"^\*+$")
1124  outlines = stdout.splitlines()
1125  nlines = len(outlines)
1126  trees = {}
1127 
1128  i = 0
1129  while i < nlines: # loop over the output
1130  # look for
1131  while i < nlines and not stars.match(outlines[i]):
1132  i += 1
1133  if i < nlines:
1134  tree, i = _parseTTreeSummary(outlines, i)
1135  if tree:
1136  trees[tree["Name"]] = tree
1137 
1138  return trees
1139 
1140 

◆ getCmpFailingValues()

def GaudiTesting.BaseTest.getCmpFailingValues (   reference,
  to_check,
  fail_path 
)

Definition at line 1175 of file BaseTest.py.

1175 def getCmpFailingValues(reference, to_check, fail_path):
1176  c = to_check
1177  r = reference
1178  for k in fail_path:
1179  c = c.get(k, None)
1180  r = r.get(k, None)
1181  if c is None or r is None:
1182  break # one of the dictionaries is not deep enough
1183  return (fail_path, r, c)
1184 
1185 
1186 # signature of the print-out of the histograms

◆ GetPlatform()

def GaudiTesting.BaseTest.GetPlatform (   self)
    Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1336 of file BaseTest.py.

1336 def GetPlatform(self):
1337  """
1338  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1339  """
1340  arch = "None"
1341  # check architecture name
1342  if "BINARY_TAG" in os.environ:
1343  arch = os.environ["BINARY_TAG"]
1344  elif "CMTCONFIG" in os.environ:
1345  arch = os.environ["CMTCONFIG"]
1346  elif "SCRAM_ARCH" in os.environ:
1347  arch = os.environ["SCRAM_ARCH"]
1348  elif os.environ.get("ENV_CMAKE_BUILD_TYPE", "") in ("Debug", "FastDebug",
1349  "Developer"):
1350  arch = "dummy-dbg"
1351  elif os.environ.get("ENV_CMAKE_BUILD_TYPE",
1352  "") in ("Release", "MinSizeRel", "RelWithDebInfo",
1353  ""): # RelWithDebInfo == -O2 -g -DNDEBUG
1354  arch = "dummy-opt"
1355  return arch
1356 
1357 

◆ isWinPlatform()

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

1358 def isWinPlatform(self):
1359  """
1360  Return True if the current platform is Windows.
1361 
1362  This function was needed because of the change in the CMTCONFIG format,
1363  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1364  """
1365  platform = GetPlatform(self)
1366  return "winxp" in platform or platform.startswith("win")

◆ kill_tree()

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

78 def kill_tree(ppid, sig):
79  '''
80  Send a signal to a process and all its child processes (starting from the
81  leaves).
82  '''
83  log = logging.getLogger('kill_tree')
84  ps_cmd = ['ps', '--no-headers', '-o', 'pid', '--ppid', str(ppid)]
85  get_children = Popen(ps_cmd, stdout=PIPE, stderr=PIPE)
86  children = map(int, get_children.communicate()[0].split())
87  for child in children:
88  kill_tree(child, sig)
89  try:
90  log.debug('killing process %d', ppid)
91  os.kill(ppid, sig)
92  except OSError as err:
93  if err.errno != 3: # No such process
94  raise
95  log.debug('no such process %d', ppid)
96 
97 
98 # -------------------------------------------------------------------------#
99 
100 

◆ parseHistosSummary()

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

1243 def parseHistosSummary(lines, pos):
1244  """
1245  Extract the histograms infos from the lines starting at pos.
1246  Returns the position of the first line after the summary block.
1247  """
1248  global h_count_re
1249  h_table_head = re.compile(
1250  r'SUCCESS\s+(1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"'
1251  )
1252  h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
1253 
1254  nlines = len(lines)
1255 
1256  # decode header
1257  m = h_count_re.search(lines[pos])
1258  name = m.group(1).strip()
1259  total = int(m.group(2))
1260  header = {}
1261  for k, v in [x.split("=") for x in m.group(3).split()]:
1262  header[k] = int(v)
1263  pos += 1
1264  header["Total"] = total
1265 
1266  summ = {}
1267  while pos < nlines:
1268  m = h_table_head.search(lines[pos])
1269  if m:
1270  t, d = m.groups(1) # type and directory
1271  t = t.replace(" profile", "Prof")
1272  pos += 1
1273  if pos < nlines:
1274  l = lines[pos]
1275  else:
1276  l = ""
1277  cont = {}
1278  if l.startswith(" | ID"):
1279  # table format
1280  titles = [x.strip() for x in l.split("|")][1:]
1281  pos += 1
1282  while pos < nlines and lines[pos].startswith(" |"):
1283  l = lines[pos]
1284  values = [x.strip() for x in l.split("|")][1:]
1285  hcont = {}
1286  for i in range(len(titles)):
1287  hcont[titles[i]] = values[i]
1288  cont[hcont["ID"]] = hcont
1289  pos += 1
1290  elif l.startswith(" ID="):
1291  while pos < nlines and lines[pos].startswith(" ID="):
1292  values = [
1293  x.strip()
1294  for x in h_short_summ.search(lines[pos]).groups()
1295  ]
1296  cont[values[0]] = values
1297  pos += 1
1298  else: # not interpreted
1299  raise RuntimeError(
1300  "Cannot understand line %d: '%s'" % (pos, l))
1301  if not d in summ:
1302  summ[d] = {}
1303  summ[d][t] = cont
1304  summ[d]["header"] = header
1305  else:
1306  break
1307  if not summ:
1308  # If the full table is not present, we use only the header
1309  summ[name] = {"header": header}
1310  return summ, pos
1311 
1312 

◆ RationalizePath()

def GaudiTesting.BaseTest.RationalizePath (   p)
Function used to normalize the used path

Definition at line 664 of file BaseTest.py.

664 def RationalizePath(p):
665  """
666  Function used to normalize the used path
667  """
668  newPath = os.path.normpath(os.path.expandvars(p))
669  if os.path.exists(newPath):
670  p = os.path.realpath(newPath)
671  return p
672 
673 

◆ ROOT6WorkAroundEnabled()

def GaudiTesting.BaseTest.ROOT6WorkAroundEnabled (   id = None)

Definition at line 656 of file BaseTest.py.

656  def ROOT6WorkAroundEnabled(id=None):
657  # dummy implementation
658  return False
659 
660 
661 # --------------------------------- TOOLS ---------------------------------#
662 
663 

◆ sanitize_for_xml()

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

51 def sanitize_for_xml(data):
52  '''
53  Take a string with invalid ASCII/UTF characters and quote them so that the
54  string can be used in an XML text.
55 
56  >>> sanitize_for_xml('this is \x1b')
57  'this is [NON-XML-CHAR-0x1B]'
58  '''
59  bad_chars = re.compile(
60  u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]')
61 
62  def quote(match):
63  'helper function'
64  return ''.join('[NON-XML-CHAR-0x%2X]' % ord(c) for c in match.group())
65 
66  return bad_chars.sub(quote, data)
67 
68 

◆ which()

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

674 def which(executable):
675  """
676  Locates an executable in the executables path ($PATH) and returns the full
677  path to it. An application is looked for with or without the '.exe' suffix.
678  If the executable cannot be found, None is returned
679  """
680  if os.path.isabs(executable):
681  if not os.path.isfile(executable):
682  if executable.endswith('.exe'):
683  if os.path.isfile(executable[:-4]):
684  return executable[:-4]
685  else:
686  executable = os.path.split(executable)[1]
687  else:
688  return executable
689  for d in os.environ.get("PATH").split(os.pathsep):
690  fullpath = os.path.join(d, executable)
691  if os.path.isfile(fullpath):
692  return fullpath
693  elif executable.endswith('.exe') and os.path.isfile(fullpath[:-4]):
694  return fullpath[:-4]
695  return None
696 
697 
698 # -------------------------------------------------------------------------#
699 # ----------------------------- Result Classe -----------------------------#
700 # -------------------------------------------------------------------------#

Variable Documentation

◆ __processLine__

GaudiTesting.BaseTest.__processLine__
private

Definition at line 900 of file BaseTest.py.

◆ h_count_re

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

Definition at line 1187 of file BaseTest.py.

◆ lineSkipper

GaudiTesting.BaseTest.lineSkipper

Definition at line 982 of file BaseTest.py.

◆ maskPointers

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

Definition at line 895 of file BaseTest.py.

◆ normalizeDate

GaudiTesting.BaseTest.normalizeDate
Initial value:
1 = RegexpReplacer(
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 896 of file BaseTest.py.

◆ normalizeEOL

GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 899 of file BaseTest.py.

◆ normalizeExamples

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers + normalizeDate

Definition at line 950 of file BaseTest.py.

◆ regexps

GaudiTesting.BaseTest.regexps

Definition at line 1071 of file BaseTest.py.

◆ skipEmptyLines

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 902 of file BaseTest.py.

MSG::hex
MsgStream & hex(MsgStream &log)
Definition: MsgStream.h:282
GaudiTesting.BaseTest.dumpProcs
def dumpProcs(name)
Definition: BaseTest.py:69
GaudiTesting.BaseTest._parseTTreeSummary
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:1191
GaudiTesting.BaseTest.sanitize_for_xml
def sanitize_for_xml(data)
Definition: BaseTest.py:51
GaudiTesting.BaseTest.getCmpFailingValues
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:1175
GaudiTesting.BaseTest._new_backslashreplace_errors
def _new_backslashreplace_errors(exc)
Definition: BaseTest.py:38
GaudiTesting.BaseTest.kill_tree
def kill_tree(ppid, sig)
Definition: BaseTest.py:78
Containers::map
struct GAUDI_API map
Parametrisation class for map-like implementation.
Definition: KeyedObjectManager.h:35
GaudiTesting.BaseTest.parseHistosSummary
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1243
GaudiTesting.BaseTest.isWinPlatform
def isWinPlatform(self)
Definition: BaseTest.py:1358
GaudiTesting.BaseTest.which
def which(executable)
Definition: BaseTest.py:674
GaudiTesting.BaseTest.cmpTreesDicts
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: BaseTest.py:1141
GaudiTesting.BaseTest.RationalizePath
def RationalizePath(p)
Definition: BaseTest.py:664
gaudirun.type
type
Definition: gaudirun.py:154
GaudiTesting.BaseTest.findHistosSummaries
def findHistosSummaries(stdout)
Definition: BaseTest.py:1313
GaudiTesting.BaseTest.findTTreeSummaries
def findTTreeSummaries(stdout)
Definition: BaseTest.py:1119
GaudiTesting.BaseTest.ROOT6WorkAroundEnabled
def ROOT6WorkAroundEnabled(id=None)
Definition: BaseTest.py:656
GaudiTesting.BaseTest.GetPlatform
def GetPlatform(self)
Definition: BaseTest.py:1336
Gaudi::Functional::details::zip::range
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
Definition: FunctionalDetails.h:97