|
Gaudi Framework, version v21r4 |
| Home | Generated: 7 Sep 2009 |
Classes | |
| class | TemporaryEnvironment |
| class | TempDir |
| class | TempFile |
| class | CMT |
| class | BasicOutputValidator |
| class | FilePreprocessor |
| class | FilePreprocessorSequence |
| class | LineSkipper |
| class | BlockSkipper |
| class | RegexpReplacer |
| class | LineSorter |
| Special preprocessor sorting the list of strings (whitespace separated) that follow a signature on a single line. More... | |
| class | ReferenceFileValidator |
| class | GaudiFilterExecutable |
| class | GaudiExeTest |
Functions | |
| def | findReferenceBlock |
| def | countErrorLines |
| def | _parseTTreeSummary |
| def | findTTreeSummaries |
| def | cmpTreesDicts |
| def | getCmpFailingValues |
| def | parseHistosSummary |
| def | findHistosSummaries |
Variables | |
| string | __author__ = 'Marco Clemencic CERN/PH-LBC' |
| string | __version__ = "$Revision: 1.52 $" |
| string | __tag__ = "$Name: $" |
| tuple | maskPointers = RegexpReplacer("0x[0-9a-fA-F]{4,16}","0x########") |
| tuple | normalizeDate |
| tuple | normalizeEOL = FilePreprocessor() |
| tuple | skipEmptyLines = FilePreprocessor() |
| normalizeExamples = maskPointers+normalizeDate | |
| tuple | h_count_re = re.compile(r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+(.*)") |
| 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 594 of file GaudiTest.py.
00594 : 00595 """ 00596 Parse the TTree summary table in lines, starting from pos. 00597 Returns a tuple with the dictionary with the digested informations and the 00598 position of the first line after the summary. 00599 """ 00600 result = {} 00601 i = pos + 1 # first line is a sequence of '*' 00602 count = len(lines) 00603 00604 splitcols = lambda l: [ f.strip() for f in l.strip("*\n").split(':',2) ] 00605 def parseblock(ll): 00606 r = {} 00607 cols = splitcols(ll[0]) 00608 r["Name"], r["Title"] = cols[1:] 00609 00610 cols = splitcols(ll[1]) 00611 r["Entries"] = int(cols[1]) 00612 00613 sizes = cols[2].split() 00614 r["Total size"] = int(sizes[2]) 00615 if sizes[-1] == "memory": 00616 r["File size"] = 0 00617 else: 00618 r["File size"] = int(sizes[-1]) 00619 00620 cols = splitcols(ll[2]) 00621 sizes = cols[2].split() 00622 if cols[0] == "Baskets": 00623 r["Baskets"] = int(cols[1]) 00624 r["Basket size"] = int(sizes[2]) 00625 r["Compression"] = float(sizes[-1]) 00626 return r 00627 00628 if i < (count - 3) and lines[i].startswith("*Tree"): 00629 result = parseblock(lines[i:i+3]) 00630 result["Branches"] = {} 00631 i += 4 00632 while i < (count - 3) and lines[i].startswith("*Br"): 00633 branch = parseblock(lines[i:i+3]) 00634 result["Branches"][branch["Name"]] = branch 00635 i += 4 00636 00637 return (result, i) 00638 def findTTreeSummaries(stdout):
| 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 660 of file GaudiTest.py.
00660 : 00661 """ 00662 Check that all the keys in reference are in to_check too, with the same value. 00663 If the value is a dict, the function is called recursively. to_check can 00664 contain more keys than reference, that will not be tested. 00665 The function returns at the first difference found. 00666 """ 00667 fail_keys = [] 00668 # filter the keys in the reference dictionary 00669 if ignore: 00670 ignore_re = re.compile(ignore) 00671 keys = [ key for key in reference if not ignore_re.match(key) ] 00672 else: 00673 keys = reference.keys() 00674 # loop over the keys (not ignored) in the reference dictionary 00675 for k in keys: 00676 if k in to_check: # the key must be in the dictionary to_check 00677 if (type(reference[k]) is dict) and (type(to_check[k]) is dict): 00678 # if both reference and to_check values are dictionaries, recurse 00679 failed = fail_keys = cmpTreesDicts(reference[k], to_check[k], ignore) 00680 else: 00681 # compare the two values 00682 failed = to_check[k] != reference[k] 00683 else: # handle missing keys in the dictionary to check (i.e. failure) 00684 to_check[k] = None 00685 failed = True 00686 if failed: 00687 fail_keys.insert(0, k) 00688 break # exit from the loop at the first failure 00689 return fail_keys # return the list of keys bringing to the different values 00690 def getCmpFailingValues(reference, to_check, fail_path):
| def GaudiTest::countErrorLines | ( | expected = {'ERROR':0, |
||
| FATAL | ||||
| ) |
Definition at line 558 of file GaudiTest.py.
00558 {'ERROR':0, 'FATAL':0}, **kwargs): 00559 """ 00560 Count the number of messages with required severity (by default ERROR and FATAL) 00561 and check if their numbers match the expected ones (0 by default). 00562 The dictionary "expected" can be used to tune the number of errors and fatals 00563 allowed, or to limit the number of expected warnings etc. 00564 """ 00565 stdout = kwargs["stdout"] 00566 result = kwargs["result"] 00567 causes = kwargs["causes"] 00568 00569 # prepare the dictionary to record the extracted lines 00570 errors = {} 00571 for sev in expected: 00572 errors[sev] = [] 00573 00574 outlines = stdout.splitlines() 00575 from math import log10 00576 fmt = "%%%dd - %%s" % (int(log10(len(outlines))+1)) 00577 00578 linecount = 0 00579 for l in outlines: 00580 linecount += 1 00581 words = l.split() 00582 if len(words) >= 2 and words[1] in errors: 00583 errors[words[1]].append(fmt%(linecount,l.rstrip())) 00584 00585 for e in errors: 00586 if len(errors[e]) != expected[e]: 00587 causes.append('%s(%d)'%(e,len(errors[e]))) 00588 result["GaudiTest.lines.%s"%e] = result.Quote('\n'.join(errors[e])) 00589 result["GaudiTest.lines.%s.expected#"%e] = result.Quote(str(expected[e])) 00590 00591 return causes 00592 00593
| def GaudiTest::findHistosSummaries | ( | stdout | ) |
Scan stdout to find ROOT TTree summaries and digest them.
Definition at line 767 of file GaudiTest.py.
00767 : 00768 """ 00769 Scan stdout to find ROOT TTree summaries and digest them. 00770 """ 00771 outlines = stdout.splitlines() 00772 nlines = len(outlines) - 1 00773 summaries = {} 00774 global h_count_re 00775 00776 pos = 0 00777 while pos < nlines: 00778 summ = {} 00779 # find first line of block: 00780 match = h_count_re.search(outlines[pos]) 00781 while pos < nlines and not match: 00782 pos += 1 00783 match = h_count_re.search(outlines[pos]) 00784 if match: 00785 summ, pos = parseHistosSummary(outlines, pos) 00786 summaries.update(summ) 00787 return summaries 00788 class GaudiFilterExecutable(qm.executable.Filter):
| 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 511 of file GaudiTest.py.
00512 : 00513 """ 00514 Given a block of text, tries to find it in the output. 00515 The block had to be identified by a signature line. By default, the first 00516 line is used as signature, or the line pointed to by signature_offset. If 00517 signature_offset points outside the block, a signature line can be passed as 00518 signature argument. Note: if 'signature' is None (the default), a negative 00519 signature_offset is interpreted as index in a list (e.g. -1 means the last 00520 line), otherwise the it is interpreted as the number of lines before the 00521 first one of the block the signature must appear. 00522 The parameter 'id' allow to distinguish between different calls to this 00523 function in the same validation code. 00524 """ 00525 # split reference file, sanitize EOLs and remove empty lines 00526 reflines = filter(None,map(lambda s: s.rstrip(), reference.splitlines())) 00527 if not reflines: 00528 raise RuntimeError("Empty (or null) reference") 00529 # the same on standard output 00530 outlines = filter(None,map(lambda s: s.rstrip(), stdout.splitlines())) 00531 00532 res_field = "GaudiTest.RefBlock" 00533 if id: 00534 res_field += "_%s" % id 00535 00536 if signature is None: 00537 if signature_offset < 0: 00538 signature_offset = len(reference)+signature_offset 00539 signature = reflines[signature_offset] 00540 # find the reference block in the output file 00541 try: 00542 pos = outlines.index(signature) 00543 outlines = outlines[pos-signature_offset:pos+len(reflines)-signature_offset] 00544 if reflines != outlines: 00545 msg = "standard output" 00546 # I do not want 2 messages in causes if teh function is called twice 00547 if not msg in causes: 00548 causes.append(msg) 00549 result[res_field + ".observed"] = result.Quote("\n".join(outlines)) 00550 except ValueError: 00551 causes.append("missing signature") 00552 result[res_field + ".signature"] = result.Quote(signature) 00553 if len(reflines) > 1 or signature != reflines[0]: 00554 result[res_field + ".expected"] = result.Quote("\n".join(reflines)) 00555 00556 return causes 00557 def countErrorLines(expected = {'ERROR':0, 'FATAL':0}, **kwargs):
| def GaudiTest::findTTreeSummaries | ( | stdout | ) |
Scan stdout to find ROOT TTree summaries and digest them.
Definition at line 639 of file GaudiTest.py.
00639 : 00640 """ 00641 Scan stdout to find ROOT TTree summaries and digest them. 00642 """ 00643 stars = re.compile(r"^\*+$") 00644 outlines = stdout.splitlines() 00645 nlines = len(outlines) 00646 trees = {} 00647 00648 i = 0 00649 while i < nlines: #loop over the output 00650 # look for 00651 while i < nlines and not stars.match(outlines[i]): 00652 i += 1 00653 if i < nlines: 00654 tree, i = _parseTTreeSummary(outlines, i) 00655 if tree: 00656 trees[tree["Name"]] = tree 00657 00658 return trees 00659 def cmpTreesDicts(reference, to_check, ignore = None):
| def GaudiTest::getCmpFailingValues | ( | reference, | ||
| to_check, | ||||
| fail_path | ||||
| ) |
Definition at line 691 of file GaudiTest.py.
00691 : 00692 c = to_check 00693 r = reference 00694 for k in fail_path: 00695 c = c.get(k,None) 00696 r = r.get(k,None) 00697 if c is None or r is None: 00698 break # one of the dictionaries is not deep enough 00699 return (fail_path, r, c) 00700 00701 # signature of the print-out of the histograms h_count_re = re.compile(r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+(.*)")
| 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 704 of file GaudiTest.py.
00704 : 00705 """ 00706 Extract the histograms infos from the lines starting at pos. 00707 Returns the position of the first line after the summary block. 00708 """ 00709 global h_count_re 00710 h_table_head = re.compile(r'SUCCESS\s+List of booked (1D|2D|3D|1D profile|2D profile) histograms in directory\s+"(\w*)"') 00711 h_short_summ = re.compile(r"ID=([^\"]+)\s+\"([^\"]+)\"\s+(.*)") 00712 00713 nlines = len(lines) 00714 00715 # decode header 00716 m = h_count_re.search(lines[pos]) 00717 name = m.group(1).strip() 00718 total = int(m.group(2)) 00719 header = {} 00720 for k, v in [ x.split("=") for x in m.group(3).split() ]: 00721 header[k] = int(v) 00722 pos += 1 00723 header["Total"] = total 00724 00725 summ = {} 00726 while pos < nlines: 00727 m = h_table_head.search(lines[pos]) 00728 if m: 00729 t, d = m.groups(1) # type and directory 00730 t = t.replace(" profile", "Prof") 00731 pos += 1 00732 if pos < nlines: 00733 l = lines[pos] 00734 else: 00735 l = "" 00736 cont = {} 00737 if l.startswith(" | ID"): 00738 # table format 00739 titles = [ x.strip() for x in l.split("|")][1:] 00740 pos += 1 00741 while pos < nlines and lines[pos].startswith(" |"): 00742 l = lines[pos] 00743 values = [ x.strip() for x in l.split("|")][1:] 00744 hcont = {} 00745 for i in range(len(titles)): 00746 hcont[titles[i]] = values[i] 00747 cont[hcont["ID"]] = hcont 00748 pos += 1 00749 elif l.startswith(" ID="): 00750 while pos < nlines and lines[pos].startswith(" ID="): 00751 values = [ x.strip() for x in h_short_summ.search(lines[pos]).groups() ] 00752 cont[values[0]] = values 00753 pos += 1 00754 else: # not interpreted 00755 raise RuntimeError("Cannot understand line %d: '%s'" % (pos, l)) 00756 if not d in summ: 00757 summ[d] = {} 00758 summ[d][t] = cont 00759 summ[d]["header"] = header 00760 else: 00761 break 00762 if not summ: 00763 # If the full table is not present, we use only the header 00764 summ[name] = {"header": header} 00765 return summ, pos 00766 def findHistosSummaries(stdout):
| string GaudiTest::__author__ = 'Marco Clemencic CERN/PH-LBC' |
Definition at line 5 of file GaudiTest.py.
| string GaudiTest::__tag__ = "$Name: $" |
Definition at line 7 of file GaudiTest.py.
| string GaudiTest::__version__ = "$Revision: 1.52 $" |
Definition at line 6 of file GaudiTest.py.
| tuple GaudiTest::h_count_re = re.compile(r"^(.*)SUCCESS\s+Booked (\d+) Histogram\(s\) :\s+(.*)") |
Definition at line 702 of file GaudiTest.py.
| tuple GaudiTest::maskPointers = RegexpReplacer("0x[0-9a-fA-F]{4,16}","0x########") |
Definition at line 390 of file GaudiTest.py.
| tuple GaudiTest::normalizeDate |
Initial value:
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)?", "00:00:00 1970-01-01")
Definition at line 391 of file GaudiTest.py.
| tuple GaudiTest::normalizeEOL = FilePreprocessor() |
Definition at line 393 of file GaudiTest.py.
Definition at line 416 of file GaudiTest.py.
| tuple GaudiTest::skipEmptyLines = FilePreprocessor() |
Definition at line 396 of file GaudiTest.py.