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

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

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

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

Definition at line 914 of file BaseTest.py.

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

Definition at line 966 of file BaseTest.py.

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

Definition at line 1126 of file BaseTest.py.

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

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

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

Definition at line 1116 of file BaseTest.py.

1116 def PlatformIsNotSupported(self, context, result):
1117  platform = GetPlatform(self)
1118  unsupported = [ re.compile(x) for x in [ str(y).strip() for y in unsupported_platforms ] if x]
1119  for p_re in unsupported :
1120  if p_re.search(platform):
1121  result.SetOutcome(result.UNTESTED)
1122  result[result.CAUSE] = 'Platform not supported.'
1123  return True
1124  return False
1125 
def GetPlatform(self)
Definition: BaseTest.py:1126
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1116
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 977 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.