| The Gaudi Framework v27r1

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- Namespace List
- Namespace Members

Classes | Functions | Variables
GaudiTest Namespace Reference

## Classes
class | BasicOutputValidator
| Output Validation Classes. More...
class | BlockSkipper
class | CMT
class | FilePreprocessor
class | FilePreprocessorSequence
class | GaudiExeTest
class | GaudiFilterExecutable
class | HTMLResultStream
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 | TempDir
class | TempFile
class | TemporaryEnvironment
| Utility Classes. More...
class | XMLResultStream

## Functions
def | ROOT6WorkAroundEnabled
def | total_seconds_replacement (timedelta)
def | which (executable)
| Locates an executable in the executables path ($PATH) and returns the full path to it. More...
def | rationalizepath (p)
def | hexreplace (match)
def | hexConvert (char)
def | convert_xml_illegal_chars (val)
def | escape_xml_illegal_chars
def | findReferenceBlock
def | countErrorLines
def | _parseTTreeSummary (lines, pos)
def | findTTreeSummaries (stdout)
def | cmpTreesDicts
def | getCmpFailingValues (reference, to_check, fail_path)
def | parseHistosSummary (lines, pos)
def | findHistosSummaries (stdout)

## Variables
string | __author__ = 'Marco Clemencic CERN/PH-LBC'
| File: GaudiTest.py Author: Marco Clemencic CERN/PH-LBC. More...
tuple | _illegal_xml_chars_RE = re.compile(u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]')
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 GaudiTest._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 712 of file GaudiTest.py.

712 def _parseTTreeSummary(lines, pos):
713 """
714 Parse the TTree summary table in lines, starting from pos.
715 Returns a tuple with the dictionary with the digested informations and the
716 position of the first line after the summary.
717 """
718 result = {}
719 i = pos + 1 # first line is a sequence of '*'
720 count = len(lines)
721
722 splitcols = lambda l: [ f.strip() for f in l.strip("*\n").split(':',2) ]
723 def parseblock(ll):
724 r = {}
725 cols = splitcols(ll[0])
726 r["Name"], r["Title"] = cols[1:]
727
728 cols = splitcols(ll[1])
729 r["Entries"] = int(cols[1])
730
731 sizes = cols[2].split()
732 r["Total size"] = int(sizes[2])
733 if sizes[-1] == "memory":
734 r["File size"] = 0
735 else:
736 r["File size"] = int(sizes[-1])
737
738 cols = splitcols(ll[2])
739 sizes = cols[2].split()
740 if cols[0] == "Baskets":
741 r["Baskets"] = int(cols[1])
742 r["Basket size"] = int(sizes[2])
743 r["Compression"] = float(sizes[-1])
744 return r
745
746 if i < (count - 3) and lines[i].startswith("*Tree"):
747 result = parseblock(lines[i:i+3])
748 result["Branches"] = {}
749 i += 4
750 while i < (count - 3) and lines[i].startswith("*Br"):
751 if i < (count - 2) and lines[i].startswith("*Branch "):
752 # skip branch header
753 i += 3
754 continue
755 branch = parseblock(lines[i:i+3])
756 result["Branches"][branch["Name"]] = branch
757 i += 4
758
759 return (result, i)
760
GaudiTest._parseTTreeSummary
def _parseTTreeSummary(lines, pos)
Definition: GaudiTest.py:712

def GaudiTest.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 782 of file GaudiTest.py.

782 def cmpTreesDicts(reference, to_check, ignore = None):
783 """
784 Check that all the keys in reference are in to_check too, with the same value.
785 If the value is a dict, the function is called recursively. to_check can
786 contain more keys than reference, that will not be tested.
787 The function returns at the first difference found.
788 """
789 fail_keys = []
790 # filter the keys in the reference dictionary
791 if ignore:
792 ignore_re = re.compile(ignore)
793 keys = [ key for key in reference if not ignore_re.match(key) ]
794 else:
795 keys = reference.keys()
796 # loop over the keys (not ignored) in the reference dictionary
797 for k in keys:
798 if k in to_check: # the key must be in the dictionary to_check
799 if (type(reference[k]) is dict) and (type(to_check[k]) is dict):
800 # if both reference and to_check values are dictionaries, recurse
801 failed = fail_keys = cmpTreesDicts(reference[k], to_check[k], ignore)
802 else:
803 # compare the two values
804 failed = to_check[k] != reference[k]
805 else: # handle missing keys in the dictionary to check (i.e. failure)
806 to_check[k] = None
807 failed = True
808 if failed:
809 fail_keys.insert(0, k)
810 break # exit from the loop at the first failure
811 return fail_keys # return the list of keys bringing to the different values
812
gaudirun.type
string type
Definition: gaudirun.py:151
GaudiTest.cmpTreesDicts
def cmpTreesDicts
Definition: GaudiTest.py:782

def GaudiTest.convert_xml_illegal_chars | ( |  | val | ) |

Definition at line 337 of file GaudiTest.py.

337 def convert_xml_illegal_chars(val):
338 return _illegal_xml_chars_RE.sub(hexreplace, val)
339
GaudiTest.convert_xml_illegal_chars
def convert_xml_illegal_chars(val)
Definition: GaudiTest.py:337

def GaudiTest.countErrorLines | ( |  | expected = `{'ERROR':0`,
|  |  | FATAL
| ) |  |

Definition at line 676 of file GaudiTest.py.

676 def countErrorLines(expected = {'ERROR':0, 'FATAL':0}, **kwargs):
677 """
678 Count the number of messages with required severity (by default ERROR and FATAL)
679 and check if their numbers match the expected ones (0 by default).
680 The dictionary "expected" can be used to tune the number of errors and fatals
681 allowed, or to limit the number of expected warnings etc.
682 """
683 stdout = kwargs["stdout"]
684 result = kwargs["result"]
685 causes = kwargs["causes"]
686
687 # prepare the dictionary to record the extracted lines
688 errors = {}
689 for sev in expected:
690 errors[sev] = []
691
692 outlines = stdout.splitlines()
693 from math import log10
694 fmt = "%%%dd - %%s" % (int(log10(len(outlines))+1))
695
696 linecount = 0
697 for l in outlines:
698 linecount += 1
699 words = l.split()
700 if len(words) >= 2 and words[1] in errors:
701 errors[words[1]].append(fmt%(linecount,l.rstrip()))
702
703 for e in errors:
704 if len(errors[e]) != expected[e]:
705 causes.append('%s(%d)'%(e,len(errors[e])))
706 result["GaudiTest.lines.%s"%e] = result.Quote('\n'.join(errors[e]))
707 result["GaudiTest.lines.%s.expected#"%e] = result.Quote(str(expected[e]))
708
709 return causes
710
711
GaudiTest.countErrorLines
def countErrorLines
Definition: GaudiTest.py:676

def GaudiTest.escape_xml_illegal_chars | ( |  | val,
|  |  | replacement = `'?'`
| ) |  |

    Filter out characters that are illegal in XML.
    Looks for any character in val that is not allowed in XML
    and replaces it with replacement ('?' by default).

Definition at line 340 of file GaudiTest.py.

340 def escape_xml_illegal_chars(val, replacement='?'):
341 """Filter out characters that are illegal in XML.
342 Looks for any character in val that is not allowed in XML
343 and replaces it with replacement ('?' by default).
344
345 """
346 return _illegal_xml_chars_RE.sub(replacement, val)
347
GaudiTest.escape_xml_illegal_chars
def escape_xml_illegal_chars
Definition: GaudiTest.py:340

def GaudiTest.findHistosSummaries | ( |  | stdout | ) |

    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 889 of file GaudiTest.py.

889 def findHistosSummaries(stdout):
890 """
891 Scan stdout to find ROOT TTree summaries and digest them.
892 """
893 outlines = stdout.splitlines()
894 nlines = len(outlines) - 1
895 summaries = {}
896 global h_count_re
897
898 pos = 0
899 while pos < nlines:
900 summ = {}
901 # find first line of block:
902 match = h_count_re.search(outlines[pos])
903 while pos < nlines and not match:
904 pos += 1
905 match = h_count_re.search(outlines[pos])
906 if match:
907 summ, pos = parseHistosSummary(outlines, pos)
908 summaries.update(summ)
909 return summaries
910
GaudiTest.parseHistosSummary
def parseHistosSummary(lines, pos)
Definition: GaudiTest.py:826
GaudiTest.findHistosSummaries
def findHistosSummaries(stdout)
Definition: GaudiTest.py:889

def GaudiTest.findReferenceBlock | ( |  | reference,
|  |  | stdout,
|  |  | result,
|  |  | causes,
|  |  | signature_offset = `0`,
|  |  | signature = `None`,
|  |  | id = `None`
| ) |  |

    Given a block of text, tries to find it in the output.
    The block had to be identified by a signature line. By default, the first
    line is used as signature, or the line pointed to by signature_offset. If
    signature_offset points outside the block, a signature line can be passed as
    signature argument. Note: if 'signature' is None (the default), a negative
    signature_offset is interpreted as index in a list (e.g. -1 means the last
    line), otherwise the it is interpreted as the number of lines before the
    first one of the block the signature must appear.
    The parameter 'id' allow to distinguish between different calls to this
    function in the same validation code.

Definition at line 630 of file GaudiTest.py.

630 id = None):
631 """
632 Given a block of text, tries to find it in the output.
633 The block had to be identified by a signature line. By default, the first
634 line is used as signature, or the line pointed to by signature_offset. If
635 signature_offset points outside the block, a signature line can be passed as
636 signature argument. Note: if 'signature' is None (the default), a negative
637 signature_offset is interpreted as index in a list (e.g. -1 means the last
638 line), otherwise the it is interpreted as the number of lines before the
639 first one of the block the signature must appear.
640 The parameter 'id' allow to distinguish between different calls to this
641 function in the same validation code.
642 """
643 # split reference file, sanitize EOLs and remove empty lines
644 reflines = filter(None,map(lambda s: s.rstrip(), reference.splitlines()))
645 if not reflines:
646 raise RuntimeError("Empty (or null) reference")
647 # the same on standard output
648 outlines = filter(None,map(lambda s: s.rstrip(), stdout.splitlines()))
649
650 res_field = "GaudiTest.RefBlock"
651 if id:
652 res_field += "_%s" % id
653
654 if signature is None:
655 if signature_offset < 0:
656 signature_offset = len(reference)+signature_offset
657 signature = reflines[signature_offset]
658 # find the reference block in the output file
659 try:
660 pos = outlines.index(signature)
661 outlines = outlines[pos-signature_offset:pos+len(reflines)-signature_offset]
662 if reflines != outlines:
663 msg = "standard output"
664 # I do not want 2 messages in causes if teh function is called twice
665 if not msg in causes:
666 causes.append(msg)
667 result[res_field + ".observed"] = result.Quote("\n".join(outlines))
668 except ValueError:
669 causes.append("missing signature")
670 result[res_field + ".signature"] = result.Quote(signature)
671 if len(reflines) > 1 or signature != reflines[0]:
672 result[res_field + ".expected"] = result.Quote("\n".join(reflines))
673
674 return causes
675
Containers::map
struct GAUDI_API map
Parametrisation class for map-like implementation.
Definition: KeyedObjectManager.h:25

def GaudiTest.findTTreeSummaries | ( |  | stdout | ) |

    Scan stdout to find ROOT TTree summaries and digest them.

Definition at line 761 of file GaudiTest.py.

761 def findTTreeSummaries(stdout):
762 """
763 Scan stdout to find ROOT TTree summaries and digest them.
764 """
765 stars = re.compile(r"^\*+$")
766 outlines = stdout.splitlines()
767 nlines = len(outlines)
768 trees = {}
769
770 i = 0
771 while i < nlines: #loop over the output
772 # look for
773 while i < nlines and not stars.match(outlines[i]):
774 i += 1
775 if i < nlines:
776 tree, i = _parseTTreeSummary(outlines, i)
777 if tree:
778 trees[tree["Name"]] = tree
779
780 return trees
781
GaudiTest._parseTTreeSummary
def _parseTTreeSummary(lines, pos)
Definition: GaudiTest.py:712
GaudiTest.findTTreeSummaries
def findTTreeSummaries(stdout)
Definition: GaudiTest.py:761

def GaudiTest.getCmpFailingValues | ( |  | reference,
|  |  | to_check,
|  |  | fail_path
| ) |  |

Definition at line 813 of file GaudiTest.py.

813 def getCmpFailingValues(reference, to_check, fail_path):
814 c = to_check
815 r = reference
816 for k in fail_path:
817 c = c.get(k,None)
818 r = r.get(k,None)
819 if c is None or r is None:
820 break # one of the dictionaries is not deep enough
821 return (fail_path, r, c)
822
823 # signature of the print-out of the histograms
GaudiTest.getCmpFailingValues
def getCmpFailingValues(reference, to_check, fail_path)
Definition: GaudiTest.py:813

def GaudiTest.hexConvert | ( |  | char | ) |

Definition at line 335 of file GaudiTest.py.

335 def hexConvert(char):
336 return hex(ord(char))
GaudiTest.hexConvert
def hexConvert(char)
Definition: GaudiTest.py:335

def GaudiTest.hexreplace | ( |  | match | ) |

Definition at line 331 of file GaudiTest.py.

331 def hexreplace( match ):
332 "Return the hex string "
333 return "".join(map(hexConvert,match.group()))
334
GaudiTest.hexreplace
def hexreplace(match)
Definition: GaudiTest.py:331
Containers::map
struct GAUDI_API map
Parametrisation class for map-like implementation.
Definition: KeyedObjectManager.h:25

def GaudiTest.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 826 of file GaudiTest.py.

826 def parseHistosSummary(lines, pos):
827 """
828 Extract the histograms infos from the lines starting at pos.
829 Returns the position of the first line after the summary block.
830 """
831 global h_count_re
832 h_table_head = re.compile(r'SUCCESS\s+List of booked (1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"')
833 h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)")
834
835 nlines = len(lines)
836
837 # decode header
838 m = h_count_re.search(lines[pos])
839 name = m.group(1).strip()
840 total = int(m.group(2))
841 header = {}
842 for k, v in [ x.split("=") for x in m.group(3).split() ]:
843 header[k] = int(v)
844 pos += 1
845 header["Total"] = total
846
847 summ = {}
848 while pos < nlines:
849 m = h_table_head.search(lines[pos])
850 if m:
851 t, d = m.groups(1) # type and directory
852 t = t.replace(" profile", "Prof")
853 pos += 1
854 if pos < nlines:
855 l = lines[pos]
856 else:
857 l = ""
858 cont = {}
859 if l.startswith(" | ID"):
860 # table format
861 titles = [ x.strip() for x in l.split("|")][1:]
862 pos += 1
863 while pos < nlines and lines[pos].startswith(" |"):
864 l = lines[pos]
865 values = [ x.strip() for x in l.split("|")][1:]
866 hcont = {}
867 for i in range(len(titles)):
868 hcont[titles[i]] = values[i]
869 cont[hcont["ID"]] = hcont
870 pos += 1
871 elif l.startswith(" ID="):
872 while pos < nlines and lines[pos].startswith(" ID="):
873 values = [ x.strip() for x in h_short_summ.search(lines[pos]).groups() ]
874 cont[values[0]] = values
875 pos += 1
876 else: # not interpreted
877 raise RuntimeError("Cannot understand line %d: '%s'" % (pos, l))
878 if not d in summ:
879 summ[d] = {}
880 summ[d][t] = cont
881 summ[d]["header"] = header
882 else:
883 break
884 if not summ:
885 # If the full table is not present, we use only the header
886 summ[name] = {"header": header}
887 return summ, pos
888
GaudiTest.parseHistosSummary
def parseHistosSummary(lines, pos)
Definition: GaudiTest.py:826
Gaudi::range
NamedRange_< CONTAINER > range(const CONTAINER &cnt, std::string name)
simple function to create the named range form arbitrary container
Definition: NamedRange.h:130

def GaudiTest.rationalizepath | ( |  | p | ) |

Definition at line 309 of file GaudiTest.py.

309 def rationalizepath(p):
310 np = os.path.normpath(os.path.expandvars(p))
311 if os.path.exists(np):
312 p = os.path.realpath(np)
313 return p
314
315 # XML Escaping character
GaudiTest.rationalizepath
def rationalizepath(p)
Definition: GaudiTest.py:309

def GaudiTest.ROOT6WorkAroundEnabled | ( |  | id = `None` | ) |

Definition at line 25 of file GaudiTest.py.

25 def ROOT6WorkAroundEnabled(id=None):
26 # dummy implementation
27 return False
28
29 # ensure the preferred locale
30 os.environ['LC_ALL'] = 'C'
31
32 # Needed for the XML wrapper
33 try:
GaudiTest.ROOT6WorkAroundEnabled
def ROOT6WorkAroundEnabled
Definition: GaudiTest.py:25

def GaudiTest.total_seconds_replacement | ( |  | timedelta | ) |

Definition at line 39 of file GaudiTest.py.

39 def total_seconds_replacement(timedelta) :
40 return timedelta.days*86400 + timedelta.seconds + timedelta.microseconds/1000000
41
42
GaudiTest.total_seconds_replacement
def total_seconds_replacement(timedelta)
Definition: GaudiTest.py:39

def GaudiTest.which | ( |  | executable | ) |

Locates an executable in the executables path ($PATH) and returns the full path to it.

If the executable cannot be found, None is returned

    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 289 of file GaudiTest.py.

289 def which(executable):
290 """
291 Locates an executable in the executables path ($PATH) and returns the full
292 path to it. An application is looked for with or without the '.exe' suffix.
293 If the executable cannot be found, None is returned
294 """
295 if os.path.isabs(executable):
296 if not os.path.exists(executable):
297 if executable.endswith('.exe'):
298 if os.path.exists(executable[:-4]):
299 return executable[:-4]
300 return executable
301 for d in os.environ.get("PATH").split(os.pathsep):
302 fullpath = os.path.join(d, executable)
303 if os.path.exists(fullpath):
304 return fullpath
305 if executable.endswith('.exe'):
306 return which(executable[:-4])
307 return None
308
GaudiTest.which
def which(executable)
Locates an executable in the executables path ($PATH) and returns the full path to it...
Definition: GaudiTest.py:289

## Variable Documentation

string GaudiTest.__author__ = 'Marco Clemencic CERN/PH-LBC'

File: GaudiTest.py Author: Marco Clemencic CERN/PH-LBC.

Definition at line 5 of file GaudiTest.py.

tuple GaudiTest._illegal_xml_chars_RE = re.compile(u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]')

Definition at line 329 of file GaudiTest.py.

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

Definition at line 824 of file GaudiTest.py.

tuple GaudiTest.lineSkipper

Definition at line 530 of file GaudiTest.py.

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

Definition at line 483 of file GaudiTest.py.

tuple GaudiTest.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] *(CES?T)?",
2 "00:00:00 1970-01-01")
GaudiTest.RegexpReplacer
Definition: GaudiTest.py:464

Definition at line 484 of file GaudiTest.py.

tuple GaudiTest.normalizeEOL = FilePreprocessor()

Definition at line 486 of file GaudiTest.py.

tuple GaudiTest.normalizeExamples = maskPointers+normalizeDate

Definition at line 509 of file GaudiTest.py.

tuple GaudiTest.skipEmptyLines = FilePreprocessor()

Definition at line 489 of file GaudiTest.py.