| The Gaudi Framework v32r1 (f65d50dc)

Classes | Functions | Variables
GaudiTesting.BaseTest Namespace Reference

## Classes
class | BaseTest
class | BasicOutputValidator
class | BlockSkipper
class | FilePreprocessor
class | FilePreprocessorSequence
class | LineSkipper
class | LineSorter
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

## Function Documentation

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

1136 def _parseTTreeSummary(lines, pos):
1137 """
1138 Parse the TTree summary table in lines, starting from pos.
1139 Returns a tuple with the dictionary with the digested informations and the
1140 position of the first line after the summary.
1141 """
1142 result = {}
1143 i = pos + 1 # first line is a sequence of '*'
1144 count = len(lines)
1145
1146 def splitcols(l):
1147 return [f.strip() for f in l.strip("*\n").split(':', 2)]
1148
1149 def parseblock(ll):
1150 r = {}
1151 cols = splitcols(ll[0])
1152 r["Name"], r["Title"] = cols[1:]
1153
1154 cols = splitcols(ll[1])
1155 r["Entries"] = int(cols[1])
1156
1157 sizes = cols[2].split()
1158 r["Total size"] = int(sizes[2])
1159 if sizes[-1] == "memory":
1160 r["File size"] = 0
1161 else:
1162 r["File size"] = int(sizes[-1])
1163
1164 cols = splitcols(ll[2])
1165 sizes = cols[2].split()
1166 if cols[0] == "Baskets":
1167 r["Baskets"] = int(cols[1])
1168 r["Basket size"] = int(sizes[2])
1169 r["Compression"] = float(sizes[-1])
1170 return r
1171
1172 if i < (count - 3) and lines[i].startswith("*Tree"):
1173 result = parseblock(lines[i:i + 3])
1174 result["Branches"] = {}
1175 i += 4
1176 while i < (count - 3) and lines[i].startswith("*Br"):
1177 if i < (count - 2) and lines[i].startswith("*Branch "):
1178 # skip branch header
1179 i += 3
1180 continue
1181 branch = parseblock(lines[i:i + 3])
1182 result["Branches"][branch["Name"]] = branch
1183 i += 4
1184
1185 return (result, i)
1186
1187
GaudiTesting.BaseTest._parseTTreeSummary
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:1136

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

1086 def cmpTreesDicts(reference, to_check, ignore=None):
1087 """
1088 Check that all the keys in reference are in to_check too, with the same value.
1089 If the value is a dict, the function is called recursively. to_check can
1090 contain more keys than reference, that will not be tested.
1091 The function returns at the first difference found.
1092 """
1093 fail_keys = []
1094 # filter the keys in the reference dictionary
1095 if ignore:
1096 ignore_re = re.compile(ignore)
1097 keys = [key for key in reference if not ignore_re.match(key)]
1098 else:
1099 keys = reference.keys()
1100 # loop over the keys (not ignored) in the reference dictionary
1101 for k in keys:
1102 if k in to_check: # the key must be in the dictionary to_check
1103 if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
1104 # if both reference and to_check values are dictionaries,
1105 # recurse
1106 failed = fail_keys = cmpTreesDicts(reference[k], to_check[k],
1107 ignore)
1108 else:
1109 # compare the two values
1110 failed = to_check[k] != reference[k]
1111 else: # handle missing keys in the dictionary to check (i.e. failure)
1112 to_check[k] = None
1113 failed = True
1114 if failed:
1115 fail_keys.insert(0, k)
1116 break # exit from the loop at the first failure
1117 return fail_keys # return the list of keys bringing to the different values
1118
1119
GaudiTesting.BaseTest.cmpTreesDicts
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: BaseTest.py:1086
gaudirun.type
type
Definition: gaudirun.py:142

## ◆ dumpProcs()

def GaudiTesting.BaseTest.dumpProcs | ( |  | name | ) |

    helper to debug GAUDI-1084, dump the list of processes

Definition at line 35 of file BaseTest.py.

35 def dumpProcs(name):
36 '''helper to debug GAUDI-1084, dump the list of processes'''
37 from getpass import getuser
38 if 'WORKSPACE' in os.environ:
39 p = Popen(['ps', '-fH', '-U', getuser()], stdout=PIPE)
40 with open(os.path.join(os.environ['WORKSPACE'], name), 'w') as f:
41 f.write(p.communicate()[0])
42
43
GaudiTesting.BaseTest.dumpProcs
def dumpProcs(name)
Definition: BaseTest.py:35

## ◆ findHistosSummaries()

def GaudiTesting.BaseTest.findHistosSummaries | ( |  | stdout | ) |

        Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 1258 of file BaseTest.py.

1258 def findHistosSummaries(stdout):
1259 """
1260 Scan stdout to find ROOT TTree summaries and digest them.
1261 """
1262 outlines = stdout.splitlines()
1263 nlines = len(outlines) - 1
1264 summaries = {}
1265 global h_count_re
1266
1267 pos = 0
1268 while pos < nlines:
1269 summ = {}
1270 # find first line of block:
1271 match = h_count_re.search(outlines[pos])
1272 while pos < nlines and not match:
1273 pos += 1
1274 match = h_count_re.search(outlines[pos])
1275 if match:
1276 summ, pos = parseHistosSummary(outlines, pos)
1277 summaries.update(summ)
1278 return summaries
1279
1280
GaudiTesting.BaseTest.findHistosSummaries
def findHistosSummaries(stdout)
Definition: BaseTest.py:1258
GaudiTesting.BaseTest.parseHistosSummary
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1188

## ◆ findTTreeSummaries()

def GaudiTesting.BaseTest.findTTreeSummaries | ( |  | stdout | ) |

        Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 1064 of file BaseTest.py.

1064 def findTTreeSummaries(stdout):
1065 """
1066 Scan stdout to find ROOT TTree summaries and digest them.
1067 """
1068 stars = re.compile(r"^\*+$")
1069 outlines = stdout.splitlines()
1070 nlines = len(outlines)
1071 trees = {}
1072
1073 i = 0
1074 while i < nlines: # loop over the output
1075 # look for
1076 while i < nlines and not stars.match(outlines[i]):
1077 i += 1
1078 if i < nlines:
1079 tree, i = _parseTTreeSummary(outlines, i)
1080 if tree:
1081 trees[tree["Name"]] = tree
1082
1083 return trees
1084
1085
GaudiTesting.BaseTest._parseTTreeSummary
def _parseTTreeSummary(lines, pos)
Definition: BaseTest.py:1136
GaudiTesting.BaseTest.findTTreeSummaries
def findTTreeSummaries(stdout)
Definition: BaseTest.py:1064

## ◆ getCmpFailingValues()

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

Definition at line 1120 of file BaseTest.py.

1120 def getCmpFailingValues(reference, to_check, fail_path):
1121 c = to_check
1122 r = reference
1123 for k in fail_path:
1124 c = c.get(k, None)
1125 r = r.get(k, None)
1126 if c is None or r is None:
1127 break # one of the dictionaries is not deep enough
1128 return (fail_path, r, c)
1129
1130
1131 # signature of the print-out of the histograms
GaudiTesting.BaseTest.getCmpFailingValues
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:1120

## ◆ GetPlatform()

def GaudiTesting.BaseTest.GetPlatform | ( |  | self | ) |

        Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1295 of file BaseTest.py.

1295 def GetPlatform(self):
1296 """
1297 Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1298 """
1299 arch = "None"
1300 # check architecture name
1301 if "BINARY_TAG" in os.environ:
1302 arch = os.environ["BINARY_TAG"]
1303 elif "CMTCONFIG" in os.environ:
1304 arch = os.environ["CMTCONFIG"]
1305 elif "SCRAM_ARCH" in os.environ:
1306 arch = os.environ["SCRAM_ARCH"]
1307 return arch
1308
1309
GaudiTesting.BaseTest.GetPlatform
def GetPlatform(self)
Definition: BaseTest.py:1295

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

1310 def isWinPlatform(self):
1311 """
1312 Return True if the current platform is Windows.
1313
1314 This function was needed because of the change in the CMTCONFIG format,
1315 from win32_vc71_dbg to i686-winxp-vc9-dbg.
1316 """
1317 platform = GetPlatform(self)
1318 return "winxp" in platform or platform.startswith("win")
GaudiTesting.BaseTest.GetPlatform
def GetPlatform(self)
Definition: BaseTest.py:1295
GaudiTesting.BaseTest.isWinPlatform
def isWinPlatform(self)
Definition: BaseTest.py:1310

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

44 def kill_tree(ppid, sig):
45 '''
46 Send a signal to a process and all its child processes (starting from the
47 leaves).
48 '''
49 log = logging.getLogger('kill_tree')
50 ps_cmd = ['ps', '--no-headers', '-o', 'pid', '--ppid', str(ppid)]
51 get_children = Popen(ps_cmd, stdout=PIPE, stderr=PIPE)
52 children = map(int, get_children.communicate()[0].split())
53 for child in children:
54 kill_tree(child, sig)
55 try:
56 log.debug('killing process %d', ppid)
57 os.kill(ppid, sig)
58 except OSError as err:
59 if err.errno != 3: # No such process
60 raise
61 log.debug('no such process %d', ppid)
62
63
64 # -------------------------------------------------------------------------#
65
66
Containers::map
struct GAUDI_API map
Parametrisation class for map-like implementation.
Definition: KeyedObjectManager.h:25
GaudiTesting.BaseTest.kill_tree
def kill_tree(ppid, sig)
Definition: BaseTest.py:44

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

1188 def parseHistosSummary(lines, pos):
1189 """
1190 Extract the histograms infos from the lines starting at pos.
1191 Returns the position of the first line after the summary block.
1192 """
1193 global h_count_re
1194 h_table_head = re.compile(
1195 r'SUCCESS\s+(1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"'
1196 )
1197 h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
1198
1199 nlines = len(lines)
1200
1201 # decode header
1202 m = h_count_re.search(lines[pos])
1203 name = m.group(1).strip()
1204 total = int(m.group(2))
1205 header = {}
1206 for k, v in [x.split("=") for x in m.group(3).split()]:
1207 header[k] = int(v)
1208 pos += 1
1209 header["Total"] = total
1210
1211 summ = {}
1212 while pos < nlines:
1213 m = h_table_head.search(lines[pos])
1214 if m:
1215 t, d = m.groups(1) # type and directory
1216 t = t.replace(" profile", "Prof")
1217 pos += 1
1218 if pos < nlines:
1219 l = lines[pos]
1220 else:
1221 l = ""
1222 cont = {}
1223 if l.startswith(" | ID"):
1224 # table format
1225 titles = [x.strip() for x in l.split("|")][1:]
1226 pos += 1
1227 while pos < nlines and lines[pos].startswith(" |"):
1228 l = lines[pos]
1229 values = [x.strip() for x in l.split("|")][1:]
1230 hcont = {}
1231 for i in range(len(titles)):
1232 hcont[titles[i]] = values[i]
1233 cont[hcont["ID"]] = hcont
1234 pos += 1
1235 elif l.startswith(" ID="):
1236 while pos < nlines and lines[pos].startswith(" ID="):
1237 values = [
1238 x.strip()
1239 for x in h_short_summ.search(lines[pos]).groups()
1240 ]
1241 cont[values[0]] = values
1242 pos += 1
1243 else: # not interpreted
1244 raise RuntimeError(
1245 "Cannot understand line %d: '%s'" % (pos, l))
1246 if not d in summ:
1247 summ[d] = {}
1248 summ[d][t] = cont
1249 summ[d]["header"] = header
1250 else:
1251 break
1252 if not summ:
1253 # If the full table is not present, we use only the header
1254 summ[name] = {"header": header}
1255 return summ, pos
1256
1257
Gaudi::Functional::details::zip::range
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
Definition: FunctionalDetails.h:71
GaudiTesting.BaseTest.parseHistosSummary
def parseHistosSummary(lines, pos)
Definition: BaseTest.py:1188

## ◆ PlatformIsNotSupported()

def GaudiTesting.BaseTest.PlatformIsNotSupported | ( |  | self,
|  |  | context,
|  |  | result
| ) |  |

Definition at line 1281 of file BaseTest.py.

1281 def PlatformIsNotSupported(self, context, result):
1282 platform = GetPlatform(self)
1283 unsupported = [
1284 re.compile(x) for x in [str(y).strip() for y in unsupported_platforms]
1285 if x
1286 ]
1287 for p_re in unsupported:
1288 if p_re.search(platform):
1289 result.SetOutcome(result.UNTESTED)
1290 result[result.CAUSE] = 'Platform not supported.'
1291 return True
1292 return False
1293
1294
GaudiTesting.BaseTest.GetPlatform
def GetPlatform(self)
Definition: BaseTest.py:1295
GaudiTesting.BaseTest.PlatformIsNotSupported
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1281

## ◆ RationalizePath()

def GaudiTesting.BaseTest.RationalizePath | ( |  | p | ) |

    Function used to normalize the used path

Definition at line 622 of file BaseTest.py.

622 def RationalizePath(p):
623 """
624 Function used to normalize the used path
625 """
626 newPath = os.path.normpath(os.path.expandvars(p))
627 if os.path.exists(newPath):
628 p = os.path.realpath(newPath)
629 return p
630
631
GaudiTesting.BaseTest.RationalizePath
def RationalizePath(p)
Definition: BaseTest.py:622

## ◆ ROOT6WorkAroundEnabled()

def GaudiTesting.BaseTest.ROOT6WorkAroundEnabled | ( |  | id = `None` | ) |

Definition at line 614 of file BaseTest.py.

614 def ROOT6WorkAroundEnabled(id=None):
615 # dummy implementation
616 return False
617
618
619 # --------------------------------- TOOLS ---------------------------------#
620
621
GaudiTesting.BaseTest.ROOT6WorkAroundEnabled
def ROOT6WorkAroundEnabled(id=None)
Definition: BaseTest.py:614

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

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

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

632 def which(executable):
633 """
634 Locates an executable in the executables path ($PATH) and returns the full
635 path to it. An application is looked for with or without the '.exe' suffix.
636 If the executable cannot be found, None is returned
637 """
638 if os.path.isabs(executable):
639 if not os.path.exists(executable):
640 if executable.endswith('.exe'):
641 if os.path.exists(executable[:-4]):
642 return executable[:-4]
643 else:
644 head, executable = os.path.split(executable)
645 else:
646 return executable
647 for d in os.environ.get("PATH").split(os.pathsep):
648 fullpath = os.path.join(d, executable)
649 if os.path.exists(fullpath):
650 return fullpath
651 if executable.endswith('.exe'):
652 return which(executable[:-4])
653 return None
654
655
656 # -------------------------------------------------------------------------#
657 # ----------------------------- Result Classe -----------------------------#
658 # -------------------------------------------------------------------------#
GaudiTesting.BaseTest.which
def which(executable)
Definition: BaseTest.py:632

## Variable Documentation

## ◆ __processLine__

GaudiTesting.BaseTest.__processLine__
| private

Definition at line 854 of file BaseTest.py.

## ◆ h_count_re

GaudiTesting.BaseTest.h_count_re

Initial value:
1 = re.compile(
2 r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+([\s\w=-]*)")

Definition at line 1132 of file BaseTest.py.

## ◆ lineSkipper

GaudiTesting.BaseTest.lineSkipper

Definition at line 933 of file BaseTest.py.

## ◆ maskPointers

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

Definition at line 849 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")

Definition at line 850 of file BaseTest.py.

## ◆ normalizeEOL

GaudiTesting.BaseTest.normalizeEOL = FilePreprocessor()

Definition at line 853 of file BaseTest.py.

## ◆ normalizeExamples

tuple GaudiTesting.BaseTest.normalizeExamples = maskPointers + normalizeDate

Definition at line 904 of file BaseTest.py.

## ◆ regexps

GaudiTesting.BaseTest.regexps

Definition at line 1016 of file BaseTest.py.

## ◆ skipEmptyLines

GaudiTesting.BaseTest.skipEmptyLines = FilePreprocessor()

Definition at line 856 of file BaseTest.py.