|
Gaudi Framework, version v21r4 |
| Home | Generated: 7 Sep 2009 |


Standard Gaudi test.
Definition at line 949 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 |
| def GaudiTest::GaudiExeTest::PlatformIsNotSupported | ( | self, | ||
| context, | ||||
| result | ||||
| ) |
Definition at line 1066 of file GaudiTest.py.
01066 : 01067 platform = self.GetPlatform() 01068 unsupported = [ re.compile(x) 01069 for x in [ str(y).strip() 01070 for y in self.unsupported_platforms ] 01071 if x 01072 ] 01073 for p_re in unsupported: 01074 if p_re.search(platform): 01075 result.SetOutcome(result.UNTESTED) 01076 result[result.CAUSE] = 'Platform not supported.' 01077 return True 01078 return False 01079 def GetPlatform(self):
| def GaudiTest::GaudiExeTest::GetPlatform | ( | self | ) |
Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
Definition at line 1080 of file GaudiTest.py.
01080 : 01081 """ 01082 Return the platform Id defined in CMTCONFIG or SCRAM_ARCH. 01083 """ 01084 arch = "None" 01085 # check architecture name 01086 if "CMTCONFIG" in os.environ: 01087 arch = os.environ["CMTCONFIG"] 01088 elif "SCRAM_ARCH" in os.environ: 01089 arch = os.environ["SCRAM_ARCH"] 01090 return arch 01091 def _expandReferenceFileName(self, reffile):
| def GaudiTest::GaudiExeTest::_expandReferenceFileName | ( | self, | ||
| reffile | ||||
| ) | [private] |
Definition at line 1092 of file GaudiTest.py.
01092 : 01093 # if no file is passed, do nothing 01094 if not reffile: 01095 return "" 01096 01097 reference = os.path.normpath(os.path.expandvars(reffile)) 01098 # old-style platform-specific reference name 01099 spec_ref = reference[:-3] + self.GetPlatform()[0:3] + reference[-3:] 01100 if os.path.isfile(spec_ref): 01101 reference = spec_ref 01102 else: # look for new-style platform specific reference files: 01103 # get all the files whose name start with the reference filename 01104 dirname, basename = os.path.split(reference) 01105 if not dirname: dirname = '.' 01106 head = basename + "." 01107 head_len = len(head) 01108 platform = self.GetPlatform() 01109 candidates = [] 01110 for f in os.listdir(dirname): 01111 if f.startswith(head) and platform.startswith(f[head_len:]): 01112 candidates.append( (len(f) - head_len, f) ) 01113 if candidates: # take the one with highest matching 01114 candidates.sort() 01115 reference = os.path.join(dirname, candidates[-1][1]) 01116 return reference 01117 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 1118 of file GaudiTest.py.
01120 : 01121 """ 01122 Compare the TTree summaries in stdout with the ones in trees_dict or in 01123 the reference file. By default ignore the size, compression and basket 01124 fields. 01125 The presence of TTree summaries when none is expected is not a failure. 01126 """ 01127 if trees_dict is None: 01128 reference = self._expandReferenceFileName(self.reference) 01129 # call the validator if the file exists 01130 if reference and os.path.isfile(reference): 01131 trees_dict = findTTreeSummaries(open(reference).read()) 01132 else: 01133 trees_dict = {} 01134 01135 from pprint import PrettyPrinter 01136 pp = PrettyPrinter() 01137 if trees_dict: 01138 result["GaudiTest.TTrees.expected"] = result.Quote(pp.pformat(trees_dict)) 01139 if ignore: 01140 result["GaudiTest.TTrees.ignore"] = result.Quote(ignore) 01141 01142 trees = findTTreeSummaries(stdout) 01143 failed = cmpTreesDicts(trees_dict, trees, ignore) 01144 if failed: 01145 causes.append("trees summaries") 01146 msg = "%s: %s != %s" % getCmpFailingValues(trees_dict, trees, failed) 01147 result["GaudiTest.TTrees.failure_on"] = result.Quote(msg) 01148 result["GaudiTest.TTrees.found"] = result.Quote(pp.pformat(trees)) 01149 01150 return causes 01151 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 1152 of file GaudiTest.py.
01154 : 01155 """ 01156 Compare the TTree summaries in stdout with the ones in trees_dict or in 01157 the reference file. By default ignore the size, compression and basket 01158 fields. 01159 The presence of TTree summaries when none is expected is not a failure. 01160 """ 01161 if dict is None: 01162 reference = self._expandReferenceFileName(self.reference) 01163 # call the validator if the file exists 01164 if reference and os.path.isfile(reference): 01165 dict = findHistosSummaries(open(reference).read()) 01166 else: 01167 dict = {} 01168 01169 from pprint import PrettyPrinter 01170 pp = PrettyPrinter() 01171 if dict: 01172 result["GaudiTest.Histos.expected"] = result.Quote(pp.pformat(dict)) 01173 if ignore: 01174 result["GaudiTest.Histos.ignore"] = result.Quote(ignore) 01175 01176 histos = findHistosSummaries(stdout) 01177 failed = cmpTreesDicts(dict, histos, ignore) 01178 if failed: 01179 causes.append("histos summaries") 01180 msg = "%s: %s != %s" % getCmpFailingValues(dict, histos, failed) 01181 result["GaudiTest.Histos.failure_on"] = result.Quote(msg) 01182 result["GaudiTest.Histos.found"] = result.Quote(pp.pformat(histos)) 01183 01184 return causes 01185 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 1186 of file GaudiTest.py.
01186 : 01187 """ 01188 Default validation action: compare standard output and error to the 01189 reference files. 01190 """ 01191 # set the default output preprocessor 01192 if preproc is None: 01193 preproc = normalizeExamples 01194 # check standard output 01195 reference = self._expandReferenceFileName(self.reference) 01196 # call the validator if the file exists 01197 if reference and os.path.isfile(reference): 01198 result["GaudiTest.output_reference"] = reference 01199 causes += ReferenceFileValidator(reference, 01200 "standard output", 01201 "GaudiTest.output_diff", 01202 preproc = preproc)(stdout, result) 01203 01204 # Compare TTree summaries 01205 causes = self.CheckTTreesSummaries(stdout, result, causes) 01206 causes = self.CheckHistosSummaries(stdout, result, causes) 01207 01208 if causes: # Write a new reference file for stdout 01209 newref = open(reference + ".new","w") 01210 # sanitize newlines 01211 for l in stdout.splitlines(): 01212 newref.write(l.rstrip() + '\n') 01213 del newref # flush and close 01214 01215 01216 # check standard error 01217 reference = self._expandReferenceFileName(self.error_reference) 01218 # call the validator if we have a file to use 01219 if reference and os.path.isfile(reference): 01220 result["GaudiTest.error_reference"] = reference 01221 newcauses = ReferenceFileValidator(reference, 01222 "standard error", 01223 "GaudiTest.error_diff", 01224 preproc = preproc)(stderr, result) 01225 causes += newcauses 01226 if newcauses: # Write a new reference file for stdedd 01227 newref = open(reference + ".new","w") 01228 # sanitize newlines 01229 for l in stderr.splitlines(): 01230 newref.write(l.rstrip() + '\n') 01231 del newref # flush and close 01232 else: 01233 causes += BasicOutputValidator(self.stderr, 01234 "standard error", 01235 "ExecTest.expected_stderr")(stderr, result) 01236 01237 return causes 01238 def ValidateOutput(self, stdout, stderr, result):
| def GaudiTest::GaudiExeTest::ValidateOutput | ( | self, | ||
| stdout, | ||||
| stderr, | ||||
| result | ||||
| ) |
Definition at line 1239 of file GaudiTest.py.
01239 : 01240 causes = [] 01241 # if the test definition contains a custom validator, use it 01242 if self.validator.strip() != "": 01243 class CallWrapper(object): 01244 """ 01245 Small wrapper class to dynamically bind some default arguments 01246 to a callable. 01247 """ 01248 def __init__(self, callable, extra_args = {}): 01249 self.callable = callable 01250 self.extra_args = extra_args 01251 # get the list of names of positional arguments 01252 from inspect import getargspec 01253 self.args_order = getargspec(callable)[0] 01254 # Remove "self" from the list of positional arguments 01255 # since it is added automatically 01256 if self.args_order[0] == "self": 01257 del self.args_order[0] 01258 def __call__(self, *args, **kwargs): 01259 # Check which positional arguments are used 01260 positional = self.args_order[:len(args)] 01261 01262 kwargs = dict(kwargs) # copy the arguments dictionary 01263 for a in self.extra_args: 01264 # use "extra_args" for the arguments not specified as 01265 # positional or keyword 01266 if a not in positional and a not in kwargs: 01267 kwargs[a] = self.extra_args[a] 01268 return apply(self.callable, args, kwargs) 01269 # local names to be exposed in the script 01270 exported_symbols = {"self":self, 01271 "stdout":stdout, 01272 "stderr":stderr, 01273 "result":result, 01274 "causes":causes, 01275 "findReferenceBlock": 01276 CallWrapper(findReferenceBlock, {"stdout":stdout, 01277 "result":result, 01278 "causes":causes}), 01279 "validateWithReference": 01280 CallWrapper(self.ValidateWithReference, {"stdout":stdout, 01281 "stderr":stderr, 01282 "result":result, 01283 "causes":causes}), 01284 "countErrorLines": 01285 CallWrapper(countErrorLines, {"stdout":stdout, 01286 "result":result, 01287 "causes":causes}), 01288 "checkTTreesSummaries": 01289 CallWrapper(self.CheckTTreesSummaries, {"stdout":stdout, 01290 "result":result, 01291 "causes":causes}), 01292 "checkHistosSummaries": 01293 CallWrapper(self.CheckHistosSummaries, {"stdout":stdout, 01294 "result":result, 01295 "causes":causes}), 01296 01297 } 01298 exec self.validator in globals(), exported_symbols 01299 else: 01300 self.ValidateWithReference(stdout, stderr, result, causes) 01301 01302 return causes 01303 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 1304 of file GaudiTest.py.
01304 : 01305 """ 01306 Add the content of the environment to the result object. 01307 01308 Copied from the QMTest class of COOL. 01309 """ 01310 vars = os.environ.keys() 01311 vars.sort() 01312 result['GaudiTest.environment'] = \ 01313 result.Quote('\n'.join(["%s=%s"%(v,os.environ[v]) for v in vars])) 01314 def _find_program(self,prog):
| def GaudiTest::GaudiExeTest::_find_program | ( | self, | ||
| prog | ||||
| ) | [private] |
Definition at line 1315 of file GaudiTest.py.
01315 : 01316 # check if it is an absolute path or the file can be found 01317 # from the local directory, otherwise search for it in PATH 01318 if not os.path.isabs(prog) and not os.path.isfile(prog): 01319 for d in os.environ["PATH"].split(os.pathsep): 01320 p = os.path.join(d,prog) 01321 if os.path.isfile(p): 01322 return p 01323 return prog 01324 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 1325 of file GaudiTest.py.
01325 : 01326 """Run the test. 01327 01328 'context' -- A 'Context' giving run-time parameters to the 01329 test. 01330 01331 'result' -- A 'Result' object. The outcome will be 01332 'Result.PASS' when this method is called. The 'result' may be 01333 modified by this method to indicate outcomes other than 01334 'Result.PASS' or to add annotations.""" 01335 01336 # Check if the platform is supported 01337 if self.PlatformIsNotSupported(context, result): 01338 return 01339 01340 def rationalizepath(p): 01341 p = os.path.normpath(os.path.expandvars(p)) 01342 if os.path.exists(p): 01343 p = os.path.realpath(p) 01344 return p 01345 01346 # Prepare program name and arguments (expanding variables, and converting to absolute) 01347 if self.program: 01348 prog = rationalizepath(self.program) 01349 elif "GAUDIEXE" in os.environ: 01350 prog = os.environ["GAUDIEXE"] 01351 else: 01352 prog = "Gaudi.exe" 01353 self.program = prog 01354 01355 dummy, prog_ext = os.path.splitext(prog) 01356 if prog_ext not in [ ".exe", ".py", ".bat" ] and self.GetPlatform()[0:3] == "win": 01357 prog += ".exe" 01358 prog_ext = ".exe" 01359 01360 prog = self._find_program(prog) 01361 01362 # Convert paths to absolute paths in arguments and reference files 01363 args = map(rationalizepath, self.args) 01364 self.reference = rationalizepath(self.reference) 01365 self.error_reference = rationalizepath(self.error_reference) 01366 01367 01368 # check if the user provided inline options 01369 tmpfile = None 01370 if self.options.strip(): 01371 ext = ".opts" 01372 if re.search(r"from\s*Gaudi.Configuration\s*import\s*\*", self.options): 01373 ext = ".py" 01374 tmpfile = TempFile(ext) 01375 tmpfile.writelines("\n".join(self.options.splitlines())) 01376 tmpfile.flush() 01377 args.append(tmpfile.name) 01378 result["GaudiTest.options"] = result.Quote(self.options) 01379 01380 # if the program is a python file, execute it through python 01381 if prog_ext == ".py": 01382 args.insert(0,prog) 01383 if self.GetPlatform()[0:3] == "win": 01384 prog = self._find_program("python.exe") 01385 else: 01386 prog = self._find_program("python") 01387 01388 # Change to the working directory if specified or to the default temporary 01389 origdir = os.getcwd() 01390 if self.workdir: 01391 os.chdir(str(os.path.normpath(os.path.expandvars(self.workdir)))) 01392 elif "qmtest.tmpdir" in context and self.use_temp_dir == "true": 01393 os.chdir(context["qmtest.tmpdir"]) 01394 01395 if "QMTEST_IGNORE_TIMEOUT" not in os.environ: 01396 self.timeout = max(self.timeout,600) 01397 else: 01398 self.timeout = -1 01399 01400 try: 01401 # Run the test 01402 self.RunProgram(prog, 01403 [ prog ] + args, 01404 context, result) 01405 # Record the content of the enfironment for failing tests 01406 if result.GetOutcome() not in [ result.PASS ]: 01407 self.DumpEnvironment(result) 01408 finally: 01409 # revert to the original directory 01410 os.chdir(origdir) 01411 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 1412 of file GaudiTest.py.
01412 : 01413 """Run the 'program'. 01414 01415 'program' -- The path to the program to run. 01416 01417 'arguments' -- A list of the arguments to the program. This 01418 list must contain a first argument corresponding to 'argv[0]'. 01419 01420 'context' -- A 'Context' giving run-time parameters to the 01421 test. 01422 01423 'result' -- A 'Result' object. The outcome will be 01424 'Result.PASS' when this method is called. The 'result' may be 01425 modified by this method to indicate outcomes other than 01426 'Result.PASS' or to add annotations. 01427 01428 @attention: This method has been copied from command.ExecTestBase 01429 (QMTest 2.3.0) and modified to keep stdout and stderr 01430 for tests that have been terminated by a signal. 01431 (Fundamental for debugging in the Application Area) 01432 """ 01433 01434 # Construct the environment. 01435 environment = self.MakeEnvironment(context) 01436 # Create the executable. 01437 if self.timeout >= 0: 01438 timeout = self.timeout 01439 else: 01440 # If no timeout was specified, we sill run this process in a 01441 # separate process group and kill the entire process group 01442 # when the child is done executing. That means that 01443 # orphaned child processes created by the test will be 01444 # cleaned up. 01445 timeout = -2 01446 e = GaudiFilterExecutable(self.stdin, timeout) 01447 # Run it. 01448 exit_status = e.Run(arguments, environment, path = program) 01449 # Get the stack trace from the temporary file (if present) 01450 if e.stack_trace_file and os.path.exists(e.stack_trace_file): 01451 stack_trace = open(e.stack_trace_file).read() 01452 os.remove(e.stack_trace_file) 01453 else: 01454 stack_trace = None 01455 if stack_trace: 01456 result["ExecTest.stack_trace"] = result.Quote(stack_trace) 01457 01458 # If the process terminated normally, check the outputs. 01459 if sys.platform == "win32" or os.WIFEXITED(exit_status): 01460 # There are no causes of failure yet. 01461 causes = [] 01462 # The target program terminated normally. Extract the 01463 # exit code, if this test checks it. 01464 if self.exit_code is None: 01465 exit_code = None 01466 elif sys.platform == "win32": 01467 exit_code = exit_status 01468 else: 01469 exit_code = os.WEXITSTATUS(exit_status) 01470 # Get the output generated by the program. 01471 stdout = e.stdout 01472 stderr = e.stderr 01473 # Record the results. 01474 result["ExecTest.exit_code"] = str(exit_code) 01475 result["ExecTest.stdout"] = result.Quote(stdout) 01476 result["ExecTest.stderr"] = result.Quote(stderr) 01477 # Check to see if the exit code matches. 01478 if exit_code != self.exit_code: 01479 causes.append("exit_code") 01480 result["ExecTest.expected_exit_code"] \ 01481 = str(self.exit_code) 01482 # Validate the output. 01483 causes += self.ValidateOutput(stdout, stderr, result) 01484 # If anything went wrong, the test failed. 01485 if causes: 01486 result.Fail("Unexpected %s." % string.join(causes, ", ")) 01487 elif os.WIFSIGNALED(exit_status): 01488 # The target program terminated with a signal. Construe 01489 # that as a test failure. 01490 signal_number = str(os.WTERMSIG(exit_status)) 01491 result.Fail("Program terminated by signal.") 01492 result["ExecTest.signal_number"] = signal_number 01493 result["ExecTest.stdout"] = result.Quote(e.stdout) 01494 result["ExecTest.stderr"] = result.Quote(e.stderr) 01495 elif os.WIFSTOPPED(exit_status): 01496 # The target program was stopped. Construe that as a 01497 # test failure. 01498 signal_number = str(os.WSTOPSIG(exit_status)) 01499 result.Fail("Program stopped by signal.") 01500 result["ExecTest.signal_number"] = signal_number 01501 result["ExecTest.stdout"] = result.Quote(e.stdout) 01502 result["ExecTest.stderr"] = result.Quote(e.stderr) 01503 else: 01504 # The target program terminated abnormally in some other 01505 # manner. (This shouldn't normally happen...) 01506 result.Fail("Program did not terminate normally.") 01507 01508 # Marco Cl.: This is a special trick to fix a "problem" with the output 01509 # of gaudi jobs when they use colors 01510 esc = '\x1b' 01511 repr_esc = '\\x1b' 01512 result["ExecTest.stdout"] = result["ExecTest.stdout"].replace(esc,repr_esc) 01513 # TODO: (MCl) improve the hack for colors in standard output 01514 # may be converting them to HTML tags # may be converting them to HTML tags
list GaudiTest::GaudiExeTest::arguments [static] |
Definition at line 952 of file GaudiTest.py.
Definition at line 1249 of file GaudiTest.py.
Definition at line 1250 of file GaudiTest.py.
Definition at line 1253 of file GaudiTest.py.
Definition at line 1353 of file GaudiTest.py.
Definition at line 1364 of file GaudiTest.py.
Definition at line 1365 of file GaudiTest.py.
Definition at line 1392 of file GaudiTest.py.
Definition at line 1396 of file GaudiTest.py.