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

968 def _parseTTreeSummary(lines, pos):
969  """
970  Parse the TTree summary table in lines, starting from pos.
971  Returns a tuple with the dictionary with the digested informations and the
972  position of the first line after the summary.
973  """
974  result = {}
975  i = pos + 1 # first line is a sequence of '*'
976  count = len(lines)
977 
978  splitcols = lambda l: [ f.strip() for f in l.strip("*\n").split(':',2) ]
979  def parseblock(ll):
980  r = {}
981  cols = splitcols(ll[0])
982  r["Name"], r["Title"] = cols[1:]
983 
984  cols = splitcols(ll[1])
985  r["Entries"] = int(cols[1])
986 
987  sizes = cols[2].split()
988  r["Total size"] = int(sizes[2])
989  if sizes[-1] == "memory":
990  r["File size"] = 0
991  else:
992  r["File size"] = int(sizes[-1])
993 
994  cols = splitcols(ll[2])
995  sizes = cols[2].split()
996  if cols[0] == "Baskets":
997  r["Baskets"] = int(cols[1])
998  r["Basket size"] = int(sizes[2])
999  r["Compression"] = float(sizes[-1])
1000  return r
1001 
1002  if i < (count - 3) and lines[i].startswith("*Tree"):
1003  result = parseblock(lines[i:i+3])
1004  result["Branches"] = {}
1005  i += 4
1006  while i < (count - 3) and lines[i].startswith("*Br"):
1007  if i < (count - 2) and lines[i].startswith("*Branch "):
1008  # skip branch header
1009  i += 3
1010  continue
1011  branch = parseblock(lines[i:i+3])
1012  result["Branches"][branch["Name"]] = branch
1013  i += 4
1014 
1015  return (result, i)
1016 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:968
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 923 of file BaseTest.py.

923 def cmpTreesDicts(reference, to_check, ignore = None):
924  """
925  Check that all the keys in reference are in to_check too, with the same value.
926  If the value is a dict, the function is called recursively. to_check can
927  contain more keys than reference, that will not be tested.
928  The function returns at the first difference found.
929  """
930  fail_keys = []
931  # filter the keys in the reference dictionary
932  if ignore:
933  ignore_re = re.compile(ignore)
934  keys = [ key for key in reference if not ignore_re.match(key) ]
935  else:
936  keys = reference.keys()
937  # loop over the keys (not ignored) in the reference dictionary
938  for k in keys:
939  if k in to_check: # the key must be in the dictionary to_check
940  if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
941  # if both reference and to_check values are dictionaries, recurse
942  failed = fail_keys = cmpTreesDicts(reference[k], to_check[k], ignore)
943  else:
944  # compare the two values
945  failed = to_check[k] != reference[k]
946  else: # handle missing keys in the dictionary to check (i.e. failure)
947  to_check[k] = None
948  failed = True
949  if failed:
950  fail_keys.insert(0, k)
951  break # exit from the loop at the first failure
952  return fail_keys # return the list of keys bringing to the different values
953 
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: BaseTest.py:923
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 1082 of file BaseTest.py.

1083  """
1084  Scan stdout to find ROOT TTree summaries and digest them.
1085  """
1086  outlines = stdout.splitlines()
1087  nlines = len(outlines) - 1
1088  summaries = {}
1089  global h_count_re
1090 
1091  pos = 0
1092  while pos < nlines:
1093  summ = {}
1094  # find first line of block:
1095  match = h_count_re.search(outlines[pos])
1096  while pos < nlines and not match:
1097  pos += 1
1098  match = h_count_re.search(outlines[pos])
1099  if match:
1100  summ, pos = parseHistosSummary(outlines, pos)
1101  summaries.update(summ)
1102  return summaries
1103 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1082
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1017
def GaudiTesting.BaseTest.findTTreeSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 902 of file BaseTest.py.

902 def findTTreeSummaries(stdout):
903  """
904  Scan stdout to find ROOT TTree summaries and digest them.
905  """
906  stars = re.compile(r"^\*+$")
907  outlines = stdout.splitlines()
908  nlines = len(outlines)
909  trees = {}
910 
911  i = 0
912  while i < nlines: #loop over the output
913  # look for
914  while i < nlines and not stars.match(outlines[i]):
915  i += 1
916  if i < nlines:
917  tree, i = _parseTTreeSummary(outlines, i)
918  if tree:
919  trees[tree["Name"]] = tree
920 
921  return trees
922 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:968
def findTTreeSummaries(stdout)
Definition: BaseTest.py:902
def GaudiTesting.BaseTest.getCmpFailingValues (   reference,
  to_check,
  fail_path 
)

Definition at line 954 of file BaseTest.py.

954 def getCmpFailingValues(reference, to_check, fail_path):
955  c = to_check
956  r = reference
957  for k in fail_path:
958  c = c.get(k,None)
959  r = r.get(k,None)
960  if c is None or r is None:
961  break # one of the dictionaries is not deep enough
962  return (fail_path, r, c)
963 
964 # signature of the print-out of the histograms
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:954
def GaudiTesting.BaseTest.GetPlatform (   self)
    Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1114 of file BaseTest.py.

1114 def GetPlatform(self):
1115  """
1116  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1117  """
1118  arch = "None"
1119  # check architecture name
1120  if "BINARY_TAG" in os.environ:
1121  arch = os.environ["BINARY_TAG"]
1122  elif "CMTCONFIG" in os.environ:
1123  arch = os.environ["CMTCONFIG"]
1124  elif "SCRAM_ARCH" in os.environ:
1125  arch = os.environ["SCRAM_ARCH"]
1126  return arch
1127 
def GetPlatform(self)
Definition: BaseTest.py:1114
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 1128 of file BaseTest.py.

1128 def isWinPlatform(self):
1129  """
1130  Return True if the current platform is Windows.
1131 
1132  This function was needed because of the change in the CMTCONFIG format,
1133  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1134  """
1135  platform = GetPlatform(self)
1136  return "winxp" in platform or platform.startswith("win")
1137 
def GetPlatform(self)
Definition: BaseTest.py:1114
def isWinPlatform(self)
Definition: BaseTest.py:1128
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 1017 of file BaseTest.py.

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

Definition at line 1104 of file BaseTest.py.

1104 def PlatformIsNotSupported(self, context, result):
1105  platform = GetPlatform(self)
1106  unsupported = [ re.compile(x) for x in [ str(y).strip() for y in unsupported_platforms ] if x]
1107  for p_re in unsupported :
1108  if p_re.search(platform):
1109  result.SetOutcome(result.UNTESTED)
1110  result[result.CAUSE] = 'Platform not supported.'
1111  return True
1112  return False
1113 
def GetPlatform(self)
Definition: BaseTest.py:1114
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1104
def GaudiTesting.BaseTest.RationalizePath (   p)
Function used to normalize the used path

Definition at line 525 of file BaseTest.py.

526  """
527  Function used to normalize the used path
528  """
529  newPath = os.path.normpath(os.path.expandvars(p))
530  if os.path.exists(newPath) :
531  p = os.path.realpath(newPath)
532  return p
533 
534 
def GaudiTesting.BaseTest.ROOT6WorkAroundEnabled (   id = None)

Definition at line 519 of file BaseTest.py.

520  # dummy implementation
521  return False
522 
523 #--------------------------------- TOOLS ---------------------------------#
524 
def ROOT6WorkAroundEnabled(id=None)
Definition: BaseTest.py:519
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 535 of file BaseTest.py.

535 def which(executable):
536  """
537  Locates an executable in the executables path ($PATH) and returns the full
538  path to it. An application is looked for with or without the '.exe' suffix.
539  If the executable cannot be found, None is returned
540  """
541  if os.path.isabs(executable):
542  if not os.path.exists(executable):
543  if executable.endswith('.exe'):
544  if os.path.exists(executable[:-4]):
545  return executable[:-4]
546  else :
547  head,executable = os.path.split(executable)
548  else :
549  return executable
550  for d in os.environ.get("PATH").split(os.pathsep):
551  fullpath = os.path.join(d, executable)
552  if os.path.exists(fullpath):
553  return fullpath
554  if executable.endswith('.exe'):
555  return which(executable[:-4])
556  return None
557 
558 
559 
560 #-------------------------------------------------------------------------#
561 #----------------------------- Result Classe -----------------------------#
562 #-------------------------------------------------------------------------#
def which(executable)
Definition: BaseTest.py:535

Variable Documentation

GaudiTesting.BaseTest.__processLine__
private

Definition at line 734 of file BaseTest.py.

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

Definition at line 965 of file BaseTest.py.

GaudiTesting.BaseTest.lineSkipper

Definition at line 797 of file BaseTest.py.

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

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

GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 733 of file BaseTest.py.

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers+normalizeDate

Definition at line 777 of file BaseTest.py.

GaudiTesting.BaseTest.regexps

Definition at line 858 of file BaseTest.py.

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 736 of file BaseTest.py.