The Gaudi Framework  v36r7 (7f57a304)
GaudiTesting.BaseTest Namespace Reference

Classes

class  BaseTest
 
class  BasicOutputValidator
 
class  BlockSkipper
 
class  FilePreprocessor
 
class  FilePreprocessorSequence
 
class  JSONOutputValidator
 
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 = re.compile(r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+([\s\w=-]*)")
 

Function Documentation

◆ _new_backslashreplace_errors()

def GaudiTesting.BaseTest._new_backslashreplace_errors (   exc)
private

Definition at line 39 of file BaseTest.py.

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

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

1283 def _parseTTreeSummary(lines, pos):
1284  """
1285  Parse the TTree summary table in lines, starting from pos.
1286  Returns a tuple with the dictionary with the digested informations and the
1287  position of the first line after the summary.
1288  """
1289  result = {}
1290  i = pos + 1 # first line is a sequence of '*'
1291  count = len(lines)
1292 
1293  def splitcols(l):
1294  return [f.strip() for f in l.strip("*\n").split(":", 2)]
1295 
1296  def parseblock(ll):
1297  r = {}
1298  cols = splitcols(ll[0])
1299  r["Name"], r["Title"] = cols[1:]
1300 
1301  cols = splitcols(ll[1])
1302  r["Entries"] = int(cols[1])
1303 
1304  sizes = cols[2].split()
1305  r["Total size"] = int(sizes[2])
1306  if sizes[-1] == "memory":
1307  r["File size"] = 0
1308  else:
1309  r["File size"] = int(sizes[-1])
1310 
1311  cols = splitcols(ll[2])
1312  sizes = cols[2].split()
1313  if cols[0] == "Baskets":
1314  r["Baskets"] = int(cols[1])
1315  r["Basket size"] = int(sizes[2])
1316  r["Compression"] = float(sizes[-1])
1317  return r
1318 
1319  if i < (count - 3) and lines[i].startswith("*Tree"):
1320  result = parseblock(lines[i : i + 3])
1321  result["Branches"] = {}
1322  i += 4
1323  while i < (count - 3) and lines[i].startswith("*Br"):
1324  if i < (count - 2) and lines[i].startswith("*Branch "):
1325  # skip branch header
1326  i += 3
1327  continue
1328  branch = parseblock(lines[i : i + 3])
1329  result["Branches"][branch["Name"]] = branch
1330  i += 4
1331 
1332  return (result, i)
1333 
1334 

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

1235 def cmpTreesDicts(reference, to_check, ignore=None):
1236  """
1237  Check that all the keys in reference are in to_check too, with the same value.
1238  If the value is a dict, the function is called recursively. to_check can
1239  contain more keys than reference, that will not be tested.
1240  The function returns at the first difference found.
1241  """
1242  fail_keys = []
1243  # filter the keys in the reference dictionary
1244  if ignore:
1245  ignore_re = re.compile(ignore)
1246  keys = [key for key in reference if not ignore_re.match(key)]
1247  else:
1248  keys = reference.keys()
1249  # loop over the keys (not ignored) in the reference dictionary
1250  for k in keys:
1251  if k in to_check: # the key must be in the dictionary to_check
1252  if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
1253  # if both reference and to_check values are dictionaries,
1254  # recurse
1255  failed = fail_keys = cmpTreesDicts(reference[k], to_check[k], ignore)
1256  else:
1257  # compare the two values
1258  failed = to_check[k] != reference[k]
1259  else: # handle missing keys in the dictionary to check (i.e. failure)
1260  to_check[k] = None
1261  failed = True
1262  if failed:
1263  fail_keys.insert(0, k)
1264  break # exit from the loop at the first failure
1265  return fail_keys # return the list of keys bringing to the different values
1266 
1267 

◆ 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 
75  if "WORKSPACE" in os.environ:
76  p = Popen(["ps", "-fH", "-U", getuser()], stdout=PIPE)
77  with open(os.path.join(os.environ["WORKSPACE"], name), "wb") as f:
78  f.write(p.communicate()[0])
79 
80 

◆ findHistosSummaries()

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

Definition at line 1403 of file BaseTest.py.

1403 def findHistosSummaries(stdout):
1404  """
1405  Scan stdout to find ROOT TTree summaries and digest them.
1406  """
1407  outlines = stdout.splitlines()
1408  nlines = len(outlines) - 1
1409  summaries = {}
1410  global h_count_re
1411 
1412  pos = 0
1413  while pos < nlines:
1414  summ = {}
1415  # find first line of block:
1416  match = h_count_re.search(outlines[pos])
1417  while pos < nlines and not match:
1418  pos += 1
1419  match = h_count_re.search(outlines[pos])
1420  if match:
1421  summ, pos = parseHistosSummary(outlines, pos)
1422  summaries.update(summ)
1423  return summaries
1424 
1425 

◆ findTTreeSummaries()

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

Definition at line 1213 of file BaseTest.py.

1213 def findTTreeSummaries(stdout):
1214  """
1215  Scan stdout to find ROOT TTree summaries and digest them.
1216  """
1217  stars = re.compile(r"^\*+$")
1218  outlines = stdout.splitlines()
1219  nlines = len(outlines)
1220  trees = {}
1221 
1222  i = 0
1223  while i < nlines: # loop over the output
1224  # look for
1225  while i < nlines and not stars.match(outlines[i]):
1226  i += 1
1227  if i < nlines:
1228  tree, i = _parseTTreeSummary(outlines, i)
1229  if tree:
1230  trees[tree["Name"]] = tree
1231 
1232  return trees
1233 
1234 

◆ getCmpFailingValues()

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

Definition at line 1268 of file BaseTest.py.

1268 def getCmpFailingValues(reference, to_check, fail_path):
1269  c = to_check
1270  r = reference
1271  for k in fail_path:
1272  c = c.get(k, None)
1273  r = r.get(k, None)
1274  if c is None or r is None:
1275  break # one of the dictionaries is not deep enough
1276  return (fail_path, r, c)
1277 
1278 
1279 # 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 1426 of file BaseTest.py.

1426 def GetPlatform(self):
1427  """
1428  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1429  """
1430  arch = "None"
1431  # check architecture name
1432  if "BINARY_TAG" in os.environ:
1433  arch = os.environ["BINARY_TAG"]
1434  elif "CMTCONFIG" in os.environ:
1435  arch = os.environ["CMTCONFIG"]
1436  elif "SCRAM_ARCH" in os.environ:
1437  arch = os.environ["SCRAM_ARCH"]
1438  elif os.environ.get("ENV_CMAKE_BUILD_TYPE", "") in (
1439  "Debug",
1440  "FastDebug",
1441  "Developer",
1442  ):
1443  arch = "dummy-dbg"
1444  elif os.environ.get("ENV_CMAKE_BUILD_TYPE", "") in (
1445  "Release",
1446  "MinSizeRel",
1447  "RelWithDebInfo",
1448  "",
1449  ): # RelWithDebInfo == -O2 -g -DNDEBUG
1450  arch = "dummy-opt"
1451  return arch
1452 
1453 

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

1454 def isWinPlatform(self):
1455  """
1456  Return True if the current platform is Windows.
1457 
1458  This function was needed because of the change in the CMTCONFIG format,
1459  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1460  """
1461  platform = GetPlatform(self)
1462  return "winxp" in platform or platform.startswith("win")
1463 
1464 

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

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

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

1335 def parseHistosSummary(lines, pos):
1336  """
1337  Extract the histograms infos from the lines starting at pos.
1338  Returns the position of the first line after the summary block.
1339  """
1340  global h_count_re
1341  h_table_head = re.compile(
1342  r'SUCCESS\s+(1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"'
1343  )
1344  h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
1345 
1346  nlines = len(lines)
1347 
1348  # decode header
1349  m = h_count_re.search(lines[pos])
1350  name = m.group(1).strip()
1351  total = int(m.group(2))
1352  header = {}
1353  for k, v in [x.split("=") for x in m.group(3).split()]:
1354  header[k] = int(v)
1355  pos += 1
1356  header["Total"] = total
1357 
1358  summ = {}
1359  while pos < nlines:
1360  m = h_table_head.search(lines[pos])
1361  if m:
1362  t, d = m.groups(1) # type and directory
1363  t = t.replace(" profile", "Prof")
1364  pos += 1
1365  if pos < nlines:
1366  l = lines[pos]
1367  else:
1368  l = ""
1369  cont = {}
1370  if l.startswith(" | ID"):
1371  # table format
1372  titles = [x.strip() for x in l.split("|")][1:]
1373  pos += 1
1374  while pos < nlines and lines[pos].startswith(" |"):
1375  l = lines[pos]
1376  values = [x.strip() for x in l.split("|")][1:]
1377  hcont = {}
1378  for i in range(len(titles)):
1379  hcont[titles[i]] = values[i]
1380  cont[hcont["ID"]] = hcont
1381  pos += 1
1382  elif l.startswith(" ID="):
1383  while pos < nlines and lines[pos].startswith(" ID="):
1384  values = [
1385  x.strip() for x in h_short_summ.search(lines[pos]).groups()
1386  ]
1387  cont[values[0]] = values
1388  pos += 1
1389  else: # not interpreted
1390  raise RuntimeError("Cannot understand line %d: '%s'" % (pos, l))
1391  if not d in summ:
1392  summ[d] = {}
1393  summ[d][t] = cont
1394  summ[d]["header"] = header
1395  else:
1396  break
1397  if not summ:
1398  # If the full table is not present, we use only the header
1399  summ[name] = {"header": header}
1400  return summ, pos
1401 
1402 

◆ RationalizePath()

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

Definition at line 735 of file BaseTest.py.

735 def RationalizePath(p):
736  """
737  Function used to normalize the used path
738  """
739  newPath = os.path.normpath(os.path.expandvars(p))
740  if os.path.exists(newPath):
741  p = os.path.realpath(newPath)
742  return p
743 
744 

◆ ROOT6WorkAroundEnabled()

def GaudiTesting.BaseTest.ROOT6WorkAroundEnabled (   id = None)

Definition at line 727 of file BaseTest.py.

727  def ROOT6WorkAroundEnabled(id=None):
728  # dummy implementation
729  return False
730 
731 
732 # --------------------------------- TOOLS ---------------------------------#
733 
734 

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

54 def sanitize_for_xml(data):
55  """
56  Take a string with invalid ASCII/UTF characters and quote them so that the
57  string can be used in an XML text.
58 
59  >>> sanitize_for_xml('this is \x1b')
60  'this is [NON-XML-CHAR-0x1B]'
61  """
62  bad_chars = re.compile("[\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 745 of file BaseTest.py.

745 def which(executable):
746  """
747  Locates an executable in the executables path ($PATH) and returns the full
748  path to it. An application is looked for with or without the '.exe' suffix.
749  If the executable cannot be found, None is returned
750  """
751  if os.path.isabs(executable):
752  if not os.path.isfile(executable):
753  if executable.endswith(".exe"):
754  if os.path.isfile(executable[:-4]):
755  return executable[:-4]
756  else:
757  executable = os.path.split(executable)[1]
758  else:
759  return executable
760  for d in os.environ.get("PATH").split(os.pathsep):
761  fullpath = os.path.join(d, executable)
762  if os.path.isfile(fullpath):
763  return fullpath
764  elif executable.endswith(".exe") and os.path.isfile(fullpath[:-4]):
765  return fullpath[:-4]
766  return None
767 
768 
769 # -------------------------------------------------------------------------#
770 # ----------------------------- Result Classe -----------------------------#
771 # -------------------------------------------------------------------------#

Variable Documentation

◆ __processLine__

GaudiTesting.BaseTest.__processLine__
private

Definition at line 973 of file BaseTest.py.

◆ h_count_re

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

Definition at line 1280 of file BaseTest.py.

◆ lineSkipper

GaudiTesting.BaseTest.lineSkipper

Definition at line 1063 of file BaseTest.py.

◆ maskPointers

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

Definition at line 967 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",
4 )

Definition at line 968 of file BaseTest.py.

◆ normalizeEOL

GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 972 of file BaseTest.py.

◆ normalizeExamples

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers + normalizeDate

Definition at line 1023 of file BaseTest.py.

◆ regexps

GaudiTesting.BaseTest.regexps

Definition at line 1155 of file BaseTest.py.

◆ SKIP_RETURN_CODE

int GaudiTesting.BaseTest.SKIP_RETURN_CODE = 77

Definition at line 51 of file BaseTest.py.

◆ skipEmptyLines

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 975 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:1283
GaudiTesting.BaseTest.sanitize_for_xml
def sanitize_for_xml(data)
Definition: BaseTest.py:54
GaudiTesting.BaseTest.getCmpFailingValues
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:1268
GaudiTesting.BaseTest._new_backslashreplace_errors
def _new_backslashreplace_errors(exc)
Definition: BaseTest.py:39
GaudiTesting.BaseTest.kill_tree
def kill_tree(ppid, sig)
Definition: BaseTest.py:81
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:1335
GaudiTesting.BaseTest.isWinPlatform
def isWinPlatform(self)
Definition: BaseTest.py:1454
GaudiTesting.BaseTest.which
def which(executable)
Definition: BaseTest.py:745
GaudiTesting.BaseTest.cmpTreesDicts
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: BaseTest.py:1235
GaudiTesting.BaseTest.RationalizePath
def RationalizePath(p)
Definition: BaseTest.py:735
gaudirun.type
type
Definition: gaudirun.py:160
GaudiTesting.BaseTest.findHistosSummaries
def findHistosSummaries(stdout)
Definition: BaseTest.py:1403
GaudiTesting.BaseTest.findTTreeSummaries
def findTTreeSummaries(stdout)
Definition: BaseTest.py:1213
GaudiTesting.BaseTest.ROOT6WorkAroundEnabled
def ROOT6WorkAroundEnabled(id=None)
Definition: BaseTest.py:727
GaudiTesting.BaseTest.GetPlatform
def GetPlatform(self)
Definition: BaseTest.py:1426
Gaudi::Functional::details::zip::range
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
Definition: FunctionalDetails.h:102