PATCH: Improve CompilerTest
Mark Mitchell
mark at codesourcery.com
Thu Dec 1 07:34:01 UTC 2005
This patch contains several little tweaks to CompilerTest:
* You can now provide arguments to the program generated by the
compiler, e.g., if the compiler generates a program named "foo", you
can run it like "foo arg1 arg2".
* You can now decide that "foo" need not exit with code zero, without
causing the test to fail.
* You can validate that the output from the executable is what you
expect by implementing _CheckExecutableOutput.
--
Mark Mitchell
CodeSourcery, LLC
mark at codesourcery.com
2005-11-30 Mark Mitchell <mark at codesourcery.com>
* qm/test/classes/compiler_test.py (CompilationStep): Provide default
values.
(CompilerBase._MakeDirectory): Do not create the temporary build
directory if it already exists.
(CompilerTest.Run): Create the temporary build directory. Record
the output from the compiler here.
(CompilerTest._GetExecutableArguments): New function.
(CompilerTest._MustExecutableExitSuccessfully): New function.
(CompilerTest._RunExecutable): Use new functions.
(CompilerTest._CheckOutput): Do not record the output here.
Adjust use of _DiagnosticsToString.
(CompilerTest._CheckExecutableOutput): New function.
(CompilerTest._DiagnosticsToString): Add annotation parameter.
Index: qm/test/classes/compiler_test.py
===================================================================
RCS file: /home/qm/Repository/qm/qm/test/classes/compiler_test.py,v
retrieving revision 1.4
diff -c -5 -p -r1.4 compiler_test.py
*** qm/test/classes/compiler_test.py 1 Dec 2005 06:46:43 -0000 1.4
--- qm/test/classes/compiler_test.py 1 Dec 2005 07:29:30 -0000
*************** import os, string
*** 23,33 ****
########################################################################
class CompilationStep:
"""A single compilation step."""
! def __init__(self, mode, files, options, output, diagnostics):
"""Construct a new 'CompilationStep'.
'mode' -- As for 'Compiler.Compile'.
'files' -- As for 'Compiler.Compile'.
--- 23,34 ----
########################################################################
class CompilationStep:
"""A single compilation step."""
! def __init__(self, mode, files, options = [],
! output = None , diagnostics = []):
"""Construct a new 'CompilationStep'.
'mode' -- As for 'Compiler.Compile'.
'files' -- As for 'Compiler.Compile'.
*************** class CompilerBase:
*** 76,87 ****
returns -- The name of the directory."""
# Get the directory name.
directory = self._GetDirectory(context)
# Create it.
! os.makedirs(directory)
!
return directory
def _RemoveDirectory(self, context, result):
"""Remove the directory in which generated files are placed.
--- 77,88 ----
returns -- The name of the directory."""
# Get the directory name.
directory = self._GetDirectory(context)
# Create it.
! if not os.path.exists(directory):
! os.makedirs(directory)
return directory
def _RemoveDirectory(self, context, result):
"""Remove the directory in which generated files are placed.
*************** class CompilerTest(Test, CompilerBase):
*** 143,152 ****
--- 144,155 ----
executable_path = None
# See what we need to run this test.
steps = self._GetCompilationSteps(context)
# See if we need to run this test.
is_execution_required = self._IsExecutionRequired()
+ # Create the temporary build directory.
+ self._MakeDirectory(context)
# Keep track of which compilation step we are performing so
# that we can annotate the result appropriately.
step_index = 1
*************** class CompilerTest(Test, CompilerBase):
*** 164,174 ****
# Run the compiler.
timeout = context.get("CompilerTest.compilation_timeout", -1)
(status, output) \
= compiler.ExecuteCommand(self._GetDirectory(context),
command, timeout)
!
# Make sure that the output is OK.
if not self._CheckOutput(context, result, prefix, output,
step.diagnostics):
# If there were errors, do not try to run the program.
is_execution_required = 0
--- 167,179 ----
# Run the compiler.
timeout = context.get("CompilerTest.compilation_timeout", -1)
(status, output) \
= compiler.ExecuteCommand(self._GetDirectory(context),
command, timeout)
! # Annotate the result with the output.
! if output:
! result[prefix + "output"] = result.Quote(output)
# Make sure that the output is OK.
if not self._CheckOutput(context, result, prefix, output,
step.diagnostics):
# If there were errors, do not try to run the program.
is_execution_required = 0
*************** class CompilerTest(Test, CompilerBase):
*** 232,241 ****
--- 237,266 ----
returns -- True if the generated executable should be run."""
return 0
+
+ def _GetExecutableArguments(self):
+ """Returns the arguments to the generated executable.
+
+ returns -- A list of strings, to be passed as argumensts to
+ the generated executable."""
+
+ return []
+
+
+ def _MustExecutableExitSuccessfully(self):
+ """Returns true if the executable must exit with code zero.
+
+ returns -- True if the generated executable (if any) must exit
+ with code zero. Note that the executable will not be run at
+ all (and so the return value of this function will be ignored)
+ if '_IsExecutionRequired' does not return true."""
+
+ return True
+
def _GetAnnotationPrefix(self):
"""Return the prefix to use for result annotations.
returns -- The prefix to use for result annotations."""
*************** class CompilerTest(Test, CompilerBase):
*** 270,280 ****
# Compute the result annotation prefix.
prefix = self._GetAnnotationPrefix() + "execution_"
# Record the command line.
path = os.path.join(self._GetDirectory(context), path)
! result[prefix + "command"] = "<tt>" + path + "</tt>"
# Compute the environment.
library_dirs = self._GetLibraryDirectories(context)
if library_dirs:
# Update LD_LIBRARY_PATH. On IRIX 6, this variable
--- 295,307 ----
# Compute the result annotation prefix.
prefix = self._GetAnnotationPrefix() + "execution_"
# Record the command line.
path = os.path.join(self._GetDirectory(context), path)
! arguments = self._GetExecutableArguments()
! result[prefix + "command"] \
! = "<tt>" + path + " " + " ".join(arguments) + "</tt>"
# Compute the environment.
library_dirs = self._GetLibraryDirectories(context)
if library_dirs:
# Update LD_LIBRARY_PATH. On IRIX 6, this variable
*************** class CompilerTest(Test, CompilerBase):
*** 293,309 ****
environment = None
target = self._GetTarget(context)
timeout = context.get("CompilerTest.execution_timeout", -1)
status, output = target.UploadAndRun(path,
! [],
environment,
timeout)
# Record the output.
result[prefix + "output"] = result.Quote(output)
# Check the output status.
! result.CheckExitStatus(prefix, "Executable", status)
def _CheckOutput(self, context, result, prefix, output, diagnostics):
"""Check that the 'output' contains appropriate diagnostics.
--- 320,338 ----
environment = None
target = self._GetTarget(context)
timeout = context.get("CompilerTest.execution_timeout", -1)
status, output = target.UploadAndRun(path,
! arguments,
environment,
timeout)
# Record the output.
result[prefix + "output"] = result.Quote(output)
+ self._CheckExecutableOutput(result, output)
# Check the output status.
! result.CheckExitStatus(prefix, "Executable", status,
! not self._MustExecutableExitSuccessfully())
def _CheckOutput(self, context, result, prefix, output, diagnostics):
"""Check that the 'output' contains appropriate diagnostics.
*************** class CompilerTest(Test, CompilerBase):
*** 321,335 ****
compilation.
returns -- True if there were no errors so severe as to
prevent execution of the test."""
- # Annotate the result with the output.
- if output:
- result[prefix + "output"] \
- = result.Quote(output)
-
# Get the compiler to use to parse the output.
compiler = self._GetCompiler(context)
# Parse the output.
emitted_diagnostics \
--- 350,359 ----
*************** class CompilerTest(Test, CompilerBase):
*** 383,403 ****
else:
result.Fail("Spurious diagnostics.")
# Add annotations showing the problem.
if spurious_diagnostics:
! result[self._GetAnnotationPrefix() + "spurious_diagnostics"] \
! = self._DiagnosticsToString(spurious_diagnostics)
if missing_diagnostics:
! result[self._GetAnnotationPrefix() + "missing_diagnostics"] \
! = self._DiagnosticsToString(missing_diagnostics)
# If errors occurred, there is no point in trying to run
# the executable.
return not errors_occurred
def _IsDiagnosticExpected(self, emitted, expected):
"""Returns true if 'emitted' matches 'expected'.
'emitted' -- A 'Diagnostic emitted by the compiler.
--- 407,442 ----
else:
result.Fail("Spurious diagnostics.")
# Add annotations showing the problem.
if spurious_diagnostics:
! self._DiagnosticsToString(result,
! "spurious_diagnostics",
! spurious_diagnostics)
if missing_diagnostics:
! self._DiagnosticsToString(result,
! "missing_diagnostics",
! missing_diagnostics)
# If errors occurred, there is no point in trying to run
# the executable.
return not errors_occurred
+ def _CheckExecutableOutput(self, result, output):
+ """Checks the output from the generated executable.
+
+ 'result' -- The 'Result' object for this test.
+
+ 'output' -- The output generated by the executable.
+
+ If the output is unsatisfactory, 'result' is modified
+ appropriately."""
+
+ pass
+
+
def _IsDiagnosticExpected(self, emitted, expected):
"""Returns true if 'emitted' matches 'expected'.
'emitted' -- A 'Diagnostic emitted by the compiler.
*************** class CompilerTest(Test, CompilerBase):
*** 430,446 ****
# There's a match.
return 1
! def _DiagnosticsToString(self, diagnostics):
"""Return a string representing the 'diagnostics'.
'diagnostics' -- A sequence of 'Diagnostic' instances.
returns -- A string representing the 'Diagnostic's, with one
diagnostic message per line."""
# Compute the string representation of each diagnostic.
diagnostic_strings = map(str, diagnostics)
# Insert a newline between each string.
! return Result.Quote("\n".join(diagnostic_strings))
--- 469,486 ----
# There's a match.
return 1
! def _DiagnosticsToString(self, result, annotation, diagnostics):
"""Return a string representing the 'diagnostics'.
'diagnostics' -- A sequence of 'Diagnostic' instances.
returns -- A string representing the 'Diagnostic's, with one
diagnostic message per line."""
# Compute the string representation of each diagnostic.
diagnostic_strings = map(str, diagnostics)
# Insert a newline between each string.
! result[self._GetAnnotationPrefix() + annotation] \
! = result.Quote("\n".join(diagnostic_strings))
More information about the qmtest
mailing list