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 58 of file BaseTest.py.

Constructor & Destructor Documentation

def GaudiTesting.BaseTest.BaseTest.__init__ (   self)

Definition at line 62 of file BaseTest.py.

62  def __init__(self):
63  self.program = ''
64  self.args = []
65  self.reference = ''
66  self.error_reference = ''
67  self.options = ''
68  self.stderr = ''
69  self.timeout = 600
70  self.exit_code = None
71  self.environment = None
73  self.signal = None
74  self.workdir = os.curdir
75  self.use_temp_dir = False
76  #Variables not for users
77  self.status = None
78  self.name = ''
79  self.causes = []
80  self.result = Result(self)
81  self.returnedCode = 0
82  self.out = ''
83  self.err = ''
84  self.proc = None
85  self.stack_trace = None
86  self.basedir = os.getcwd()
87 
def GaudiTesting.BaseTest.BaseTest.__init__ (   self)

Definition at line 62 of file BaseTest.py.

62  def __init__(self):
63  self.program = ''
64  self.args = []
65  self.reference = ''
66  self.error_reference = ''
67  self.options = ''
68  self.stderr = ''
69  self.timeout = 600
70  self.exit_code = None
71  self.environment = None
73  self.signal = None
74  self.workdir = os.curdir
75  self.use_temp_dir = False
76  #Variables not for users
77  self.status = None
78  self.name = ''
79  self.causes = []
80  self.result = Result(self)
81  self.returnedCode = 0
82  self.out = ''
83  self.err = ''
84  self.proc = None
85  self.stack_trace = None
86  self.basedir = os.getcwd()
87 

Member Function Documentation

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

Definition at line 480 of file BaseTest.py.

480  def _expandReferenceFileName(self, reffile):
481  # if no file is passed, do nothing
482  if not reffile:
483  return ""
484 
485  # function to split an extension in constituents parts
486  platformSplit = lambda p: set(p.split('-' in p and '-' or '_'))
487 
488  reference = os.path.normpath(os.path.join(self.basedir,
489  os.path.expandvars(reffile)))
490 
491  # old-style platform-specific reference name
492  spec_ref = reference[:-3] + GetPlatform(self)[0:3] + reference[-3:]
493  if os.path.isfile(spec_ref):
494  reference = spec_ref
495  else: # look for new-style platform specific reference files:
496  # get all the files whose name start with the reference filename
497  dirname, basename = os.path.split(reference)
498  if not dirname: dirname = '.'
499  head = basename + "."
500  head_len = len(head)
501  platform = platformSplit(GetPlatform(self))
502  if 'do0' in platform:
503  platform.add('dbg')
504  candidates = []
505  for f in os.listdir(dirname):
506  if f.startswith(head):
507  req_plat = platformSplit(f[head_len:])
508  if platform.issuperset(req_plat):
509  candidates.append( (len(req_plat), f) )
510  if candidates: # take the one with highest matching
511  # FIXME: it is not possible to say if x86_64-slc5-gcc43-dbg
512  # has to use ref.x86_64-gcc43 or ref.slc5-dbg
513  candidates.sort()
514  reference = os.path.join(dirname, candidates[-1][1])
515  return reference
516 
517 #---------------------------------------------------------------------------------------------------#
518 #---------------------------------------------------------------------------------------------------#
519 #-----------------------------------------GAUDI TOOLS-----------------------------------------------------#
520 #---------------------------------------------------------------------------------------------------#
521 #---------------------------------------------------------------------------------------------------#
522 
def GetPlatform(self)
Definition: BaseTest.py:1091
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:480
def GaudiTesting.BaseTest.BaseTest._expandReferenceFileName (   self,
  reffile 
)
private

Definition at line 480 of file BaseTest.py.

480  def _expandReferenceFileName(self, reffile):
481  # if no file is passed, do nothing
482  if not reffile:
483  return ""
484 
485  # function to split an extension in constituents parts
486  platformSplit = lambda p: set(p.split('-' in p and '-' or '_'))
487 
488  reference = os.path.normpath(os.path.join(self.basedir,
489  os.path.expandvars(reffile)))
490 
491  # old-style platform-specific reference name
492  spec_ref = reference[:-3] + GetPlatform(self)[0:3] + reference[-3:]
493  if os.path.isfile(spec_ref):
494  reference = spec_ref
495  else: # look for new-style platform specific reference files:
496  # get all the files whose name start with the reference filename
497  dirname, basename = os.path.split(reference)
498  if not dirname: dirname = '.'
499  head = basename + "."
500  head_len = len(head)
501  platform = platformSplit(GetPlatform(self))
502  if 'do0' in platform:
503  platform.add('dbg')
504  candidates = []
505  for f in os.listdir(dirname):
506  if f.startswith(head):
507  req_plat = platformSplit(f[head_len:])
508  if platform.issuperset(req_plat):
509  candidates.append( (len(req_plat), f) )
510  if candidates: # take the one with highest matching
511  # FIXME: it is not possible to say if x86_64-slc5-gcc43-dbg
512  # has to use ref.x86_64-gcc43 or ref.slc5-dbg
513  candidates.sort()
514  reference = os.path.join(dirname, candidates[-1][1])
515  return reference
516 
517 #---------------------------------------------------------------------------------------------------#
518 #---------------------------------------------------------------------------------------------------#
519 #-----------------------------------------GAUDI TOOLS-----------------------------------------------------#
520 #---------------------------------------------------------------------------------------------------#
521 #---------------------------------------------------------------------------------------------------#
522 
def GetPlatform(self)
Definition: BaseTest.py:1091
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:480
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 387 of file BaseTest.py.

387  ignore = None):
388  """
389  Compare the TTree summaries in stdout with the ones in trees_dict or in
390  the reference file. By default ignore the size, compression and basket
391  fields.
392  The presence of TTree summaries when none is expected is not a failure.
393  """
394  if stdout is None : stdout=self.out
395  if result is None : result=self.result
396  if causes is None : causes=self.causes
397 
398  if dict is None:
399  lreference = self._expandReferenceFileName(self.reference)
400  # call the validator if the file exists
401  if lreference and os.path.isfile(lreference):
402  dict = findHistosSummaries(open(lreference).read())
403  else:
404  dict = {}
405 
406  from pprint import PrettyPrinter
407  pp = PrettyPrinter()
408  if dict:
409  result["GaudiTest.Histos.expected"] = result.Quote(pp.pformat(dict))
410  if ignore:
411  result["GaudiTest.Histos.ignore"] = result.Quote(ignore)
412 
413  histos = findHistosSummaries(stdout)
414  failed = cmpTreesDicts(dict, histos, ignore)
415  if failed:
416  causes.append("histos summaries")
417  msg = "%s: %s != %s" % getCmpFailingValues(dict, histos, failed)
418  result["GaudiTest.Histos.failure_on"] = result.Quote(msg)
419  result["GaudiTest.Histos.found"] = result.Quote(pp.pformat(histos))
420 
421  return causes
422 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1059
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:931
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:480
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 387 of file BaseTest.py.

387  ignore = None):
388  """
389  Compare the TTree summaries in stdout with the ones in trees_dict or in
390  the reference file. By default ignore the size, compression and basket
391  fields.
392  The presence of TTree summaries when none is expected is not a failure.
393  """
394  if stdout is None : stdout=self.out
395  if result is None : result=self.result
396  if causes is None : causes=self.causes
397 
398  if dict is None:
399  lreference = self._expandReferenceFileName(self.reference)
400  # call the validator if the file exists
401  if lreference and os.path.isfile(lreference):
402  dict = findHistosSummaries(open(lreference).read())
403  else:
404  dict = {}
405 
406  from pprint import PrettyPrinter
407  pp = PrettyPrinter()
408  if dict:
409  result["GaudiTest.Histos.expected"] = result.Quote(pp.pformat(dict))
410  if ignore:
411  result["GaudiTest.Histos.ignore"] = result.Quote(ignore)
412 
413  histos = findHistosSummaries(stdout)
414  failed = cmpTreesDicts(dict, histos, ignore)
415  if failed:
416  causes.append("histos summaries")
417  msg = "%s: %s != %s" % getCmpFailingValues(dict, histos, failed)
418  result["GaudiTest.Histos.failure_on"] = result.Quote(msg)
419  result["GaudiTest.Histos.found"] = result.Quote(pp.pformat(histos))
420 
421  return causes
422 
def findHistosSummaries(stdout)
Definition: BaseTest.py:1059
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:931
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:480
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 350 of file BaseTest.py.

350  ignore = r"Basket|.*size|Compression"):
351  """
352  Compare the TTree summaries in stdout with the ones in trees_dict or in
353  the reference file. By default ignore the size, compression and basket
354  fields.
355  The presence of TTree summaries when none is expected is not a failure.
356  """
357  if stdout is None : stdout=self.out
358  if result is None : result=self.result
359  if causes is None : causes=self.causes
360  if trees_dict is None:
361  lreference = self._expandReferenceFileName(self.reference)
362  # call the validator if the file exists
363  if lreference and os.path.isfile(lreference):
364  trees_dict = findTTreeSummaries(open(lreference).read())
365  else:
366  trees_dict = {}
367 
368  from pprint import PrettyPrinter
369  pp = PrettyPrinter()
370  if trees_dict:
371  result["GaudiTest.TTrees.expected"] = result.Quote(pp.pformat(trees_dict))
372  if ignore:
373  result["GaudiTest.TTrees.ignore"] = result.Quote(ignore)
374 
375  trees = findTTreeSummaries(stdout)
376  failed = cmpTreesDicts(trees_dict, trees, ignore)
377  if failed:
378  causes.append("trees summaries")
379  msg = "%s: %s != %s" % getCmpFailingValues(trees_dict, trees, failed)
380  result["GaudiTest.TTrees.failure_on"] = result.Quote(msg)
381  result["GaudiTest.TTrees.found"] = result.Quote(pp.pformat(trees))
382 
383  return causes
384 
def findTTreeSummaries(stdout)
Definition: BaseTest.py:879
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:931
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:480
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 350 of file BaseTest.py.

350  ignore = r"Basket|.*size|Compression"):
351  """
352  Compare the TTree summaries in stdout with the ones in trees_dict or in
353  the reference file. By default ignore the size, compression and basket
354  fields.
355  The presence of TTree summaries when none is expected is not a failure.
356  """
357  if stdout is None : stdout=self.out
358  if result is None : result=self.result
359  if causes is None : causes=self.causes
360  if trees_dict is None:
361  lreference = self._expandReferenceFileName(self.reference)
362  # call the validator if the file exists
363  if lreference and os.path.isfile(lreference):
364  trees_dict = findTTreeSummaries(open(lreference).read())
365  else:
366  trees_dict = {}
367 
368  from pprint import PrettyPrinter
369  pp = PrettyPrinter()
370  if trees_dict:
371  result["GaudiTest.TTrees.expected"] = result.Quote(pp.pformat(trees_dict))
372  if ignore:
373  result["GaudiTest.TTrees.ignore"] = result.Quote(ignore)
374 
375  trees = findTTreeSummaries(stdout)
376  failed = cmpTreesDicts(trees_dict, trees, ignore)
377  if failed:
378  causes.append("trees summaries")
379  msg = "%s: %s != %s" % getCmpFailingValues(trees_dict, trees, failed)
380  result["GaudiTest.TTrees.failure_on"] = result.Quote(msg)
381  result["GaudiTest.TTrees.found"] = result.Quote(pp.pformat(trees))
382 
383  return causes
384 
def findTTreeSummaries(stdout)
Definition: BaseTest.py:879
def getCmpFailingValues(reference, to_check, fail_path)
Definition: BaseTest.py:931
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:480
def GaudiTesting.BaseTest.BaseTest.countErrorLines (   self,
  expected = {'ERROR':0,
  FATAL 
)

Definition at line 312 of file BaseTest.py.

312  def countErrorLines(self, expected = {'ERROR':0, 'FATAL':0}, stdout=None, result=None,causes=None):
313  """
314  Count the number of messages with required severity (by default ERROR and FATAL)
315  and check if their numbers match the expected ones (0 by default).
316  The dictionary "expected" can be used to tune the number of errors and fatals
317  allowed, or to limit the number of expected warnings etc.
318  """
319 
320  if stdout is None : stdout=self.out
321  if result is None : result=self.result
322  if causes is None : causes=self.causes
323 
324  # prepare the dictionary to record the extracted lines
325  errors = {}
326  for sev in expected:
327  errors[sev] = []
328 
329  outlines = stdout.splitlines()
330  from math import log10
331  fmt = "%%%dd - %%s" % (int(log10(len(outlines)+1)))
332 
333  linecount = 0
334  for l in outlines:
335  linecount += 1
336  words = l.split()
337  if len(words) >= 2 and words[1] in errors:
338  errors[words[1]].append(fmt%(linecount,l.rstrip()))
339 
340  for e in errors:
341  if len(errors[e]) != expected[e]:
342  causes.append('%s(%d)'%(e,len(errors[e])))
343  result["GaudiTest.lines.%s"%e] = result.Quote('\n'.join(errors[e]))
344  result["GaudiTest.lines.%s.expected#"%e] = result.Quote(str(expected[e]))
345 
346  return causes
347 
def GaudiTesting.BaseTest.BaseTest.countErrorLines (   self,
  expected = {'ERROR':0,
  FATAL 
)

Definition at line 312 of file BaseTest.py.

312  def countErrorLines(self, expected = {'ERROR':0, 'FATAL':0}, stdout=None, result=None,causes=None):
313  """
314  Count the number of messages with required severity (by default ERROR and FATAL)
315  and check if their numbers match the expected ones (0 by default).
316  The dictionary "expected" can be used to tune the number of errors and fatals
317  allowed, or to limit the number of expected warnings etc.
318  """
319 
320  if stdout is None : stdout=self.out
321  if result is None : result=self.result
322  if causes is None : causes=self.causes
323 
324  # prepare the dictionary to record the extracted lines
325  errors = {}
326  for sev in expected:
327  errors[sev] = []
328 
329  outlines = stdout.splitlines()
330  from math import log10
331  fmt = "%%%dd - %%s" % (int(log10(len(outlines)+1)))
332 
333  linecount = 0
334  for l in outlines:
335  linecount += 1
336  words = l.split()
337  if len(words) >= 2 and words[1] in errors:
338  errors[words[1]].append(fmt%(linecount,l.rstrip()))
339 
340  for e in errors:
341  if len(errors[e]) != expected[e]:
342  causes.append('%s(%d)'%(e,len(errors[e])))
343  result["GaudiTest.lines.%s"%e] = result.Quote('\n'.join(errors[e]))
344  result["GaudiTest.lines.%s.expected#"%e] = result.Quote(str(expected[e]))
345 
346  return causes
347 
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 271 of file BaseTest.py.

271  def findReferenceBlock(self,reference=None, stdout=None, result=None, causes=None, signature_offset=0, signature=None, id = None):
272  """
273  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.
274  """
275 
276  if reference is None : reference=self.reference
277  if stdout is None : stdout=self.out
278  if result is None : result=self.result
279  if causes is None : causes=self.causes
280 
281  reflines = filter(None,map(lambda s: s.rstrip(), reference.splitlines()))
282  if not reflines:
283  raise RuntimeError("Empty (or null) reference")
284  # the same on standard output
285  outlines = filter(None,map(lambda s: s.rstrip(), stdout.splitlines()))
286 
287  res_field = "GaudiTest.RefBlock"
288  if id:
289  res_field += "_%s" % id
290 
291  if signature is None:
292  if signature_offset < 0:
293  signature_offset = len(reference)+signature_offset
294  signature = reflines[signature_offset]
295  # find the reference block in the output file
296  try:
297  pos = outlines.index(signature)
298  outlines = outlines[pos-signature_offset:pos+len(reflines)-signature_offset]
299  if reflines != outlines:
300  msg = "standard output"
301  # I do not want 2 messages in causes if teh function is called twice
302  if not msg in causes:
303  causes.append(msg)
304  result[res_field + ".observed"] = result.Quote("\n".join(outlines))
305  except ValueError:
306  causes.append("missing signature")
307  result[res_field + ".signature"] = result.Quote(signature)
308  if len(reflines) > 1 or signature != reflines[0]:
309  result[res_field + ".expected"] = result.Quote("\n".join(reflines))
310  return causes
311 
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 271 of file BaseTest.py.

271  def findReferenceBlock(self,reference=None, stdout=None, result=None, causes=None, signature_offset=0, signature=None, id = None):
272  """
273  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.
274  """
275 
276  if reference is None : reference=self.reference
277  if stdout is None : stdout=self.out
278  if result is None : result=self.result
279  if causes is None : causes=self.causes
280 
281  reflines = filter(None,map(lambda s: s.rstrip(), reference.splitlines()))
282  if not reflines:
283  raise RuntimeError("Empty (or null) reference")
284  # the same on standard output
285  outlines = filter(None,map(lambda s: s.rstrip(), stdout.splitlines()))
286 
287  res_field = "GaudiTest.RefBlock"
288  if id:
289  res_field += "_%s" % id
290 
291  if signature is None:
292  if signature_offset < 0:
293  signature_offset = len(reference)+signature_offset
294  signature = reflines[signature_offset]
295  # find the reference block in the output file
296  try:
297  pos = outlines.index(signature)
298  outlines = outlines[pos-signature_offset:pos+len(reflines)-signature_offset]
299  if reflines != outlines:
300  msg = "standard output"
301  # I do not want 2 messages in causes if teh function is called twice
302  if not msg in causes:
303  causes.append(msg)
304  result[res_field + ".observed"] = result.Quote("\n".join(outlines))
305  except ValueError:
306  causes.append("missing signature")
307  result[res_field + ".signature"] = result.Quote(signature)
308  if len(reflines) > 1 or signature != reflines[0]:
309  result[res_field + ".expected"] = result.Quote("\n".join(reflines))
310  return causes
311 
struct GAUDI_API map
Parametrisation class for map-like implementation.
def GaudiTesting.BaseTest.BaseTest.run (   self)

Definition at line 91 of file BaseTest.py.

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

Definition at line 91 of file BaseTest.py.

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

Definition at line 255 of file BaseTest.py.

255  def ValidateOutput(self, stdout, stderr, result):
256  # checking if default validation or not
257  if self.validator is not BaseTest.validator:
258  self.validator(stdout, stderr, result, self.causes,
259  self.reference, self.error_reference)
260  else:
261  if self.stderr == '':
262  self.validateWithReference(stdout, stderr, result, causes)
263  elif stderr.strip() != self.stderr.strip():
264  self.causes.append('standard error')
265 
266 
267  return result, causes
268 
269 
270 
def ValidateOutput(self, stdout, stderr, result)
Definition: BaseTest.py:255
def GaudiTesting.BaseTest.BaseTest.ValidateOutput (   self,
  stdout,
  stderr,
  result 
)

Definition at line 255 of file BaseTest.py.

255  def ValidateOutput(self, stdout, stderr, result):
256  # checking if default validation or not
257  if self.validator is not BaseTest.validator:
258  self.validator(stdout, stderr, result, self.causes,
259  self.reference, self.error_reference)
260  else:
261  if self.stderr == '':
262  self.validateWithReference(stdout, stderr, result, causes)
263  elif stderr.strip() != self.stderr.strip():
264  self.causes.append('standard error')
265 
266 
267  return result, causes
268 
269 
270 
def ValidateOutput(self, stdout, stderr, result)
Definition: BaseTest.py:255
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 424 of file BaseTest.py.

424  causes=None, preproc=None):
425  '''
426  Default validation acti*on: compare standard output and error to the
427  reference files.
428  '''
429 
430  if stdout is None : stdout = self.out
431  if stderr is None : stderr = self.err
432  if result is None : result = self.result
433  if causes is None : causes = self.causes
434 
435  # set the default output preprocessor
436  if preproc is None:
437  preproc = normalizeExamples
438  # check standard output
439  lreference = self._expandReferenceFileName(self.reference)
440  # call the validator if the file exists
441  if lreference and os.path.isfile(lreference):
442  causes += ReferenceFileValidator(lreference,
443  "standard output",
444  "Output Diff",
445  preproc=preproc)(stdout, result)
446  # Compare TTree summaries
447  causes = self.CheckTTreesSummaries(stdout, result, causes)
448  causes = self.CheckHistosSummaries(stdout, result, causes)
449  if causes: # Write a new reference file for stdout
450  try:
451  newref = open(lreference + ".new","w")
452  # sanitize newlines
453  for l in stdout.splitlines():
454  newref.write(l.rstrip() + '\n')
455  del newref # flush and close
456  except IOError:
457  # Ignore IO errors when trying to update reference files
458  # because we may be in a read-only filesystem
459  pass
460 
461  # check standard error
462  lreference = self._expandReferenceFileName(self.error_reference)
463  # call the validator if we have a file to use
464  if lreference and os.path.isfile(lreference):
465  newcauses = ReferenceFileValidator(lreference,
466  "standard error",
467  "Error Diff",
468  preproc=preproc)(stderr, result)
469  causes += newcauses
470  if newcauses: # Write a new reference file for stdedd
471  newref = open(lreference + ".new","w")
472  # sanitize newlines
473  for l in stderr.splitlines():
474  newref.write(l.rstrip() + '\n')
475  del newref # flush and close
476  else:
477  causes += BasicOutputValidator(lreference, "standard error", "ExecTest.expected_stderr")(stderr, result)
478  return causes
479 
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:480
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 424 of file BaseTest.py.

424  causes=None, preproc=None):
425  '''
426  Default validation acti*on: compare standard output and error to the
427  reference files.
428  '''
429 
430  if stdout is None : stdout = self.out
431  if stderr is None : stderr = self.err
432  if result is None : result = self.result
433  if causes is None : causes = self.causes
434 
435  # set the default output preprocessor
436  if preproc is None:
437  preproc = normalizeExamples
438  # check standard output
439  lreference = self._expandReferenceFileName(self.reference)
440  # call the validator if the file exists
441  if lreference and os.path.isfile(lreference):
442  causes += ReferenceFileValidator(lreference,
443  "standard output",
444  "Output Diff",
445  preproc=preproc)(stdout, result)
446  # Compare TTree summaries
447  causes = self.CheckTTreesSummaries(stdout, result, causes)
448  causes = self.CheckHistosSummaries(stdout, result, causes)
449  if causes: # Write a new reference file for stdout
450  try:
451  newref = open(lreference + ".new","w")
452  # sanitize newlines
453  for l in stdout.splitlines():
454  newref.write(l.rstrip() + '\n')
455  del newref # flush and close
456  except IOError:
457  # Ignore IO errors when trying to update reference files
458  # because we may be in a read-only filesystem
459  pass
460 
461  # check standard error
462  lreference = self._expandReferenceFileName(self.error_reference)
463  # call the validator if we have a file to use
464  if lreference and os.path.isfile(lreference):
465  newcauses = ReferenceFileValidator(lreference,
466  "standard error",
467  "Error Diff",
468  preproc=preproc)(stderr, result)
469  causes += newcauses
470  if newcauses: # Write a new reference file for stdedd
471  newref = open(lreference + ".new","w")
472  # sanitize newlines
473  for l in stderr.splitlines():
474  newref.write(l.rstrip() + '\n')
475  del newref # flush and close
476  else:
477  causes += BasicOutputValidator(lreference, "standard error", "ExecTest.expected_stderr")(stderr, result)
478  return causes
479 
def _expandReferenceFileName(self, reffile)
Definition: BaseTest.py:480
def GaudiTesting.BaseTest.BaseTest.validator (   self,
  stdout = '',
  stderr = '' 
)

Definition at line 88 of file BaseTest.py.

88  def validator(self, stdout='',stderr=''):
89  pass
90 
def GaudiTesting.BaseTest.BaseTest.validator (   self,
  stdout = '',
  stderr = '' 
)

Definition at line 88 of file BaseTest.py.

88  def validator(self, stdout='',stderr=''):
89  pass
90 

Member Data Documentation

GaudiTesting.BaseTest.BaseTest._common_tmpdir = None
staticprivate

Definition at line 60 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.args

Definition at line 64 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.basedir

Definition at line 86 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.causes

Definition at line 79 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.environment

Definition at line 71 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.err

Definition at line 83 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.error_reference

Definition at line 66 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.exit_code

Definition at line 70 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.name

Definition at line 78 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.options

Definition at line 67 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.out

Definition at line 82 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.proc

Definition at line 84 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.program

Definition at line 63 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.reference

Definition at line 65 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.result

Definition at line 80 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.returnedCode

Definition at line 81 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.signal

Definition at line 73 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.stack_trace

Definition at line 85 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.status

Definition at line 77 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.stderr

Definition at line 68 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.timeout

Definition at line 69 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.unsupported_platforms

Definition at line 72 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.use_temp_dir

Definition at line 75 of file BaseTest.py.

GaudiTesting.BaseTest.BaseTest.workdir

Definition at line 74 of file BaseTest.py.


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