The Gaudi Framework  v36r2 (27905625)
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

int SKIP_RETURN_CODE = 77
 
 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 1196 of file BaseTest.py.

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

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

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

◆ dumpProcs()

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

Definition at line 71 of file BaseTest.py.

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

◆ findHistosSummaries()

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

Definition at line 1318 of file BaseTest.py.

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

◆ findTTreeSummaries()

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

Definition at line 1124 of file BaseTest.py.

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

◆ getCmpFailingValues()

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

Definition at line 1180 of file BaseTest.py.

1180 def getCmpFailingValues(reference, to_check, fail_path):
1181  c = to_check
1182  r = reference
1183  for k in fail_path:
1184  c = c.get(k, None)
1185  r = r.get(k, None)
1186  if c is None or r is None:
1187  break # one of the dictionaries is not deep enough
1188  return (fail_path, r, c)
1189 
1190 
1191 # 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 1341 of file BaseTest.py.

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

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

1363 def isWinPlatform(self):
1364  """
1365  Return True if the current platform is Windows.
1366 
1367  This function was needed because of the change in the CMTCONFIG format,
1368  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1369  """
1370  platform = GetPlatform(self)
1371  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 80 of file BaseTest.py.

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

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

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

◆ RationalizePath()

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

Definition at line 669 of file BaseTest.py.

669 def RationalizePath(p):
670  """
671  Function used to normalize the used path
672  """
673  newPath = os.path.normpath(os.path.expandvars(p))
674  if os.path.exists(newPath):
675  p = os.path.realpath(newPath)
676  return p
677 
678 

◆ ROOT6WorkAroundEnabled()

def GaudiTesting.BaseTest.ROOT6WorkAroundEnabled (   id = None)

Definition at line 661 of file BaseTest.py.

661  def ROOT6WorkAroundEnabled(id=None):
662  # dummy implementation
663  return False
664 
665 
666 # --------------------------------- TOOLS ---------------------------------#
667 
668 

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

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

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

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

Variable Documentation

◆ __processLine__

GaudiTesting.BaseTest.__processLine__
private

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

◆ lineSkipper

GaudiTesting.BaseTest.lineSkipper

Definition at line 987 of file BaseTest.py.

◆ maskPointers

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

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

◆ normalizeEOL

GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 904 of file BaseTest.py.

◆ normalizeExamples

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers + normalizeDate

Definition at line 955 of file BaseTest.py.

◆ regexps

GaudiTesting.BaseTest.regexps

Definition at line 1076 of file BaseTest.py.

◆ SKIP_RETURN_CODE

int GaudiTesting.BaseTest.SKIP_RETURN_CODE = 77

Definition at line 50 of file BaseTest.py.

◆ skipEmptyLines

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 907 of file BaseTest.py.

MSG::hex
MsgStream & hex(MsgStream &log)
Definition: MsgStream.h:282
GaudiTesting.BaseTest.dumpProcs
def dumpProcs(name)
Definition: BaseTest.py:71
GaudiTesting.BaseTest._parseTTreeSummary
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:1196
GaudiTesting.BaseTest.sanitize_for_xml
def sanitize_for_xml(data)
Definition: BaseTest.py:53
GaudiTesting.BaseTest.getCmpFailingValues
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:1180
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:80
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:1248
GaudiTesting.BaseTest.isWinPlatform
def isWinPlatform(self)
Definition: BaseTest.py:1363
GaudiTesting.BaseTest.which
def which(executable)
Definition: BaseTest.py:679
GaudiTesting.BaseTest.cmpTreesDicts
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: BaseTest.py:1146
GaudiTesting.BaseTest.RationalizePath
def RationalizePath(p)
Definition: BaseTest.py:669
gaudirun.type
type
Definition: gaudirun.py:154
GaudiTesting.BaseTest.findHistosSummaries
def findHistosSummaries(stdout)
Definition: BaseTest.py:1318
GaudiTesting.BaseTest.findTTreeSummaries
def findTTreeSummaries(stdout)
Definition: BaseTest.py:1124
GaudiTesting.BaseTest.ROOT6WorkAroundEnabled
def ROOT6WorkAroundEnabled(id=None)
Definition: BaseTest.py:661
GaudiTesting.BaseTest.GetPlatform
def GetPlatform(self)
Definition: BaseTest.py:1341
Gaudi::Functional::details::zip::range
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
Definition: FunctionalDetails.h:101