GaudiTesting.BaseTest Namespace Reference

Classes

class  BaseTest
 
class  BasicOutputValidator
 
class  BlockSkipper
 
class  FilePreprocessor
 
class  FilePreprocessorSequence
 
class  LineSkipper
 
class  LineSorter
 Special preprocessor sorting the list of strings (whitespace separated) that follow a signature on a single line. More...
 
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 = re.compile(r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+([\s\w=-]*)")
 

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

984 def _parseTTreeSummary(lines, pos):
985  """
986  Parse the TTree summary table in lines, starting from pos.
987  Returns a tuple with the dictionary with the digested informations and the
988  position of the first line after the summary.
989  """
990  result = {}
991  i = pos + 1 # first line is a sequence of '*'
992  count = len(lines)
993 
994  splitcols = lambda l: [ f.strip() for f in l.strip("*\n").split(':',2) ]
995  def parseblock(ll):
996  r = {}
997  cols = splitcols(ll[0])
998  r["Name"], r["Title"] = cols[1:]
999 
1000  cols = splitcols(ll[1])
1001  r["Entries"] = int(cols[1])
1002 
1003  sizes = cols[2].split()
1004  r["Total size"] = int(sizes[2])
1005  if sizes[-1] == "memory":
1006  r["File size"] = 0
1007  else:
1008  r["File size"] = int(sizes[-1])
1009 
1010  cols = splitcols(ll[2])
1011  sizes = cols[2].split()
1012  if cols[0] == "Baskets":
1013  r["Baskets"] = int(cols[1])
1014  r["Basket size"] = int(sizes[2])
1015  r["Compression"] = float(sizes[-1])
1016  return r
1017 
1018  if i < (count - 3) and lines[i].startswith("*Tree"):
1019  result = parseblock(lines[i:i+3])
1020  result["Branches"] = {}
1021  i += 4
1022  while i < (count - 3) and lines[i].startswith("*Br"):
1023  if i < (count - 2) and lines[i].startswith("*Branch "):
1024  # skip branch header
1025  i += 3
1026  continue
1027  branch = parseblock(lines[i:i+3])
1028  result["Branches"][branch["Name"]] = branch
1029  i += 4
1030 
1031  return (result, i)
1032 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:984
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 939 of file BaseTest.py.

939 def cmpTreesDicts(reference, to_check, ignore = None):
940  """
941  Check that all the keys in reference are in to_check too, with the same value.
942  If the value is a dict, the function is called recursively. to_check can
943  contain more keys than reference, that will not be tested.
944  The function returns at the first difference found.
945  """
946  fail_keys = []
947  # filter the keys in the reference dictionary
948  if ignore:
949  ignore_re = re.compile(ignore)
950  keys = [ key for key in reference if not ignore_re.match(key) ]
951  else:
952  keys = reference.keys()
953  # loop over the keys (not ignored) in the reference dictionary
954  for k in keys:
955  if k in to_check: # the key must be in the dictionary to_check
956  if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
957  # if both reference and to_check values are dictionaries, recurse
958  failed = fail_keys = cmpTreesDicts(reference[k], to_check[k], ignore)
959  else:
960  # compare the two values
961  failed = to_check[k] != reference[k]
962  else: # handle missing keys in the dictionary to check (i.e. failure)
963  to_check[k] = None
964  failed = True
965  if failed:
966  fail_keys.insert(0, k)
967  break # exit from the loop at the first failure
968  return fail_keys # return the list of keys bringing to the different values
969 
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: BaseTest.py:939
def GaudiTesting.BaseTest.dumpProcs (   name)
helper to debug GAUDI-1084, dump the list of processes

Definition at line 30 of file BaseTest.py.

30 def dumpProcs(name):
31  '''helper to debug GAUDI-1084, dump the list of processes'''
32  from getpass import getuser
33  if 'WORKSPACE' in os.environ:
34  p = Popen(['ps', '-fH', '-U', getuser()], stdout=PIPE)
35  with open(os.path.join(os.environ['WORKSPACE'], name), 'w') as f:
36  f.write(p.communicate()[0])
37 
def dumpProcs(name)
Definition: BaseTest.py:30
def GaudiTesting.BaseTest.findHistosSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 1098 of file BaseTest.py.

1099  """
1100  Scan stdout to find ROOT TTree summaries and digest them.
1101  """
1102  outlines = stdout.splitlines()
1103  nlines = len(outlines) - 1
1104  summaries = {}
1105  global h_count_re
1106 
1107  pos = 0
1108  while pos < nlines:
1109  summ = {}
1110  # find first line of block:
1111  match = h_count_re.search(outlines[pos])
1112  while pos < nlines and not match:
1113  pos += 1
1114  match = h_count_re.search(outlines[pos])
1115  if match:
1116  summ, pos = parseHistosSummary(outlines, pos)
1117  summaries.update(summ)
1118  return summaries
1119 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1098
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1033
def GaudiTesting.BaseTest.findTTreeSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 918 of file BaseTest.py.

918 def findTTreeSummaries(stdout):
919  """
920  Scan stdout to find ROOT TTree summaries and digest them.
921  """
922  stars = re.compile(r"^\*+$")
923  outlines = stdout.splitlines()
924  nlines = len(outlines)
925  trees = {}
926 
927  i = 0
928  while i < nlines: #loop over the output
929  # look for
930  while i < nlines and not stars.match(outlines[i]):
931  i += 1
932  if i < nlines:
933  tree, i = _parseTTreeSummary(outlines, i)
934  if tree:
935  trees[tree["Name"]] = tree
936 
937  return trees
938 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:984
def findTTreeSummaries(stdout)
Definition: BaseTest.py:918
def GaudiTesting.BaseTest.getCmpFailingValues (   reference,
  to_check,
  fail_path 
)

Definition at line 970 of file BaseTest.py.

970 def getCmpFailingValues(reference, to_check, fail_path):
971  c = to_check
972  r = reference
973  for k in fail_path:
974  c = c.get(k,None)
975  r = r.get(k,None)
976  if c is None or r is None:
977  break # one of the dictionaries is not deep enough
978  return (fail_path, r, c)
979 
980 # signature of the print-out of the histograms
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:970
def GaudiTesting.BaseTest.GetPlatform (   self)
    Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1130 of file BaseTest.py.

1130 def GetPlatform(self):
1131  """
1132  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1133  """
1134  arch = "None"
1135  # check architecture name
1136  if "BINARY_TAG" in os.environ:
1137  arch = os.environ["BINARY_TAG"]
1138  elif "CMTCONFIG" in os.environ:
1139  arch = os.environ["CMTCONFIG"]
1140  elif "SCRAM_ARCH" in os.environ:
1141  arch = os.environ["SCRAM_ARCH"]
1142  return arch
1143 
def GetPlatform(self)
Definition: BaseTest.py:1130
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 1144 of file BaseTest.py.

1144 def isWinPlatform(self):
1145  """
1146  Return True if the current platform is Windows.
1147 
1148  This function was needed because of the change in the CMTCONFIG format,
1149  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1150  """
1151  platform = GetPlatform(self)
1152  return "winxp" in platform or platform.startswith("win")
1153 
def GetPlatform(self)
Definition: BaseTest.py:1130
def isWinPlatform(self)
Definition: BaseTest.py:1144
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 38 of file BaseTest.py.

38 def kill_tree(ppid, sig):
39  '''
40  Send a signal to a process and all its child processes (starting from the
41  leaves).
42  '''
43  log = logging.getLogger('kill_tree')
44  ps_cmd = ['ps', '--no-headers', '-o', 'pid', '--ppid', str(ppid)]
45  get_children = Popen(ps_cmd, stdout=PIPE, stderr=PIPE)
46  children = map(int, get_children.communicate()[0].split())
47  for child in children:
48  kill_tree(child, sig)
49  try:
50  log.debug('killing process %d', ppid)
51  os.kill(ppid, sig)
52  except OSError, err:
53  if err.errno != 3: # No such process
54  raise
55  log.debug('no such process %d', ppid)
56 
57 #-------------------------------------------------------------------------#
struct GAUDI_API map
Parametrisation class for map-like implementation.
def kill_tree(ppid, sig)
Definition: BaseTest.py:38
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 1033 of file BaseTest.py.

1033 def parseHistosSummary(lines, pos):
1034  """
1035  Extract the histograms infos from the lines starting at pos.
1036  Returns the position of the first line after the summary block.
1037  """
1038  global h_count_re
1039  h_table_head = re.compile(r'SUCCESS\s+List of booked (1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"')
1040  h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
1041 
1042  nlines = len(lines)
1043 
1044  # decode header
1045  m = h_count_re.search(lines[pos])
1046  name = m.group(1).strip()
1047  total = int(m.group(2))
1048  header = {}
1049  for k, v in [ x.split("=") for x in m.group(3).split() ]:
1050  header[k] = int(v)
1051  pos += 1
1052  header["Total"] = total
1053 
1054  summ = {}
1055  while pos < nlines:
1056  m = h_table_head.search(lines[pos])
1057  if m:
1058  t, d = m.groups(1) # type and directory
1059  t = t.replace(" profile", "Prof")
1060  pos += 1
1061  if pos < nlines:
1062  l = lines[pos]
1063  else:
1064  l = ""
1065  cont = {}
1066  if l.startswith(" | ID"):
1067  # table format
1068  titles = [ x.strip() for x in l.split("|")][1:]
1069  pos += 1
1070  while pos < nlines and lines[pos].startswith(" |"):
1071  l = lines[pos]
1072  values = [ x.strip() for x in l.split("|")][1:]
1073  hcont = {}
1074  for i in range(len(titles)):
1075  hcont[titles[i]] = values[i]
1076  cont[hcont["ID"]] = hcont
1077  pos += 1
1078  elif l.startswith(" ID="):
1079  while pos < nlines and lines[pos].startswith(" ID="):
1080  values = [ x.strip() for x in h_short_summ.search(lines[pos]).groups() ]
1081  cont[values[0]] = values
1082  pos += 1
1083  else: # not interpreted
1084  raise RuntimeError("Cannot understand line %d: '%s'" % (pos, l))
1085  if not d in summ:
1086  summ[d] = {}
1087  summ[d][t] = cont
1088  summ[d]["header"] = header
1089  else:
1090  break
1091  if not summ:
1092  # If the full table is not present, we use only the header
1093  summ[name] = {"header": header}
1094  return summ, pos
1095 
1096 
1097 
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1033
def GaudiTesting.BaseTest.PlatformIsNotSupported (   self,
  context,
  result 
)

Definition at line 1120 of file BaseTest.py.

1120 def PlatformIsNotSupported(self, context, result):
1121  platform = GetPlatform(self)
1122  unsupported = [ re.compile(x) for x in [ str(y).strip() for y in unsupported_platforms ] if x]
1123  for p_re in unsupported :
1124  if p_re.search(platform):
1125  result.SetOutcome(result.UNTESTED)
1126  result[result.CAUSE] = 'Platform not supported.'
1127  return True
1128  return False
1129 
def GetPlatform(self)
Definition: BaseTest.py:1130
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1120
def GaudiTesting.BaseTest.RationalizePath (   p)
Function used to normalize the used path

Definition at line 537 of file BaseTest.py.

538  """
539  Function used to normalize the used path
540  """
541  newPath = os.path.normpath(os.path.expandvars(p))
542  if os.path.exists(newPath) :
543  p = os.path.realpath(newPath)
544  return p
545 
546 
def GaudiTesting.BaseTest.ROOT6WorkAroundEnabled (   id = None)

Definition at line 531 of file BaseTest.py.

532  # dummy implementation
533  return False
534 
535 #--------------------------------- TOOLS ---------------------------------#
536 
def ROOT6WorkAroundEnabled(id=None)
Definition: BaseTest.py:531
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 16 of file BaseTest.py.

16 def sanitize_for_xml(data):
17  '''
18  Take a string with invalid ASCII/UTF characters and quote them so that the
19  string can be used in an XML text.
20 
21  >>> sanitize_for_xml('this is \x1b')
22  'this is [NON-XML-CHAR-0x1B]'
23  '''
24  bad_chars = re.compile(u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]')
25  def quote(match):
26  'helper function'
27  return ''.join('[NON-XML-CHAR-0x%2X]' % ord(c) for c in match.group())
28  return bad_chars.sub(quote, data)
29 
def sanitize_for_xml(data)
Definition: BaseTest.py:16
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 547 of file BaseTest.py.

547 def which(executable):
548  """
549  Locates an executable in the executables path ($PATH) and returns the full
550  path to it. An application is looked for with or without the '.exe' suffix.
551  If the executable cannot be found, None is returned
552  """
553  if os.path.isabs(executable):
554  if not os.path.exists(executable):
555  if executable.endswith('.exe'):
556  if os.path.exists(executable[:-4]):
557  return executable[:-4]
558  else :
559  head,executable = os.path.split(executable)
560  else :
561  return executable
562  for d in os.environ.get("PATH").split(os.pathsep):
563  fullpath = os.path.join(d, executable)
564  if os.path.exists(fullpath):
565  return fullpath
566  if executable.endswith('.exe'):
567  return which(executable[:-4])
568  return None
569 
570 
571 
572 #-------------------------------------------------------------------------#
573 #----------------------------- Result Classe -----------------------------#
574 #-------------------------------------------------------------------------#
def which(executable)
Definition: BaseTest.py:547

Variable Documentation

GaudiTesting.BaseTest.__processLine__
private

Definition at line 746 of file BaseTest.py.

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

Definition at line 981 of file BaseTest.py.

GaudiTesting.BaseTest.lineSkipper

Definition at line 812 of file BaseTest.py.

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

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

GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 745 of file BaseTest.py.

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers+normalizeDate

Definition at line 789 of file BaseTest.py.

GaudiTesting.BaseTest.regexps

Definition at line 874 of file BaseTest.py.

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 748 of file BaseTest.py.