2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-16 13:22:11 +00:00
Files
build/v1/testing.jam
Dave Abrahams 21c7471c3a * Fixed Boost.Thread jamfile to add the missing #include paths
* Modified Python testing code to use the facilities of testing.jam,
  so that it can be processed with process_jam_log

* Updated Python library tests to use a test suite

* Added Python test suite to status/Jamfile

* Added --run-all-tests option to force tests to run even when up-to-date.


Also,
boost-base.jam:

    Added some missing rule signatures

    RUN_LD_LIBRARY_PATH became LINK_LIBPATH because it was only really
    used during linking.

    Reformed the movement of path variables up the dependency graph

    Removed the defunct Run rule

    Set up generalized constants for path manipulation

darwin-tools.jam, gcc-tools.jam:

   use LINK_LIBPATH

python.jam:

   Reformed the choice of Python executable

testing.jam:

   Refactored testing code so it could be used for Python

   Now building all environment variable setup code ahead of time

   RUN_TEST became TEST_EXE


[SVN r20815]
2003-11-15 15:41:41 +00:00

433 lines
13 KiB
Plaintext
Executable File

# (C) Copyright David Abrahams 2002. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears in
# all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
if ! $(.testing.jam-included)
{
.testing.jam-included = "}" ; # The brace makes emacs indentation happy
# Decide which toolsets should be treated like an ordinary (unix) GCC installation
gcc-compilers = [ MATCH ^(gcc.*)$ : $(TOOLS) ] ;
mingw-compilers = [ MATCH ^(mingw.*)$ ^(gcc-nocygwin.*) : $(TOOLS) ] ;
gcc-compilers = [ difference $(gcc-compilers) : $(mingw-compilers) ] ;
local rule get-var-value ( name + )
{
return $($(name)) ;
}
# Declares a test target. If name is not supplied, it is taken from the name of
# the first source file, sans extension and directory path.
#
# type should be a target type (e.g. OBJ, DLL, LIB, EXE)
#
# RETURNS the name(s) of the generated test target(s).
rule boost-test ( sources + : target-type : requirements * : test-name ? : default-build * )
{
if ! $(gIN_LIB_INCLUDE) # No need to execute this code twice
{
local result ;
{
# manufacture a test name if none supplied explicitly
test-name ?= $(sources[1]:D=:S=) ;
# Make sure that targets don't become part of "all"
local gSUPPRESS_FAKE_TARGETS = true ;
result = [
declare-local-target $(test-name)
: $(sources)
: $(requirements) <sysinclude>$(BOOST_ROOT)
: $(default-build)
: $(target-type)
] ;
if $(result) in $(.all-boost-tests)
{
EXIT boost-test \"$(result)\" declared twice ;
.all-boost-tests += $(result) ;
}
if ( --dump-tests in $(ARGV) )
{
dump-test ;
}
}
Clean clean : $(result) ;
# make NOTFILE targets of the same base name as the sources which can
# be used to build a single test.
type-DEPENDS $(sources:B:S=) : $(result) ;
# The NOTFILE target called "test" builds all tests
type-DEPENDS test : $(result) ;
# Make sure the test result doesn't hang around if the test fails
RMOLD $(result) ;
return $(result) ;
}
}
# Helper for boost-test above. Uses dynamic scoping to access
# boost-test's locals.
local rule dump-test ( )
{
local srcs = [ on $(result) get-var-value source-files ] ;
local pwd = [ PWD ] ;
# locate each source file
local source-files ;
for local s in $(srcs)
{
# find out where to look for the file
local paths = [ on $(s) get-var-value LOCATE SEARCH ] ;
s = $(s:G=) ; # strip grist
# build all the potential full paths of the file
local full-paths = $(s:R=$(paths)) ;
# look there
local files = [ GLOB $(full-paths:D) : $(s:D=) ] ;
if $(files)
{
# make relative to the project root instead of "."
local file = $(files[1]:R=$(pwd)) ;
# try to undo absolute paths
source-files += [ relative-path $(file) ] ;
}
}
# Extract values of the <test-info> feature
local dump-test-info = [ get-values <test-info> : $(requirements) ] ;
# Format them into a single string of quoted strings
dump-test-info = \"$(dump-test-info:J=\"\ \")\" ;
ECHO boost-test($(target-type)) \"$(test-name)\"
[$(dump-test-info)]
":" \"$(source-files)\"
;
}
#######
BOOST_TEST_SUFFIX ?= .test ;
# Set a variable which says how to dump a file to stdout
if $(NT)
{
CATENATE = type ;
}
else
{
CATENATE = cat ;
}
actions **passed** bind source-files
{
echo $(source-files) > $(<)
}
actions (failed-as-expected)
{
echo failed as expected > $(<)
}
# a utility rule which causes test-file to be built successfully only if
# dependency fails to build. Used for expected-failure tests.
rule failed-test-file ( test-file : dependency + )
{
local grist = [ MATCH ^<(.*)> : $(dependency:G) ] ;
local marker = $(dependency:G=$(grist)*fail) ;
(failed-as-expected) $(marker) ;
FAIL_EXPECTED $(dependency) ;
MakeLocate $(marker) : $(LOCATE_TARGET) ;
RMOLD $(marker) ;
DEPENDS $(marker) : $(dependency) ;
succeeded-test-file $(test-file) : $(marker) ;
}
# a utility rule which causes test-file to be built successfully only if
# dependency builds. Used for expected-success tests.
rule succeeded-test-file ( test-file : dependency + )
{
**passed** $(test-file) ;
DEPENDS $(test-file) : $(dependency) ;
}
rule declare-build-succeed-test ( test-type : dependency-type )
{
gGENERATOR_FUNCTION($(test-type)) = build-test succeeded-test-file ;
gDEPENDENCY_TYPE($(test-type)) = $(dependency-type) ;
SUF$(test-type) = $(BOOST_TEST_SUFFIX) ;
}
# A utility rule which declares test-type to be a target type which
# depends on the /failed/ construction of a target of type
# dependency-type.
rule declare-build-fail-test ( test-type : dependency-type )
{
gGENERATOR_FUNCTION($(test-type)) = build-test failed-test-file ;
gDEPENDENCY_TYPE($(test-type)) = $(dependency-type) ;
SUF$(test-type) = $(BOOST_TEST_SUFFIX) ;
}
# When the appropriate generator function is bound to the
# test-file-generator argument, this is a target generator function
# for target types declared with declare-build-succeed-test and
# declare-build-fail-test, above.
rule build-test ( test-file-generator test-file + : sources * : requirements * )
{
# Get the target type of the current target out of the build properties
local target-type = [ get-values <target-type> : $(gBUILD_PROPERTIES) ] ;
# Get the type of target to attempt to build; the outcome of this
# attempt determines the result of the test.
local dependency-type = $(gDEPENDENCY_TYPE($(target-type))) ;
# Get the actual name of the target to attempt to build
local dependency = $(test-file[1]:S=$(SUF$(dependency-type))) ;
# record the source file names so we can put them in the .test
# file.
source-files on $(test-file) = $(sources) ;
# Make sure that the test-file is erased upon failure, so as not
# to give a false indication of success.
RMOLD $(test-file) ;
# Call dependency-type's generator function to attempt the build
$(gGENERATOR_FUNCTION($(dependency-type))) $(dependency) : $(sources) : $(requirements) ;
# Generator functions don't handle this job for us; perhaps they should.
set-target-variables $(dependency) ;
if $(test-file:S) != $(BOOST_TEST_SUFFIX)
{
EXIT unexpected test file suffix. Filename: $(test-file) ;
}
# The test files go with the other subvariant targets
MakeLocate $(test-file) : $(LOCATE_TARGET) ;
Clean clean : $(test-file) ;
# Generate the test file
$(test-file-generator) $(test-file) : $(dependency) ;
}
### Rules for testing whether a file compiles ###
# Establish the rule which generates targets of type "OBJ". Should really go
# into basic build system, but wasn't needed 'till now.
gGENERATOR_FUNCTION(OBJ) = Object ;
declare-build-fail-test COMPILE_FAIL : OBJ ;
declare-build-succeed-test COMPILE : OBJ ;
# Test that the given source-file(s) compile
rule compile ( sources + : requirements * : test-name ? )
{
return [ boost-test $(sources) : COMPILE : $(requirements) : $(test-name) ] ;
}
# Test that the given source-file(s) fail to compile
rule compile-fail ( sources + : requirements * : test-name ? )
{
return [ boost-test $(sources) : COMPILE_FAIL : $(requirements) : $(test-name) ] ;
}
### Rules for testing whether a program runs ###
gGENERATOR_FUNCTION(TEST_EXE) = run-test EXE ;
SUFTEST_EXE = .run ;
rule test-executable(EXE) ( target-to-test )
{
return $(target-to-test) ;
}
rule nt-paths-to-cygwin ( paths * )
{
local result ;
for local p in $(paths)
{
# if already rooted...
if [ MATCH ^([A-Za-z]:[/\\]) : $(p) ]
{
p = [ split-path $(p) ] ;
p = [ join-path /cygdrive [ MATCH ^(.).* : $(p[1]) ] $(p[2-]) ] ;
}
result += $(p:T) ;
}
return $(result) ;
}
rule run-test ( type-to-test run-target : sources * )
{
local targets-to-test = $(run-target:S=$(SUF$(type-to-test))) ;
local parent = $(run-target:S=.test) ;
local main-target = $(gTARGET_SUBVARIANT($(parent))) ;
set-target-variables $(targets-to-test) ;
generate-dependencies $(main-target) : $(targets-to-test) ;
if $(sources)
{
$(gGENERATOR_FUNCTION($(type-to-test))) $(targets-to-test) : $(sources) ;
}
# The .test file goes with the other subvariant targets
# normalization is a hack to get the slashes going the right way on Windoze
local LOCATE_TARGET = [ FDirName [ split-path $(LOCATE_TARGET) ] ] ;
MakeLocate $(run-target) : $(LOCATE_TARGET) ;
local executable = [ test-executable($(type-to-test)) $(targets-to-test[1]) ] ;
DEPENDS $(run-target) : $(executable) $(targets-to-test) $(gRUN_TEST_INPUT_FILES) ;
INPUT_FILES on $(run-target) = $(gRUN_TEST_INPUT_FILES) ;
ARGS on $(run-target) = $(gRUN_TEST_ARGS) ;
#
# Prepare path setup
#
local path-sources = $(parent) $(executable) ; # where do we get paths from?
local $(.run-path-shell-vars) ; # declare local path variables
# initialize path variables from the path-sources
for local v in $(.run-path-vars)
{
local shell-var = $(.shell-var($(v))) ;
$(shell-var) = [ unique $($(shell-var)) $(gRUN_$(v)($(path-sources))) ] ;
}
local nt-cygwin ;
if $(NT) && $(gCURRENT_TOOLSET) in $(gcc-compilers)
{
nt-cygwin = true ;
}
# build up a fragment of shell command
local path-setup ;
for local shell-var in $(.run-path-shell-vars)
{
if $($(shell-var))
{
local dirs = $($(shell-var)) ;
local splitpath = $(SPLITPATH) ;
# PATH gets translated automatically; the rest must be
# cygwin-native when running with Cygwin GCC under NT
if $(nt-cygwin) && $(shell-var) != PATH
{
dirs = [ nt-paths-to-cygwin $(dirs) ] ;
splitpath = ":" ;
}
if $(.run-path-shell-var-value($(shell-var)))
{
dirs += $(.env-prefix)$(shell-var)$(.env-suffix) ;
}
path-setup += $(SHELL_SET)$(shell-var)=$(dirs:J=$(splitpath)) ;
path-setup += $(SHELL_EXPORT)$(shell-var) ;
}
}
local newline = "
" ;
PATH_SETUP on $(run-target) = $(path-setup:J=$(newline))$(newline) ;
capture-run-output $(run-target) : $(executable) ;
}
# The rule is just used for argument checking
rule capture-run-output ( target : executable + )
{
gTEST_OUTPUT_FILE($(target)) = $(target:S=.output) ;
INCLUDES $(target) : $(target:S=.output) ;
MakeLocate $(test-file:S=.output) : $(LOCATE_TARGET) ;
Clean clean : $(test-file:S=.output) ;
output-file on $(target) = $(target:S=.output) ;
execute-test $(target) : $(executable) ;
if --run-all-tests in $(ARGV)
{
ALWAYS $(target) ;
}
}
if $(NT)
{
CATENATE = type ;
}
else
{
CATENATE = cat ;
}
RUN_OUTPUT_HEADER = "echo ====== BEGIN OUTPUT ====== &&" ;
RUN_OUTPUT_FOOTER = " && echo ====== END OUTPUT ======" ;
if --verbose-test in $(ARGV)
{
VERBOSE_CAT = "&& "$(RUN_OUTPUT_HEADER)" "$(CATENATE)" " ;
}
actions execute-test bind INPUT_FILES output-file
{
$(PATH_SETUP:E=)$(>) $(ARGS) "$(INPUT_FILES)" > $(output-file) 2>&1 && $(CP) $(output-file) $(<) $(VERBOSE_CAT)$(<)$(RUN_OUTPUT_FOOTER) || ( $(RUN_OUTPUT_HEADER) $(CATENATE) $(output-file) $(RUN_OUTPUT_FOOTER) && exit 1 )
}
declare-build-fail-test RUN_FAIL : TEST_EXE ;
declare-build-succeed-test RUN : TEST_EXE ;
rule run ( sources + : args * : input-files * : requirements * : name ? : default-build * )
{
local gRUN_TEST_ARGS = $(args) ;
local gRUN_TEST_INPUT_FILES = $(input-files) ;
SEARCH on $(input-files) = $(SEARCH_SOURCE) ;
return [ boost-test $(sources) : RUN : $(requirements) : $(name) : $(default-build) ] ;
}
rule run-fail ( sources + : args * : input-files * : requirements * : name ? )
{
local gRUN_TEST_ARGS = $(2) ;
local gRUN_TEST_INPUT_FILES = $(3) ;
SEARCH on $(3) = $(SEARCH_SOURCE) ;
return [ boost-test $(<) : RUN_FAIL : $(4) : $(name) ] ;
}
### Rules for testing whether a program links
declare-build-fail-test LINK_FAIL : EXE ;
rule link-fail ( sources + : requirements * : name ? )
{
return [ boost-test $(<) : LINK_FAIL : $(2) : $(name) ] ;
}
declare-build-succeed-test LINK : EXE ;
rule link ( sources + : requirements * : name ? )
{
return [ boost-test $(<) : LINK : $(2) : $(name) ] ;
}
### Rules for grouping tests into suites:
rule test-suite # pseudotarget-name : test-targets...
{
NOTFILE $(<) ;
type-DEPENDS $(<) : $(>) ;
}
} # include guard