The Gaudi Framework  v32r2 (46d42edc)
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 1185 of file GaudiTest.py.

Member Function Documentation

◆ _CreateEclipseLaunch()

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

Definition at line 1819 of file GaudiTest.py.

1819  def _CreateEclipseLaunch(self, prog, args, destdir=None):
1820  if 'NO_ECLIPSE_LAUNCHERS' in os.environ:
1821  # do not generate eclipse launchers if the user asks so
1822  return
1823  # Find the project name used in ecplise.
1824  # The name is in a file called ".project" in one of the parent directories
1825  projbasedir = os.path.normpath(destdir)
1826  while not os.path.exists(os.path.join(projbasedir, ".project")):
1827  oldprojdir = projbasedir
1828  projbasedir = os.path.normpath(
1829  os.path.join(projbasedir, os.pardir))
1830  # FIXME: the root level is invariant when trying to go up one level,
1831  # but it must be cheched on windows
1832  if oldprojdir == projbasedir:
1833  # If we cannot find a .project, so no point in creating a .launch file
1834  return
1835  # Ensure that we have a place where to write.
1836  if not os.path.exists(destdir):
1837  os.makedirs(destdir)
1838  # Use ElementTree to parse the XML file
1839  from xml.etree import ElementTree as ET
1840  t = ET.parse(os.path.join(projbasedir, ".project"))
1841  projectName = t.find("name").text
1842 
1843  # prepare the name/path of the generated file
1844  destfile = "%s.launch" % self._Runnable__id
1845  if destdir:
1846  destfile = os.path.join(destdir, destfile)
1847 
1848  if self.options.strip():
1849  # this means we have some custom options in the qmt file, so we have
1850  # to copy them from the temporary file at the end of the arguments
1851  # in another file
1852  tempfile = args.pop()
1853  optsfile = destfile + os.path.splitext(tempfile)[1]
1854  shutil.copyfile(tempfile, optsfile)
1855  args.append(optsfile)
1856 
1857  # prepare the data to insert in the XML file
1858  from xml.sax.saxutils import quoteattr # useful to quote XML special chars
1859  data = {}
1860  # Note: the "quoteattr(k)" is not needed because special chars cannot be part of a variable name,
1861  # but it doesn't harm.
1862  data["environment"] = "\n".join([
1863  '<mapEntry key=%s value=%s/>' % (quoteattr(k), quoteattr(v))
1864  for k, v in os.environ.iteritems()
1865  if k not in ('MAKEOVERRIDES', 'MAKEFLAGS', 'MAKELEVEL')
1866  ])
1867 
1868  data["exec"] = which(prog) or prog
1869  if os.path.basename(data["exec"]).lower().startswith("python"):
1870  # do not stop at main when debugging Python scripts
1871  data["stopAtMain"] = "false"
1872  else:
1873  data["stopAtMain"] = "true"
1874 
1875  data["args"] = "&#10;".join(map(rationalizepath, args))
1876  if self.isWinPlatform():
1877  data["args"] = "&#10;".join(
1878  ["/debugexe"] + map(rationalizepath, [data["exec"]] + args))
1879  data["exec"] = which("vcexpress.exe")
1880 
1881  if not self.use_temp_dir:
1882  data["workdir"] = os.getcwd()
1883  else:
1884  # If the test is using a tmporary directory, it is better to run it
1885  # in the same directory as the .launch file when debugged in eclipse
1886  data["workdir"] = destdir
1887 
1888  data["project"] = projectName.strip()
1889 
1890  # Template for the XML file, based on eclipse 3.4
1891  xml_template = u"""<?xml version="1.0" encoding="UTF-8" standalone="no"?>
1892 <launchConfiguration type="org.eclipse.cdt.launch.applicationLaunchType">
1893 <booleanAttribute key="org.eclipse.cdt.debug.mi.core.AUTO_SOLIB" value="true"/>
1894 <listAttribute key="org.eclipse.cdt.debug.mi.core.AUTO_SOLIB_LIST"/>
1895 <stringAttribute key="org.eclipse.cdt.debug.mi.core.DEBUG_NAME" value="gdb"/>
1896 <stringAttribute key="org.eclipse.cdt.debug.mi.core.GDB_INIT" value=".gdbinit"/>
1897 <listAttribute key="org.eclipse.cdt.debug.mi.core.SOLIB_PATH"/>
1898 <booleanAttribute key="org.eclipse.cdt.debug.mi.core.STOP_ON_SOLIB_EVENTS" value="false"/>
1899 <booleanAttribute key="org.eclipse.cdt.debug.mi.core.breakpointsFullPath" value="false"/>
1900 <stringAttribute key="org.eclipse.cdt.debug.mi.core.commandFactory" value="org.eclipse.cdt.debug.mi.core.standardCommandFactory"/>
1901 <stringAttribute key="org.eclipse.cdt.debug.mi.core.protocol" value="mi"/>
1902 <booleanAttribute key="org.eclipse.cdt.debug.mi.core.verboseMode" value="false"/>
1903 <intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="0"/>
1904 <stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
1905 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="org.eclipse.cdt.debug.mi.core.CDebuggerNew"/>
1906 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
1907 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="run"/>
1908 <booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="%(stopAtMain)s"/>
1909 <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="main"/>
1910 <booleanAttribute key="org.eclipse.cdt.launch.ENABLE_REGISTER_BOOKKEEPING" value="false"/>
1911 <booleanAttribute key="org.eclipse.cdt.launch.ENABLE_VARIABLE_BOOKKEEPING" value="false"/>
1912 <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;"/>
1913 <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;"/>
1914 <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;"/>
1915 <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_ARGUMENTS" value="%(args)s"/>
1916 <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="%(exec)s"/>
1917 <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="%(project)s"/>
1918 <stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/>
1919 <stringAttribute key="org.eclipse.cdt.launch.WORKING_DIRECTORY" value="%(workdir)s"/>
1920 <booleanAttribute key="org.eclipse.cdt.launch.ui.ApplicationCDebuggerTab.DEFAULTS_SET" value="true"/>
1921 <booleanAttribute key="org.eclipse.cdt.launch.use_terminal" value="true"/>
1922 <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
1923 <listEntry value="/%(project)s"/>
1924 </listAttribute>
1925 <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
1926 <listEntry value="4"/>
1927 </listAttribute>
1928 <booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="false"/>
1929 <mapAttribute key="org.eclipse.debug.core.environmentVariables">
1930 %(environment)s
1931 </mapAttribute>
1932 <mapAttribute key="org.eclipse.debug.core.preferred_launchers">
1933 <mapEntry key="[debug]" value="org.eclipse.cdt.cdi.launch.localCLaunch"/>
1934 </mapAttribute>
1935 <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
1936 <listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
1937 </listAttribute>
1938 </launchConfiguration>
1939 """
1940  try:
1941  # ensure the correct encoding of data values
1942  for k in data:
1943  data[k] = codecs.decode(data[k], 'utf-8')
1944  xml = xml_template % data
1945 
1946  # Write the output file
1947  codecs.open(destfile, "w", encoding='utf-8').write(xml)
1948  except:
1949  print('WARNING: problem generating Eclipse launcher')
1950 
1951 
1952 try:
def which(executable)
Definition: GaudiTest.py:310
struct GAUDI_API map
Parametrisation class for map-like implementation.

◆ _expandReferenceFileName()

def GaudiTest.GaudiExeTest._expandReferenceFileName (   self,
  reffile 
)
private

Definition at line 1334 of file GaudiTest.py.

1334  def _expandReferenceFileName(self, reffile):
1335  # if no file is passed, do nothing
1336  if not reffile:
1337  return ""
1338 
1339  # function to split an extension in constituents parts
1340  def platformSplit(p):
1341  return set(p.split('-' in p and '-' or '_'))
1342 
1343  reference = os.path.normpath(os.path.expandvars(reffile))
1344  # old-style platform-specific reference name
1345  spec_ref = reference[:-3] + self.GetPlatform()[0:3] + reference[-3:]
1346  if os.path.isfile(spec_ref):
1347  reference = spec_ref
1348  else: # look for new-style platform specific reference files:
1349  # get all the files whose name start with the reference filename
1350  dirname, basename = os.path.split(reference)
1351  if not dirname:
1352  dirname = '.'
1353  head = basename + "."
1354  head_len = len(head)
1355  platform = platformSplit(self.GetPlatform())
1356  if 'do0' in platform:
1357  platform.add('dbg')
1358  candidates = []
1359  for f in os.listdir(dirname):
1360  if f.startswith(head):
1361  req_plat = platformSplit(f[head_len:])
1362  if platform.issuperset(req_plat):
1363  candidates.append((len(req_plat), f))
1364  if candidates: # take the one with highest matching
1365  # FIXME: it is not possible to say if x86_64-slc5-gcc43-dbg
1366  # has to use ref.x86_64-gcc43 or ref.slc5-dbg
1367  candidates.sort()
1368  reference = os.path.join(dirname, candidates[-1][1])
1369  return reference
1370 

◆ CheckHistosSummaries()

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 1410 of file GaudiTest.py.

1410  def CheckHistosSummaries(self,
1411  stdout,
1412  result,
1413  causes,
1414  dict=None,
1415  ignore=None):
1416  """
1417  Compare the TTree summaries in stdout with the ones in trees_dict or in
1418  the reference file. By default ignore the size, compression and basket
1419  fields.
1420  The presence of TTree summaries when none is expected is not a failure.
1421  """
1422  if dict is None:
1423  reference = self._expandReferenceFileName(self.reference)
1424  # call the validator if the file exists
1425  if reference and os.path.isfile(reference):
1426  dict = findHistosSummaries(open(reference).read())
1427  else:
1428  dict = {}
1429 
1430  from pprint import PrettyPrinter
1431  pp = PrettyPrinter()
1432  if dict:
1433  result["GaudiTest.Histos.expected"] = result.Quote(
1434  pp.pformat(dict))
1435  if ignore:
1436  result["GaudiTest.Histos.ignore"] = result.Quote(ignore)
1437 
1438  histos = findHistosSummaries(stdout)
1439  failed = cmpTreesDicts(dict, histos, ignore)
1440  if failed:
1441  causes.append("histos summaries")
1442  msg = "%s: %s != %s" % getCmpFailingValues(dict, histos, failed)
1443  result["GaudiTest.Histos.failure_on"] = result.Quote(msg)
1444  result["GaudiTest.Histos.found"] = result.Quote(pp.pformat(histos))
1445 
1446  return causes
1447 
def read(f, regex='.*', skipevents=0)
Definition: hivetimeline.py:23
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: GaudiTest.py:876
def getCmpFailingValues(reference, to_check, fail_path)
Definition: GaudiTest.py:909
def findHistosSummaries(stdout)
Definition: GaudiTest.py:994

◆ CheckTTreesSummaries()

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 1371 of file GaudiTest.py.

1371  def CheckTTreesSummaries(self,
1372  stdout,
1373  result,
1374  causes,
1375  trees_dict=None,
1376  ignore=r"Basket|.*size|Compression"):
1377  """
1378  Compare the TTree summaries in stdout with the ones in trees_dict or in
1379  the reference file. By default ignore the size, compression and basket
1380  fields.
1381  The presence of TTree summaries when none is expected is not a failure.
1382  """
1383  if trees_dict is None:
1384  reference = self._expandReferenceFileName(self.reference)
1385  # call the validator if the file exists
1386  if reference and os.path.isfile(reference):
1387  trees_dict = findTTreeSummaries(open(reference).read())
1388  else:
1389  trees_dict = {}
1390 
1391  from pprint import PrettyPrinter
1392  pp = PrettyPrinter()
1393  if trees_dict:
1394  result["GaudiTest.TTrees.expected"] = result.Quote(
1395  pp.pformat(trees_dict))
1396  if ignore:
1397  result["GaudiTest.TTrees.ignore"] = result.Quote(ignore)
1398 
1399  trees = findTTreeSummaries(stdout)
1400  failed = cmpTreesDicts(trees_dict, trees, ignore)
1401  if failed:
1402  causes.append("trees summaries")
1403  msg = "%s: %s != %s" % getCmpFailingValues(trees_dict, trees,
1404  failed)
1405  result["GaudiTest.TTrees.failure_on"] = result.Quote(msg)
1406  result["GaudiTest.TTrees.found"] = result.Quote(pp.pformat(trees))
1407 
1408  return causes
1409 
def read(f, regex='.*', skipevents=0)
Definition: hivetimeline.py:23
def cmpTreesDicts(reference, to_check, ignore=None)
Definition: GaudiTest.py:876
def getCmpFailingValues(reference, to_check, fail_path)
Definition: GaudiTest.py:909
def findTTreeSummaries(stdout)
Definition: GaudiTest.py:854

◆ DumpEnvironment()

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 1597 of file GaudiTest.py.

1597  def DumpEnvironment(self, result):
1598  """
1599  Add the content of the environment to the result object.
1600 
1601  Copied from the QMTest class of COOL.
1602  """
1603  vars = os.environ.keys()
1604  vars.sort()
1605  result['GaudiTest.environment'] = \
1606  result.Quote(
1607  '\n'.join(["%s=%s" % (v, os.environ[v]) for v in vars]))
1608 

◆ GetPlatform()

def GaudiTest.GaudiExeTest.GetPlatform (   self)
Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.

Definition at line 1312 of file GaudiTest.py.

1312  def GetPlatform(self):
1313  """
1314  Return the platform Id defined in CMTCONFIG or SCRAM_ARCH.
1315  """
1316  arch = "None"
1317  # check architecture name
1318  if "CMTCONFIG" in os.environ:
1319  arch = os.environ["CMTCONFIG"]
1320  elif "SCRAM_ARCH" in os.environ:
1321  arch = os.environ["SCRAM_ARCH"]
1322  return arch
1323 
def GetPlatform(self)
Definition: BaseTest.py:1319

◆ isWinPlatform()

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 1324 of file GaudiTest.py.

1324  def isWinPlatform(self):
1325  """
1326  Return True if the current platform is Windows.
1327 
1328  This function was needed because of the change in the CMTCONFIG format,
1329  from win32_vc71_dbg to i686-winxp-vc9-dbg.
1330  """
1331  platform = self.GetPlatform()
1332  return "winxp" in platform or platform.startswith("win")
1333 
def isWinPlatform(self)
Definition: BaseTest.py:1334

◆ PlatformIsNotSupported()

def GaudiTest.GaudiExeTest.PlatformIsNotSupported (   self,
  context,
  result 
)

Definition at line 1299 of file GaudiTest.py.

1299  def PlatformIsNotSupported(self, context, result):
1300  platform = self.GetPlatform()
1301  unsupported = [
1302  re.compile(x)
1303  for x in [str(y).strip() for y in self.unsupported_platforms] if x
1304  ]
1305  for p_re in unsupported:
1306  if p_re.search(platform):
1307  result.SetOutcome(result.UNTESTED)
1308  result[result.CAUSE] = 'Platform not supported.'
1309  return True
1310  return False
1311 
def PlatformIsNotSupported(self, context, result)
Definition: BaseTest.py:1305

◆ Run()

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 1609 of file GaudiTest.py.

1609  def Run(self, context, result):
1610  """Run the test.
1611 
1612  'context' -- A 'Context' giving run-time parameters to the
1613  test.
1614 
1615  'result' -- A 'Result' object. The outcome will be
1616  'Result.PASS' when this method is called. The 'result' may be
1617  modified by this method to indicate outcomes other than
1618  'Result.PASS' or to add annotations."""
1619 
1620  # Check if the platform is supported
1621  if self.PlatformIsNotSupported(context, result):
1622  return
1623 
1624  # Prepare program name and arguments (expanding variables, and converting to absolute)
1625  if self.program:
1626  prog = rationalizepath(self.program)
1627  elif "GAUDIEXE" in os.environ:
1628  prog = os.environ["GAUDIEXE"]
1629  else:
1630  prog = "Gaudi.exe"
1631  self.program = prog
1632 
1633  dummy, prog_ext = os.path.splitext(prog)
1634  if prog_ext not in [".exe", ".py", ".bat"] and self.isWinPlatform():
1635  prog += ".exe"
1636  prog_ext = ".exe"
1637 
1638  prog = which(prog) or prog
1639 
1640  # Convert paths to absolute paths in arguments and reference files
1641  args = map(rationalizepath, self.args)
1642  self.reference = rationalizepath(self.reference)
1643  self.error_reference = rationalizepath(self.error_reference)
1644 
1645  # check if the user provided inline options
1646  tmpfile = None
1647  if self.options.strip():
1648  ext = ".opts"
1649  if re.search(
1650  r"from\s+Gaudi.Configuration\s+import\s+\*|from\s+Configurables\s+import",
1651  self.options):
1652  ext = ".py"
1653  tmpfile = TempFile(ext)
1654  tmpfile.writelines("\n".join(self.options.splitlines()))
1655  tmpfile.flush()
1656  args.append(tmpfile.name)
1657  result["GaudiTest.options"] = result.Quote(self.options)
1658 
1659  # if the program is a python file, execute it through python
1660  if prog_ext == ".py":
1661  args.insert(0, prog)
1662  if self.isWinPlatform():
1663  prog = which("python.exe") or "python.exe"
1664  else:
1665  prog = which("python") or "python"
1666 
1667  # Change to the working directory if specified or to the default temporary
1668  origdir = os.getcwd()
1669  if self.workdir:
1670  os.chdir(str(os.path.normpath(os.path.expandvars(self.workdir))))
1671  elif self.use_temp_dir == "true":
1672  if "QMTEST_TMPDIR" in os.environ:
1673  qmtest_tmpdir = os.environ["QMTEST_TMPDIR"]
1674  if not os.path.exists(qmtest_tmpdir):
1675  os.makedirs(qmtest_tmpdir)
1676  os.chdir(qmtest_tmpdir)
1677  elif "qmtest.tmpdir" in context:
1678  os.chdir(context["qmtest.tmpdir"])
1679 
1680  if "QMTEST_IGNORE_TIMEOUT" not in os.environ:
1681  self.timeout = max(self.timeout, 600)
1682  else:
1683  self.timeout = -1
1684 
1685  try:
1686  # Generate eclipse.org debug launcher for the test
1687  self._CreateEclipseLaunch(
1688  prog, args, destdir=os.path.join(origdir, '.eclipse'))
1689  # Run the test
1690  self.RunProgram(prog, [prog] + args, context, result)
1691  # Record the content of the enfironment for failing tests
1692  if result.GetOutcome() not in [result.PASS]:
1693  self.DumpEnvironment(result)
1694  finally:
1695  # revert to the original directory
1696  os.chdir(origdir)
1697 
EventIDBase max(const EventIDBase &lhs, const EventIDBase &rhs)
Definition: EventIDBase.h:215
def which(executable)
Definition: GaudiTest.py:310
struct GAUDI_API map
Parametrisation class for map-like implementation.
def rationalizepath(p)
Definition: GaudiTest.py:331

◆ RunProgram()

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 1698 of file GaudiTest.py.

1698  def RunProgram(self, program, arguments, context, result):
1699  """Run the 'program'.
1700 
1701  'program' -- The path to the program to run.
1702 
1703  'arguments' -- A list of the arguments to the program. This
1704  list must contain a first argument corresponding to 'argv[0]'.
1705 
1706  'context' -- A 'Context' giving run-time parameters to the
1707  test.
1708 
1709  'result' -- A 'Result' object. The outcome will be
1710  'Result.PASS' when this method is called. The 'result' may be
1711  modified by this method to indicate outcomes other than
1712  'Result.PASS' or to add annotations.
1713 
1714  @attention: This method has been copied from command.ExecTestBase
1715  (QMTest 2.3.0) and modified to keep stdout and stderr
1716  for tests that have been terminated by a signal.
1717  (Fundamental for debugging in the Application Area)
1718  """
1719 
1720  # Construct the environment.
1721  environment = self.MakeEnvironment(context)
1722  # FIXME: whithout this, we get some spurious '\x1b[?1034' in the std out on SLC6
1723  if "slc6" in environment.get('CMTCONFIG', ''):
1724  environment['TERM'] = 'dumb'
1725  # Create the executable.
1726  if self.timeout >= 0:
1727  timeout = self.timeout
1728  else:
1729  # If no timeout was specified, we sill run this process in a
1730  # separate process group and kill the entire process group
1731  # when the child is done executing. That means that
1732  # orphaned child processes created by the test will be
1733  # cleaned up.
1734  timeout = -2
1735  e = GaudiFilterExecutable(self.stdin, timeout)
1736  # Run it.
1737  exit_status = e.Run(arguments, environment, path=program)
1738  # Get the stack trace from the temporary file (if present)
1739  if e.stack_trace_file and os.path.exists(e.stack_trace_file):
1740  stack_trace = open(e.stack_trace_file).read()
1741  os.remove(e.stack_trace_file)
1742  else:
1743  stack_trace = None
1744  if stack_trace:
1745  result["ExecTest.stack_trace"] = result.Quote(stack_trace)
1746 
1747  # If the process terminated normally, check the outputs.
1748  if (sys.platform == "win32" or os.WIFEXITED(exit_status)
1749  or self.signal == os.WTERMSIG(exit_status)):
1750  # There are no causes of failure yet.
1751  causes = []
1752  # The target program terminated normally. Extract the
1753  # exit code, if this test checks it.
1754  if self.exit_code is None:
1755  exit_code = None
1756  elif sys.platform == "win32":
1757  exit_code = exit_status
1758  else:
1759  exit_code = os.WEXITSTATUS(exit_status)
1760  # Get the output generated by the program.
1761  stdout = e.stdout
1762  stderr = e.stderr
1763  # Record the results.
1764  result["ExecTest.exit_code"] = str(exit_code)
1765  result["ExecTest.stdout"] = result.Quote(stdout)
1766  result["ExecTest.stderr"] = result.Quote(stderr)
1767  # Check to see if the exit code matches.
1768  if exit_code != self.exit_code:
1769  causes.append("exit_code")
1770  result["ExecTest.expected_exit_code"] \
1771  = str(self.exit_code)
1772  # Validate the output.
1773  causes += self.ValidateOutput(stdout, stderr, result)
1774  # If anything went wrong, the test failed.
1775  if causes:
1776  result.Fail("Unexpected %s." % string.join(causes, ", "))
1777  elif os.WIFSIGNALED(exit_status):
1778  # The target program terminated with a signal. Construe
1779  # that as a test failure.
1780  signal_number = str(os.WTERMSIG(exit_status))
1781  if not stack_trace:
1782  result.Fail("Program terminated by signal.")
1783  else:
1784  # The presence of stack_trace means tha we stopped the job because
1785  # of a time-out
1786  result.Fail("Exceeded time limit (%ds), terminated." % timeout)
1787  result["ExecTest.signal_number"] = signal_number
1788  result["ExecTest.stdout"] = result.Quote(e.stdout)
1789  result["ExecTest.stderr"] = result.Quote(e.stderr)
1790  if self.signal:
1791  result["ExecTest.expected_signal_number"] = str(self.signal)
1792  elif os.WIFSTOPPED(exit_status):
1793  # The target program was stopped. Construe that as a
1794  # test failure.
1795  signal_number = str(os.WSTOPSIG(exit_status))
1796  if not stack_trace:
1797  result.Fail("Program stopped by signal.")
1798  else:
1799  # The presence of stack_trace means tha we stopped the job because
1800  # of a time-out
1801  result.Fail("Exceeded time limit (%ds), stopped." % timeout)
1802  result["ExecTest.signal_number"] = signal_number
1803  result["ExecTest.stdout"] = result.Quote(e.stdout)
1804  result["ExecTest.stderr"] = result.Quote(e.stderr)
1805  else:
1806  # The target program terminated abnormally in some other
1807  # manner. (This shouldn't normally happen...)
1808  result.Fail("Program did not terminate normally.")
1809 
1810  # Marco Cl.: This is a special trick to fix a "problem" with the output
1811  # of gaudi jobs when they use colors
1812  esc = '\x1b'
1813  repr_esc = '\\x1b'
1814  result["ExecTest.stdout"] = result["ExecTest.stdout"].replace(
1815  esc, repr_esc)
1816  # TODO: (MCl) improve the hack for colors in standard output
1817  # may be converting them to HTML tags
1818 
def read(f, regex='.*', skipevents=0)
Definition: hivetimeline.py:23

◆ ValidateOutput()

def GaudiTest.GaudiExeTest.ValidateOutput (   self,
  stdout,
  stderr,
  result 
)

Definition at line 1512 of file GaudiTest.py.

1512  def ValidateOutput(self, stdout, stderr, result):
1513  causes = []
1514  # if the test definition contains a custom validator, use it
1515  if self.validator.strip() != "":
1516 
1517  class CallWrapper(object):
1518  """
1519  Small wrapper class to dynamically bind some default arguments
1520  to a callable.
1521  """
1522 
1523  def __init__(self, callable, extra_args={}):
1524  self.callable = callable
1525  self.extra_args = extra_args
1526  # get the list of names of positional arguments
1527  from inspect import getargspec
1528  self.args_order = getargspec(callable)[0]
1529  # Remove "self" from the list of positional arguments
1530  # since it is added automatically
1531  if self.args_order[0] == "self":
1532  del self.args_order[0]
1533 
1534  def __call__(self, *args, **kwargs):
1535  # Check which positional arguments are used
1536  positional = self.args_order[:len(args)]
1537 
1538  kwargs = dict(kwargs) # copy the arguments dictionary
1539  for a in self.extra_args:
1540  # use "extra_args" for the arguments not specified as
1541  # positional or keyword
1542  if a not in positional and a not in kwargs:
1543  kwargs[a] = self.extra_args[a]
1544  return self.callable(*args, **kwargs)
1545 
1546  # local names to be exposed in the script
1547  exported_symbols = {
1548  "self":
1549  self,
1550  "stdout":
1551  stdout,
1552  "stderr":
1553  stderr,
1554  "result":
1555  result,
1556  "causes":
1557  causes,
1558  "findReferenceBlock":
1559  CallWrapper(findReferenceBlock, {
1560  "stdout": stdout,
1561  "result": result,
1562  "causes": causes
1563  }),
1564  "validateWithReference":
1565  CallWrapper(
1566  self.ValidateWithReference, {
1567  "stdout": stdout,
1568  "stderr": stderr,
1569  "result": result,
1570  "causes": causes
1571  }),
1572  "countErrorLines":
1573  CallWrapper(countErrorLines, {
1574  "stdout": stdout,
1575  "result": result,
1576  "causes": causes
1577  }),
1578  "checkTTreesSummaries":
1579  CallWrapper(self.CheckTTreesSummaries, {
1580  "stdout": stdout,
1581  "result": result,
1582  "causes": causes
1583  }),
1584  "checkHistosSummaries":
1585  CallWrapper(self.CheckHistosSummaries, {
1586  "stdout": stdout,
1587  "result": result,
1588  "causes": causes
1589  }),
1590  }
1591  exec (self.validator, globals(), exported_symbols)
1592  else:
1593  self.ValidateWithReference(stdout, stderr, result, causes)
1594 
1595  return causes
1596 

◆ ValidateWithReference()

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 1448 of file GaudiTest.py.

1448  def ValidateWithReference(self,
1449  stdout,
1450  stderr,
1451  result,
1452  causes,
1453  preproc=None):
1454  """
1455  Default validation action: compare standard output and error to the
1456  reference files.
1457  """
1458  # set the default output preprocessor
1459  if preproc is None:
1460  preproc = normalizeExamples
1461  # check standard output
1462  reference = self._expandReferenceFileName(self.reference)
1463  # call the validator if the file exists
1464  if reference and os.path.isfile(reference):
1465  result["GaudiTest.output_reference"] = reference
1466  causes += ReferenceFileValidator(
1467  reference,
1468  "standard output",
1469  "GaudiTest.output_diff",
1470  preproc=preproc)(stdout, result)
1471 
1472  # Compare TTree summaries
1473  causes = self.CheckTTreesSummaries(stdout, result, causes)
1474  causes = self.CheckHistosSummaries(stdout, result, causes)
1475 
1476  if causes: # Write a new reference file for stdout
1477  try:
1478  newref = open(reference + ".new", "w")
1479  # sanitize newlines
1480  for l in stdout.splitlines():
1481  newref.write(l.rstrip() + '\n')
1482  del newref # flush and close
1483  except IOError:
1484  # Ignore IO errors when trying to update reference files
1485  # because we may be in a read-only filesystem
1486  pass
1487 
1488  # check standard error
1489  reference = self._expandReferenceFileName(self.error_reference)
1490  # call the validator if we have a file to use
1491  if reference and os.path.isfile(reference):
1492  result["GaudiTest.error_reference"] = reference
1493  newcauses = ReferenceFileValidator(
1494  reference,
1495  "standard error",
1496  "GaudiTest.error_diff",
1497  preproc=preproc)(stderr, result)
1498  causes += newcauses
1499  if newcauses: # Write a new reference file for stdedd
1500  newref = open(reference + ".new", "w")
1501  # sanitize newlines
1502  for l in stderr.splitlines():
1503  newref.write(l.rstrip() + '\n')
1504  del newref # flush and close
1505  else:
1506  causes += BasicOutputValidator(self.stderr, "standard error",
1507  "ExecTest.expected_stderr")(stderr,
1508  result)
1509 
1510  return causes
1511 

Member Data Documentation

◆ args_order

GaudiTest.GaudiExeTest.args_order

Definition at line 1528 of file GaudiTest.py.

◆ arguments

list GaudiTest.GaudiExeTest.arguments
static

Definition at line 1188 of file GaudiTest.py.

◆ callable

GaudiTest.GaudiExeTest.callable

Definition at line 1524 of file GaudiTest.py.

◆ error_reference

GaudiTest.GaudiExeTest.error_reference

Definition at line 1643 of file GaudiTest.py.

◆ extra_args

GaudiTest.GaudiExeTest.extra_args

Definition at line 1525 of file GaudiTest.py.

◆ program

GaudiTest.GaudiExeTest.program

Definition at line 1631 of file GaudiTest.py.

◆ reference

GaudiTest.GaudiExeTest.reference

Definition at line 1642 of file GaudiTest.py.

◆ signal

GaudiTest.GaudiExeTest.signal

Definition at line 1749 of file GaudiTest.py.

◆ timeout

GaudiTest.GaudiExeTest.timeout

Definition at line 1681 of file GaudiTest.py.

◆ use_temp_dir

GaudiTest.GaudiExeTest.use_temp_dir

Definition at line 1671 of file GaudiTest.py.


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