2006-06-17 18:23:38 +00:00
|
|
|
#==============================================================================
|
|
|
|
# Jam rules for unit testing with CppTest (http://cpptest.sourceforge.net/)
|
|
|
|
# Copyright (C) 2005 by Eric Sunshine <sunshine@sunshineco.com>
|
|
|
|
#
|
|
|
|
# This library is free software; you can redistribute it and/or modify it
|
|
|
|
# under the terms of the GNU Library General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or (at your
|
|
|
|
# option) any later version.
|
|
|
|
#
|
|
|
|
# This library is distributed in the hope that it will be useful, but
|
|
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
|
|
|
# License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Library General Public License
|
|
|
|
# along with this library; if not, write to the Free Software Foundation,
|
|
|
|
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
#
|
|
|
|
#==============================================================================
|
|
|
|
if $(CPPUNIT.AVAILABLE) = yes
|
|
|
|
{
|
|
|
|
|
|
|
|
UNITTEST_VERBOSE ?= yes ;
|
|
|
|
UNITTEST_RUNFLAGS ?= ;
|
|
|
|
if $(UNITTEST_VERBOSE) = yes
|
|
|
|
{
|
|
|
|
UNITTEST_RUNFLAGS += "--verbose" ;
|
|
|
|
}
|
|
|
|
|
|
|
|
## UnitTest module [ : testdirs [ : extensions ] ]
|
|
|
|
##
|
|
|
|
## This rule provides a dynamic unit testing framework which utilizes CppUnit
|
|
|
|
## (http://cpptest.sourceforge.net/). The invocation:
|
|
|
|
##
|
|
|
|
## UnitTest <module> ;
|
|
|
|
##
|
|
|
|
## sets up unit testing support for `module' if $(SUBDIR)/t/ exists for
|
|
|
|
## `module' and contains test fragment files (*.t) and/or header (*.h) files.
|
|
|
|
## If `testdirs' is provided, then it is a list of directory to scan for test
|
|
|
|
## fragments instead of `t/'. If `extensions' is provided, then it is a list of
|
|
|
|
## file extensions for which to search instead of `.t'.
|
|
|
|
##
|
|
|
|
## It is safe to invoke this rule for modules which do not have a `t/'
|
|
|
|
## subdirectory, in which case the rule invocation is silently ignored. The
|
|
|
|
## UnitTest rule automatically synthesizes an appropriate driver program which
|
|
|
|
## incorporates the test fragment files (*.t), thus eliminating a boring and
|
|
|
|
## error-prone task.
|
|
|
|
##
|
|
|
|
## The Application, Library, and Plugin rules automatically invoke UnitTest on
|
|
|
|
## behalf of the client (unless given the `notest' option), so the vast
|
|
|
|
## majority of modules in a project inherit unit testing support automatically
|
|
|
|
## and for free. Simply populating a `t/' subdirectory with unit testing
|
|
|
|
## fragment files (*.t) is typically all that is needed to enable unit testing
|
|
|
|
## for an application, library, or plugin.
|
|
|
|
##
|
|
|
|
## The unit testing Jam target for `module' is named "check_module". In
|
|
|
|
## addition to this module-level granularity, the UnitTest rule also provides
|
|
|
|
## dynamic directory-based granularity. For example, presume that the following
|
|
|
|
## abbreviated list of directories exist in a project tree:
|
|
|
|
##
|
|
|
|
## apps/example
|
|
|
|
## libs/common
|
|
|
|
## plugins/bindings/perl_b
|
|
|
|
## plugins/bindings/python_b
|
|
|
|
## plugins/bindings/ruby_b
|
|
|
|
##
|
|
|
|
## The following module-based unit testing Jam targets will be created
|
|
|
|
## (assuming that the appropriate test fragment files, $(SUBDIR)/t/*.t, exist
|
|
|
|
## in each directory):
|
|
|
|
##
|
|
|
|
## check_example
|
|
|
|
## check_common
|
|
|
|
## check_perl_b
|
|
|
|
## check_python_b
|
|
|
|
## check_ruby_b
|
|
|
|
##
|
|
|
|
## Furthermore, the following directory-based targets also will be created
|
|
|
|
## dynamically:
|
|
|
|
##
|
|
|
|
## check (and its alias check_all)
|
|
|
|
## check_apps
|
|
|
|
## check_apps_example
|
|
|
|
## check_libs
|
|
|
|
## check_libs_common
|
|
|
|
## check_plugins
|
|
|
|
## check_plugins_bindings
|
|
|
|
## check_plugins_bindings_perl_b
|
|
|
|
## check_plugins_bindings_python_b
|
|
|
|
## check_plugins_bindings_ruby_b
|
|
|
|
##
|
|
|
|
## The very neat thing about the directory-based targets is that they
|
|
|
|
## automatically synthesize a driver program which incorporates all of the
|
|
|
|
## tests contained in child directories. For instance, the `check_plugins'
|
|
|
|
## target creates a unit testing driver which incorporates the tests from the
|
|
|
|
## bindings/perl_b/t, bindings/python_b/t, and bindings/ruby_b/t directories;
|
|
|
|
## and the `check_all' target creates a driver which incorporates all tests in
|
|
|
|
## the entire project. This allows entire selected branches of tests to be run
|
|
|
|
## all at once rather than having to run several different driver programs to
|
|
|
|
## get a complete report.
|
|
|
|
##
|
|
|
|
## The unit testing framework automatically wraps each test fragment file (*.t)
|
|
|
|
## into a synthesized C++ source file containing CppUnit boilerplate, such as
|
|
|
|
## necessary #include directives, #defines, etc. This allows the fragment
|
|
|
|
## files to be as simple as possible. They need #include only headers related
|
|
|
|
## to the actual module being tested, but need not worry about setting up the
|
|
|
|
## CppUnit environment since that is done automatically. A typical fragment
|
|
|
|
## file might look like this:
|
|
|
|
##
|
|
|
|
## /* Test file: libs/common/t/array.t */
|
|
|
|
##
|
|
|
|
## #include "common/myarray.h"
|
|
|
|
##
|
|
|
|
## class MyArrayTest : public CppUnit::TestFixture
|
|
|
|
## {
|
|
|
|
## public:
|
|
|
|
## void setUp() { ...set up test data... }
|
|
|
|
## void tearDown() { ...destroy test data... }
|
|
|
|
##
|
|
|
|
## void testInsert() { ...test array insertion methods... }
|
|
|
|
## void testDelete() { ...test array deletion methods... }
|
|
|
|
##
|
|
|
|
## CPPUNIT_TEST_SUITE(MyArrayTest);
|
|
|
|
## CPPUNIT_TEST(testInsert);
|
|
|
|
## CPPUNIT_TEST(testDelete);
|
|
|
|
## CPPUNIT_TEST_SUITE_END();
|
|
|
|
## };
|
|
|
|
##
|
|
|
|
## When the UnitTest rule synthesizes C++ wrappers for the test fragments, it
|
|
|
|
## needs to figure out the names of classes which contain tests. The synthesis
|
|
|
|
## process makes this determination by examining *.t and *.h files for
|
|
|
|
## subclasses of CppUnit::TestFixture. For this to work correctly, the
|
|
|
|
## "class Foo : public CppUnit::TestFixture" declaration must not be split over
|
|
|
|
## multiple lines.
|
|
|
|
##
|
|
|
|
## It is possible to have extra text added at the beginning and end of the
|
|
|
|
## synthesized C++ source code for both the *.t wrappers and the driver
|
|
|
|
## programs by optionally defining the following Jam variables (perhaps in
|
|
|
|
## Jamrules) with whatever text you would like inserted into the synthesized
|
|
|
|
## files:
|
|
|
|
##
|
|
|
|
## UNITTEST_BOILERPLATE_TEST_PRE
|
|
|
|
## UNITTEST_BOILERPLATE_TEST_POST
|
|
|
|
## UNITTEST_BOILERPLATE_MAIN_PRE
|
|
|
|
## UNITTEST_BOILERPLATE_MAIN_POST
|
|
|
|
##
|
|
|
|
## Thest `TEST' variables apply to the *.t wrappers, and the `MAIN' variables
|
|
|
|
## apply to the driver programs into which the wrappers are linked. If you find
|
|
|
|
## that you are including common code in all of your *.t files, then you may
|
|
|
|
## want to simplify by propagating the common code to the `TEST' boilerplate
|
|
|
|
## instead.
|
|
|
|
##
|
|
|
|
rule UnitTest
|
|
|
|
{
|
|
|
|
local mod = $(1) ;
|
|
|
|
local testdirs = $(2) ;
|
|
|
|
local exts = $(3) ;
|
|
|
|
if ! $(testdirs) { testdirs = t ; }
|
|
|
|
if ! $(exts) { exts = .t ; }
|
|
|
|
|
|
|
|
local test_clean = [ UnitTestNameClean $(mod) ] ;
|
|
|
|
local oldsubdir = $(SUBDIR_TOKENS) ;
|
|
|
|
|
|
|
|
local testdir ;
|
|
|
|
for testdir in $(testdirs)
|
|
|
|
{
|
|
|
|
SubDir TOP $(oldsubdir) $(testdir) ;
|
|
|
|
|
|
|
|
local tests_obj ;
|
|
|
|
local tests = [ Recurse : $(exts) ] ;
|
|
|
|
local headers = [ Recurse : .h .hpp .hxx .H ] ;
|
|
|
|
if $(tests) || $(headers)
|
|
|
|
{
|
|
|
|
tests = [ DoSourceGrist $(tests) ] ;
|
|
|
|
SEARCH on $(tests) = $(SEARCH_SOURCE) ;
|
|
|
|
|
|
|
|
local tests_src = $(tests:S=.cpp) ;
|
|
|
|
MakeLocate $(tests_src) : $(LOCATE_TARGET) ;
|
|
|
|
Clean $(test_clean) : $(tests_src) ;
|
|
|
|
|
|
|
|
# For each fragment (*.t), create a C++ wrapper. Automatically register
|
|
|
|
# subclasses of CppUnit::TestFixture.
|
|
|
|
local i ;
|
|
|
|
for i in $(tests)
|
|
|
|
{
|
|
|
|
Includes $(i:S=.cpp) : $(i) ;
|
|
|
|
UnitTestSource $(i:S=.cpp) : $(i) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Also search for CppUnit::TestFixture subclasses in headers (*.h) and
|
|
|
|
# synthesize a C++ wrapper which registers them.
|
|
|
|
if $(headers)
|
|
|
|
{
|
|
|
|
headers = [ DoSourceGrist $(headers) ] ;
|
|
|
|
SEARCH on $(headers) = $(SEARCH_SOURCE) ;
|
|
|
|
local suitereg = [ DoSourceGrist __suitereg.cpp ] ;
|
|
|
|
MakeLocate $(suitereg) : $(LOCATE_TARGET) ;
|
|
|
|
UnitTestSource $(suitereg) : $(headers) ;
|
|
|
|
Includes $(suitereg) : $(headers) ;
|
|
|
|
tests_src += $(suitereg) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Compile all synthesized sources.
|
|
|
|
tests_obj = [ CompileObjects $(tests_src) ] ;
|
|
|
|
CCHDRS on $(tests_obj) += [ FIncludes $(SEARCH_SOURCE) ] ;
|
|
|
|
C++FLAGS on $(tests_obj) += $(COMPILER.C++FLAGS.EXCEPTIONS.ENABLE)
|
|
|
|
$(CPPUNIT.CFLAGS) ;
|
|
|
|
Clean $(test_clean) : $(tests_obj) ;
|
|
|
|
|
|
|
|
# Create the driver for "check_module".
|
|
|
|
UnitTestDriver $(mod) : $(tests_obj) ;
|
|
|
|
# Dynamically create the drivers for all parent directories.
|
|
|
|
UnitTestDynamicTargets $(mod) : $(tests_obj) : $(oldsubdir) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SubDir TOP $(oldsubdir) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
# PRIVATE UTILITY RULES
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
# UnitTestDriver module : objs [ : owner ]
|
|
|
|
# Given a set of object files which represent test fragment wrappers for
|
|
|
|
# `module', set up the driver program which incorporates them, and create the
|
|
|
|
# "check_module" and "check_moduleclean" targets. For invocations which arise
|
|
|
|
# from the UnitTest rule, `module' will be the actual module for which
|
|
|
|
# testing is being arranged, and `objs' will be the complete set of test
|
|
|
|
# objects for `module'. For directory-based testing drivers, `module' will be
|
|
|
|
# the dynamically synthesized module name representing the directory for
|
|
|
|
# which testing is being arranged, and `objs' will be only a subset of all
|
|
|
|
# objects which ultimately will be incorporated into this synthesized driver
|
|
|
|
# (specifically, the subset will be the objects belonging to `owner'). This
|
|
|
|
# rule may be invoked multiple times for the same synthesized directory-based
|
|
|
|
# driver `module' in order to accumulate the object files from all child
|
|
|
|
# directories (recursively).
|
|
|
|
#
|
|
|
|
# Since the driver programs in parent directories are actually conglomerates
|
|
|
|
# of the objects from many different modules, this rule is invoked multiple
|
|
|
|
# times for any given directory-based driver program. Each invocations
|
|
|
|
# presents it with a different set of object files. Therefore, it must take
|
|
|
|
# special care. In particular, the first time this rule is invoked for a
|
|
|
|
# synthesized driver in a particular directory, it actually creates the
|
|
|
|
# application target; on subsequent invocations for the same directory, it
|
|
|
|
# merely adds `objs' to the already-created application target. This way,
|
|
|
|
# the a directory's dynamically synthesized driver program can incorporate
|
|
|
|
# objects from all of its child directories (recursively).
|
|
|
|
#
|
|
|
|
# The `owner' is the module which owns the object files, `objs'. In the
|
|
|
|
# example illustrated for the UnitTest rule, when the "check_libs" driver
|
|
|
|
# program is under creation from within the `UnitTest common' invocation, the
|
|
|
|
# owner will be "common". This information is needed in order to ensure that
|
|
|
|
# the driver program synthesized at the "libs" level, which incorporates
|
|
|
|
# "common"'s object files, can gain access to "common's" linker flags (since
|
|
|
|
# they will be needed for linking the directory-based driver). If `owner' is
|
|
|
|
# not provided, then it defaults to `module'.
|
|
|
|
rule UnitTestDriver
|
|
|
|
{
|
|
|
|
local mod = $(1) ;
|
|
|
|
local objs = $(2) ;
|
|
|
|
local owner = $(3) ;
|
|
|
|
if ! $(owner) { owner = $(mod) ; }
|
|
|
|
|
|
|
|
local test_name = [ UnitTestNameTest $(mod) ] ;
|
|
|
|
local test_clean = [ UnitTestNameClean $(mod) ] ;
|
|
|
|
|
|
|
|
# This is the low-level target name by which a unit testing driver program is
|
|
|
|
# known. We only create the target the first time we are called at a
|
|
|
|
# particular directory level (thus the module_UNITTESTS check). Upon
|
|
|
|
# subsequent invocations, we merely add the new objects files to the existing
|
|
|
|
# driver.
|
|
|
|
|
|
|
|
local test_driver = $(mod)_unittest ;
|
|
|
|
if ! $($(mod)_UNITTESTS)
|
|
|
|
{
|
|
|
|
$(mod)_UNITTESTS = $(test_driver) ;
|
|
|
|
|
|
|
|
# Create the actual driver program represented by the `test_driver' target.
|
|
|
|
local test_driver_target =
|
|
|
|
[ DoObjectGrist [ ConstructApplicationTarget __unittest : console ] ] ;
|
|
|
|
MakeLocate $(test_driver_target) : $(LOCATE_TARGET) ;
|
|
|
|
$(test_driver)_TYPE = application ;
|
|
|
|
$(test_driver)_TARGET = $(test_driver_target) ;
|
|
|
|
$(test_driver)_OBJECTS = $(objs) ;
|
|
|
|
SystemLinkApplication $(test_driver) : $(objs) [ UnitTestCommonObj ] :
|
|
|
|
console ;
|
|
|
|
CFlags $(test_driver) : $(APPLICATION.CFLAGS) ;
|
|
|
|
LFlags $(test_driver) : $(LINKLIBS) $(APPLICATION.LFLAGS)
|
|
|
|
$(CPPUNIT.LFLAGS) ;
|
|
|
|
|
|
|
|
Depends $(test_name) : $(test_driver_target) ;
|
|
|
|
Clean $(test_clean) : $(test_driver_target) ;
|
|
|
|
|
|
|
|
# Actually run the unit tests.
|
|
|
|
NotFile $(test_name) $(test_clean) ;
|
|
|
|
Always $(test_name) $(test_clean) ;
|
|
|
|
Depends checkclean : $(test_clean) ;
|
|
|
|
UnitTestRun $(test_name) : $(test_driver_target) ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ExtraObjects $(test_driver) : $(objs) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Apply appropriate linker flags to the driver program. This has two parts:
|
|
|
|
# (1) If these are the unit tests for a library, then, as a convenience,
|
|
|
|
# assume that the tests need to link against that library.
|
|
|
|
# (2) For directory-based test targets, the driver needs all of the linker
|
|
|
|
# flags required by its child directories (recursively). For example, in
|
|
|
|
# the earlier cited illustration, the "check_all", and "check_libs"
|
|
|
|
# targets will also need whatever linker flags libs/common itself
|
|
|
|
# requires.
|
|
|
|
|
|
|
|
if $($(owner)_TYPE) = library { LinkWith $(test_driver) : $(owner) ; }
|
|
|
|
LinkWith $(test_driver) : [ on $($(owner)_TARGET) GetVar NEEDLIBS ] ;
|
|
|
|
|
|
|
|
return $(test_driver) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
# UnitTestCommonObj
|
|
|
|
# Create object files common to all driver programs. Presently, the only
|
|
|
|
# common component is the main() function, which utilizes CppUnit's automatic
|
|
|
|
# test discovery protocol to discover test classes. (These are the subclasses
|
|
|
|
# of CppUnit::TestFixture for which we scan and pass to the
|
|
|
|
# CPPUNIT_TEST_SUITE_REGISTRATION() macro.)
|
|
|
|
rule UnitTestCommonObj
|
|
|
|
{
|
|
|
|
if ! $(UNITTEST_COMMON_OBJ)
|
|
|
|
{
|
|
|
|
local test_main_dir = [ ConcatDirs $(LOCATE.OBJECTS) __unittest_common ] ;
|
|
|
|
local test_main_src = main.cpp ;
|
|
|
|
test_main_src = $(test_main_src:G=__unittest) ;
|
|
|
|
MakeLocate $(test_main_src) : $(test_main_dir) ;
|
|
|
|
UnitTestMain $(test_main_src) ;
|
|
|
|
Clean checkclean : $(test_main_src) ;
|
|
|
|
|
|
|
|
local test_main_obj = [ CompileObjects $(test_main_src) ] ;
|
|
|
|
MakeLocate $(test_main_obj) : $(test_main_dir) ;
|
|
|
|
C++FLAGS on $(test_main_obj) += $(COMPILER.C++FLAGS.EXCEPTIONS.ENABLE)
|
|
|
|
$(CPPUNIT.CFLAGS) ;
|
|
|
|
Clean checkclean : $(test_main_obj) ;
|
|
|
|
|
|
|
|
UNITTEST_COMMON_OBJ = $(test_main_obj) ;
|
|
|
|
}
|
|
|
|
return $(UNITTEST_COMMON_OBJ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
# UnitTestDynamicTargets module : objs : subdir_tokens
|
|
|
|
# Given a set of subdirectory tokens representing the location of `module' in
|
|
|
|
# the source tree, dynamically synthesize a test driver program in each
|
|
|
|
# parent directory leading up to module's location. Each synthesized test
|
|
|
|
# program will incorporate module's `objs', as well as the objects of all
|
|
|
|
# other children (recursively) of the directory containing each driver. (The
|
|
|
|
# additional objects will be incorporated by subsequent invocations for the
|
|
|
|
# same directories.)
|
|
|
|
rule UnitTestDynamicTargets
|
|
|
|
{
|
|
|
|
local mod = $(1) ;
|
|
|
|
local objs = $(2) ;
|
|
|
|
local subdir_tokens = $(3) ;
|
|
|
|
|
|
|
|
# There is no need to synthesize a driver for the directory in which `module'
|
|
|
|
# itself resides, since we already have a "check_module" target for that.
|
|
|
|
# Therefore, simply alias this directory entry to the existing "check_module"
|
|
|
|
# target.
|
|
|
|
|
|
|
|
local deepest_name = [ UnitTestNameTest $(subdir_tokens:J=_) ] ;
|
|
|
|
local deepest_clean = [ UnitTestNameClean $(subdir_tokens:J=_) ] ;
|
|
|
|
NotFile $(deepest_name) $(deepest_clean) ;
|
|
|
|
Depends $(deepest_name) : [ UnitTestNameTest $(mod) ] ;
|
|
|
|
Depends $(deepest_clean) : [ UnitTestNameClean $(mod) ] ;
|
|
|
|
|
|
|
|
# For each parent directory of `module', synthesize a driver target.
|
|
|
|
local tokens = [ FReverse $(subdir_tokens) ] ;
|
|
|
|
tokens = $(tokens[2-]) ;
|
|
|
|
while $(tokens)
|
|
|
|
{
|
|
|
|
UnitTestDynamicTarget $(mod) : $(objs) : [ FReverse $(tokens) ] ;
|
|
|
|
tokens = $(tokens[2-]) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Synthesize a "check_all" target which incorporates all tests projectwide.
|
|
|
|
UnitTestDynamicTarget $(mod) : $(objs) : : all ;
|
|
|
|
}
|
|
|
|
|
|
|
|
# UnitTestDynamicTarget module : objs : dir_tokens [ : dyn_module ]
|
|
|
|
# The workhorse for UnitTestDynamicTargets which actually changes to the
|
|
|
|
# specified directory and creates the driver program. The "check_foo" target
|
|
|
|
# name is normally composed of the directory tokens joined with underscores
|
|
|
|
# (i.e. "check_dir_tokens") unless the optional `dyn_module' is provided, in
|
|
|
|
# which case the target name becomes "check_dyn_module".
|
|
|
|
rule UnitTestDynamicTarget
|
|
|
|
{
|
|
|
|
local mod = $(1) ;
|
|
|
|
local objs = $(2) ;
|
|
|
|
local dir_tokens = $(3) ;
|
|
|
|
local dyn_mod = $(4) ;
|
|
|
|
if ! $(dyn_mod) { dyn_mod = $(dir_tokens:J=_) ; }
|
|
|
|
|
|
|
|
local olddir = $(SUBDIR_TOKENS) ;
|
|
|
|
SubDir TOP $(dir_tokens) ;
|
|
|
|
|
|
|
|
local test_driver = [ UnitTestDriver $(dyn_mod) : $(objs) : $(mod) ] ;
|
|
|
|
|
|
|
|
# Use module_UNITTESTS to remember that this dynamically synthesized driver
|
|
|
|
# has a relation to `module'. This information is needed later when clients
|
|
|
|
# invoke CFlags, LFlags, and LibDepends for `module'. Not only must those
|
|
|
|
# settings be applied to `module', but we must also apply them to module's
|
|
|
|
# test driver, as well as all of the directory-based drivers which
|
|
|
|
# incorporate module's test objects. This is what the UnitTestCFlags,
|
|
|
|
# UnitTestLFlags, and UnitTestLibDepends rules do.
|
|
|
|
|
|
|
|
$(mod)_UNITTESTS += $(test_driver) ;
|
|
|
|
|
|
|
|
SubDir TOP $(olddir) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
# UnitTestNameTest module
|
|
|
|
# Return the name of the "check_module" target for `module'.
|
|
|
|
rule UnitTestNameTest
|
|
|
|
{ return check_$(<) ; }
|
|
|
|
|
|
|
|
# UnitTestNameClean module
|
|
|
|
# Return the name of the "check_moduleclean" target for `module'.
|
|
|
|
rule UnitTestNameClean
|
|
|
|
{ local n = [ UnitTestNameTest $(<) ] ; return $(n)clean ; }
|
|
|
|
|
|
|
|
# UnitTestCFlags module : flags [ : options ]
|
|
|
|
# Hook invoked automatically by CFlags. Applies `flags' also to module's test
|
|
|
|
# driver.
|
|
|
|
rule UnitTestCFlags
|
|
|
|
{
|
|
|
|
# Empty for now. Presumably the compiler flags are needed only by the actual
|
|
|
|
# sources of `module'; not by its tests which merely link against module's
|
|
|
|
# objects. This assumption may be wrong, and may change in the future.
|
|
|
|
}
|
|
|
|
|
|
|
|
# UnitTestLFlags module : flags [ : options ]
|
|
|
|
# Hook invoked automatically by LFlags. Applies `flags' also to module's test
|
|
|
|
# driver and to all directory-based drivers which incorporate module's test
|
|
|
|
# objects.
|
|
|
|
rule UnitTestLFlags
|
|
|
|
{
|
|
|
|
local mod = $(1) ;
|
|
|
|
local flags = $(2) ;
|
|
|
|
local options = $(3) ;
|
|
|
|
local unittests = $($(mod)_UNITTESTS) ;
|
|
|
|
local u ;
|
|
|
|
for u in $(unittests)
|
|
|
|
{
|
|
|
|
LFlags $(u) : $(flags) : $(options) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# UnitTestLibDepends module : deps
|
|
|
|
# Hook invoked automatically by LibDepends. Applies `deps' also to module's
|
|
|
|
# test driver and to all directory-based drivers which incorporate module's
|
|
|
|
# test objects.
|
|
|
|
rule UnitTestLibDepends
|
|
|
|
{
|
|
|
|
local mod = $(1) ;
|
|
|
|
local libs = $(2) ;
|
|
|
|
local unittests = $($(mod)_UNITTESTS) ;
|
|
|
|
local u ;
|
|
|
|
for u in $(unittests)
|
|
|
|
{
|
|
|
|
LinkWith $(u) : $(libs) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# UnitTestSource wrapper : files
|
|
|
|
# Create a `wrapper' which #includes all `files' (which are probably *.t test
|
|
|
|
# fragments or headers). Also scan `files' for subclasses of
|
|
|
|
# CppUnit::TestFixture and invoke CPPUNIT_TEST_SUITE_REGISTRATION() for each
|
|
|
|
# discovery.
|
|
|
|
actions UnitTestSource
|
|
|
|
{
|
|
|
|
cat <<EOF > $(<)
|
|
|
|
// Automatically generated; do not edit.
|
|
|
|
#include <string>
|
|
|
|
#include <cppunit/TestCaller.h>
|
|
|
|
#include <cppunit/TestFixture.h>
|
|
|
|
#include <cppunit/TestSuite.h>
|
|
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
$(UNITTEST_BOILERPLATE_TEST_PRE)
|
|
|
|
EOF
|
|
|
|
for i in $(>:BS); do
|
|
|
|
echo '#include "'$i'"' >> $(<)
|
|
|
|
done
|
|
|
|
for i in $(>); do
|
|
|
|
classes=`sed '/public[ ][ ]*CppUnit::TestFixture/!d;\
|
|
|
|
s/class[ ][ ]*\([^ ][^ ]*\)[ ]*:.*/\1/' < $i`
|
|
|
|
for c in $classes; do
|
|
|
|
echo "CPPUNIT_TEST_SUITE_REGISTRATION($c);" >> $(<)
|
|
|
|
done
|
|
|
|
done
|
|
|
|
cat <<EOF >> $(<)
|
|
|
|
$(UNITTEST_BOILERPLATE_TEST_POST)
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
# UnitTestMain file
|
|
|
|
# Create a generic main() which is used for all test driver programs. It
|
|
|
|
# uses CppUnit's automated test class discovery protocol to discover classes
|
|
|
|
# containing tests, therefore it is entirely generic and can be used by any
|
|
|
|
# number of driver programs.
|
|
|
|
actions UnitTestMain
|
|
|
|
{
|
|
|
|
cat <<EOF > $(<)
|
|
|
|
// Automatically generated; do not edit.
|
|
|
|
#include <string>
|
|
|
|
#include <cppunit/BriefTestProgressListener.h>
|
|
|
|
#include <cppunit/TestResult.h>
|
|
|
|
#include <cppunit/extensions/TestFactoryRegistry.h>
|
|
|
|
#include <cppunit/ui/text/TestRunner.h>
|
|
|
|
$(UNITTEST_BOILERPLATE_MAIN_PRE)
|
|
|
|
int main(int argc, char** argv)
|
|
|
|
{
|
|
|
|
bool verbose = false;
|
|
|
|
for (int i = 1; i < argc; i++)
|
|
|
|
{
|
|
|
|
char const* s = argv[i];
|
|
|
|
if (*s == '-')
|
|
|
|
{
|
|
|
|
do { s++; } while (*s == '-');
|
|
|
|
verbose = (*s == 'v' || *s == 'V');
|
|
|
|
if (verbose)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CppUnit::TextUi::TestRunner runner;
|
|
|
|
CppUnit::TestFactoryRegistry& registry =
|
|
|
|
CppUnit::TestFactoryRegistry::getRegistry();
|
|
|
|
CppUnit::BriefTestProgressListener listener;
|
|
|
|
if (verbose)
|
|
|
|
runner.eventManager().addListener(&listener);
|
|
|
|
runner.addTest(registry.makeTest());
|
|
|
|
return runner.run("", false, true, !verbose) ? 0 : -1;
|
|
|
|
}
|
|
|
|
$(UNITTEST_BOILERPLATE_MAIN_POST)
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
# UnitTestRun check_target : program
|
|
|
|
# Actually run the unit test driver `program' for the invocation target
|
|
|
|
# `check_target'.
|
|
|
|
actions UnitTestRun
|
|
|
|
{
|
|
|
|
$(>) $(UNITTEST_RUNFLAGS)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else # !CPPUNIT.AVAILABLE
|
|
|
|
{
|
|
|
|
|
|
|
|
rule UnitTest { }
|
|
|
|
rule UnitTestCFlags { }
|
|
|
|
rule UnitTestLFlags { }
|
|
|
|
rule UnitTestLibDepends { }
|
|
|
|
|
|
|
|
actions UnitTestDisabled
|
|
|
|
{
|
|
|
|
echo "$(<): Unit testing disabled (CppUnit not installed)."
|
|
|
|
}
|
|
|
|
|
|
|
|
Always check_all ;
|
|
|
|
Depends check : check_all ;
|
|
|
|
UnitTestDisabled check_all ;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
NotFile check checkclean check_all check_allclean ;
|
|
|
|
Depends check : check_all ;
|
|
|
|
Depends clean : checkclean ;
|
|
|
|
Help check : "Run unit tests" ;
|