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
 

Functions

def sanitize_for_xml (data)
 
def dumpProcs (name)
 
def kill_tree (ppid, sig)
 
def ROOT6WorkAroundEnabled
 
def RationalizePath (p)
 
def which (executable)
 
def findTTreeSummaries (stdout)
 
def cmpTreesDicts
 
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

tuple maskPointers = RegexpReplacer("0x[0-9a-fA-F]{4,16}","0x########")
 
tuple normalizeDate
 
tuple normalizeEOL = FilePreprocessor()
 
tuple skipEmptyLines = FilePreprocessor()
 
 normalizeExamples = maskPointers+normalizeDate
 
tuple lineSkipper
 
tuple h_count_re = re.compile(r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+(.*)")
 

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

947 def _parseTTreeSummary(lines, pos):
948  """
949  Parse the TTree summary table in lines, starting from pos.
950  Returns a tuple with the dictionary with the digested informations and the
951  position of the first line after the summary.
952  """
953  result = {}
954  i = pos + 1 # first line is a sequence of '*'
955  count = len(lines)
956 
957  splitcols = lambda l: [ f.strip() for f in l.strip("*\n").split(':',2) ]
958  def parseblock(ll):
959  r = {}
960  cols = splitcols(ll[0])
961  r["Name"], r["Title"] = cols[1:]
962 
963  cols = splitcols(ll[1])
964  r["Entries"] = int(cols[1])
965 
966  sizes = cols[2].split()
967  r["Total size"] = int(sizes[2])
968  if sizes[-1] == "memory":
969  r["File size"] = 0
970  else:
971  r["File size"] = int(sizes[-1])
972 
973  cols = splitcols(ll[2])
974  sizes = cols[2].split()
975  if cols[0] == "Baskets":
976  r["Baskets"] = int(cols[1])
977  r["Basket size"] = int(sizes[2])
978  r["Compression"] = float(sizes[-1])
979  return r
980 
981  if i < (count - 3) and lines[i].startswith("*Tree"):
982  result = parseblock(lines[i:i+3])
983  result["Branches"] = {}
984  i += 4
985  while i < (count - 3) and lines[i].startswith("*Br"):
986  if i < (count - 2) and lines[i].startswith("*Branch "):
987  # skip branch header
988  i += 3
989  continue
990  branch = parseblock(lines[i:i+3])
991  result["Branches"][branch["Name"]] = branch
992  i += 4
993 
994  return (result, i)
995 
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:947
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 902 of file BaseTest.py.

902 def cmpTreesDicts(reference, to_check, ignore = None):
903  """
904  Check that all the keys in reference are in to_check too, with the same value.
905  If the value is a dict, the function is called recursively. to_check can
906  contain more keys than reference, that will not be tested.
907  The function returns at the first difference found.
908  """
909  fail_keys = []
910  # filter the keys in the reference dictionary
911  if ignore:
912  ignore_re = re.compile(ignore)
913  keys = [ key for key in reference if not ignore_re.match(key) ]
914  else:
915  keys = reference.keys()
916  # loop over the keys (not ignored) in the reference dictionary
917  for k in keys:
918  if k in to_check: # the key must be in the dictionary to_check
919  if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
920  # if both reference and to_check values are dictionaries, recurse
921  failed = fail_keys = cmpTreesDicts(reference[k], to_check[k], ignore)
922  else:
923  # compare the two values
924  failed = to_check[k] != reference[k]
925  else: # handle missing keys in the dictionary to check (i.e. failure)
926  to_check[k] = None
927  failed = True
928  if failed:
929  fail_keys.insert(0, k)
930  break # exit from the loop at the first failure
931  return fail_keys # return the list of keys bringing to the different values
932 
string type
Definition: gaudirun.py:151
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 1061 of file BaseTest.py.

1062  """
1063  Scan stdout to find ROOT TTree summaries and digest them.
1064  """
1065  outlines = stdout.splitlines()
1066  nlines = len(outlines) - 1
1067  summaries = {}
1068  global h_count_re
1069 
1070  pos = 0
1071  while pos < nlines:
1072  summ = {}
1073  # find first line of block:
1074  match = h_count_re.search(outlines[pos])
1075  while pos < nlines and not match:
1076  pos += 1
1077  match = h_count_re.search(outlines[pos])
1078  if match:
1079  summ, pos = parseHistosSummary(outlines, pos)
1080  summaries.update(summ)
1081  return summaries
1082 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1061
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:996
def GaudiTesting.BaseTest.findTTreeSummaries (   stdout)
    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 881 of file BaseTest.py.

881 def findTTreeSummaries(stdout):
882  """
883  Scan stdout to find ROOT TTree summaries and digest them.
884  """
885  stars = re.compile(r"^\*+$")
886  outlines = stdout.splitlines()
887  nlines = len(outlines)
888  trees = {}
889 
890  i = 0
891  while i < nlines: #loop over the output
892  # look for
893  while i < nlines and not stars.match(outlines[i]):
894  i += 1
895  if i < nlines:
896  tree, i = _parseTTreeSummary(outlines, i)
897  if tree:
898  trees[tree["Name"]] = tree
899 
900  return trees
901 
def findTTreeSummaries(stdout)
Definition: BaseTest.py:881
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:947
def GaudiTesting.BaseTest.getCmpFailingValues (   reference,
  to_check,
  fail_path 
)

Definition at line 933 of file BaseTest.py.

933 def getCmpFailingValues(reference, to_check, fail_path):
934  c = to_check
935  r = reference
936  for k in fail_path:
937  c = c.get(k,None)
938  r = r.get(k,None)
939  if c is None or r is None:
940  break # one of the dictionaries is not deep enough
941  return (fail_path, r, c)
942 
943 # signature of the print-out of the histograms
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:933
def GaudiTesting.BaseTest.GetPlatform (   self)
    Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1093 of file BaseTest.py.

1093 def GetPlatform(self):
1094  """
1095  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1096  """
1097  arch = "None"
1098  # check architecture name
1099  if "BINARY_TAG" in os.environ:
1100  arch = os.environ["BINARY_TAG"]
1101  elif "CMTCONFIG" in os.environ:
1102  arch = os.environ["CMTCONFIG"]
1103  elif "SCRAM_ARCH" in os.environ:
1104  arch = os.environ["SCRAM_ARCH"]
1105  return arch
1106 
def GetPlatform(self)
Definition: BaseTest.py:1093
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 1107 of file BaseTest.py.

1107 def isWinPlatform(self):
1108  """
1109  Return True if the current platform is Windows.
1110 
1111  This function was needed because of the change in the CMTCONFIG format,
1112  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1113  """
1114  platform = GetPlatform(self)
1115  return "winxp" in platform or platform.startswith("win")
1116 
1117 
def GetPlatform(self)
Definition: BaseTest.py:1093
def isWinPlatform(self)
Definition: BaseTest.py:1107
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 #-------------------------------------------------------------------------#
def kill_tree(ppid, sig)
Definition: BaseTest.py:38
struct GAUDI_API map
Parametrisation class for map-like implementation.
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 996 of file BaseTest.py.

996 def parseHistosSummary(lines, pos):
997  """
998  Extract the histograms infos from the lines starting at pos.
999  Returns the position of the first line after the summary block.
1000  """
1001  global h_count_re
1002  h_table_head = re.compile(r'SUCCESS\s+List of booked (1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"')
1003  h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
1004 
1005  nlines = len(lines)
1006 
1007  # decode header
1008  m = h_count_re.search(lines[pos])
1009  name = m.group(1).strip()
1010  total = int(m.group(2))
1011  header = {}
1012  for k, v in [ x.split("=") for x in m.group(3).split() ]:
1013  header[k] = int(v)
1014  pos += 1
1015  header["Total"] = total
1016 
1017  summ = {}
1018  while pos < nlines:
1019  m = h_table_head.search(lines[pos])
1020  if m:
1021  t, d = m.groups(1) # type and directory
1022  t = t.replace(" profile", "Prof")
1023  pos += 1
1024  if pos < nlines:
1025  l = lines[pos]
1026  else:
1027  l = ""
1028  cont = {}
1029  if l.startswith(" | ID"):
1030  # table format
1031  titles = [ x.strip() for x in l.split("|")][1:]
1032  pos += 1
1033  while pos < nlines and lines[pos].startswith(" |"):
1034  l = lines[pos]
1035  values = [ x.strip() for x in l.split("|")][1:]
1036  hcont = {}
1037  for i in range(len(titles)):
1038  hcont[titles[i]] = values[i]
1039  cont[hcont["ID"]] = hcont
1040  pos += 1
1041  elif l.startswith(" ID="):
1042  while pos < nlines and lines[pos].startswith(" ID="):
1043  values = [ x.strip() for x in h_short_summ.search(lines[pos]).groups() ]
1044  cont[values[0]] = values
1045  pos += 1
1046  else: # not interpreted
1047  raise RuntimeError("Cannot understand line %d: '%s'" % (pos, l))
1048  if not d in summ:
1049  summ[d] = {}
1050  summ[d][t] = cont
1051  summ[d]["header"] = header
1052  else:
1053  break
1054  if not summ:
1055  # If the full table is not present, we use only the header
1056  summ[name] = {"header": header}
1057  return summ, pos
1058 
1059 
1060 
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:996
def GaudiTesting.BaseTest.PlatformIsNotSupported (   self,
  context,
  result 
)

Definition at line 1083 of file BaseTest.py.

1083 def PlatformIsNotSupported(self, context, result):
1084  platform = GetPlatform(self)
1085  unsupported = [ re.compile(x) for x in [ str(y).strip() for y in unsupported_platforms ] if x]
1086  for p_re in unsupported :
1087  if p_re.search(platform):
1088  result.SetOutcome(result.UNTESTED)
1089  result[result.CAUSE] = 'Platform not supported.'
1090  return True
1091  return False
1092 
def GetPlatform(self)
Definition: BaseTest.py:1093
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1083
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 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

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

Definition at line 944 of file BaseTest.py.

tuple GaudiTesting.BaseTest.lineSkipper

Definition at line 786 of file BaseTest.py.

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

Definition at line 739 of file BaseTest.py.

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

tuple GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 742 of file BaseTest.py.

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers+normalizeDate

Definition at line 765 of file BaseTest.py.

tuple GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 745 of file BaseTest.py.