| # Gaudi Framework, version v20r4
Generated: 8 Jan 2009

# GaudiTest::GaudiExeTest Class Reference

Inheritance diagram for GaudiTest::GaudiExeTest:

[legend]
Collaboration diagram for GaudiTest::GaudiExeTest:

[legend]

List of all members.

## Detailed Description

    Standard Gaudi test.

Definition at line 751 of file GaudiTest.py.

## Public Member Functions
def | PlatformIsNotSupported
def | GetPlatform
def | CheckTTreesSummaries
def | CheckHistosSummaries
def | ValidateWithReference
def | ValidateOutput
def | DumpEnvironment
def | Run
def | RunProgram
## Public Attributes
| callable
| extra_args
| args_order
| program
| reference
| error_reference
| use_temp_dir
| timeout
## Static Public Attributes
list | arguments
## Private Member Functions
def | _expandReferenceFileName
def | _find_program

## Member Function Documentation

def GaudiTest::GaudiExeTest::PlatformIsNotSupported | ( |  | self,
|  |  | context,
|  |  | result |
| ) |  |  |

Definition at line 868 of file GaudiTest.py.

    00868                                                      :
    00869         platform = self.GetPlatform()
    00870         unsupported = [ re.compile(x)
    00871                         for x in [ str(y).strip()
    00872                                    for y in self.unsupported_platforms ]
    00873                         if x
    00874                        ]
    00875         for p_re in unsupported:
    00876             if p_re.search(platform):
    00877                 result.SetOutcome(result.UNTESTED)
    00878                 result[result.CAUSE] = 'Platform not supported.'
    00879                 return True
    00880         return False
    00881
        def GetPlatform(self):

def GaudiTest::GaudiExeTest::GetPlatform | ( |  | self | ) |

    Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 882 of file GaudiTest.py.

    00882                          :
    00883         """
    00884         Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
    00885         """
    00886         arch = "None"
    00887         # check architecture name
    00888         if "CMTCONFIG" in os.environ:
    00889             arch = os.environ["CMTCONFIG"]
    00890         elif "SCRAM_ARCH" in os.environ:
    00891             arch = os.environ["SCRAM_ARCH"]
    00892         return arch
    00893
        def _expandReferenceFileName(self, reffile):

def GaudiTest::GaudiExeTest::_expandReferenceFileName | ( |  | self,
|  |  | reffile |
| ) |  |  | `[private]`

Definition at line 894 of file GaudiTest.py.

    00894                                                :
    00895         # if no file is passed, do nothing
    00896         if not reffile:
    00897             return ""
    00898
    00899         reference = os.path.normpath(os.path.expandvars(reffile))
    00900         # old-style platform-specific reference name
    00901         spec_ref = reference[:-3] + self.GetPlatform()[0:3] + reference[-3:]
    00902         if os.path.isfile(spec_ref):
    00903             reference = spec_ref
    00904         else: # look for new-style platform specific reference files:
    00905             # get all the files whose name start with the reference filename
    00906             dirname, basename = os.path.split(reference)
    00907             if not dirname: dirname = '.'
    00908             head = basename + "."
    00909             head_len = len(head)
    00910             platform = self.GetPlatform()
    00911             candidates = []
    00912             for f in os.listdir(dirname):
    00913                 if f.startswith(head) and platform.startswith(f[head_len:]):
    00914                     candidates.append( (len(f) - head_len, f) )
    00915             if candidates: # take the one with highest matching
    00916                 candidates.sort()
    00917                 reference = os.path.join(dirname, candidates[-1][1])
    00918         return reference
    00919
        def CheckTTreesSummaries(self, stdout, result, causes,

def GaudiTest::GaudiExeTest::CheckTTreesSummaries | ( |  | self,
|  |  | stdout,
|  |  | result,
|  |  | causes,
|  |  | trees_dict = `None`,
|  |  | ignore = `r"Basket|.*size|Compression"` |
| ) |  |  |

    Compare the TTree summaries in stdout with the ones in trees_dict or in
    the reference file. By default ignore the size, compression and basket
    fields.
    The presence of TTree summaries when none is expected is not a failure.

Definition at line 920 of file GaudiTest.py.

    00922                                                                    :
    00923         """
    00924         Compare the TTree summaries in stdout with the ones in trees_dict or in
    00925         the reference file. By default ignore the size, compression and basket
    00926         fields.
    00927         The presence of TTree summaries when none is expected is not a failure.
    00928         """
    00929         if trees_dict is None:
    00930             reference = self._expandReferenceFileName(self.reference)
    00931             # call the validator if the file exists
    00932             if reference and os.path.isfile(reference):
    00933                 trees_dict = findTTreeSummaries(open(reference).read())
    00934             else:
    00935                 trees_dict = {}
    00936
    00937         from pprint import PrettyPrinter
    00938         pp = PrettyPrinter()
    00939         if trees_dict:
    00940             result["GaudiTest.TTrees.expected"] = result.Quote(pp.pformat(trees_dict))
    00941             if ignore:
    00942                 result["GaudiTest.TTrees.ignore"] = result.Quote(ignore)
    00943
    00944         trees = findTTreeSummaries(stdout)
    00945         failed = cmpTreesDicts(trees_dict, trees, ignore)
    00946         if failed:
    00947             causes.append("trees summaries")
    00948             msg = "%s: %s != %s" % getCmpFailingValues(trees_dict, trees, failed)
    00949             result["GaudiTest.TTrees.failure_on"] = result.Quote(msg)
    00950             result["GaudiTest.TTrees.found"] = result.Quote(pp.pformat(trees))
    00951
    00952         return causes
    00953
        def CheckHistosSummaries(self, stdout, result, causes,

def GaudiTest::GaudiExeTest::CheckHistosSummaries | ( |  | self,
|  |  | stdout,
|  |  | result,
|  |  | causes,
|  |  | dict = `None`,
|  |  | ignore = `None` |
| ) |  |  |

    Compare the TTree summaries in stdout with the ones in trees_dict or in
    the reference file. By default ignore the size, compression and basket
    fields.
    The presence of TTree summaries when none is expected is not a failure.

Definition at line 954 of file GaudiTest.py.

    00956                                            :
    00957         """
    00958         Compare the TTree summaries in stdout with the ones in trees_dict or in
    00959         the reference file. By default ignore the size, compression and basket
    00960         fields.
    00961         The presence of TTree summaries when none is expected is not a failure.
    00962         """
    00963         if dict is None:
    00964             reference = self._expandReferenceFileName(self.reference)
    00965             # call the validator if the file exists
    00966             if reference and os.path.isfile(reference):
    00967                 dict = findHistosSummaries(open(reference).read())
    00968             else:
    00969                 dict = {}
    00970
    00971         from pprint import PrettyPrinter
    00972         pp = PrettyPrinter()
    00973         if dict:
    00974             result["GaudiTest.Histos.expected"] = result.Quote(pp.pformat(dict))
    00975             if ignore:
    00976                 result["GaudiTest.Histos.ignore"] = result.Quote(ignore)
    00977
    00978         histos = findHistosSummaries(stdout)
    00979         failed = cmpTreesDicts(dict, histos, ignore)
    00980         if failed:
    00981             causes.append("histos summaries")
    00982             msg = "%s: %s != %s" % getCmpFailingValues(dict, histos, failed)
    00983             result["GaudiTest.Histos.failure_on"] = result.Quote(msg)
    00984             result["GaudiTest.Histos.found"] = result.Quote(pp.pformat(histos))
    00985
    00986         return causes
    00987
        def ValidateWithReference(self, stdout, stderr, result, causes, preproc = None):

def GaudiTest::GaudiExeTest::ValidateWithReference | ( |  | self,
|  |  | stdout,
|  |  | stderr,
|  |  | result,
|  |  | causes,
|  |  | preproc = `None` |
| ) |  |  |

    Default validation action: compare standard output and error to the
    reference files.

Definition at line 988 of file GaudiTest.py.

    00988                                                                                    :
    00989         """
    00990         Default validation action: compare standard output and error to the
    00991         reference files.
    00992         """
    00993         # set the default output preprocessor
    00994         if preproc is None:
    00995             preproc = normalizeExamples
    00996         # check standard output
    00997         reference = self._expandReferenceFileName(self.reference)
    00998         # call the validator if the file exists
    00999         if reference and os.path.isfile(reference):
    01000             result["GaudiTest.output_reference"] = reference
    01001             causes += ReferenceFileValidator(reference,
    01002                                              "standard output",
    01003                                              "GaudiTest.output_diff",
    01004                                              preproc = preproc)(stdout, result)
    01005
    01006         # Compare TTree summaries
    01007         causes = self.CheckTTreesSummaries(stdout, result, causes)
    01008         causes = self.CheckHistosSummaries(stdout, result, causes)
    01009
    01010         if causes: # Write a new reference file for stdout
    01011             newref = open(reference + ".new","w")
    01012             # sanitize newlines
    01013             for l in stdout.splitlines():
    01014                 newref.write(l.rstrip() + '\n')
    01015             del newref # flush and close
    01016
    01017
    01018         # check standard error
    01019         reference = self._expandReferenceFileName(self.error_reference)
    01020         # call the validator if we have a file to use
    01021         if reference and os.path.isfile(reference):
    01022             result["GaudiTest.error_reference"] = reference
    01023             newcauses = ReferenceFileValidator(reference,
    01024                                                "standard error",
    01025                                                "GaudiTest.error_diff",
    01026                                                preproc = preproc)(stderr, result)
    01027             causes += newcauses
    01028             if newcauses: # Write a new reference file for stdedd
    01029                 newref = open(reference + ".new","w")
    01030                 # sanitize newlines
    01031                 for l in stderr.splitlines():
    01032                     newref.write(l.rstrip() + '\n')
    01033                 del newref # flush and close
    01034         else:
    01035             causes += BasicOutputValidator(self.stderr,
    01036                                            "standard error",
    01037                                            "ExecTest.expected_stderr")(stderr, result)
    01038
    01039         return causes
    01040
        def ValidateOutput(self, stdout, stderr, result):

def GaudiTest::GaudiExeTest::ValidateOutput | ( |  | self,
|  |  | stdout,
|  |  | stderr,
|  |  | result |
| ) |  |  |

Definition at line 1041 of file GaudiTest.py.

    01041                                                     :
    01042         causes = []
    01043         # if the test definition contains a custom validator, use it
    01044         if self.validator.strip() != "":
    01045             class CallWrapper(object):
    01046                 """
    01047                 Small wrapper class to dynamically bind some default arguments
    01048                 to a callable.
    01049                 """
    01050                 def __init__(self, callable, extra_args = {}):
    01051                     self.callable = callable
    01052                     self.extra_args = extra_args
    01053                     # get the list of names of positional arguments
    01054                     from inspect import getargspec
    01055                     self.args_order = getargspec(callable)[0]
    01056                     # Remove "self" from the list of positional arguments
    01057                     # since it is added automatically
    01058                     if self.args_order[0] == "self":
    01059                         del self.args_order[0]
    01060                 def __call__(self, *args, **kwargs):
    01061                     # Check which positional arguments are used
    01062                     positional = self.args_order[:len(args)]
    01063
    01064                     kwargs = dict(kwargs) # copy the arguments dictionary
    01065                     for a in self.extra_args:
    01066                         # use "extra_args" for the arguments not specified as
    01067                         # positional or keyword
    01068                         if a not in positional and a not in kwargs:
    01069                             kwargs[a] = self.extra_args[a]
    01070                     return apply(self.callable, args, kwargs)
    01071             # local names to be exposed in the script
    01072             exported_symbols = {"self":self,
    01073                                 "stdout":stdout,
    01074                                 "stderr":stderr,
    01075                                 "result":result,
    01076                                 "causes":causes,
    01077                                 "findReferenceBlock":
    01078                                     CallWrapper(findReferenceBlock, {"stdout":stdout,
    01079                                                                      "result":result,
    01080                                                                      "causes":causes}),
    01081                                 "validateWithReference":
    01082                                     CallWrapper(self.ValidateWithReference, {"stdout":stdout,
    01083                                                                              "stderr":stderr,
    01084                                                                              "result":result,
    01085                                                                              "causes":causes}),
    01086                                 "countErrorLines":
    01087                                     CallWrapper(countErrorLines, {"stdout":stdout,
    01088                                                                   "result":result,
    01089                                                                   "causes":causes}),
    01090                                 "checkTTreesSummaries":
    01091                                     CallWrapper(self.CheckTTreesSummaries, {"stdout":stdout,
    01092                                                                             "result":result,
    01093                                                                             "causes":causes}),
    01094                                 "checkHistosSummaries":
    01095                                     CallWrapper(self.CheckHistosSummaries, {"stdout":stdout,
    01096                                                                             "result":result,
    01097                                                                             "causes":causes}),
    01098
    01099                                 }
    01100             exec self.validator in globals(), exported_symbols
    01101         else:
    01102             self.ValidateWithReference(stdout, stderr, result, causes)
    01103
    01104         return causes
    01105
        def DumpEnvironment(self, result):

def GaudiTest::GaudiExeTest::DumpEnvironment | ( |  | self,
|  |  | result |
| ) |  |  |

    Add the content of the environment to the result object.

    Copied from the QMTest class of COOL.

Definition at line 1106 of file GaudiTest.py.

    01106                                      :
    01107         """
    01108         Add the content of the environment to the result object.
    01109
    01110         Copied from the QMTest class of COOL.
    01111         """
    01112         vars = os.environ.keys()
    01113         vars.sort()
    01114         result['GaudiTest.environment'] = \
    01115             result.Quote('\n'.join(["%s=%s"%(v,os.environ[v]) for v in vars]))
    01116
        def _find_program(self,prog):

def GaudiTest::GaudiExeTest::_find_program | ( |  | self,
|  |  | prog |
| ) |  |  | `[private]`

Definition at line 1117 of file GaudiTest.py.

    01117                                 :
    01118         # check if it is an absolute path or the file can be found
    01119         # from the local directory, otherwise search for it in PATH
    01120         if not os.path.isabs(prog) and not os.path.isfile(prog):
    01121             for d in os.environ["PATH"].split(os.pathsep):
    01122                 p = os.path.join(d,prog)
    01123                 if os.path.isfile(p):
    01124                     return p
    01125         return prog
    01126
        def Run(self, context, result):

def GaudiTest::GaudiExeTest::Run | ( |  | self,
|  |  | context,
|  |  | result |
| ) |  |  |

    Run the test.

    'context' -- A 'Context' giving run-time parameters to the
    test.

    'result' -- A 'Result' object.  The outcome will be
    'Result.PASS' when this method is called.  The 'result' may be
    modified by this method to indicate outcomes other than
    'Result.PASS' or to add annotations.

Definition at line 1127 of file GaudiTest.py.

    01127                                   :
    01128         """Run the test.
    01129
    01130         'context' -- A 'Context' giving run-time parameters to the
    01131         test.
    01132
    01133         'result' -- A 'Result' object.  The outcome will be
    01134         'Result.PASS' when this method is called.  The 'result' may be
    01135         modified by this method to indicate outcomes other than
    01136         'Result.PASS' or to add annotations."""
    01137
    01138         # Check if the platform is supported
    01139         if self.PlatformIsNotSupported(context, result):
    01140             return
    01141
    01142         def rationalizepath(p):
    01143             p = os.path.normpath(os.path.expandvars(p))
    01144             if os.path.exists(p):
    01145                 p = os.path.realpath(p)
    01146             return p
    01147
    01148         # Prepare program name and arguments (expanding variables, and converting to absolute)
    01149         if self.program:
    01150             prog = rationalizepath(self.program)
    01151         elif "GAUDIEXE" in os.environ:
    01152             prog = os.environ["GAUDIEXE"]
    01153         else:
    01154             prog = "Gaudi.exe"
    01155         self.program = prog
    01156
    01157         dummy, prog_ext = os.path.splitext(prog)
    01158         if prog_ext not in [ ".exe", ".py", ".bat" ] and self.GetPlatform()[0:3] == "win":
    01159             prog += ".exe"
    01160             prog_ext = ".exe"
    01161
    01162         prog = self._find_program(prog)
    01163
    01164         # Convert paths to absolute paths in arguments and reference files
    01165         args = map(rationalizepath, self.args)
    01166         self.reference = rationalizepath(self.reference)
    01167         self.error_reference = rationalizepath(self.error_reference)
    01168
    01169
    01170         # check if the user provided inline options
    01171         tmpfile = None
    01172         if self.options.strip():
    01173             ext = ".opts"
    01174             if re.search(r"from\s*Gaudi.Configuration\s*import\s*\*", self.options):
    01175                 ext = ".py"
    01176             tmpfile = TempFile(ext)
    01177             tmpfile.writelines("\n".join(self.options.splitlines()))
    01178             tmpfile.flush()
    01179             args.append(tmpfile.name)
    01180             result["GaudiTest.options"] = result.Quote(self.options)
    01181
    01182         # if the program is a python file, execute it through python
    01183         if prog_ext == ".py":
    01184             args.insert(0,prog)
    01185             if self.GetPlatform()[0:3] == "win":
    01186                 prog = self._find_program("python.exe")
    01187             else:
    01188                 prog = self._find_program("python")
    01189
    01190         # Change to the working directory if specified or to the default temporary
    01191         origdir = os.getcwd()
    01192         if self.workdir:
    01193             os.chdir(str(os.path.normpath(os.path.expandvars(self.workdir))))
    01194         elif "qmtest.tmpdir" in context and self.use_temp_dir == "true":
    01195             os.chdir(context["qmtest.tmpdir"])
    01196
    01197         if "QMTEST_IGNORE_TIMEOUT" not in os.environ:
    01198             self.timeout = max(self.timeout,600)
    01199         else:
    01200             self.timeout = -1
    01201
    01202         try:
    01203             # Run the test
    01204             self.RunProgram(prog,
    01205                             [ prog ] + args,
    01206                             context, result)
    01207             # Record the content of the enfironment for failing tests
    01208             if result.GetOutcome() not in [ result.PASS ]:
    01209                 self.DumpEnvironment(result)
    01210         finally:
    01211             # revert to the original directory
    01212             os.chdir(origdir)
    01213
        def RunProgram(self, program, arguments, context, result):

def GaudiTest::GaudiExeTest::RunProgram | ( |  | self,
|  |  | program,
|  |  | arguments,
|  |  | context,
|  |  | result |
| ) |  |  |

    Run the 'program'.

    'program' -- The path to the program to run.

    'arguments' -- A list of the arguments to the program.  This
    list must contain a first argument corresponding to 'argv[0]'.

    'context' -- A 'Context' giving run-time parameters to the
    test.

    'result' -- A 'Result' object.  The outcome will be
    'Result.PASS' when this method is called.  The 'result' may be
    modified by this method to indicate outcomes other than
    'Result.PASS' or to add annotations.

    @attention: This method has been copied from command.ExecTestBase
        (QMTest 2.3.0) and modified to keep stdout and stderr
        for tests that have been terminated by a signal.
        (Fundamental for debugging in the Application Area)

Definition at line 1214 of file GaudiTest.py.

    01214                                                              :
    01215         """Run the 'program'.
    01216
    01217         'program' -- The path to the program to run.
    01218
    01219         'arguments' -- A list of the arguments to the program.  This
    01220         list must contain a first argument corresponding to 'argv[0]'.
    01221
    01222         'context' -- A 'Context' giving run-time parameters to the
    01223         test.
    01224
    01225         'result' -- A 'Result' object.  The outcome will be
    01226         'Result.PASS' when this method is called.  The 'result' may be
    01227         modified by this method to indicate outcomes other than
    01228         'Result.PASS' or to add annotations.
    01229
    01230         @attention: This method has been copied from command.ExecTestBase
    01231                     (QMTest 2.3.0) and modified to keep stdout and stderr
    01232                     for tests that have been terminated by a signal.
    01233                     (Fundamental for debugging in the Application Area)
    01234         """
    01235
    01236         # Construct the environment.
    01237         environment = self.MakeEnvironment(context)
    01238         # Create the executable.
    01239         if self.timeout >= 0:
    01240             timeout = self.timeout
    01241         else:
    01242             # If no timeout was specified, we sill run this process in a
    01243             # separate process group and kill the entire process group
    01244             # when the child is done executing.  That means that
    01245             # orphaned child processes created by the test will be
    01246             # cleaned up.
    01247             timeout = -2
    01248         e = qm.executable.Filter(self.stdin, timeout)
    01249         # Run it.
    01250         exit_status = e.Run(arguments, environment, path = program)
    01251
    01252         # If the process terminated normally, check the outputs.
    01253         if sys.platform == "win32" or os.WIFEXITED(exit_status):
    01254             # There are no causes of failure yet.
    01255             causes = []
    01256             # The target program terminated normally.  Extract the
    01257             # exit code, if this test checks it.
    01258             if self.exit_code is None:
    01259                 exit_code = None
    01260             elif sys.platform == "win32":
    01261                 exit_code = exit_status
    01262             else:
    01263                 exit_code = os.WEXITSTATUS(exit_status)
    01264             # Get the output generated by the program.
    01265             stdout = e.stdout
    01266             stderr = e.stderr
    01267             # Record the results.
    01268             result["ExecTest.exit_code"] = str(exit_code)
    01269             result["ExecTest.stdout"] = result.Quote(stdout)
    01270             result["ExecTest.stderr"] = result.Quote(stderr)
    01271             # Check to see if the exit code matches.
    01272             if exit_code != self.exit_code:
    01273                 causes.append("exit_code")
    01274                 result["ExecTest.expected_exit_code"] \
    01275                     = str(self.exit_code)
    01276             # Validate the output.
    01277             causes += self.ValidateOutput(stdout, stderr, result)
    01278             # If anything went wrong, the test failed.
    01279             if causes:
    01280                 result.Fail("Unexpected %s." % string.join(causes, ", "))
    01281         elif os.WIFSIGNALED(exit_status):
    01282             # The target program terminated with a signal.  Construe
    01283             # that as a test failure.
    01284             signal_number = str(os.WTERMSIG(exit_status))
    01285             result.Fail("Program terminated by signal.")
    01286             result["ExecTest.signal_number"] = signal_number
    01287             result["ExecTest.stdout"] = result.Quote(e.stdout)
    01288             result["ExecTest.stderr"] = result.Quote(e.stderr)
    01289         elif os.WIFSTOPPED(exit_status):
    01290             # The target program was stopped.  Construe that as a
    01291             # test failure.
    01292             signal_number = str(os.WSTOPSIG(exit_status))
    01293             result.Fail("Program stopped by signal.")
    01294             result["ExecTest.signal_number"] = signal_number
    01295             result["ExecTest.stdout"] = result.Quote(e.stdout)
    01296             result["ExecTest.stderr"] = result.Quote(e.stderr)
    01297         else:
    01298             # The target program terminated abnormally in some other
    01299             # manner.  (This shouldn't normally happen...)
    01300             result.Fail("Program did not terminate normally.")
    01301
    01302         # Marco Cl.: This is a special trick to fix a "problem" with the output
    01303         # of gaudi jobs when they use colors
    01304         esc = '\x1b'
    01305         repr_esc = '\\x1b'
    01306         result["ExecTest.stdout"] = result["ExecTest.stdout"].replace(esc,repr_esc)
    01307         # TODO: (MCl) improve the hack for colors in standard output
    01308         #             may be converting them to HTML tags
            #             may be converting them to HTML tags

## Member Data Documentation

list GaudiTest::GaudiExeTest::arguments`[static]`

Definition at line 754 of file GaudiTest.py.

GaudiTest::GaudiExeTest::callable

Definition at line 1051 of file GaudiTest.py.

GaudiTest::GaudiExeTest::extra_args

Definition at line 1052 of file GaudiTest.py.

GaudiTest::GaudiExeTest::args_order

Definition at line 1055 of file GaudiTest.py.

GaudiTest::GaudiExeTest::program

Definition at line 1155 of file GaudiTest.py.

GaudiTest::GaudiExeTest::reference

Definition at line 1166 of file GaudiTest.py.

GaudiTest::GaudiExeTest::error_reference

Definition at line 1167 of file GaudiTest.py.

GaudiTest::GaudiExeTest::use_temp_dir

Definition at line 1194 of file GaudiTest.py.

GaudiTest::GaudiExeTest::timeout

Definition at line 1198 of file GaudiTest.py.

The documentation for this class was generated from the following file:

- /afs/cern.ch/sw/Gaudi/releases/GAUDI/GAUDI_v20r4/GaudiPolicy/qmtest_classes/GaudiTest.py