GaudiTesting.BaseTest.BaseTest Class Reference
Inheritance diagram for GaudiTesting.BaseTest.BaseTest:
Collaboration diagram for GaudiTesting.BaseTest.BaseTest:

Public Member Functions

def __init__ (self)
 
def validator
 
def run (self)
 
def ValidateOutput (self, stdout, stderr, result)
 
def findReferenceBlock
 
def countErrorLines
 
def CheckTTreesSummaries
 
def CheckHistosSummaries
 
def validateWithReference
 
def __init__ (self)
 
def validator
 
def run (self)
 
def ValidateOutput (self, stdout, stderr, result)
 
def findReferenceBlock
 
def countErrorLines
 
def CheckTTreesSummaries
 
def CheckHistosSummaries
 
def validateWithReference
 

Public Attributes

 program
 
 args
 
 reference
 
 error_reference
 
 options
 
 stderr
 
 timeout
 
 exit_code
 
 environment
 
 unsupported_platforms
 
 signal
 
 workdir
 
 use_temp_dir
 
 status
 
 name
 
 causes
 
 result
 
 returnedCode
 
 out
 
 err
 
 proc
 
 stack_trace
 
 basedir
 

Private Member Functions

def _expandReferenceFileName (self, reffile)
 
def _expandReferenceFileName (self, reffile)
 

Static Private Attributes

 _common_tmpdir = None
 

Detailed Description

Definition at line 31 of file BaseTest.py.

Constructor & Destructor Documentation

def GaudiTesting.BaseTest.BaseTest.__init__ (   self)

Definition at line 35 of file BaseTest.py.

35  def __init__(self):
36  self.program = ''
37  self.args = []
38  self.reference = ''
39  self.error_reference = ''
40  self.options = ''
41  self.stderr = ''
42  self.timeout = 600
43  self.exit_code = None
44  self.environment = None
46  self.signal = None
47  self.workdir = os.curdir
48  self.use_temp_dir = False
49  #Variables not for users
50  self.status = None
51  self.name = ''
52  self.causes = []
53  self.result = Result(self)
54  self.returnedCode = 0
55  self.out = ''
56  self.err = ''
57  self.proc = None
58  self.stack_trace = None
59  self.basedir = os.getcwd()
60 
def GaudiTesting.BaseTest.BaseTest.__init__ (   self)

Definition at line 35 of file BaseTest.py.

35  def __init__(self):
36  self.program = ''
37  self.args = []
38  self.reference = ''
39  self.error_reference = ''
40  self.options = ''
41  self.stderr = ''
42  self.timeout = 600
43  self.exit_code = None
44  self.environment = None
46  self.signal = None
47  self.workdir = os.curdir
48  self.use_temp_dir = False
49  #Variables not for users
50  self.status = None
51  self.name = ''
52  self.causes = []
53  self.result = Result(self)
54  self.returnedCode = 0
55  self.out = ''
56  self.err = ''
57  self.proc = None
58  self.stack_trace = None
59  self.basedir = os.getcwd()
60 

Member Function Documentation

def GaudiTesting.BaseTest.BaseTest._expandReferenceFileName (   self,
  reffile 
)
private

Definition at line 452 of file BaseTest.py.

452  def _expandReferenceFileName(self, reffile):
453  # if no file is passed, do nothing
454  if not reffile:
455  return ""
456 
457  # function to split an extension in constituents parts
458  platformSplit = lambda p: set(p.split('-' in p and '-' or '_'))
459 
460  reference = os.path.normpath(os.path.join(self.basedir,
461  os.path.expandvars(reffile)))
462 
463  # old-style platform-specific reference name
464  spec_ref = reference[:-3] + GetPlatform(self)[0:3] + reference[-3:]
465  if os.path.isfile(spec_ref):
466  reference = spec_ref
467  else: # look for new-style platform specific reference files:
468  # get all the files whose name start with the reference filename
469  dirname, basename = os.path.split(reference)
470  if not dirname: dirname = '.'
471  head = basename + "."
472  head_len = len(head)
473  platform = platformSplit(GetPlatform(self))
474  if 'do0' in platform:
475  platform.add('dbg')
476  candidates = []
477  for f in os.listdir(dirname):
478  if f.startswith(head):
479  req_plat = platformSplit(f[head_len:])
480  if platform.issuperset(req_plat):
481  candidates.append( (len(req_plat), f) )
482  if candidates: # take the one with highest matching
483  # FIXME: it is not possible to say if x86_64-slc5-gcc43-dbg
484  # has to use ref.x86_64-gcc43 or ref.slc5-dbg
485  candidates.sort()
486  reference = os.path.join(dirname, candidates[-1][1])
487  return reference
488 
489 #---------------------------------------------------------------------------------------------------#
490 #---------------------------------------------------------------------------------------------------#
491 #-----------------------------------------GAUDI TOOLS-----------------------------------------------------#
492 #---------------------------------------------------------------------------------------------------#
493 #---------------------------------------------------------------------------------------------------#
494 
def GetPlatform(self)
Definition: BaseTest.py:1063
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:452
def GaudiTesting.BaseTest.BaseTest._expandReferenceFileName (   self,
  reffile 
)
private

Definition at line 452 of file BaseTest.py.

452  def _expandReferenceFileName(self, reffile):
453  # if no file is passed, do nothing
454  if not reffile:
455  return ""
456 
457  # function to split an extension in constituents parts
458  platformSplit = lambda p: set(p.split('-' in p and '-' or '_'))
459 
460  reference = os.path.normpath(os.path.join(self.basedir,
461  os.path.expandvars(reffile)))
462 
463  # old-style platform-specific reference name
464  spec_ref = reference[:-3] + GetPlatform(self)[0:3] + reference[-3:]
465  if os.path.isfile(spec_ref):
466  reference = spec_ref
467  else: # look for new-style platform specific reference files:
468  # get all the files whose name start with the reference filename
469  dirname, basename = os.path.split(reference)
470  if not dirname: dirname = '.'
471  head = basename + "."
472  head_len = len(head)
473  platform = platformSplit(GetPlatform(self))
474  if 'do0' in platform:
475  platform.add('dbg')
476  candidates = []
477  for f in os.listdir(dirname):
478  if f.startswith(head):
479  req_plat = platformSplit(f[head_len:])
480  if platform.issuperset(req_plat):
481  candidates.append( (len(req_plat), f) )
482  if candidates: # take the one with highest matching
483  # FIXME: it is not possible to say if x86_64-slc5-gcc43-dbg
484  # has to use ref.x86_64-gcc43 or ref.slc5-dbg
485  candidates.sort()
486  reference = os.path.join(dirname, candidates[-1][1])
487  return reference
488 
489 #---------------------------------------------------------------------------------------------------#
490 #---------------------------------------------------------------------------------------------------#
491 #-----------------------------------------GAUDI TOOLS-----------------------------------------------------#
492 #---------------------------------------------------------------------------------------------------#
493 #---------------------------------------------------------------------------------------------------#
494 
def GetPlatform(self)
Definition: BaseTest.py:1063
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:452
def GaudiTesting.BaseTest.BaseTest.CheckHistosSummaries (   self,
  stdout = None,
  result = None,
  causes = None,
  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 359 of file BaseTest.py.

359  ignore = None):
360  """
361  Compare the TTree summaries in stdout with the ones in trees_dict or in
362  the reference file. By default ignore the size, compression and basket
363  fields.
364  The presence of TTree summaries when none is expected is not a failure.
365  """
366  if stdout is None : stdout=self.out
367  if result is None : result=self.result
368  if causes is None : causes=self.causes
369 
370  if dict is None:
371  lreference = self._expandReferenceFileName(self.reference)
372  # call the validator if the file exists
373  if lreference and os.path.isfile(lreference):
374  dict = findHistosSummaries(open(lreference).read())
375  else:
376  dict = {}
377 
378  from pprint import PrettyPrinter
379  pp = PrettyPrinter()
380  if dict:
381  result["GaudiTest.Histos.expected"] = result.Quote(pp.pformat(dict))
382  if ignore:
383  result["GaudiTest.Histos.ignore"] = result.Quote(ignore)
384 
385  histos = findHistosSummaries(stdout)
386  failed = cmpTreesDicts(dict, histos, ignore)
387  if failed:
388  causes.append("histos summaries")
389  msg = "%s: %s != %s" % getCmpFailingValues(dict, histos, failed)
390  result["GaudiTest.Histos.failure_on"] = result.Quote(msg)
391  result["GaudiTest.Histos.found"] = result.Quote(pp.pformat(histos))
392 
393  return causes
394 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1031
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:903
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:452
def GaudiTesting.BaseTest.BaseTest.CheckHistosSummaries (   self,
  stdout = None,
  result = None,
  causes = None,
  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 359 of file BaseTest.py.

359  ignore = None):
360  """
361  Compare the TTree summaries in stdout with the ones in trees_dict or in
362  the reference file. By default ignore the size, compression and basket
363  fields.
364  The presence of TTree summaries when none is expected is not a failure.
365  """
366  if stdout is None : stdout=self.out
367  if result is None : result=self.result
368  if causes is None : causes=self.causes
369 
370  if dict is None:
371  lreference = self._expandReferenceFileName(self.reference)
372  # call the validator if the file exists
373  if lreference and os.path.isfile(lreference):
374  dict = findHistosSummaries(open(lreference).read())
375  else:
376  dict = {}
377 
378  from pprint import PrettyPrinter
379  pp = PrettyPrinter()
380  if dict:
381  result["GaudiTest.Histos.expected"] = result.Quote(pp.pformat(dict))
382  if ignore:
383  result["GaudiTest.Histos.ignore"] = result.Quote(ignore)
384 
385  histos = findHistosSummaries(stdout)
386  failed = cmpTreesDicts(dict, histos, ignore)
387  if failed:
388  causes.append("histos summaries")
389  msg = "%s: %s != %s" % getCmpFailingValues(dict, histos, failed)
390  result["GaudiTest.Histos.failure_on"] = result.Quote(msg)
391  result["GaudiTest.Histos.found"] = result.Quote(pp.pformat(histos))
392 
393  return causes
394 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1031
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:903
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:452
def GaudiTesting.BaseTest.BaseTest.CheckTTreesSummaries (   self,
  stdout = None,
  result = None,
  causes = None,
  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 322 of file BaseTest.py.

322  ignore = r"Basket|.*size|Compression"):
323  """
324  Compare the TTree summaries in stdout with the ones in trees_dict or in
325  the reference file. By default ignore the size, compression and basket
326  fields.
327  The presence of TTree summaries when none is expected is not a failure.
328  """
329  if stdout is None : stdout=self.out
330  if result is None : result=self.result
331  if causes is None : causes=self.causes
332  if trees_dict is None:
333  lreference = self._expandReferenceFileName(self.reference)
334  # call the validator if the file exists
335  if lreference and os.path.isfile(lreference):
336  trees_dict = findTTreeSummaries(open(lreference).read())
337  else:
338  trees_dict = {}
339 
340  from pprint import PrettyPrinter
341  pp = PrettyPrinter()
342  if trees_dict:
343  result["GaudiTest.TTrees.expected"] = result.Quote(pp.pformat(trees_dict))
344  if ignore:
345  result["GaudiTest.TTrees.ignore"] = result.Quote(ignore)
346 
347  trees = findTTreeSummaries(stdout)
348  failed = cmpTreesDicts(trees_dict, trees, ignore)
349  if failed:
350  causes.append("trees summaries")
351  msg = "%s: %s != %s" % getCmpFailingValues(trees_dict, trees, failed)
352  result["GaudiTest.TTrees.failure_on"] = result.Quote(msg)
353  result["GaudiTest.TTrees.found"] = result.Quote(pp.pformat(trees))
354 
355  return causes
356 
def findTTreeSummaries(stdout)
Definition: BaseTest.py:851
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:903
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:452
def GaudiTesting.BaseTest.BaseTest.CheckTTreesSummaries (   self,
  stdout = None,
  result = None,
  causes = None,
  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 322 of file BaseTest.py.

322  ignore = r"Basket|.*size|Compression"):
323  """
324  Compare the TTree summaries in stdout with the ones in trees_dict or in
325  the reference file. By default ignore the size, compression and basket
326  fields.
327  The presence of TTree summaries when none is expected is not a failure.
328  """
329  if stdout is None : stdout=self.out
330  if result is None : result=self.result
331  if causes is None : causes=self.causes
332  if trees_dict is None:
333  lreference = self._expandReferenceFileName(self.reference)
334  # call the validator if the file exists
335  if lreference and os.path.isfile(lreference):
336  trees_dict = findTTreeSummaries(open(lreference).read())
337  else:
338  trees_dict = {}
339 
340  from pprint import PrettyPrinter
341  pp = PrettyPrinter()
342  if trees_dict:
343  result["GaudiTest.TTrees.expected"] = result.Quote(pp.pformat(trees_dict))
344  if ignore:
345  result["GaudiTest.TTrees.ignore"] = result.Quote(ignore)
346 
347  trees = findTTreeSummaries(stdout)
348  failed = cmpTreesDicts(trees_dict, trees, ignore)
349  if failed:
350  causes.append("trees summaries")
351  msg = "%s: %s != %s" % getCmpFailingValues(trees_dict, trees, failed)
352  result["GaudiTest.TTrees.failure_on"] = result.Quote(msg)
353  result["GaudiTest.TTrees.found"] = result.Quote(pp.pformat(trees))
354 
355  return causes
356 
def findTTreeSummaries(stdout)
Definition: BaseTest.py:851
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:903
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:452
def GaudiTesting.BaseTest.BaseTest.countErrorLines (   self,
  expected = {'ERROR':0,
  FATAL 
)

Definition at line 284 of file BaseTest.py.

284  def countErrorLines(self, expected = {'ERROR':0, 'FATAL':0}, stdout=None, result=None,causes=None):
285  """
286  Count the number of messages with required severity (by default ERROR and FATAL)
287  and check if their numbers match the expected ones (0 by default).
288  The dictionary "expected" can be used to tune the number of errors and fatals
289  allowed, or to limit the number of expected warnings etc.
290  """
291 
292  if stdout is None : stdout=self.out
293  if result is None : result=self.result
294  if causes is None : causes=self.causes
295 
296  # prepare the dictionary to record the extracted lines
297  errors = {}
298  for sev in expected:
299  errors[sev] = []
300 
301  outlines = stdout.splitlines()
302  from math import log10
303  fmt = "%%%dd - %%s" % (int(log10(len(outlines)+1)))
304 
305  linecount = 0
306  for l in outlines:
307  linecount += 1
308  words = l.split()
309  if len(words) >= 2 and words[1] in errors:
310  errors[words[1]].append(fmt%(linecount,l.rstrip()))
311 
312  for e in errors:
313  if len(errors[e]) != expected[e]:
314  causes.append('%s(%d)'%(e,len(errors[e])))
315  result["GaudiTest.lines.%s"%e] = result.Quote('\n'.join(errors[e]))
316  result["GaudiTest.lines.%s.expected#"%e] = result.Quote(str(expected[e]))
317 
318  return causes
319 
def GaudiTesting.BaseTest.BaseTest.countErrorLines (   self,
  expected = {'ERROR':0,
  FATAL 
)

Definition at line 284 of file BaseTest.py.

284  def countErrorLines(self, expected = {'ERROR':0, 'FATAL':0}, stdout=None, result=None,causes=None):
285  """
286  Count the number of messages with required severity (by default ERROR and FATAL)
287  and check if their numbers match the expected ones (0 by default).
288  The dictionary "expected" can be used to tune the number of errors and fatals
289  allowed, or to limit the number of expected warnings etc.
290  """
291 
292  if stdout is None : stdout=self.out
293  if result is None : result=self.result
294  if causes is None : causes=self.causes
295 
296  # prepare the dictionary to record the extracted lines
297  errors = {}
298  for sev in expected:
299  errors[sev] = []
300 
301  outlines = stdout.splitlines()
302  from math import log10
303  fmt = "%%%dd - %%s" % (int(log10(len(outlines)+1)))
304 
305  linecount = 0
306  for l in outlines:
307  linecount += 1
308  words = l.split()
309  if len(words) >= 2 and words[1] in errors:
310  errors[words[1]].append(fmt%(linecount,l.rstrip()))
311 
312  for e in errors:
313  if len(errors[e]) != expected[e]:
314  causes.append('%s(%d)'%(e,len(errors[e])))
315  result["GaudiTest.lines.%s"%e] = result.Quote('\n'.join(errors[e]))
316  result["GaudiTest.lines.%s.expected#"%e] = result.Quote(str(expected[e]))
317 
318  return causes
319 
def GaudiTesting.BaseTest.BaseTest.findReferenceBlock (   self,
  reference = None,
  stdout = None,
  result = None,
  causes = None,
  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 243 of file BaseTest.py.

243  def findReferenceBlock(self,reference=None, stdout=None, result=None, causes=None, signature_offset=0, signature=None, id = None):
244  """
245  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.
246  """
247 
248  if reference is None : reference=self.reference
249  if stdout is None : stdout=self.out
250  if result is None : result=self.result
251  if causes is None : causes=self.causes
252 
253  reflines = filter(None,map(lambda s: s.rstrip(), reference.splitlines()))
254  if not reflines:
255  raise RuntimeError("Empty (or null) reference")
256  # the same on standard output
257  outlines = filter(None,map(lambda s: s.rstrip(), stdout.splitlines()))
258 
259  res_field = "GaudiTest.RefBlock"
260  if id:
261  res_field += "_%s" % id
262 
263  if signature is None:
264  if signature_offset < 0:
265  signature_offset = len(reference)+signature_offset
266  signature = reflines[signature_offset]
267  # find the reference block in the output file
268  try:
269  pos = outlines.index(signature)
270  outlines = outlines[pos-signature_offset:pos+len(reflines)-signature_offset]
271  if reflines != outlines:
272  msg = "standard output"
273  # I do not want 2 messages in causes if teh function is called twice
274  if not msg in causes:
275  causes.append(msg)
276  result[res_field + ".observed"] = result.Quote("\n".join(outlines))
277  except ValueError:
278  causes.append("missing signature")
279  result[res_field + ".signature"] = result.Quote(signature)
280  if len(reflines) > 1 or signature != reflines[0]:
281  result[res_field + ".expected"] = result.Quote("\n".join(reflines))
282  return causes
283 
struct GAUDI_API map
Parametrisation class for map-like implementation.
def GaudiTesting.BaseTest.BaseTest.findReferenceBlock (   self,
  reference = None,
  stdout = None,
  result = None,
  causes = None,
  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 243 of file BaseTest.py.

243  def findReferenceBlock(self,reference=None, stdout=None, result=None, causes=None, signature_offset=0, signature=None, id = None):
244  """
245  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.
246  """
247 
248  if reference is None : reference=self.reference
249  if stdout is None : stdout=self.out
250  if result is None : result=self.result
251  if causes is None : causes=self.causes
252 
253  reflines = filter(None,map(lambda s: s.rstrip(), reference.splitlines()))
254  if not reflines:
255  raise RuntimeError("Empty (or null) reference")
256  # the same on standard output
257  outlines = filter(None,map(lambda s: s.rstrip(), stdout.splitlines()))
258 
259  res_field = "GaudiTest.RefBlock"
260  if id:
261  res_field += "_%s" % id
262 
263  if signature is None:
264  if signature_offset < 0:
265  signature_offset = len(reference)+signature_offset
266  signature = reflines[signature_offset]
267  # find the reference block in the output file
268  try:
269  pos = outlines.index(signature)
270  outlines = outlines[pos-signature_offset:pos+len(reflines)-signature_offset]
271  if reflines != outlines:
272  msg = "standard output"
273  # I do not want 2 messages in causes if teh function is called twice
274  if not msg in causes:
275  causes.append(msg)
276  result[res_field + ".observed"] = result.Quote("\n".join(outlines))
277  except ValueError:
278  causes.append("missing signature")
279  result[res_field + ".signature"] = result.Quote(signature)
280  if len(reflines) > 1 or signature != reflines[0]:
281  result[res_field + ".expected"] = result.Quote("\n".join(reflines))
282  return causes
283 
struct GAUDI_API map
Parametrisation class for map-like implementation.
def GaudiTesting.BaseTest.BaseTest.run (   self)

Definition at line 64 of file BaseTest.py.

64  def run(self):
65  logging.debug('running test %s', self.name)
66 
67  if self.options:
68  if re.search(r'from\s+Gaudi.Configuration\s+import\s+\*|'
69  'from\s+Configurables\s+import', self.options):
70  optionFile = tempfile.NamedTemporaryFile(suffix='.py')
71  else:
72  optionFile = tempfile.NamedTemporaryFile(suffix='.opts')
73  optionFile.file.write(self.options)
74  optionFile.seek(0)
75  self.args.append(RationalizePath(optionFile.name))
76 
77  #If not specified, setting the environment
78  if self.environment is None : self.environment = os.environ
79  else : self.environment=dict(self.environment.items()+os.environ.items())
80 
81  platform_id = (os.environ.get('BINARY_TAG') or
82  os.environ.get('CMTCONFIG') or
83  platform.platform())
84  # If at least one regex matches we skip the test.
85  skip_test = bool([None
86  for prex in self.unsupported_platforms
87  if re.search(prex, platform_id)])
88 
89  if not skip_test:
90  # handle working/temporary directory options
91  workdir = self.workdir
92  if self.use_temp_dir:
93  if self._common_tmpdir:
94  workdir = self._common_tmpdir
95  else:
96  workdir = tempfile.mkdtemp()
97 
98  # prepare the command to execute
99  prog=''
100  if self.program != '':
101  prog = self.program
102  elif "GAUDIEXE" in os.environ :
103  prog = os.environ["GAUDIEXE"]
104  else :
105  prog = "Gaudi.exe"
106 
107  dummy, prog_ext = os.path.splitext(prog)
108  if prog_ext not in [ ".exe", ".py", ".bat" ]:
109  prog += ".exe"
110  prog_ext = ".exe"
111 
112  prog = which(prog) or prog
113 
114  args = map(RationalizePath, self.args)
115 
116  if prog_ext == ".py" :
117  params = ['python', RationalizePath(prog)] + args
118  else :
119  params = [RationalizePath(prog)] + args
120 
121  validatorRes = Result({'CAUSE': None, 'EXCEPTION': None,
122  'RESOURCE': None, 'TARGET': None,
123  'TRACEBACK': None, 'START_TIME': None,
124  'END_TIME': None, 'TIMEOUT_DETAIL': None})
125  self.result = validatorRes
126 
127  # we need to switch directory because the validator expects to run
128  # in the same dir as the program
129  os.chdir(workdir)
130 
131  #launching test in a different thread to handle timeout exception
132  def target() :
133  logging.debug('executing %r in %s',
134  params, workdir)
135  self.proc = Popen(params, stdout=PIPE, stderr=PIPE,
136  env=self.environment)
137  self.out, self.err = self.proc.communicate()
138 
139  thread = threading.Thread(target=target)
140  thread.start()
141  #catching timeout
142  thread.join(self.timeout)
143 
144  if thread.is_alive():
145  # get the stack trace of the stuck process
146  cmd = ['gdb', '-p', str(self.proc.pid), '-n', '-q']
147  gdb = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
148  self.stack_trace = gdb.communicate('set pagination off\n'
149  'set confirm off\n'
150  'thread apply all backtrace\n'
151  'quit\n')[0]
152 
153  self.proc.send_signal(signal.SIGKILL)
154  logging.debug('time out in test %s', self.name)
155  thread.join()
156  self.causes.append('timeout')
157  else:
158  logging.debug('completed test %s', self.name)
159 
160  #Getting the error code
161  logging.debug('returnedCode = %s', self.proc.returncode)
162  self.returnedCode = self.proc.returncode
163 
164  logging.debug('validating test...')
165  self.result, self.causes = self.ValidateOutput(stdout=self.out,
166  stderr=self.err,
167  result=validatorRes)
168 
169  # remove the temporary directory if we created it
170  if self.use_temp_dir and not self._common_tmpdir:
171  shutil.rmtree(workdir, True)
172 
173  os.chdir(self.basedir)
174 
175  # handle application exit code
176  if self.signal is not None:
177  if int(self.returnedCode) != -int(self.signal):
178  self.causes.append('exit code')
179 
180  elif self.exit_code is not None:
181  if int(self.returnedCode) != int(self.exit_code):
182  self.causes.append('exit code')
183 
184  elif self.returnedCode != 0:
185  self.causes.append("exit code")
186 
187  if self.causes:
188  self.status = "failed"
189  else:
190  self.status = "passed"
191 
192  else:
193  self.status = "skipped"
194 
195  logging.debug('%s: %s', self.name, self.status)
196  field_mapping = {'Exit Code': 'returnedCode',
197  'stderr': 'err',
198  'Arguments': 'args',
199  'Environment': 'environment',
200  'Status': 'status',
201  'stdout': 'out',
202  'Program Name': 'program',
203  'Name': 'name',
204  'Validator': 'validator',
205  'Output Reference File': 'reference',
206  'Error Reference File': 'error_reference',
207  'Causes': 'causes',
208  #'Validator Result': 'result.annotations',
209  'Unsupported Platforms': 'unsupported_platforms',
210  'Stack Trace': 'stack_trace'}
211  resultDict = [(key, getattr(self, attr))
212  for key, attr in field_mapping.iteritems()
213  if getattr(self, attr)]
214  resultDict.append(('Working Directory',
215  RationalizePath(os.path.join(os.getcwd(),
216  self.workdir))))
217  #print dict(resultDict).keys()
218  resultDict.extend(self.result.annotations.iteritems())
219  #print self.result.annotations.keys()
220  return dict(resultDict)
221 
222 
def ValidateOutput(self, stdout, stderr, result)
Definition: BaseTest.py:227
struct GAUDI_API map
Parametrisation class for map-like implementation.
def which(executable)
Definition: BaseTest.py:519
def GaudiTesting.BaseTest.BaseTest.run (   self)

Definition at line 64 of file BaseTest.py.

64  def run(self):
65  logging.debug('running test %s', self.name)
66 
67  if self.options:
68  if re.search(r'from\s+Gaudi.Configuration\s+import\s+\*|'
69  'from\s+Configurables\s+import', self.options):
70  optionFile = tempfile.NamedTemporaryFile(suffix='.py')
71  else:
72  optionFile = tempfile.NamedTemporaryFile(suffix='.opts')
73  optionFile.file.write(self.options)
74  optionFile.seek(0)
75  self.args.append(RationalizePath(optionFile.name))
76 
77  #If not specified, setting the environment
78  if self.environment is None : self.environment = os.environ
79  else : self.environment=dict(self.environment.items()+os.environ.items())
80 
81  platform_id = (os.environ.get('BINARY_TAG') or
82  os.environ.get('CMTCONFIG') or
83  platform.platform())
84  # If at least one regex matches we skip the test.
85  skip_test = bool([None
86  for prex in self.unsupported_platforms
87  if re.search(prex, platform_id)])
88 
89  if not skip_test:
90  # handle working/temporary directory options
91  workdir = self.workdir
92  if self.use_temp_dir:
93  if self._common_tmpdir:
94  workdir = self._common_tmpdir
95  else:
96  workdir = tempfile.mkdtemp()
97 
98  # prepare the command to execute
99  prog=''
100  if self.program != '':
101  prog = self.program
102  elif "GAUDIEXE" in os.environ :
103  prog = os.environ["GAUDIEXE"]
104  else :
105  prog = "Gaudi.exe"
106 
107  dummy, prog_ext = os.path.splitext(prog)
108  if prog_ext not in [ ".exe", ".py", ".bat" ]:
109  prog += ".exe"
110  prog_ext = ".exe"
111 
112  prog = which(prog) or prog
113 
114  args = map(RationalizePath, self.args)
115 
116  if prog_ext == ".py" :
117  params = ['python', RationalizePath(prog)] + args
118  else :
119  params = [RationalizePath(prog)] + args
120 
121  validatorRes = Result({'CAUSE': None, 'EXCEPTION': None,
122  'RESOURCE': None, 'TARGET': None,
123  'TRACEBACK': None, 'START_TIME': None,
124  'END_TIME': None, 'TIMEOUT_DETAIL': None})
125  self.result = validatorRes
126 
127  # we need to switch directory because the validator expects to run
128  # in the same dir as the program
129  os.chdir(workdir)
130 
131  #launching test in a different thread to handle timeout exception
132  def target() :
133  logging.debug('executing %r in %s',
134  params, workdir)
135  self.proc = Popen(params, stdout=PIPE, stderr=PIPE,
136  env=self.environment)
137  self.out, self.err = self.proc.communicate()
138 
139  thread = threading.Thread(target=target)
140  thread.start()
141  #catching timeout
142  thread.join(self.timeout)
143 
144  if thread.is_alive():
145  # get the stack trace of the stuck process
146  cmd = ['gdb', '-p', str(self.proc.pid), '-n', '-q']
147  gdb = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
148  self.stack_trace = gdb.communicate('set pagination off\n'
149  'set confirm off\n'
150  'thread apply all backtrace\n'
151  'quit\n')[0]
152 
153  self.proc.send_signal(signal.SIGKILL)
154  logging.debug('time out in test %s', self.name)
155  thread.join()
156  self.causes.append('timeout')
157  else:
158  logging.debug('completed test %s', self.name)
159 
160  #Getting the error code
161  logging.debug('returnedCode = %s', self.proc.returncode)
162  self.returnedCode = self.proc.returncode
163 
164  logging.debug('validating test...')
165  self.result, self.causes = self.ValidateOutput(stdout=self.out,
166  stderr=self.err,
167  result=validatorRes)
168 
169  # remove the temporary directory if we created it
170  if self.use_temp_dir and not self._common_tmpdir:
171  shutil.rmtree(workdir, True)
172 
173  os.chdir(self.basedir)
174 
175  # handle application exit code
176  if self.signal is not None:
177  if int(self.returnedCode) != -int(self.signal):
178  self.causes.append('exit code')
179 
180  elif self.exit_code is not None:
181  if int(self.returnedCode) != int(self.exit_code):
182  self.causes.append('exit code')
183 
184  elif self.returnedCode != 0:
185  self.causes.append("exit code")
186 
187  if self.causes:
188  self.status = "failed"
189  else:
190  self.status = "passed"
191 
192  else:
193  self.status = "skipped"
194 
195  logging.debug('%s: %s', self.name, self.status)
196  field_mapping = {'Exit Code': 'returnedCode',
197  'stderr': 'err',
198  'Arguments': 'args',
199  'Environment': 'environment',
200  'Status': 'status',
201  'stdout': 'out',
202  'Program Name': 'program',
203  'Name': 'name',
204  'Validator': 'validator',
205  'Output Reference File': 'reference',
206  'Error Reference File': 'error_reference',
207  'Causes': 'causes',
208  #'Validator Result': 'result.annotations',
209  'Unsupported Platforms': 'unsupported_platforms',
210  'Stack Trace': 'stack_trace'}
211  resultDict = [(key, getattr(self, attr))
212  for key, attr in field_mapping.iteritems()
213  if getattr(self, attr)]
214  resultDict.append(('Working Directory',
215  RationalizePath(os.path.join(os.getcwd(),
216  self.workdir))))
217  #print dict(resultDict).keys()
218  resultDict.extend(self.result.annotations.iteritems())
219  #print self.result.annotations.keys()
220  return dict(resultDict)
221 
222 
def ValidateOutput(self, stdout, stderr, result)
Definition: BaseTest.py:227
struct GAUDI_API map
Parametrisation class for map-like implementation.
def which(executable)
Definition: BaseTest.py:519
def GaudiTesting.BaseTest.BaseTest.ValidateOutput (   self,
  stdout,
  stderr,
  result 
)

Definition at line 227 of file BaseTest.py.

227  def ValidateOutput(self, stdout, stderr, result):
228  # checking if default validation or not
229  if self.validator is not BaseTest.validator:
230  self.validator(stdout, stderr, result, self.causes,
231  self.reference, self.error_reference)
232  else:
233  if self.stderr == '':
234  self.validateWithReference(stdout, stderr, result, causes)
235  elif stderr.strip() != self.stderr.strip():
236  self.causes.append('standard error')
237 
238 
239  return result, causes
240 
241 
242 
def ValidateOutput(self, stdout, stderr, result)
Definition: BaseTest.py:227
def GaudiTesting.BaseTest.BaseTest.ValidateOutput (   self,
  stdout,
  stderr,
  result 
)

Definition at line 227 of file BaseTest.py.

227  def ValidateOutput(self, stdout, stderr, result):
228  # checking if default validation or not
229  if self.validator is not BaseTest.validator:
230  self.validator(stdout, stderr, result, self.causes,
231  self.reference, self.error_reference)
232  else:
233  if self.stderr == '':
234  self.validateWithReference(stdout, stderr, result, causes)
235  elif stderr.strip() != self.stderr.strip():
236  self.causes.append('standard error')
237 
238 
239  return result, causes
240 
241 
242 
def ValidateOutput(self, stdout, stderr, result)
Definition: BaseTest.py:227
def GaudiTesting.BaseTest.BaseTest.validateWithReference (   self,
  stdout = None,
  stderr = None,
  result = None,
  causes = None,
  preproc = None 
)
Default validation acti*on: compare standard output and error to the
reference files.

Definition at line 396 of file BaseTest.py.

396  causes=None, preproc=None):
397  '''
398  Default validation acti*on: compare standard output and error to the
399  reference files.
400  '''
401 
402  if stdout is None : stdout = self.out
403  if stderr is None : stderr = self.err
404  if result is None : result = self.result
405  if causes is None : causes = self.causes
406 
407  # set the default output preprocessor
408  if preproc is None:
409  preproc = normalizeExamples
410  # check standard output
411  lreference = self._expandReferenceFileName(self.reference)
412  # call the validator if the file exists
413  if lreference and os.path.isfile(lreference):
414  causes += ReferenceFileValidator(lreference,
415  "standard output",
416  "Output Diff",
417  preproc=preproc)(stdout, result)
418  # Compare TTree summaries
419  causes = self.CheckTTreesSummaries(stdout, result, causes)
420  causes = self.CheckHistosSummaries(stdout, result, causes)
421  if causes: # Write a new reference file for stdout
422  try:
423  newref = open(lreference + ".new","w")
424  # sanitize newlines
425  for l in stdout.splitlines():
426  newref.write(l.rstrip() + '\n')
427  del newref # flush and close
428  except IOError:
429  # Ignore IO errors when trying to update reference files
430  # because we may be in a read-only filesystem
431  pass
432 
433  # check standard error
434  lreference = self._expandReferenceFileName(self.error_reference)
435  # call the validator if we have a file to use
436  if lreference and os.path.isfile(lreference):
437  newcauses = ReferenceFileValidator(lreference,
438  "standard error",
439  "Error Diff",
440  preproc=preproc)(stderr, result)
441  causes += newcauses
442  if newcauses: # Write a new reference file for stdedd
443  newref = open(lreference + ".new","w")
444  # sanitize newlines
445  for l in stderr.splitlines():
446  newref.write(l.rstrip() + '\n')
447  del newref # flush and close
448  else:
449  causes += BasicOutputValidator(lreference, "standard error", "ExecTest.expected_stderr")(stderr, result)
450  return causes
451 
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:452
def GaudiTesting.BaseTest.BaseTest.validateWithReference (   self,
  stdout = None,
  stderr = None,
  result = None,
  causes = None,
  preproc = None 
)
Default validation acti*on: compare standard output and error to the
reference files.

Definition at line 396 of file BaseTest.py.

396  causes=None, preproc=None):
397  '''
398  Default validation acti*on: compare standard output and error to the
399  reference files.
400  '''
401 
402  if stdout is None : stdout = self.out
403  if stderr is None : stderr = self.err
404  if result is None : result = self.result
405  if causes is None : causes = self.causes
406 
407  # set the default output preprocessor
408  if preproc is None:
409  preproc = normalizeExamples
410  # check standard output
411  lreference = self._expandReferenceFileName(self.reference)
412  # call the validator if the file exists
413  if lreference and os.path.isfile(lreference):
414  causes += ReferenceFileValidator(lreference,
415  "standard output",
416  "Output Diff",
417  preproc=preproc)(stdout, result)
418  # Compare TTree summaries
419  causes = self.CheckTTreesSummaries(stdout, result, causes)
420  causes = self.CheckHistosSummaries(stdout, result, causes)
421  if causes: # Write a new reference file for stdout
422  try:
423  newref = open(lreference + ".new","w")
424  # sanitize newlines
425  for l in stdout.splitlines():
426  newref.write(l.rstrip() + '\n')
427  del newref # flush and close
428  except IOError:
429  # Ignore IO errors when trying to update reference files
430  # because we may be in a read-only filesystem
431  pass
432 
433  # check standard error
434  lreference = self._expandReferenceFileName(self.error_reference)
435  # call the validator if we have a file to use
436  if lreference and os.path.isfile(lreference):
437  newcauses = ReferenceFileValidator(lreference,
438  "standard error",
439  "Error Diff",
440  preproc=preproc)(stderr, result)
441  causes += newcauses
442  if newcauses: # Write a new reference file for stdedd
443  newref = open(lreference + ".new","w")
444  # sanitize newlines
445  for l in stderr.splitlines():
446  newref.write(l.rstrip() + '\n')
447  del newref # flush and close
448  else:
449  causes += BasicOutputValidator(lreference, "standard error", "ExecTest.expected_stderr")(stderr, result)
450  return causes
451 
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:452
def GaudiTesting.BaseTest.BaseTest.validator (   self,
  stdout = '',
  stderr = '' 
)

Definition at line 61 of file BaseTest.py.

61  def validator(self, stdout='',stderr=''):
62  pass
63 
def GaudiTesting.BaseTest.BaseTest.validator (   self,
  stdout = '',
  stderr = '' 
)

Definition at line 61 of file BaseTest.py.

61  def validator(self, stdout='',stderr=''):
62  pass
63 

Member Data Documentation

GaudiTesting.BaseTest.BaseTest._common_tmpdir = None
staticprivate

Definition at line 33 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.args

Definition at line 37 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.basedir

Definition at line 59 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.causes

Definition at line 52 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.environment

Definition at line 44 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.err

Definition at line 56 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.error_reference

Definition at line 39 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.exit_code

Definition at line 43 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.name

Definition at line 51 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.options

Definition at line 40 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.out

Definition at line 55 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.proc

Definition at line 57 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.program

Definition at line 36 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.reference

Definition at line 38 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.result

Definition at line 53 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.returnedCode

Definition at line 54 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.signal

Definition at line 46 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.stack_trace

Definition at line 58 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.status

Definition at line 50 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.stderr

Definition at line 41 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.timeout

Definition at line 42 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.unsupported_platforms

Definition at line 45 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.use_temp_dir

Definition at line 48 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.workdir

Definition at line 47 of file BaseTest.py.


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