mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 13:22:11 +00:00
* 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]
433 lines
13 KiB
Plaintext
Executable File
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
|
|
|