[PATCH] qmtest_gcc: Support libstdc++ testing under QMTest
Nathaniel Smith
njs at pobox.com
Thu Mar 18 18:39:15 UTC 2004
-- Nathaniel
--
So let us espouse a less contested notion of truth and falsehood, even
if it is philosophically debatable (if we listen to philosophers, we
must debate everything, and there would be no end to the discussion).
-- Serendipities, Umberto Eco
-------------- next part --------------
Index: classes.qmc
===================================================================
RCS file: /home/qm/Repository/qmtest_gcc/classes.qmc,v
retrieving revision 1.11
diff -u -r1.11 classes.qmc
--- classes.qmc 23 Jun 2003 06:34:04 -0000 1.11
+++ classes.qmc 18 Mar 2004 18:33:55 -0000
@@ -1,2 +1,36 @@
<?xml version="1.0" ?>
-<class-directory><class kind="database">gcc_database.GCCDatabase</class><class kind="resource">gpp_init.GPPInit</class><class kind="resource">dg_tls_test.GPPTLSInit</class><class kind="test">dg_tls_test.GPPDGTLSTest</class><class kind="resource">debug_test.GPPDebugInit</class><class kind="test">gpp_dg_test.GPPDGTest</class><class kind="test">gpp_profile_test.GPPProfileTest</class><class kind="test">gpp_gcov_test.GPPGCOVTest</class><class kind="test">gpp_old_deja_test.GPPOldDejaTest</class><class kind="test">gcc_dg_test.GCCDGTest</class><class kind="test">gcc_dg_test.GCCDGNoncompileTest</class><class kind="resource">debug_test.GCCDebugInit</class><class kind="test">debug_test.GPPDGDebugTest</class><class kind="test">debug_test.GCCDGDebugTest</class><class kind="test">gcc_dg_test.GCCDGCPPTradTest</class><class kind="test">dg_pch_test.GPPDGPCHTest</class><class kind="test">dg_pch_test.GCCDGPCHTest</class><class kind="test">gcc_dg_test.GCCDGCPPTest</class><class kind="test">gcc_dg_test.GCCDGFormatTest</class><class kind="resource">dg_tls_test.GCCTLSInit</class><class kind="test">dg_tls_test.GCCDGTLSTest</class><class kind="test">gcc_dg_test.GCCDGTortureTest</class><class kind="resource">gcc_init.GCCInit</class><class kind="test">compat_test.GCCCompatTest</class><class kind="test">compat_test.GPPCompatTest</class><class kind="test">gcc_dg_test.GCCCTortureCompileTest</class></class-directory>
+<!DOCTYPE class-directory
+ PUBLIC '-//QM/2.2/Class-Directory//EN'
+ 'http://www.codesourcery.com/qm/dtds/2.2/-//qm/2.2/class-directory//en.dtd'>
+<class-directory>
+ <class kind="resource" name="gpp_init.GPPInit"/>
+ <class kind="resource" name="dg_tls_test.GPPTLSInit"/>
+ <class kind="resource" name="debug_test.GPPDebugInit"/>
+ <class kind="resource" name="debug_test.GCCDebugInit"/>
+ <class kind="resource" name="dg_tls_test.GCCTLSInit"/>
+ <class kind="resource" name="gcc_init.GCCInit"/>
+ <class kind="database" name="gcc_database.GCCDatabase"/>
+ <class kind="database" name="v3_database.V3Database"/>
+ <class kind="test" name="dg_tls_test.GPPDGTLSTest"/>
+ <class kind="test" name="gpp_dg_test.GPPDGTest"/>
+ <class kind="test" name="gpp_profile_test.GPPProfileTest"/>
+ <class kind="test" name="gpp_gcov_test.GPPGCOVTest"/>
+ <class kind="test" name="gpp_old_deja_test.GPPOldDejaTest"/>
+ <class kind="test" name="gcc_dg_test.GCCDGTest"/>
+ <class kind="test" name="gcc_dg_test.GCCDGNoncompileTest"/>
+ <class kind="test" name="debug_test.GPPDGDebugTest"/>
+ <class kind="test" name="debug_test.GCCDGDebugTest"/>
+ <class kind="test" name="gcc_dg_test.GCCDGCPPTradTest"/>
+ <class kind="test" name="dg_pch_test.GPPDGPCHTest"/>
+ <class kind="test" name="dg_pch_test.GCCDGPCHTest"/>
+ <class kind="test" name="gcc_dg_test.GCCDGCPPTest"/>
+ <class kind="test" name="gcc_dg_test.GCCDGFormatTest"/>
+ <class kind="test" name="dg_tls_test.GCCDGTLSTest"/>
+ <class kind="test" name="gcc_dg_test.GCCDGTortureTest"/>
+ <class kind="test" name="compat_test.GCCCompatTest"/>
+ <class kind="test" name="compat_test.GPPCompatTest"/>
+ <class kind="test" name="gcc_dg_test.GCCCTortureCompileTest"/>
+ <class kind="test" name="v3_test.V3DGTest"/>
+ <class kind="test" name="v3_test.V3ABITest"/>
+ <class kind="resource" name="v3_test.V3Init"/>
+</class-directory>
Index: debug_test.py
===================================================================
RCS file: /home/qm/Repository/qmtest_gcc/debug_test.py,v
retrieving revision 1.2
diff -u -r1.2 debug_test.py
--- debug_test.py 24 Feb 2004 08:23:12 -0000 1.2
+++ debug_test.py 18 Mar 2004 18:33:55 -0000
@@ -103,18 +103,23 @@
basename = os.path.basename(self._GetSourcePath())
+ def isanywhere(string, list):
+ for s in list:
+ if s.find(string) != -1:
+ return True
+ return False
+
self._SetUp(context)
for opts in context[GCCDebugInit.OPTIONS_TAG]:
- optstring = " ".join(opts)
if (basename in ["debug-1.c", "debug-2.c", "debug-6.c"]
and opts[0].endswith("1")):
continue
elif (basename in ["debug-1.c", "debug-2.c"]
- and optstring.find("03") != -1
- and (optstring.find("coff") != -1
- or optstring.find("stabs") != -1)):
+ and isanywhere("03", opts) != -1
+ and (isanywhere("coff", opts) != -1
+ or isanywhere("stabs", opts) != -1)):
continue
- self._RunDGTest(optstring, "", context, result)
+ self._RunDGTest(opts, [], context, result)
Index: dg_pch_test.py
===================================================================
RCS file: /home/qm/Repository/qmtest_gcc/dg_pch_test.py,v
retrieving revision 1.3
diff -u -r1.3 dg_pch_test.py
--- dg_pch_test.py 24 Feb 2004 08:23:12 -0000 1.3
+++ dg_pch_test.py 18 Mar 2004 18:33:55 -0000
@@ -65,7 +65,7 @@
pass
shutil.copyfile(os.path.splitext(source)[0] + suffix + "s",
basename + suffix)
- self._RunDGTest(o, "", context, result,
+ self._RunDGTest(o, [], context, result,
basename + suffix,
self.KIND_PRECOMPILE,
keep_output = 1)
@@ -73,15 +73,15 @@
assembly_outcome = self.UNTESTED
if os.path.exists(basename + suffix + ".gch"):
os.remove(basename + suffix)
- options = o + " -I" + context.GetTemporaryDirectory()
- self._RunDGTest(options, "", context, result, keep_output = 1)
+ options = o + ["-I" + context.GetTemporaryDirectory()]
+ self._RunDGTest(options, [], context, result, keep_output = 1)
os.remove(basename + suffix + ".gch")
if os.path.exists(basename + ".s"):
os.rename(basename + ".s", basename + ".s-gch")
shutil.copyfile((os.path.splitext(source)[0]
+ suffix + "s"),
basename + suffix)
- self._RunDGTest(options, "", context, result,
+ self._RunDGTest(options, [], context, result,
keep_output = 1)
if filecmp.cmp(basename + ".s", basename + ".s-gch"):
assembly_outcome = self.PASS
@@ -104,7 +104,7 @@
_suffix = ".h"
- _pch_options = ["-O0 -g"] + GCCDGTortureTest._torture_without_loops
+ _pch_options = [["-O0", "-g"]] + GCCDGTortureTest._torture_without_loops
@@ -113,5 +113,5 @@
_suffix = ".H"
- _pch_options = ("-g", "-O2 -g", "-O2")
+ _pch_options = (["-g"], ["-O2", "-g"], ["-O2"])
Index: gcc_dg_test.py
===================================================================
RCS file: /home/qm/Repository/qmtest_gcc/gcc_dg_test.py,v
retrieving revision 1.5
diff -u -r1.5 gcc_dg_test.py
--- gcc_dg_test.py 23 Jun 2003 06:34:04 -0000 1.5
+++ gcc_dg_test.py 18 Mar 2004 18:33:55 -0000
@@ -30,7 +30,7 @@
This test class emulates the 'gcc-dg.exp' source file in the GCC
testsuite."""
- _default_options = "-ansi -pedantic-errors"
+ _default_options = ["-ansi", "-pedantic-errors"]
def _DGrequire_weak(self, line_num, args, context):
"""Emulate the 'dg-require-weak' command.
@@ -99,7 +99,7 @@
This test class emulates the 'noncompile.exp' source file in the
GCC testsuite."""
- _default_options = ""
+ _default_options = []
@@ -109,7 +109,7 @@
This test class emulates the 'cpp.exp' source file in the GCC
testsuite."""
- _default_options = "-ansi -pedantic-errors"
+ _default_options = ["-ansi", "-pedantic-errors"]
@@ -119,24 +119,25 @@
This test class emulates the 'trad.exp' source file in the GCC
testsuite."""
- _default_options = "-traditional-cpp"
+ _default_options = ["-traditional-cpp"]
class GCCDGTortureTest(GCCDGTest):
"""A 'GCCDGTortureTest' emulates 'gcc.dg/torture/dg-torture.exp'."""
- _default_options = ""
+ _default_options = []
_torture_with_loops = [
- "-O0",
- "-O1",
- "-O2",
- "-O3 -fomit-frame-pointer",
- "-O3 -fomit-frame-pointer -funroll-loops",
- "-O3 -fomit-frame-pointer -funroll-all-loops -finline-functions",
- "-O3 -g",
- "-Os"
+ ["-O0"],
+ ["-O1"],
+ ["-O2"],
+ ["-O3", "-fomit-frame-pointer"],
+ ["-O3", "-fomit-frame-pointer", "-funroll-loops"],
+ ["-O3", "-fomit-frame-pointer",
+ "-funroll-all-loops", "-finline-functions"],
+ ["-O3", "-g"],
+ ["-Os"],
]
"""A list of command-line options to use for "torture" tests.
@@ -207,7 +208,7 @@
class GCCDGFormatTest(GCCDGTortureTest):
"""A 'GCCDGFormatTest' emulates 'gcc.dg/format/format.exp'."""
- _default_options = ""
+ _default_options = []
_torture_with_loops = [ "", "-DWIDE" ]
@@ -220,4 +221,4 @@
_default_kind = GCCDGTortureTest.KIND_ASSEMBLE
- _default_options = "-w"
+ _default_options = ["-w"]
Index: gcc_dg_test_base.py
===================================================================
RCS file: /home/qm/Repository/qmtest_gcc/gcc_dg_test_base.py,v
retrieving revision 1.4
diff -u -r1.4 gcc_dg_test_base.py
--- gcc_dg_test_base.py 12 Jun 2003 23:43:00 -0000 1.4
+++ gcc_dg_test_base.py 18 Mar 2004 18:33:55 -0000
@@ -63,7 +63,7 @@
def Run(self, context, result):
self._SetUp(context)
- self._RunDGTest("", self._default_options, context, result)
+ self._RunDGTest([], self._default_options, context, result)
def _ExecuteFinalCommand(self, command, args, context, result):
@@ -160,7 +160,6 @@
dirname = os.path.dirname(path)
source_files += map(lambda f: os.path.join(dirname, f),
self.__additional_source_files)
- options = self._ParseTclWords(options)
if "-frepo" in options:
is_repo_test = 1
kind = DGTest.KIND_ASSEMBLE
@@ -220,6 +219,9 @@
This method emulates 'dg-scan' in the GCC testsuite."""
+ print "__ScanFile: %s, %s, %s" % tuple(map(repr, [command,
+ output_file, args]))
+
# See if there is a target selector applied to this test.
expectation = self.PASS
if len(args) > 1:
@@ -247,7 +249,13 @@
outcome = self.PASS
else:
outcome = self.FAIL
- message = self._name + " " + command + " " + pattern
+ print "Pattern is %s" % repr(pattern)
+ printable_pattern = pattern
+ for old, new in [("\\", "\\\\"), ("\n", "\\n"),
+ ("\r", "\\r"), ("\t", "\\t")]:
+ printable_pattern = printable_pattern.replace(old, new)
+ print "Printable pattern is %s" % repr(printable_pattern)
+ message = self._name + " " + command + " " + printable_pattern
self._RecordDejaGNUOutcome(result, outcome, message, expectation)
Index: gcc_test_base.py
===================================================================
RCS file: /home/qm/Repository/qmtest_gcc/gcc_test_base.py,v
retrieving revision 1.2
diff -u -r1.2 gcc_test_base.py
--- gcc_test_base.py 2 Jun 2003 23:50:18 -0000 1.2
+++ gcc_test_base.py 18 Mar 2004 18:33:56 -0000
@@ -85,39 +85,39 @@
"""A map from DejaGNU compilation modes to 'Compiler' modes."""
def _RecordPass(self, result, testcase, cflags):
- """Emulate '${tool}_pass'.
+ """Emulate '${tool}_pass'.
- 'result' -- The 'Result'.
-
- 'testcase' -- The name of the test.
-
- 'cflags' -- The options provided to the test."""
-
- if cflags:
- message = "%s, %s" % (testcase, cflags)
- else:
- message = testcase
- self._RecordDejaGNUOutcome(result, DejaGNUTest.PASS, message)
+ 'result' -- The 'Result'.
+
+ 'testcase' -- The name of the test.
+
+ 'cflags' -- The options provided to the test."""
+
+ if cflags:
+ message = "%s, %s" % (testcase, cflags)
+ else:
+ message = testcase
+ self._RecordDejaGNUOutcome(result, DejaGNUTest.PASS, message)
def _RecordFail(self, result, testcase, cflags):
- """Emulate '${tool}_fail'.
+ """Emulate '${tool}_fail'.
- 'result' -- The 'Result'.
-
- 'testcase' -- The name of the test.
-
- 'cflags' -- The options provided to the test."""
-
- if cflags:
- message = "%s, %s" % (testcase, cflags)
- else:
- message = testcase
- self._RecordDejaGNUOutcome(result, DejaGNUTest.FAIL, message)
+ 'result' -- The 'Result'.
+
+ 'testcase' -- The name of the test.
+
+ 'cflags' -- The options provided to the test."""
+
+ if cflags:
+ message = "%s, %s" % (testcase, cflags)
+ else:
+ message = testcase
+ self._RecordDejaGNUOutcome(result, DejaGNUTest.FAIL, message)
def _Compile(self, context, result, source_files, output_file, mode,
- options = []):
+ options = [], post_options = []):
"""Compile the 'source_files'.
'context' -- The 'Context' in which the test is running.
@@ -175,7 +175,7 @@
# Run the compiler.
index = self._RecordCommand(result, command)
status, output \
- = compiler.ExecuteCommand(context.GetTemporaryDirectory(), command)
+ = compiler.ExecuteCommand(context.GetTemporaryDirectory(), command)
self._RecordCommandOutput(result, index, status, output)
# If there was no output, DejaGNU uses the exit status.
@@ -186,43 +186,43 @@
def _CheckCompile(self, result, testcase, option, objname, gcc_output):
- """Check the result of a compilation.
+ """Check the result of a compilation.
+
+ 'result' -- The QMTest 'Result' object.
+
+ 'testcase' -- The name of the test.
+
+ 'option' -- The options used when performing the test.
+
+ 'objname' -- The name of the output file.
+
+ 'gcc_output' -- The output generated by the compiler.
+
+ returns -- '1' if the compilation suceeded, '0' otherwise. If
+ '0' is returned, the 'result' has been updated to indicate the
+ problem.
+
+ This function emulates 'g++_check_compile' in
+ 'gcc-defs.exp'."""
- 'result' -- The QMTest 'Result' object.
-
- 'testcase' -- The name of the test.
-
- 'option' -- The options used when performing the test.
-
- 'objname' -- The name of the output file.
-
- 'gcc_output' -- The output generated by the compiler.
-
- returns -- '1' if the compilation suceeded, '0' otherwise. If
- '0' is returned, the 'result' has been updated to indicate the
- problem.
-
- This function emulates 'g++_check_compile' in
- 'gcc-defs.exp'."""
-
- match = GCCTestBase.__signal_regexp.match(gcc_output)
- if match:
- self._RecordFail(result, testcase,
- "Got Signal %s, %s" % (match.group(1), option))
- return 0
+ match = GCCTestBase.__signal_regexp.match(gcc_output)
+ if match:
+ self._RecordFail(result, testcase,
+ "Got Signal %s, %s" % (match.group(1), option))
+ return 0
gcc_output = GCCTestBase.__newline_regexp.sub(gcc_output, "")
-
+
if gcc_output != "":
- self._RecordFail(result, testcase, option)
- return 0
-
- if objname and not os.path.exists(objname):
- self._RecordFail(result, testcase, option)
- return 0
+ self._RecordFail(result, testcase, option)
+ return 0
+
+ if objname and not os.path.exists(objname):
+ self._RecordFail(result, testcase, option)
+ return 0
self._RecordPass(result, testcase, option)
- return 1
+ return 1
Index: gpp_dg_test.py
===================================================================
RCS file: /home/qm/Repository/qmtest_gcc/gpp_dg_test.py,v
retrieving revision 1.6
diff -u -r1.6 gpp_dg_test.py
--- gpp_dg_test.py 2 Jun 2003 21:08:50 -0000 1.6
+++ gpp_dg_test.py 18 Mar 2004 18:33:56 -0000
@@ -29,7 +29,7 @@
This test class emulates the 'g++-dg.exp' source file in the GCC
testsuite."""
- _default_options = "-ansi -pedantic-errors -Wno-long-long"
+ _default_options = ["-ansi", "-pedantic-errors", "-Wno-long-long"]
def _GetTargetEnvironment(self, context):
Index: gpp_init.py
===================================================================
RCS file: /home/qm/Repository/qmtest_gcc/gpp_init.py,v
retrieving revision 1.6
diff -u -r1.6 gpp_init.py
--- gpp_init.py 24 Feb 2004 08:23:12 -0000 1.6
+++ gpp_init.py 18 Mar 2004 18:33:56 -0000
@@ -20,6 +20,7 @@
from dejagnu_base import DejaGNUBase
from qm.executable import RedirectedExecutable
from qm.test.resource import Resource
+from qm.test.result import Result
import os
import sys
@@ -87,8 +88,8 @@
executable.Run(command)
options += executable.stdout.split()
except:
- result.Fail("Could not run testsuite_flags")
- result[result.EXCEPTION] = "%s: %s" % sys.exc_info()[:2]
+ result.NoteException("Could not run testsuite_flags",
+ Result.FAIL)
return
# Avoid splitting diagnostic message lines.
-------------- next part --------------
#!/usr/bin/python
import sys
import os
import os.path
import shutil
import glob
import getpass
import time
from optparse import OptionParser
j = os.path.join
optparser = OptionParser("usage: %prog [options] <gcc-version> "
"<source-directory> <qmtc-directory> "
"<qmtest_gcc-directory>")
optparser.add_option("-v", "--version", action="store",
dest="pkg_version", default="1.0",
metavar="VERSION",
help="Package version (default 1.0)")
optparser.add_option("-o", "--output", action="store",
dest="targetdir", metavar="DIR",
help="Output directory"
"(default qmtest_libstdcpp_GCCVER-PKGVER)")
optparser.add_option("-f", "--force", action="store_true",
dest="force", default=False,
help="If output directory already exists, delete it")
optparser.add_option("-a", "--add-results", action="append",
dest="baselines", default=[],
help="Additional result file to distribute (may be "
"used multiple times)")
def usage(name):
print "Usage: %s <full-gcc-version> <source-directory> " \
"<destination-directory>" % name
print "E.g., %s 3.3.3 gcc-3.3.3 my-gcc-3.3.3-package" % name
sys.exit(2)
def ensure_dir(dir):
# Assume we're given foo/bar/baz/quux, and foo/bar already exists.
fragments = []
while dir:
if os.path.exists(dir):
break
dir, tail = os.path.split(dir)
fragments.insert(0, tail)
# Now dir == "foo/bar" and fragments == ["baz", "quux"]
# Iterate through the fragments, building up dir and creating
# directories.
for frag in fragments:
dir = j(dir, frag)
os.mkdir(dir)
def main(name, args):
options, args = optparser.parse_args(args)
if len(args) != 4:
optparser.error("Wrong number of arguments")
gcc_version, srcdir, qmtcdir, qmtest_gccdir = args
pkg_version = options.pkg_version
targetdir = options.targetdir
if targetdir is None:
targetdir = "./qmtest_libstdcpp_%s-%s" % (gcc_version,
pkg_version)
if os.path.exists(targetdir):
if options.force:
shutil.rmtree(targetdir)
else:
print "Error: Target directory '%s' already exists and " \
"deletion not requested" % targetdir
sys.exit(2)
if not gcc_version.startswith("3.3"):
print "Error: Unsupported gcc version %s" % gcc_version
sys.exit(2)
v3src = j(srcdir, "libstdc++-v3")
ensure_dir(targetdir)
# Open a file to record which directories exist (and thus need
# installing).
content_files = open(j(targetdir, "contents"), "w")
# Mark that this will be a standalone installation, for later use by
# the QMTest scripts.
f = open(j(targetdir, "THIS-IS-STANDALONE-V3"), "w")
# In case we need to version stuff later:
f.write("1\n")
f.close()
content_files.write("THIS-IS-STANDALONE-V3\n")
# Copy gcc stuff over:
shutil.copytree(j(v3src, "testsuite"), j(targetdir, "testsuite"))
content_files.write("testsuite\n")
shutil.copytree(j(v3src, "po"), j(targetdir, "po"))
content_files.write("po\n")
ensure_dir(j(targetdir, "config"))
shutil.copytree(j(v3src, "config", "abi"),
j(targetdir, "config", "abi"))
content_files.write("config\n")
# gcc 3.4 has a scripts dir that we need.
if os.path.exists(j(v3src, "scripts")):
shutil.copytree(j(v3src, "scripts"), j(targetdir, "scripts"))
content_files.write("scripts\n")
# Copy in QMTest extension classes.
ensure_dir(j(targetdir, "qm-classes"))
content_files.write("qm-classes\n")
shutil.copytree(qmtcdir, j(targetdir, "qm-classes", "qmtc"))
shutil.copytree(qmtest_gccdir,
j(targetdir, "qm-classes", "qmtest_gcc"))
# And then clean them up a bit (remove backup files, compiled files,
# and CVS/ directories).
for g in "*~", "*.pyc", "*.pyo":
for file in glob.glob(j(targetdir, "qm-classes", "*", g)):
os.unlink(file)
for dir in glob.glob(j(targetdir, "qm-classes", "*", "CVS")):
shutil.rmtree(dir)
# Copy over any supplied baselines.
ensure_dir(j(targetdir, "qm-baselines"))
content_files.write("qm-baselines\n")
for b in options.baselines:
shutil.copyfile(b, j(targetdir, "qm-baselines",
os.path.basename(b)))
# Now create the misc. files.
miscdir = j(targetdir, "qm-misc")
ensure_dir(miscdir)
content_files.write("qm-misc\n")
substitutions = {"prog_name": name,
"gcc_version": gcc_version,
"pkg_version": pkg_version,
"prog_args": " ".join(args),
"user": getpass.getuser(),
"time": time.strftime("%Y-%m-%d %H:%M:%S "),
}
f = open(j(miscdir, "locale-Makefile"), "w")
f.write(locale_Makefile % substitutions)
f.close()
f = open(j(miscdir, "util-Makefile"), "w")
f.write(util_Makefile % substitutions)
f.close()
# And the distribution-level files.
f = open(j(targetdir, "README"), "w")
f.write(README_file % substitutions)
f.close()
f = open(j(targetdir, "PKGINFO"), "w")
f.write(PKGINFO_file % substitutions)
f.close()
f = open(j(targetdir,
"qmtest_libstdcpp_%(gcc_version)s.spec"
% substitutions),
"w")
f.write(spec_file % substitutions)
f.close()
locale_Makefile = """\
# Do not edit -- this file automatically generated by %(prog_name)s.
# Makefile to build locale files needed by libstdc++-v3 testsuite.
root := @ROOT@
podir := $(root)/po
POS := $(wildcard $(podir)/*.po)
LANGS := $(basename $(notdir $(POS)))
MOS := $(addsuffix /LC_MESSAGES/libstdc++.mo,$(LANGS))
DIRS := $(addsuffix /LC_MESSAGES,$(LANGS))
# Allow the user to set MSGFMT in their environment
MSGFMT ?= msgfmt
.PHONY: locales
locales: $(POS)
\tmkdir -p $(DIRS)
\tfor lang in $(LANGS); \\
\t do $(MSGFMT) $(podir)/$$lang.po -o $$lang/LC_MESSAGES/libstdc++.mo; \\
\tdone
"""
util_Makefile = """\
# Do not edit -- this file automatically generated by %(prog_name)s.
# Makefile to build utility files needed by libstdc++-v3 testsuite.
root := @ROOT@
CXX := @CXX@
CXXFLAGS := @CXXFLAGS@
VPATH := $(root)/testsuite
v3test_SOURCES := testsuite_hooks.cc testsuite_allocator.cc
abi_check_SOURCES := abi_check.cc
v3test_OBJECTS := $(v3test_SOURCES:.cc=.o)
libv3test.a: $(v3test_OBJECTS)
\t$(AR) r $@ $^
abi_check: $(abi_check_SOURCES)
\t$(CXX) $(CXXFLAGS) $^ -o $@
"""
README_file = """\
GNU C++ RUNTIME LIBRARY TESTSUITE
=================================
This package contains the GNU C++ Runtime Library Testsuite for
version %(gcc_version)s of the GNU Compiler Collection. The tests contained in
this package are the same tests distributed with the GNU Compiler
Collection. The QMTest extension modules included in this package was
developed by CodeSourcery, LLC under contract from the Free Standards
Group.
For assistance with this software, please contact:
support at codesourcery.com
For general information about QMTest, the software used to run these
tests, please visit:
http://www.qmtest.com
You can also send mail to the QMTest mailing list:
qmtest at codesourcery.com
if you have questions about QMTest.
PREREQUISITES
=============
- Python 2.2 (or later)
Python binary packages are available for all popular GNU/Linux
distributions and for many other operating systems. If you do not
already have Python, visit http://www.python.org.
- QMTest 2.2 (or later)
As of this writing QMTest 2.2 has not yet been released.
A Red Hat Package Manager (RPM) distribution of a QMTest snapshot
that works with this testsuite is available at:
http://www.codesourcery.com/qm/qmtest_downloads/qm-20040317/qm-20040317.noarch.rpm
The RPM is architecture-independent; it can be installed on any
GNU/Linux system that supports the RPM format.
You can also obtain the source for QMTest from CVS by following the
directions at:
http://www.codesourcery.com/qm/qmtest_development
- GNU Compiler Collection
In order to test the GNU C++ Runtime Library, you must install
the GNU C++ Compiler (G++) and its associated Runtime Library.
INSTALLATION
============
There are two installation methods for the Testsuite, depending on
which package format you select. Both package formats contain
identical files; which package format you select is purely a matter of
preference.
GNU Zip Tape Archive
--------------------
Download the file:
qmtest_libstdcpp_%(gcc_version)s-%(pkg_version)s.tar.gz
Then, unpack the file with the following command:
tar xzf qmtest_libstdcpp_%(gcc_version)s-%(pkg_version)s.tar.gz
Red Hat Package Manager
-----------------------
Download the file:
qmtest_libstdcpp_%(gcc_version)s-%(pkg_version)s-1.noarch.rpm
Then, install the file with the following command, which must be run
as "root":
rpm -i qmtest_libstdcpp_%(gcc_version)s-%(pkg_version)s-1.noarch.rpm
The package will be installed in:
/usr/share/qmtest_libstdcpp_%(gcc_version)s
USAGE
=====
The following examples all assume that you are using the Bourne shell.
If you are using an alternative shell, you may have to make minor
changes to the commands. Furthermore, these commands assume that the
environment variable "PKGROOT" is the path to the directory in which
you installed the Testsuite. For example, if you used the RPM
installation, "PKGROOT" should be set to
"/usr/share/qmtest_libstdcpp_%(gcc_version)s". These examples assume that both
"qmtest" and "g++" are in your "PATH" and that "g++" is the compiler
that you wish to test. You must also ensure that the
"LD_LIBRARY_PATH" environment variable includes the directory in which
the GNU C++ Runtime Library has been installed. If your "g++" is in
"/path/to/bin/g++", then your "LD_LIBRARY_PATH" should include
"/path/to/lib".
There are four steps required to run the testsuite:
1. Tell QMTest where to find the extension classes required for the
Testsuite:
$ QMTEST_CLASS_PATH=$PKGROOT/qm-classes/qmtc:$PKGROOT/qm-classes/qmtest_gcc
$ export QMTEST_CLASS_PATH
2. Create a test database.
$ qmtest -D v3db create-tdb -c v3_database.V3Database \\
-a srcdir=$PKGROOT/testsuite
3. Create a context file.
The file should be named "v3db/context" and should contain contents
similar to:
CompilerTable.languages=cplusplus
CompilerTable.cplusplus_kind=GCC
CompilerTable.cplusplus_path=g++
CompilerTable.cplusplus_options=
DejaGNUTest.target=i686-pc-linux-gnu
V3Init.scratch_dir=scratch
You should adjust the "DejaGNUTest.target" line to indicate the GNU
triplet for your operating system.
4. Run the tests:
$ cd v3db
$ qmtest run
QMTest will display the results on the standard error stream.
All released versions of G++ fail some of these tests. Therefore,
you should not be surprised to see some failures.
If you would like the results in the TET output format, use the
following command:
$ qmtest run \\
--result-stream="tet_stream.TETStream(filename='results.tet')"
This command will write the results into the file "results.tet"
using TET output format.
If you would like to compare the results with the benchmark results
available obtained with version %(gcc_version)s of the GNU Compiler
Collection on an i686-pc-linux-gnu machine, use the
following command:
$ qmtest run \\
-O $PKGROOT/qm-baselines/%(gcc_version)s_i686-pc-linux-gnu.qmr
QMTest supports a variety of more complex usage scenarios. For more
information see the QMTest manual, available at:
http://www.codesourcery.com/qm/qmtest_manual
"""
PKGINFO_file = """\
This package generated automatically by %(prog_name)s.
Invoked by %(user)s at %(time)s.
Call was:
$ %(prog_name)s %(prog_args)s
"""
spec_file = """\
# Do not edit -- this file automatically generated by %(prog_name)s.
Summary: libstdc++-v3 testsuite packaged to be run under QMTest.
Name: qmtest_libstdcpp_%(gcc_version)s
Packager: Nathaniel Smith <njs at codesourcery.com>
Copyright: Various
Version: %(pkg_version)s
Release: 1
Group: Development/Tools
BuildRoot: %%{_tmppath}/%%{name}-buildroot
Source: qmtest_libstdcpp_%(gcc_version)s-%(pkg_version)s.tar.gz
Vendor: CodeSourcery LLC
BuildArchitectures: noarch
%%description
This package includes the libstdc++-v3 testsuite from gcc version
%(gcc_version)s, together with QMTest extensions allowing one to run the
testsuite against an installed version of libstdc++.
%%prep
%%setup -q
%%build
%%install
rm -rf $RPM_BUILD_ROOT
DIR=$RPM_BUILD_ROOT/usr/share/qmtest_libstdcpp_%(gcc_version)s
mkdir -p $DIR
for thing in `cat contents`; do
if [ -d "$thing" ]; then
cp -r "$thing" "$DIR/$thing"
else
cp "$thing" "$DIR/$thing"
fi
done
%%clean
rm -rf $RPM_BUILD_ROOT
%%files
# Install all files as root:
%%defattr(-,root,root)
/usr/share/qmtest_libstdcpp_%(gcc_version)s/
%%doc README
%%changelog
* Tue Mar 16 2004 Nathaniel Smith <njs at codesourcery.com>
- Initial release.
"""
if __name__ == "__main__":
main(sys.argv[0], sys.argv[1:])
-------------- next part --------------
########################################################################
#
# File: v3_test.py
# Author: Nathaniel Smith
# Date: 03/08/2004
#
# Contents:
# V3Init, V3DGTest, V3ABICheck
#
# Copyright (c) 2004 by CodeSourcery, LLC. All rights reserved.
#
########################################################################
########################################################################
# Imports
########################################################################
import shutil
import fnmatch
import glob
import os
import os.path
import re
import qm
from qm.executable import RedirectedExecutable
from qm.test.test import Test
from qm.test.resource import Resource
from dg_test import DGTest
from dejagnu_base import DejaGNUBase
from qm.test.result import Result
from gcc_test_base import GCCTestBase
from compiler import CompilerExecutable
########################################################################
# Classes
########################################################################
_ld_library_path_names = ["LD_LIBRARY_PATH", "SHLIB_PATH",
"LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH",
"LD_RUN_PATH", "LD_LIBRARY_PATH_32",
"LD_LIBRARY_PATH_64", "DYLD_LIBRARY_PATH"]
"""All the different envvars that might mean LD_LIBRARY_PATH."""
class V3Init(Resource):
"""All V3 tests depend on one of these for setup."""
def SetUp(self, context, result):
# Get general information that will be used through the rest of
# the setup.
srcdir = self.GetDatabase().GetRoot()
target = context["DejaGNUTest.target"]
# Are we using the standalone testsuite to test an installed
# libstdc++/g++, or the integrated testsuite to test a
# just-built libstdc++/g++? Check for the magic file that the
# standalone package contains.
standalone_marker = os.path.join(srcdir, "..",
"THIS-IS-STANDALONE-V3")
standalone = os.path.exists(standalone_marker)
if standalone:
standalone_root = os.path.join(srcdir, "..")
context["V3Init.is_standalone"] = standalone
# Find the compiler.
compilers = context["CompilerTable.compiler_table"]
compiler = compilers["cplusplus"]
if not standalone:
# Find blddir and outdir, and make outdir available to later
# tests.
options = compiler.GetOptions()
compiler_executable = CompilerExecutable()
compiler_executable.Run([compiler.GetPath()]
+ options
+ ['--print-multi-dir'])
directory = compiler_executable.stdout[:-1]
for o in options:
if o.startswith("-B"):
# Calling 'normpath' is necessary to remove any possible
# trailing /.
objdir = os.path.dirname(os.path.normpath(o[2:]))
break
else:
result.SetOutcome(result.ERROR,
"Cannot find build directory; no -B in "
"compiler options")
return
objdir = os.path.abspath(objdir)
blddir = os.path.normpath(os.path.join(objdir,
target,
directory,
"libstdc++-v3"))
outdir = os.path.join(blddir, "testsuite")
else:
# User must provide build directory.
# Our code always refers to this directory as 'outdir' for
# parallelism with the DejaGNU code we emulate, but we call
# it "scratch_dir" for UI purposes.
if context.has_key("V3Init.outdir"):
result.SetOutcome(result.ERROR,
"Set V3Init.scratch_dir, not outdir")
return
outdir = context["V3Init.scratch_dir"]
outdir = os.path.abspath(outdir)
if not os.path.exists(outdir):
os.mkdir(outdir)
context["V3Init.outdir"] = outdir
# print "options = %s" % repr(options)
# print "directory = '%s'" % directory
# print "objdir = '%s'" % objdir
# print "target = '%s'" % target
# print "blddir = '%s'" % blddir
# print "outdir = '%s'" % outdir
# print "srcdir = '%s'" % srcdir
# Ensure that the message format files are available.
# This requires different commands depending on whether we're
# using the gcc build system or not.
if not standalone:
locale_dir = os.path.join(blddir, "po")
make_command = ["make", "-j1", "check"]
else:
# Standalone build needs to set up the locale stuff in its
# own directory.
locale_dir = os.path.join(outdir, "qm_locale")
try:
os.mkdir(locale_dir)
except OSError:
pass
makefile_in = open(os.path.join(standalone_root,
"qm-misc",
"locale-Makefile"))
makefile_str = makefile_in.read()
makefile_str = makefile_str.replace("@ROOT@",
standalone_root)
makefile_out = open(os.path.join(locale_dir, "Makefile"),
"w")
makefile_out.write(makefile_str)
makefile_out.close()
make_command = ["make", "-j1", "locales"]
make_executable = RedirectedExecutable()
status = make_executable.Run(make_command, dir=locale_dir)
if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0:
result.SetOutcome(result.ERROR,
"Error building locale information",
{"status": str(status),
"stdout": "<pre>"
+ make_executable.stdout
+ "</pre>",
"stderr": "<pre>"
+ make_executable.stderr
+ "</pre>",
"command": " ".join(make_command),
})
return
# Copy data files.
for file in "*.tst", "*.txt":
if os.path.isdir(os.path.join(srcdir, "data")):
# 3.4+ store these files in a special data/ directory.
subdirs = ["data"]
else:
# But earlier versions store them scattered through the
# tree.
subdirs = ["*", os.path.join("*", "*")]
for subdir in subdirs:
for f in glob.glob(os.path.join(srcdir, subdir, file)):
shutil.copy(f, outdir)
# Set up environment and -L switches.
for name in _ld_library_path_names:
if os.environ.has_key(name):
original_ld_library_path = os.environ[name].split(":")
break
else:
original_ld_library_path = []
libpaths = []
# Each branch sets ld_library_path and modifies libpaths.
if not standalone:
gccdir = os.path.join(objdir, "gcc")
libpaths.append(gccdir)
command = compiler.GetPath()
compiler_executable.Run([compiler.GetPath()]
+ options
+ ["--print-multi-lib"])
for line in compiler_executable.stdout.split():
dir, args = line.split(";", 1)
if dir == ".":
continue
if glob.glob(os.path.join(gccdir, dir, "libgcc_s*.so.*")):
libpaths.append(dir)
libpaths.append(os.path.join(blddir, "src", ".libs"))
ld_library_path = ":".join(libpaths + original_ld_library_path)
else:
ld_library_path = ":".join(original_ld_library_path)
libpaths.append(outdir)
context["V3Init.libpaths"] = libpaths
context["V3Init.ld_library_path"] = ld_library_path
result["V3Init.ld_library_path"] = ld_library_path
# Calculate default g++ flags. Both branches create basic_flags
# and default_flags.
if not standalone:
# Use the build tree mechanisms.
try:
all_flags = self._CalcBuildTreeFlags(result, context,
blddir, compiler)
except:
result.NoteException(cause="Error calculating default flags",
outcome=Result.FAIL)
return
basic_flags, default_flags = all_flags
else:
# We take the union of the 3.3 and the 3.4 defines; it
# doesn't seem to hurt.
basic_flags = [# v3.4 only:
"-D_GLIBCXX_ASSERT",
# v3.3 only:
"-DDEBUG_ASSERT",
# Common:
"-g", "-O2",
"-ffunction-sections", "-fdata-sections",
"-fmessage-length=0",
"-DLOCALEDIR=\"%s\"" % locale_dir,
"-I%s" % srcdir]
default_flags = []
default_flags.append("-D_GLIBCXX_ASSERT")
if fnmatch.fnmatch(context["DejaGNUTest.target"],
"powerpc-*-darwin*"):
default_flags += ["-multiply_defined", "suppress"]
context["V3Init.basic_cxx_flags"] = basic_flags
context["V3Init.default_cxx_flags"] = default_flags
if standalone:
# Build libv3test.a.
makefile_in = open(os.path.join(standalone_root,
"qm-misc",
"util-Makefile"))
makefile_str = makefile_in.read()
makefile_str = makefile_str.replace("@ROOT@",
standalone_root)
makefile_str = makefile_str.replace("@CXX@",
compiler.GetPath())
flags = compiler.GetOptions() + basic_flags
makefile_str = makefile_str.replace("@CXXFLAGS@",
" ".join(flags))
makefile_out = open(os.path.join(outdir, "Makefile"), "w")
makefile_out.write(makefile_str)
makefile_out.close()
make_executable = RedirectedExecutable()
make_command = ["make", "libv3test.a"]
status = make_executable.Run(make_command, dir=outdir)
if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0:
result.SetOutcome(result.ERROR,
"Error building libv3test.a",
{"status": str(status),
"stdout": "<pre>"
+ make_executable.stdout
+ "</pre>",
"stderr": "<pre>"
+ make_executable.stderr
+ "</pre>",
"command": " ".join(make_command),
})
return
def _CalcBuildTreeFlags(self, result, context, blddir, compiler):
"""This function emulates a bit of normal.exp and a bit of
v3-init."""
basic_flags = []
default_flags = []
# Find the command to use.
for subdir in "", "scripts":
command = os.path.join(blddir, subdir, "testsuite_flags")
if os.path.isfile(command):
break
result["V3Init.testsuite_flags_command"] = \
"<pre>" + command + "</pre>"
executable = RedirectedExecutable()
executable.Run([command, "--cxxflags"])
basic_flags += executable.stdout.split()
executable.Run([command, "--build-includes"])
basic_flags += executable.stdout.split()
# 'normal.exp' checks for the existence of 'testsuite_flags' and
# pretends the output is "" if it doesn't exist; we simply
# assume it always exists.
executable.Run([command, "--cxxpchflags"])
if executable.stdout.find("sage:") != -1:
# This 'testsuite_flags' does not support --cxxpchflags.
pass
else:
default_flags += executable.stdout.split()
return (basic_flags, default_flags)
# dg-runtest calls dg-test calls "libstdc++-dg-test prog do_what
# DEFAULT_CXXFLAGS" (DEFAULT_CXXFLAGS as in normal.exp)
# Which calls
# v3_target_compile $prog $output_file $compile_type additional_flags=$DEFAULT_CXXFLAGS
# Which sets cxx_final to "$cxx [libgloss_link_flags] $cxxflags $includes"
# then calls
# target_compile $prog $output_file $compile_type additional_flags=$DEFAULT_CXXFLAGS,compiler=$cxx_final,ldflags=-L$blddir/testsuite,libs=-lv3test
# for us, libgloss doesn't exist, which simplifies things.
class V3DGTest(DGTest, GCCTestBase):
"""A 'V3DGTest' is a libstdc++-v3 test using the 'dg' driver.
This test class emulates the 'lib/libstdc++.exp' and 'lib/prune.exp
and 'libstdc++-dg/normal.exp' source files in the libstdc++-v3
testsuite."""
_default_kind = DGTest.KIND_RUN
_language = "cplusplus"
_libdir_context_property = "V3Init.libpaths"
def Run(self, context, result):
self._SetUp(context)
self._RunDGTest(context["V3Init.basic_cxx_flags"],
context["V3Init.default_cxx_flags"],
context,
result)
def _PruneOutput(self, output):
"""This method emulates 'prune.exp'."""
# Prune out Cygwin warnings and parts of warnings that refer to
# location of previous definitions etc.
output = re.sub(r"(^|\n)[^\n]*: -ffunction-sections may affect "
r"debugging on some targets[^\n]",
"", output)
output = re.sub(r"(^|\n)[^\n]*: In function [^\n]*", "", output)
return output
def _GetTargetEnvironment(self, context):
env = {}
for name in _ld_library_path_names:
env[name] = context["V3Init.ld_library_path"]
return env
def _RunTargetExecutable(self, context, result, file, dir = None):
if dir is None:
dir = context["V3Init.outdir"]
sup = super(V3DGTest, self)
return sup._RunTargetExecutable(context, result, file, dir)
def _RunTool(self, path, kind, options, context, result):
"""This method emulates libstdc++-dg-test."""
source_files = [path]
file = self._GetOutputFile(context, kind, path)
kind = self._test_kind_map[kind]
if kind == GCCTestBase.KIND_EXECUTABLE:
source_files += ["-lv3test"]
output = self._Compile(context, result, source_files, file,
kind, options)
return (output, file)
def _GetOutputFile(self, context, kind, path):
base = os.path.basename(path)
if kind != self.KIND_PRECOMPILE:
base = os.path.splitext(base)[0]
base += { DGTest.KIND_PREPROCESS : ".i",
DGTest.KIND_COMPILE : ".s",
DGTest.KIND_ASSEMBLE : ".o",
DGTest.KIND_LINK: ".exe",
DGTest.KIND_RUN : ".exe",
GCCTestBase.KIND_PRECOMPILE : ".gch",
}[kind]
return os.path.join(context.GetTemporaryDirectory(), base)
def _DGrequire_iconv(self, line_num, args, context):
"""Emulate the 'dg-require-iconv' command.
Emulates code from 'libstdc++-v3/testsuite/lib/dg-options.exp'
and 'gcc/testsuite/lib/target-supports.exp'.
'line_num' -- The number at which the command was found.
'args' -- The arguments to the command, as a list of
strings.
'context' -- The 'Context' in which the test is running."""
# Parse arguments.
if len(args) != 1:
self._Error("dg-require-iconv: wrong number of arguments")
return
charset = args[0]
# Check to see if iconv does exist and work.
# First by creating and compiling a test program...
tmpdir = context.GetTemporaryDirectory()
tmpc = os.path.join(tmpdir, "tmp.c")
tmpx = os.path.join(tmpdir, "tmp.x")
f = open(tmpc, "w")
f.write("""\
#include <iconv.h>
int main (void)
{
iconv_t cd;
cd = iconv_open("%(charset)s", "UTF-8");
if (cd == (iconv_t) -1)
return 1;
return 0;
}
"""
% {"charset": charset})
f.close()
compiler = context["CompilerTable.compiler_table"][self._language]
options = []
options += context["V3Init.basic_cxx_flags"]
options += context["V3Init.default_cxx_flags"]
libpaths = context["V3Init.libpaths"]
options += ["-L" + p for p in libpaths]
if context.has_key("GCCTest.libiconv"):
libiconv_opts = context["GCCTest.libiconv"].split()
else:
libiconv_opts = []
(status, output) = compiler.Compile(compiler.MODE_LINK,
[tmpc] + libiconv_opts,
tmpdir, options, tmpx)
if output == "":
# ...and then running it, if there are no errors.
executable = self.TargetExecutable(self.executable_timeout)
command = [tmpx]
environment = self._GetTargetEnvironment(context)
status = executable.Run(command, environment, tmpdir)
if os.WIFEXITED(status) and os.WEXITSTATUS(status) == 0:
# We have working libiconv. Continue as normal.
return
# Something went wrong somewhere -- libiconv is not available.
# Turn off the test.
self._selected = 0
# Not clear that setting the expectation here serves any
# purpose, but it's what 'dg-options.exp' does, so we do too.
self._expectation = Result.PASS
# check-abi first builds
# abi_check
# baseline_symbols
# current_symbols.txt
# then does
# ./abi_check --check(-verbose) ./current_symbols.txt ${baseline_file}
#
# abi_check is built by automake as a program.
# baseline_symbols just checks to see if a baseline file exists
# current_symbols.txt depends on ${extract_symvers} ../src/.libs/libstdc++.so
#
#
# new-abi-baseline is what actually generates a new baseline.
# it does it with ${extract_symvers} ../src/.libs/libstdc++.so ${baseline_file}
# baseline_file = ${baseline_dir}/baseline_symbols.txt
# baseline_dir is set by autoconf to some mad thing...
# $glibcxx_srcdir/config/abi/${abi_baseline_pair}\$(MULTISUBDIR)"
# abi_baseline_pair is set by autoconf to host_cpu-host_os by default.
# but there are some special cases, in particular:
# x86_64-*-linux* -> x86_64-linux-gnu
# alpha*-*-freebsd5* -> alpha-freebsd5
# i*86-*-freebsd4* -> i386-freebsd4
# i*86-*-freebsd5* -> i386-freebsd5
# sparc*-*-freebsd5* -> sparc-freebsd5
#
# extract_symvers = $(glibcxx_srcdir)/scripts/extract_symvers
# extract_symvers is actually just a shell script
class V3ABITest(Test):
"""A 'V3ABITest' checks the ABI of libstdc++ against a baseline.
Depends on context variable 'V3Test.abi_baseline_file'."""
def Run(self, context, result):
# Some variables we'll need throughout.
executable = RedirectedExecutable()
tmpdir = context.GetTemporaryDirectory()
outdir = context["V3Init.outdir"]
srcdir = self.GetDatabase().GetRoot()
# First we make sure that the abi_check program exists.
abi_check = os.path.join(outdir, "abi_check")
status = executable.Run(["make", "abi_check"], dir=outdir)
result["make_abi_check_stdout"] = ("<pre>" + executable.stdout
+ "</pre>")
result["make_abi_check_stderr"] = ("<pre>" + executable.stderr
+ "</pre>")
result["make_abi_check_status"] = str(status)
if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0:
result.SetOutcome(result.ERROR, "Error building abi_check")
return
if not os.path.isfile(abi_check):
result.SetOutcome(result.ERROR,
"No abi_check program '%s'" % abi_check)
return
# Now make sure the baseline file exists.
baseline_type = self._GetAbiName(context["DejaGNUTest.target"])
baseline_file = os.path.join(srcdir, "..", "config", "abi",
baseline_type,
"baseline_symbols.txt")
result["baseline_file"] = baseline_file
if not os.path.isfile(baseline_file):
result.SetOutcome(result.ERROR,
"No baseline file '%s'" % baseline_file)
return
# Check that we have the 'extract_symvers' script.
# 3.4+ stores it in scripts; 3.3 stores it in config/abi.
subdirs = ["scripts", os.path.join("config", "abi")]
for subdir in subdirs:
extract_symvers = os.path.join(srcdir, "..",
subdir,
"extract_symvers")
if os.path.isfile(extract_symvers):
break
else:
result.SetOutcome(result.ERROR,
"Can't find extract_symvers")
return
# Extract the current symbols.
# First use ldd to find the libstdc++ in use.
status = executable.Run(["ldd", "abi_check"], dir=outdir)
result["ldd_stdout"] = ("<pre>" + executable.stdout
+ "</pre>")
result["ldd_stderr"] = ("<pre>" + executable.stderr
+ "</pre>")
result["ldd_status"] = str(status)
if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0:
result.SetOutcome(result.ERROR,
"Error running ldd to find libstdc++")
return
for token in executable.stdout.split():
if os.sep in token and token.find("libstdc++") != -1:
libstdcpp = token
break
else:
result.SetOutcome(result.ERROR,
"Could not find path to libstdc++ in "
"ldd output")
return
# libstdcpp = os.path.join(outdir, "..", "src", ".libs",
# "libstdc++.so")
result["libstdcpp_path"] = libstdcpp
curr_symbols = os.path.join(tmpdir, "current_symbols.txt")
status = executable.Run([extract_symvers,
libstdcpp,
curr_symbols])
result["extract_symvers_stdout"] = ("<pre>" + executable.stdout
+ "</pre>")
result["extract_symvers_stderr"] = ("<pre>" + executable.stderr
+ "</pre>")
result["extract_symvers_status"] = str(status)
if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0:
result.SetOutcome(result.ERROR, "Error extracting symbols")
return
if not os.path.isfile(curr_symbols):
result.SetOutcome(result.ERROR, "No symbols extracted")
return
# We have the checker program, we have the baseline, we have the
# current symbols. Now we use the former to compare the
# latter.
status = executable.Run([abi_check, "--check-verbose",
curr_symbols, baseline_file])
result["comparison_stdout"] = ("<pre>" + executable.stdout
+ "</pre>")
result["comparison_stderr"] = ("<pre>" + executable.stderr
+ "</pre>")
result["comparison_status"] = str(status)
if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0:
result.SetOutcome(result.ERROR,
"Error comparing symbols to baseline")
return
# Parse the output.
for line in executable.stdout.split("\n"):
if line.startswith("# of "):
num_changes_str = line.split(":", 1)[1].strip()
num_changes = int(num_changes_str)
if num_changes != 0:
result.Fail("Changes against ABI baseline detected")
result["failing_line"] = line.strip()
return
def _GetAbiName(self, host):
"""Map a target triple to a abi directory name.
Emulates 'configure.host'."""
cpu, vendor, os = host.split("-", 2)
m = fnmatch.fnmatch
if m(cpu, "alpha*"):
cpu = "alpha"
elif m(cpu, "i[567]86") or m(cpu, "x86_64"):
cpu = "i486"
elif m(cpu, "hppa*"):
cpu = "hppa"
elif m(cpu, "powerpc*") or m(cpu, "rs6000"):
cpu = "powerpc"
elif m(cpu, "s390x"):
cpu = "s390"
elif m(cpu, "sparc*") or m(cpu, "ultrasparc"):
cpu = "sparc"
return "%s-%s" % (cpu, os)
-------------- next part --------------
########################################################################
#
# File: v3_database.py
# Author: Nathaniel Smith
# Date: 03/01/2004
#
# Contents:
# V3Database
#
# Copyright (c) 2004 by CodeSourcery, LLC. All rights reserved.
#
########################################################################
########################################################################
# Imports
########################################################################
import fnmatch
import os
import qm
import qm.test.base
from qm.attachment import Attachment, FileAttachmentStore
from qm.test.database import ResourceDescriptor, TestDescriptor
from qm.test.file_database import FileDatabase
from qm.test.runnable import Runnable
########################################################################
# Classes
########################################################################
class V3Database(FileDatabase):
"""A 'V3Database' stores the libstc++-v3 regression tests."""
arguments = [
qm.fields.TextField(
name = "srcdir",
title = "Source Directory",
description ="""The root of the libstdc++-v3 test source directory.
This directory is the one named 'testsuite'."""),
# The libstdc++ database uses filenames as labels.
qm.fields.TextField(
name = "label_class",
default_value = "file_label.FileLabel",
computed = "true"
),
# The libstdc++ database cannot be modified programmatically.
qm.fields.BooleanField(
name = "modifiable",
default_value = "false",
computed = "true",
),
]
def __init__(self, path, arguments):
# Initialize the base class.
super(V3Database, self).__init__(path, arguments)
# Create an attachment store.
self.__store = FileAttachmentStore()
def GetResource(self, resource_id):
if resource_id == "compiler_table":
return ResourceDescriptor(self, resource_id,
"compiler_table.CompilerTable",
{})
elif resource_id == "v3_init":
return ResourceDescriptor(self, resource_id,
"v3_test.V3Init",
{ Runnable.RESOURCE_FIELD_ID :
["compiler_table"] })
raise self.NoSuchResourceError, resource_id
def GetRoot(self):
return self.srcdir
def GetAttachmentStore(self):
return self.__store
def GetTestIds(self, directory="", scan_subdirs=1):
result = super(V3Database, self).GetTestIds(directory,
scan_subdirs)
if directory == "":
return result + ["v3_abi_test"]
else:
return result
def GetTest(self, test_id):
if test_id == "v3_abi_test":
return TestDescriptor(self, test_id,
"v3_test.V3ABITest",
{ Runnable.RESOURCE_FIELD_ID:
["v3_init"]})
else:
return super(V3Database, self).GetTest(test_id)
def _GetTestFromPath(self, test_id, path):
# Construct the attachment representing the primary source
# file.
basename = os.path.basename(path)
attachment = Attachment("text/plain", basename,
basename, path,
self.GetAttachmentStore())
# Create the test descriptor.
resources = ["v3_init"]
descriptor = TestDescriptor(self, test_id,
"v3_test.V3DGTest",
{ 'source_file' : attachment,
Runnable.RESOURCE_FIELD_ID :
resources })
return descriptor
def _IsResourceFile(self, path):
# No resources are stored in files.
return False
def _IsSuiteFile(self, path):
# All directories are suites.
return os.path.isdir(path)
def _IsTestFile(self, path):
"""This function emulates scripts/create_testsuite_files."""
assert path.startswith(self.GetRoot() + os.sep)
rel_path = path[len(self.GetRoot()) + 1:]
if os.sep not in rel_path:
return False
if not rel_path.endswith(".cc"):
return False
forbidden_substrings = ["_xin", "performance"]
# FIXME: create_testsuite_files checks to see if wchar_t support
# is enabled (by checking for the existence of
# $outdir/testsuite_wchar_t), and if it isn't, then "wchar_t" is
# added to the forbidden list. The right way to handle this in
# QMTest is not obvious, so for now we ignore this.
for f in forbidden_substrings:
if rel_path.find(f) != -1:
return False
return True
More information about the qmtest
mailing list