![]() |
|
|
Generated: 8 Jan 2009 |


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 |
| 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
list GaudiTest::GaudiExeTest::arguments [static] |
Definition at line 754 of file GaudiTest.py.
Definition at line 1051 of file GaudiTest.py.
Definition at line 1052 of file GaudiTest.py.
Definition at line 1055 of file GaudiTest.py.
Definition at line 1155 of file GaudiTest.py.
Definition at line 1166 of file GaudiTest.py.
Definition at line 1167 of file GaudiTest.py.
Definition at line 1194 of file GaudiTest.py.
Definition at line 1198 of file GaudiTest.py.