GaudiTest.GaudiExeTest Class Reference
Inheritance diagram for GaudiTest.GaudiExeTest:
Collaboration diagram for GaudiTest.GaudiExeTest:

Public Member Functions

def PlatformIsNotSupported (self, context, result)
 
def GetPlatform (self)
 
def isWinPlatform (self)
 
def CheckTTreesSummaries (self, stdout, result, causes, trees_dict=None, ignore=r"Basket|.*size|Compression")
 
def CheckHistosSummaries (self, stdout, result, causes, dict=None, ignore=None)
 
def ValidateWithReference (self, stdout, stderr, result, causes, preproc=None)
 
def ValidateOutput (self, stdout, stderr, result)
 
def DumpEnvironment (self, result)
 
def Run (self, context, result)
 
def RunProgram (self, program, arguments, context, result)
 

Public Attributes

 callable
 
 extra_args
 
 args_order
 
 program
 
 reference
 
 error_reference
 
 use_temp_dir
 
 timeout
 
 signal
 

Static Public Attributes

list arguments
 

Private Member Functions

def _expandReferenceFileName (self, reffile)
 
def _CreateEclipseLaunch (self, prog, args, destdir=None)
 

Detailed Description

Standard Gaudi test.

Definition at line 1071 of file GaudiTest.py.

Member Function Documentation

def GaudiTest.GaudiExeTest._CreateEclipseLaunch (   self,
  prog,
  args,
  destdir = None 
)
private

Definition at line 1676 of file GaudiTest.py.

1676  def _CreateEclipseLaunch(self, prog, args, destdir = None):
1677  if 'NO_ECLIPSE_LAUNCHERS' in os.environ:
1678  # do not generate eclipse launchers if the user asks so
1679  return
1680  # Find the project name used in ecplise.
1681  # The name is in a file called ".project" in one of the parent directories
1682  projbasedir = os.path.normpath(destdir)
1683  while not os.path.exists(os.path.join(projbasedir, ".project")):
1684  oldprojdir = projbasedir
1685  projbasedir = os.path.normpath(os.path.join(projbasedir, os.pardir))
1686  # FIXME: the root level is invariant when trying to go up one level,
1687  # but it must be cheched on windows
1688  if oldprojdir == projbasedir:
1689  # If we cannot find a .project, so no point in creating a .launch file
1690  return
1691  # Ensure that we have a place where to write.
1692  if not os.path.exists(destdir):
1693  os.makedirs(destdir)
1694  # Use ElementTree to parse the XML file
1695  from xml.etree import ElementTree as ET
1696  t = ET.parse(os.path.join(projbasedir, ".project"))
1697  projectName = t.find("name").text
1698 
1699  # prepare the name/path of the generated file
1700  destfile = "%s.launch" % self._Runnable__id
1701  if destdir:
1702  destfile = os.path.join(destdir, destfile)
1703 
1704  if self.options.strip():
1705  # this means we have some custom options in the qmt file, so we have
1706  # to copy them from the temporary file at the end of the arguments
1707  # in another file
1708  tempfile = args.pop()
1709  optsfile = destfile + os.path.splitext(tempfile)[1]
1710  shutil.copyfile(tempfile, optsfile)
1711  args.append(optsfile)
1712 
1713  # prepare the data to insert in the XML file
1714  from xml.sax.saxutils import quoteattr # useful to quote XML special chars
1715  data = {}
1716  # Note: the "quoteattr(k)" is not needed because special chars cannot be part of a variable name,
1717  # but it doesn't harm.
1718  data["environment"] = "\n".join(['<mapEntry key=%s value=%s/>' % (quoteattr(k), quoteattr(v))
1719  for k, v in os.environ.iteritems()
1720  if k not in ('MAKEOVERRIDES', 'MAKEFLAGS', 'MAKELEVEL')])
1721 
1722  data["exec"] = which(prog) or prog
1723  if os.path.basename(data["exec"]).lower().startswith("python"):
1724  data["stopAtMain"] = "false" # do not stop at main when debugging Python scripts
1725  else:
1726  data["stopAtMain"] = "true"
1727 
1728  data["args"] = "&#10;".join(map(rationalizepath, args))
1729  if self.isWinPlatform():
1730  data["args"] = "&#10;".join(["/debugexe"] + map(rationalizepath, [data["exec"]] + args))
1731  data["exec"] = which("vcexpress.exe")
1732 
1733  if not self.use_temp_dir:
1734  data["workdir"] = os.getcwd()
1735  else:
1736  # If the test is using a tmporary directory, it is better to run it
1737  # in the same directory as the .launch file when debugged in eclipse
1738  data["workdir"] = destdir
1739 
1740  data["project"] = projectName.strip()
1741 
1742  # Template for the XML file, based on eclipse 3.4
1743  xml_template = u"""<?xml version="1.0" encoding="UTF-8" standalone="no"?>
1744 <launchConfiguration type="org.eclipse.cdt.launch.applicationLaunchType">
1745 <booleanAttribute key="org.eclipse.cdt.debug.mi.core.AUTO_SOLIB" value="true"/>
1746 <listAttribute key="org.eclipse.cdt.debug.mi.core.AUTO_SOLIB_LIST"/>
1747 <stringAttribute key="org.eclipse.cdt.debug.mi.core.DEBUG_NAME" value="gdb"/>
1748 <stringAttribute key="org.eclipse.cdt.debug.mi.core.GDB_INIT" value=".gdbinit"/>
1749 <listAttribute key="org.eclipse.cdt.debug.mi.core.SOLIB_PATH"/>
1750 <booleanAttribute key="org.eclipse.cdt.debug.mi.core.STOP_ON_SOLIB_EVENTS" value="false"/>
1751 <booleanAttribute key="org.eclipse.cdt.debug.mi.core.breakpointsFullPath" value="false"/>
1752 <stringAttribute key="org.eclipse.cdt.debug.mi.core.commandFactory" value="org.eclipse.cdt.debug.mi.core.standardCommandFactory"/>
1753 <stringAttribute key="org.eclipse.cdt.debug.mi.core.protocol" value="mi"/>
1754 <booleanAttribute key="org.eclipse.cdt.debug.mi.core.verboseMode" value="false"/>
1755 <intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="0"/>
1756 <stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
1757 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="org.eclipse.cdt.debug.mi.core.CDebuggerNew"/>
1758 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
1759 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="run"/>
1760 <booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="%(stopAtMain)s"/>
1761 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="main"/>
1762 <booleanAttribute key="org.eclipse.cdt.launch.ENABLE_REGISTER_BOOKKEEPING" value="false"/>
1763 <booleanAttribute key="org.eclipse.cdt.launch.ENABLE_VARIABLE_BOOKKEEPING" value="false"/>
1764 <stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList/&gt;"/>
1765 <stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;globalVariableList/&gt;&#10;"/>
1766 <stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList/&gt;&#10;"/>
1767 <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_ARGUMENTS" value="%(args)s"/>
1768 <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="%(exec)s"/>
1769 <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="%(project)s"/>
1770 <stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/>
1771 <stringAttribute key="org.eclipse.cdt.launch.WORKING_DIRECTORY" value="%(workdir)s"/>
1772 <booleanAttribute key="org.eclipse.cdt.launch.ui.ApplicationCDebuggerTab.DEFAULTS_SET" value="true"/>
1773 <booleanAttribute key="org.eclipse.cdt.launch.use_terminal" value="true"/>
1774 <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
1775 <listEntry value="/%(project)s"/>
1776 </listAttribute>
1777 <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
1778 <listEntry value="4"/>
1779 </listAttribute>
1780 <booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="false"/>
1781 <mapAttribute key="org.eclipse.debug.core.environmentVariables">
1782 %(environment)s
1783 </mapAttribute>
1784 <mapAttribute key="org.eclipse.debug.core.preferred_launchers">
1785 <mapEntry key="[debug]" value="org.eclipse.cdt.cdi.launch.localCLaunch"/>
1786 </mapAttribute>
1787 <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
1788 <listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
1789 </listAttribute>
1790 </launchConfiguration>
1791 """
1792  try:
1793  # ensure the correct encoding of data values
1794  for k in data:
1795  data[k] = codecs.decode(data[k], 'utf-8')
1796  xml = xml_template % data
1797 
1798  # Write the output file
1799  codecs.open(destfile, "w", encoding='utf-8').write(xml)
1800  except:
1801  print 'WARNING: problem generating Eclipse launcher'
1802 
1803 
1804 try:
def which(executable)
Locates an executable in the executables path ($PATH) and returns the full path to it...
Definition: GaudiTest.py:289
struct GAUDI_API map
Parametrisation class for map-like implementation.
def _CreateEclipseLaunch(self, prog, args, destdir=None)
Definition: GaudiTest.py:1676
def GaudiTest.GaudiExeTest._expandReferenceFileName (   self,
  reffile 
)
private

Definition at line 1231 of file GaudiTest.py.

1231  def _expandReferenceFileName(self, reffile):
1232  # if no file is passed, do nothing
1233  if not reffile:
1234  return ""
1235 
1236  # function to split an extension in constituents parts
1237  platformSplit = lambda p: set(p.split('-' in p and '-' or '_'))
1238 
1239  reference = os.path.normpath(os.path.expandvars(reffile))
1240  # old-style platform-specific reference name
1241  spec_ref = reference[:-3] + self.GetPlatform()[0:3] + reference[-3:]
1242  if os.path.isfile(spec_ref):
1243  reference = spec_ref
1244  else: # look for new-style platform specific reference files:
1245  # get all the files whose name start with the reference filename
1246  dirname, basename = os.path.split(reference)
1247  if not dirname: dirname = '.'
1248  head = basename + "."
1249  head_len = len(head)
1250  platform = platformSplit(self.GetPlatform())
1251  if 'do0' in platform:
1252  platform.add('dbg')
1253  candidates = []
1254  for f in os.listdir(dirname):
1255  if f.startswith(head):
1256  req_plat = platformSplit(f[head_len:])
1257  if platform.issuperset(req_plat):
1258  candidates.append( (len(req_plat), f) )
1259  if candidates: # take the one with highest matching
1260  # FIXME: it is not possible to say if x86_64-slc5-gcc43-dbg
1261  # has to use ref.x86_64-gcc43 or ref.slc5-dbg
1262  candidates.sort()
1263  reference = os.path.join(dirname, candidates[-1][1])
1264  return reference
1265 
def _expandReferenceFileName(self, reffile)
Definition: GaudiTest.py:1231
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 1302 of file GaudiTest.py.

1302  ignore = None):
1303  """
1304  Compare the TTree summaries in stdout with the ones in trees_dict or in
1305  the reference file. By default ignore the size, compression and basket
1306  fields.
1307  The presence of TTree summaries when none is expected is not a failure.
1308  """
1309  if dict is None:
1310  reference = self._expandReferenceFileName(self.reference)
1311  # call the validator if the file exists
1312  if reference and os.path.isfile(reference):
1313  dict = findHistosSummaries(open(reference).read())
1314  else:
1315  dict = {}
1316 
1317  from pprint import PrettyPrinter
1318  pp = PrettyPrinter()
1319  if dict:
1320  result["GaudiTest.Histos.expected"] = result.Quote(pp.pformat(dict))
1321  if ignore:
1322  result["GaudiTest.Histos.ignore"] = result.Quote(ignore)
1323 
1324  histos = findHistosSummaries(stdout)
1325  failed = cmpTreesDicts(dict, histos, ignore)
1326  if failed:
1327  causes.append("histos summaries")
1328  msg = "%s: %s != %s" % getCmpFailingValues(dict, histos, failed)
1329  result["GaudiTest.Histos.failure_on"] = result.Quote(msg)
1330  result["GaudiTest.Histos.found"] = result.Quote(pp.pformat(histos))
1331 
1332  return causes
1333 
def _expandReferenceFileName(self, reffile)
Definition: GaudiTest.py:1231
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: GaudiTest.py:782
def getCmpFailingValues(reference, to_check, fail_path)
Definition: GaudiTest.py:813
def findHistosSummaries(stdout)
Definition: GaudiTest.py:889
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 1268 of file GaudiTest.py.

1268  ignore = r"Basket|.*size|Compression"):
1269  """
1270  Compare the TTree summaries in stdout with the ones in trees_dict or in
1271  the reference file. By default ignore the size, compression and basket
1272  fields.
1273  The presence of TTree summaries when none is expected is not a failure.
1274  """
1275  if trees_dict is None:
1276  reference = self._expandReferenceFileName(self.reference)
1277  # call the validator if the file exists
1278  if reference and os.path.isfile(reference):
1279  trees_dict = findTTreeSummaries(open(reference).read())
1280  else:
1281  trees_dict = {}
1282 
1283  from pprint import PrettyPrinter
1284  pp = PrettyPrinter()
1285  if trees_dict:
1286  result["GaudiTest.TTrees.expected"] = result.Quote(pp.pformat(trees_dict))
1287  if ignore:
1288  result["GaudiTest.TTrees.ignore"] = result.Quote(ignore)
1289 
1290  trees = findTTreeSummaries(stdout)
1291  failed = cmpTreesDicts(trees_dict, trees, ignore)
1292  if failed:
1293  causes.append("trees summaries")
1294  msg = "%s: %s != %s" % getCmpFailingValues(trees_dict, trees, failed)
1295  result["GaudiTest.TTrees.failure_on"] = result.Quote(msg)
1296  result["GaudiTest.TTrees.found"] = result.Quote(pp.pformat(trees))
1297 
1298  return causes
1299 
def _expandReferenceFileName(self, reffile)
Definition: GaudiTest.py:1231
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: GaudiTest.py:782
def getCmpFailingValues(reference, to_check, fail_path)
Definition: GaudiTest.py:813
def findTTreeSummaries(stdout)
Definition: GaudiTest.py:761
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 1456 of file GaudiTest.py.

1456  def DumpEnvironment(self, result):
1457  """
1458  Add the content of the environment to the result object.
1459 
1460  Copied from the QMTest class of COOL.
1461  """
1462  vars = os.environ.keys()
1463  vars.sort()
1464  result['GaudiTest.environment'] = \
1465  result.Quote('\n'.join(["%s=%s"%(v,os.environ[v]) for v in vars]))
1466 
def DumpEnvironment(self, result)
Definition: GaudiTest.py:1456
def GaudiTest.GaudiExeTest.GetPlatform (   self)
Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1209 of file GaudiTest.py.

1209  def GetPlatform(self):
1210  """
1211  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1212  """
1213  arch = "None"
1214  # check architecture name
1215  if "CMTCONFIG" in os.environ:
1216  arch = os.environ["CMTCONFIG"]
1217  elif "SCRAM_ARCH" in os.environ:
1218  arch = os.environ["SCRAM_ARCH"]
1219  return arch
1220 
def GaudiTest.GaudiExeTest.isWinPlatform (   self)
Return True if the current platform is Windows.

This function was needed because of the change in the CMTCONFIG format,
from win32_vc71_dbg to i686-winxp-vc9-dbg.

Definition at line 1221 of file GaudiTest.py.

1221  def isWinPlatform(self):
1222  """
1223  Return True if the current platform is Windows.
1224 
1225  This function was needed because of the change in the CMTCONFIG format,
1226  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1227  """
1228  platform = self.GetPlatform()
1229  return "winxp" in platform or platform.startswith("win")
1230 
def GaudiTest.GaudiExeTest.PlatformIsNotSupported (   self,
  context,
  result 
)

Definition at line 1195 of file GaudiTest.py.

1195  def PlatformIsNotSupported(self, context, result):
1196  platform = self.GetPlatform()
1197  unsupported = [ re.compile(x)
1198  for x in [ str(y).strip()
1199  for y in self.unsupported_platforms ]
1200  if x
1201  ]
1202  for p_re in unsupported:
1203  if p_re.search(platform):
1204  result.SetOutcome(result.UNTESTED)
1205  result[result.CAUSE] = 'Platform not supported.'
1206  return True
1207  return False
1208 
def PlatformIsNotSupported(self, context, result)
Definition: GaudiTest.py:1195
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 1467 of file GaudiTest.py.

1467  def Run(self, context, result):
1468  """Run the test.
1469 
1470  'context' -- A 'Context' giving run-time parameters to the
1471  test.
1472 
1473  'result' -- A 'Result' object. The outcome will be
1474  'Result.PASS' when this method is called. The 'result' may be
1475  modified by this method to indicate outcomes other than
1476  'Result.PASS' or to add annotations."""
1477 
1478  # Check if the platform is supported
1479  if self.PlatformIsNotSupported(context, result):
1480  return
1481 
1482  # Prepare program name and arguments (expanding variables, and converting to absolute)
1483  if self.program:
1484  prog = rationalizepath(self.program)
1485  elif "GAUDIEXE" in os.environ:
1486  prog = os.environ["GAUDIEXE"]
1487  else:
1488  prog = "Gaudi.exe"
1489  self.program = prog
1490 
1491  dummy, prog_ext = os.path.splitext(prog)
1492  if prog_ext not in [ ".exe", ".py", ".bat" ] and self.isWinPlatform():
1493  prog += ".exe"
1494  prog_ext = ".exe"
1495 
1496  prog = which(prog) or prog
1497 
1498  # Convert paths to absolute paths in arguments and reference files
1499  args = map(rationalizepath, self.args)
1502 
1503 
1504  # check if the user provided inline options
1505  tmpfile = None
1506  if self.options.strip():
1507  ext = ".opts"
1508  if re.search(r"from\s+Gaudi.Configuration\s+import\s+\*|from\s+Configurables\s+import", self.options):
1509  ext = ".py"
1510  tmpfile = TempFile(ext)
1511  tmpfile.writelines("\n".join(self.options.splitlines()))
1512  tmpfile.flush()
1513  args.append(tmpfile.name)
1514  result["GaudiTest.options"] = result.Quote(self.options)
1515 
1516  # if the program is a python file, execute it through python
1517  if prog_ext == ".py":
1518  args.insert(0,prog)
1519  if self.isWinPlatform():
1520  prog = which("python.exe") or "python.exe"
1521  else:
1522  prog = which("python") or "python"
1523 
1524  # Change to the working directory if specified or to the default temporary
1525  origdir = os.getcwd()
1526  if self.workdir:
1527  os.chdir(str(os.path.normpath(os.path.expandvars(self.workdir))))
1528  elif self.use_temp_dir == "true":
1529  if "QMTEST_TMPDIR" in os.environ:
1530  qmtest_tmpdir = os.environ["QMTEST_TMPDIR"]
1531  if not os.path.exists(qmtest_tmpdir):
1532  os.makedirs(qmtest_tmpdir)
1533  os.chdir(qmtest_tmpdir)
1534  elif "qmtest.tmpdir" in context:
1535  os.chdir(context["qmtest.tmpdir"])
1536 
1537  if "QMTEST_IGNORE_TIMEOUT" not in os.environ:
1538  self.timeout = max(self.timeout,600)
1539  else:
1540  self.timeout = -1
1541 
1542  try:
1543  # Generate eclipse.org debug launcher for the test
1544  self._CreateEclipseLaunch(prog, args, destdir = os.path.join(origdir, '.eclipse'))
1545  # Run the test
1546  self.RunProgram(prog,
1547  [ prog ] + args,
1548  context, result)
1549  # Record the content of the enfironment for failing tests
1550  if result.GetOutcome() not in [ result.PASS ]:
1551  self.DumpEnvironment(result)
1552  finally:
1553  # revert to the original directory
1554  os.chdir(origdir)
1555 
def PlatformIsNotSupported(self, context, result)
Definition: GaudiTest.py:1195
def DumpEnvironment(self, result)
Definition: GaudiTest.py:1456
def which(executable)
Locates an executable in the executables path ($PATH) and returns the full path to it...
Definition: GaudiTest.py:289
def RunProgram(self, program, arguments, context, result)
Definition: GaudiTest.py:1556
struct GAUDI_API map
Parametrisation class for map-like implementation.
def Run(self, context, result)
Definition: GaudiTest.py:1467
def _CreateEclipseLaunch(self, prog, args, destdir=None)
Definition: GaudiTest.py:1676
def rationalizepath(p)
Definition: GaudiTest.py:309
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 1556 of file GaudiTest.py.

1556  def RunProgram(self, program, arguments, context, result):
1557  """Run the 'program'.
1558 
1559  'program' -- The path to the program to run.
1560 
1561  'arguments' -- A list of the arguments to the program. This
1562  list must contain a first argument corresponding to 'argv[0]'.
1563 
1564  'context' -- A 'Context' giving run-time parameters to the
1565  test.
1566 
1567  'result' -- A 'Result' object. The outcome will be
1568  'Result.PASS' when this method is called. The 'result' may be
1569  modified by this method to indicate outcomes other than
1570  'Result.PASS' or to add annotations.
1571 
1572  @attention: This method has been copied from command.ExecTestBase
1573  (QMTest 2.3.0) and modified to keep stdout and stderr
1574  for tests that have been terminated by a signal.
1575  (Fundamental for debugging in the Application Area)
1576  """
1577 
1578  # Construct the environment.
1579  environment = self.MakeEnvironment(context)
1580  # FIXME: whithout this, we get some spurious '\x1b[?1034' in the std out on SLC6
1581  if "slc6" in environment.get('CMTCONFIG', ''):
1582  environment['TERM'] = 'dumb'
1583  # Create the executable.
1584  if self.timeout >= 0:
1585  timeout = self.timeout
1586  else:
1587  # If no timeout was specified, we sill run this process in a
1588  # separate process group and kill the entire process group
1589  # when the child is done executing. That means that
1590  # orphaned child processes created by the test will be
1591  # cleaned up.
1592  timeout = -2
1593  e = GaudiFilterExecutable(self.stdin, timeout)
1594  # Run it.
1595  exit_status = e.Run(arguments, environment, path = program)
1596  # Get the stack trace from the temporary file (if present)
1597  if e.stack_trace_file and os.path.exists(e.stack_trace_file):
1598  stack_trace = open(e.stack_trace_file).read()
1599  os.remove(e.stack_trace_file)
1600  else:
1601  stack_trace = None
1602  if stack_trace:
1603  result["ExecTest.stack_trace"] = result.Quote(stack_trace)
1604 
1605  # If the process terminated normally, check the outputs.
1606  if (sys.platform == "win32" or os.WIFEXITED(exit_status)
1607  or self.signal == os.WTERMSIG(exit_status)):
1608  # There are no causes of failure yet.
1609  causes = []
1610  # The target program terminated normally. Extract the
1611  # exit code, if this test checks it.
1612  if self.exit_code is None:
1613  exit_code = None
1614  elif sys.platform == "win32":
1615  exit_code = exit_status
1616  else:
1617  exit_code = os.WEXITSTATUS(exit_status)
1618  # Get the output generated by the program.
1619  stdout = e.stdout
1620  stderr = e.stderr
1621  # Record the results.
1622  result["ExecTest.exit_code"] = str(exit_code)
1623  result["ExecTest.stdout"] = result.Quote(stdout)
1624  result["ExecTest.stderr"] = result.Quote(stderr)
1625  # Check to see if the exit code matches.
1626  if exit_code != self.exit_code:
1627  causes.append("exit_code")
1628  result["ExecTest.expected_exit_code"] \
1629  = str(self.exit_code)
1630  # Validate the output.
1631  causes += self.ValidateOutput(stdout, stderr, result)
1632  # If anything went wrong, the test failed.
1633  if causes:
1634  result.Fail("Unexpected %s." % string.join(causes, ", "))
1635  elif os.WIFSIGNALED(exit_status):
1636  # The target program terminated with a signal. Construe
1637  # that as a test failure.
1638  signal_number = str(os.WTERMSIG(exit_status))
1639  if not stack_trace:
1640  result.Fail("Program terminated by signal.")
1641  else:
1642  # The presence of stack_trace means tha we stopped the job because
1643  # of a time-out
1644  result.Fail("Exceeded time limit (%ds), terminated." % timeout)
1645  result["ExecTest.signal_number"] = signal_number
1646  result["ExecTest.stdout"] = result.Quote(e.stdout)
1647  result["ExecTest.stderr"] = result.Quote(e.stderr)
1648  if self.signal:
1649  result["ExecTest.expected_signal_number"] = str(self.signal)
1650  elif os.WIFSTOPPED(exit_status):
1651  # The target program was stopped. Construe that as a
1652  # test failure.
1653  signal_number = str(os.WSTOPSIG(exit_status))
1654  if not stack_trace:
1655  result.Fail("Program stopped by signal.")
1656  else:
1657  # The presence of stack_trace means tha we stopped the job because
1658  # of a time-out
1659  result.Fail("Exceeded time limit (%ds), stopped." % timeout)
1660  result["ExecTest.signal_number"] = signal_number
1661  result["ExecTest.stdout"] = result.Quote(e.stdout)
1662  result["ExecTest.stderr"] = result.Quote(e.stderr)
1663  else:
1664  # The target program terminated abnormally in some other
1665  # manner. (This shouldn't normally happen...)
1666  result.Fail("Program did not terminate normally.")
1667 
1668  # Marco Cl.: This is a special trick to fix a "problem" with the output
1669  # of gaudi jobs when they use colors
1670  esc = '\x1b'
1671  repr_esc = '\\x1b'
1672  result["ExecTest.stdout"] = result["ExecTest.stdout"].replace(esc,repr_esc)
1673  # TODO: (MCl) improve the hack for colors in standard output
1674  # may be converting them to HTML tags
1675 
def RunProgram(self, program, arguments, context, result)
Definition: GaudiTest.py:1556
def ValidateOutput(self, stdout, stderr, result)
Definition: GaudiTest.py:1391
def GaudiTest.GaudiExeTest.ValidateOutput (   self,
  stdout,
  stderr,
  result 
)

Definition at line 1391 of file GaudiTest.py.

1391  def ValidateOutput(self, stdout, stderr, result):
1392  causes = []
1393  # if the test definition contains a custom validator, use it
1394  if self.validator.strip() != "":
1395  class CallWrapper(object):
1396  """
1397  Small wrapper class to dynamically bind some default arguments
1398  to a callable.
1399  """
1400  def __init__(self, callable, extra_args = {}):
1401  self.callable = callable
1402  self.extra_args = extra_args
1403  # get the list of names of positional arguments
1404  from inspect import getargspec
1405  self.args_order = getargspec(callable)[0]
1406  # Remove "self" from the list of positional arguments
1407  # since it is added automatically
1408  if self.args_order[0] == "self":
1409  del self.args_order[0]
1410  def __call__(self, *args, **kwargs):
1411  # Check which positional arguments are used
1412  positional = self.args_order[:len(args)]
1413 
1414  kwargs = dict(kwargs) # copy the arguments dictionary
1415  for a in self.extra_args:
1416  # use "extra_args" for the arguments not specified as
1417  # positional or keyword
1418  if a not in positional and a not in kwargs:
1419  kwargs[a] = self.extra_args[a]
1420  return apply(self.callable, args, kwargs)
1421  # local names to be exposed in the script
1422  exported_symbols = {"self":self,
1423  "stdout":stdout,
1424  "stderr":stderr,
1425  "result":result,
1426  "causes":causes,
1427  "findReferenceBlock":
1428  CallWrapper(findReferenceBlock, {"stdout":stdout,
1429  "result":result,
1430  "causes":causes}),
1431  "validateWithReference":
1432  CallWrapper(self.ValidateWithReference, {"stdout":stdout,
1433  "stderr":stderr,
1434  "result":result,
1435  "causes":causes}),
1436  "countErrorLines":
1437  CallWrapper(countErrorLines, {"stdout":stdout,
1438  "result":result,
1439  "causes":causes}),
1440  "checkTTreesSummaries":
1441  CallWrapper(self.CheckTTreesSummaries, {"stdout":stdout,
1442  "result":result,
1443  "causes":causes}),
1444  "checkHistosSummaries":
1445  CallWrapper(self.CheckHistosSummaries, {"stdout":stdout,
1446  "result":result,
1447  "causes":causes}),
1448 
1449  }
1450  exec self.validator in globals(), exported_symbols
1451  else:
1452  self.ValidateWithReference(stdout, stderr, result, causes)
1453 
1454  return causes
1455 
def CheckHistosSummaries(self, stdout, result, causes, dict=None, ignore=None)
Definition: GaudiTest.py:1302
def CheckTTreesSummaries(self, stdout, result, causes, trees_dict=None, ignore=r"Basket|.*size|Compression")
Definition: GaudiTest.py:1268
def ValidateOutput(self, stdout, stderr, result)
Definition: GaudiTest.py:1391
def ValidateWithReference(self, stdout, stderr, result, causes, preproc=None)
Definition: GaudiTest.py:1334
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 1334 of file GaudiTest.py.

1334  def ValidateWithReference(self, stdout, stderr, result, causes, preproc = None):
1335  """
1336  Default validation action: compare standard output and error to the
1337  reference files.
1338  """
1339  # set the default output preprocessor
1340  if preproc is None:
1341  preproc = normalizeExamples
1342  # check standard output
1343  reference = self._expandReferenceFileName(self.reference)
1344  # call the validator if the file exists
1345  if reference and os.path.isfile(reference):
1346  result["GaudiTest.output_reference"] = reference
1347  causes += ReferenceFileValidator(reference,
1348  "standard output",
1349  "GaudiTest.output_diff",
1350  preproc = preproc)(stdout, result)
1351 
1352  # Compare TTree summaries
1353  causes = self.CheckTTreesSummaries(stdout, result, causes)
1354  causes = self.CheckHistosSummaries(stdout, result, causes)
1355 
1356  if causes: # Write a new reference file for stdout
1357  try:
1358  newref = open(reference + ".new","w")
1359  # sanitize newlines
1360  for l in stdout.splitlines():
1361  newref.write(l.rstrip() + '\n')
1362  del newref # flush and close
1363  except IOError:
1364  # Ignore IO errors when trying to update reference files
1365  # because we may be in a read-only filesystem
1366  pass
1367 
1368  # check standard error
1369  reference = self._expandReferenceFileName(self.error_reference)
1370  # call the validator if we have a file to use
1371  if reference and os.path.isfile(reference):
1372  result["GaudiTest.error_reference"] = reference
1373  newcauses = ReferenceFileValidator(reference,
1374  "standard error",
1375  "GaudiTest.error_diff",
1376  preproc = preproc)(stderr, result)
1377  causes += newcauses
1378  if newcauses: # Write a new reference file for stdedd
1379  newref = open(reference + ".new","w")
1380  # sanitize newlines
1381  for l in stderr.splitlines():
1382  newref.write(l.rstrip() + '\n')
1383  del newref # flush and close
1384  else:
1385  causes += BasicOutputValidator(self.stderr,
1386  "standard error",
1387  "ExecTest.expected_stderr")(stderr, result)
1388 
1389  return causes
1390 
def CheckHistosSummaries(self, stdout, result, causes, dict=None, ignore=None)
Definition: GaudiTest.py:1302
def _expandReferenceFileName(self, reffile)
Definition: GaudiTest.py:1231
def CheckTTreesSummaries(self, stdout, result, causes, trees_dict=None, ignore=r"Basket|.*size|Compression")
Definition: GaudiTest.py:1268
Output Validation Classes.
Definition: GaudiTest.py:351
def ValidateWithReference(self, stdout, stderr, result, causes, preproc=None)
Definition: GaudiTest.py:1334

Member Data Documentation

GaudiTest.GaudiExeTest.args_order

Definition at line 1405 of file GaudiTest.py.

list GaudiTest.GaudiExeTest.arguments
static

Definition at line 1074 of file GaudiTest.py.

GaudiTest.GaudiExeTest.callable

Definition at line 1401 of file GaudiTest.py.

GaudiTest.GaudiExeTest.error_reference

Definition at line 1501 of file GaudiTest.py.

GaudiTest.GaudiExeTest.extra_args

Definition at line 1402 of file GaudiTest.py.

GaudiTest.GaudiExeTest.program

Definition at line 1489 of file GaudiTest.py.

GaudiTest.GaudiExeTest.reference

Definition at line 1500 of file GaudiTest.py.

GaudiTest.GaudiExeTest.signal

Definition at line 1607 of file GaudiTest.py.

GaudiTest.GaudiExeTest.timeout

Definition at line 1538 of file GaudiTest.py.

GaudiTest.GaudiExeTest.use_temp_dir

Definition at line 1528 of file GaudiTest.py.


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