Backport lots of new features from the 1.41.0 branch.
[boost:cmake.git] / tools / build / CMake / BoostTesting.cmake
1 ##########################################################################
2 # Regression Testing Support for Boost                                   #
3 ##########################################################################
4 # Copyright (C) 2007-8 Douglas Gregor <doug.gregor@gmail.com>            #
5 # Copyright (C) 2007-8 Troy D. Straszheim                                #
6 #                                                                        #
7 # Distributed under the Boost Software License, Version 1.0.             #
8 # See accompanying file LICENSE_1_0.txt or copy at                       #
9 #   http://www.boost.org/LICENSE_1_0.txt                                 #
10 ##########################################################################
11 # This file provides a set of CMake macros that support regression
12 # testing for Boost libraries. For each of the test macros below, the
13 # first argument, testname, states the name of the test that will be
14 # created. If no other arguments are provided, the source file
15 # testname.cpp will be used as the source file; otherwise, source
16 # files should be listed immediately after the name of the test.
17 #
18 # The macros for creating regression tests are:
19 #   boost_test_run: Builds an executable and runs it as a test. The test
20 #                   succeeds if it builds and returns 0 when executed.
21 #
22 #   boost_test_run_fail: Builds an executable and runs it as a test. The
23 #                        test succeeds if it builds but returns a non-zero
24 #                        exit code when executed.
25 #  
26 #   boost_test_compile: Tests that the given source file compiles without 
27 #                       any errors.
28 #
29 #   boost_test_compile_fail: Tests that the given source file produces 
30 #                            errors when compiled.
31 #
32 #   boost_additional_test_dependencies: Adds needed include directories for
33 #                                       the tests.
34
35 # User-controlled option that can be used to enable/disable regression
36 # testing. By default, we disable testing, because most users won't
37 # want or need to perform regression testing on Boost. The Boost build
38 # is significantly faster when we aren't also building regression
39 # tests.
40
41 if (BOOST_CMAKE_SELFTEST)
42   set(tests "ALL")
43 else()
44   set(tests "NONE")
45 endif()
46
47 set(BUILD_TESTS ${tests} CACHE STRING "Semicolon-separated list of lowercase librarary names to test, or \"ALL\"")
48 enable_testing()
49
50 if (BUILD_TESTS STREQUAL "NONE")
51   #
52   # Add a little "message" if tests are run while BUILD_TESTS is NONE
53   #
54   add_test(BUILD_TESTS_is_NONE_nothing_to_test
55     /bin/false)
56 endif()
57  
58 set(DART_TESTING_TIMEOUT 15 
59   CACHE INTEGER 
60   "Timeout after this many seconds of madness")
61
62 #-------------------------------------------------------------------------------
63 # This macro adds additional include directories based on the dependencies of 
64 # the library being tested 'libname' and all of its dependencies.
65 #
66 #   boost_additional_test_dependencies(libname 
67 #                         BOOST_DEPENDS libdepend1 libdepend2 ...)
68 #
69 #   libname is the name of the boost library being tested. (signals)
70 #
71 # There is mandatory argument to the macro: 
72 #
73 #   BOOST_DEPENDS: The list of the extra boost libraries that the test suite will
74 #    depend on. You do NOT have to list those libraries already listed by the 
75 #    module.cmake file as these will be used.
76 #
77 #
78 # example usage:
79 #  boost_additional_test_dependencies(signals BOOST_DEPENDS test optional)
80 #
81 macro(boost_additional_test_dependencies libname)
82   parse_arguments(BOOST_TEST 
83     "BOOST_DEPENDS"
84     ""
85     ${ARGN}
86   )
87   # Get the list of libraries that this test depends on
88   # Set THIS_PROJECT_DEPENDS_ALL to the set of all of its
89   # dependencies, its dependencies' dependencies, etc., transitively.
90   string(TOUPPER "BOOST_${libname}_DEPENDS" THIS_PROJECT_DEPENDS)
91   set(THIS_TEST_DEPENDS_ALL ${libname} ${${THIS_PROJECT_DEPENDS}} )
92   set(ADDED_DEPS TRUE)
93   while (ADDED_DEPS)
94     set(ADDED_DEPS FALSE)
95     foreach(DEP ${THIS_TEST_DEPENDS_ALL})
96       string(TOUPPER "BOOST_${DEP}_DEPENDS" DEP_DEPENDS)
97       foreach(DEPDEP ${${DEP_DEPENDS}})
98         list(FIND THIS_TEST_DEPENDS_ALL ${DEPDEP} DEPDEP_INDEX)
99         if (DEPDEP_INDEX EQUAL -1)
100           list(APPEND THIS_TEST_DEPENDS_ALL ${DEPDEP})
101           set(ADDED_DEPS TRUE)
102         endif()
103       endforeach()
104     endforeach()
105   endwhile()
106  
107   # Get the list of dependencies for the additional libraries arguments
108   foreach(additional_lib ${BOOST_TEST_BOOST_DEPENDS})
109    list(FIND THIS_TEST_DEPENDS_ALL ${additional_lib} DEPDEP_INDEX)
110    if (DEPDEP_INDEX EQUAL -1)
111      list(APPEND THIS_TEST_DEPENDS_ALL ${additional_lib})
112      set(ADDED_DEPS TRUE)
113    endif()
114     string(TOUPPER "BOOST_${additional_lib}_DEPENDS" THIS_PROJECT_DEPENDS)
115     set(ADDED_DEPS TRUE)
116     while (ADDED_DEPS)
117       set(ADDED_DEPS FALSE)
118       foreach(DEP ${THIS_TEST_DEPENDS_ALL})
119         string(TOUPPER "BOOST_${DEP}_DEPENDS" DEP_DEPENDS)
120         foreach(DEPDEP ${${DEP_DEPENDS}})
121           list(FIND THIS_TEST_DEPENDS_ALL ${DEPDEP} DEPDEP_INDEX)
122           if (DEPDEP_INDEX EQUAL -1)
123             list(APPEND THIS_TEST_DEPENDS_ALL ${DEPDEP})
124             set(ADDED_DEPS TRUE)
125           endif()
126         endforeach()
127       endforeach()
128     endwhile()
129   endforeach()
130   
131   foreach (include ${THIS_TEST_DEPENDS_ALL})
132     #
133     # Modularization temporarily disabled
134     #
135     # include_directories("${Boost_SOURCE_DIR}/libs/${include}/include")
136     #
137   endforeach (include ${includes})
138   
139 endmacro(boost_additional_test_dependencies libname)
140 #-------------------------------------------------------------------------------
141
142 #-------------------------------------------------------------------------------
143 # This macro is an internal utility macro that helps parse the
144 # arguments passed to the Boost testing commands. It will generally
145 # not be used by Boost developers.
146 #
147 #   boost_test_parse_args(testname 
148 #                         [source1 source2 ...]
149 #                         [ARGS arg1 arg2... ]
150 #                         [COMPILE_FLAGS compileflags]
151 #                         [LINK_FLAGS linkflags]
152 #                         [LINK_LIBS linklibs]
153 #                         [DEPENDS libdepend1 libdepend2 ...]
154 #                         [KNOWN_FAILURES string1 string2 ...]
155 #                         [COMPILE] [RUN] [FAIL])
156 #
157 # testname is the name of the test. The remaining arguments passed to
158 # this macro will be parsed and categorized for the developer-level
159 # test macros to use. 
160 #
161 # Variables affected:
162 #
163 #   BOOST_TEST_OKAY: Will be set to TRUE if it is okay to build and
164 #   run this test.
165 #
166 #   BOOST_TEST_SOURCES: Will be populated with the set of source files
167 #   that should be used to compile this test. If the user has provided
168 #   source files, BOOST_TEST_SOURCES will contain those; otherwise,
169 #   BOOST_TEST_SOURCES will only contain "testname.cpp".
170 #
171 #   BOOST_TEST_TESTNAME: A (hopefully) globally unique target name
172 #   for the test, constructed from PROJECT-testname-TAG
173 #
174 #   BOOST_TEST_arg: Will be populated with the arguments provided for
175 #   the arguemnt "arg", where "arg" can be any of the extra arguments
176 #   specified above.
177 #
178 #   
179 macro(boost_test_parse_args testname)
180   #message("boost_test_parse_args ${testname} ${ARGN}")
181   set(BOOST_TEST_OKAY TRUE)
182   set(BOOST_TEST_COMPILE_FLAGS "")
183   parse_arguments(BOOST_TEST 
184     "BOOST_LIB;LINK_LIBS;LINK_FLAGS;DEPENDS;COMPILE_FLAGS;ARGS;EXTRA_OPTIONS;KNOWN_FAILURES"
185     "COMPILE;RUN;LINK;FAIL;RELEASE;DEBUG"
186     ${ARGN}
187     )
188     
189   # Check each of the dependencies to see if we can still build this
190   # test.
191   foreach(ARG ${BOOST_TEST_DEPENDS})
192     get_target_property(DEPEND_TYPE ${ARG} TYPE)
193     get_target_property(DEPEND_LOCATION ${ARG} LOCATION)
194     # If building static libraries is turned off, don't try to build
195     # the test
196     if (NOT ENABLE_STATIC AND ${DEPEND_TYPE} STREQUAL "STATIC_LIBRARY")
197       set(BOOST_TEST_OKAY FALSE)
198     endif (NOT ENABLE_STATIC AND ${DEPEND_TYPE} STREQUAL "STATIC_LIBRARY")
199
200     # If building shared libraries is turned off, don't try to build
201     # the test
202     if (NOT ENABLE_SHARED AND ${DEPEND_TYPE} STREQUAL "SHARED_LIBRARY")
203       set(BOOST_TEST_OKAY FALSE)
204     endif (NOT ENABLE_SHARED AND ${DEPEND_TYPE} STREQUAL "SHARED_LIBRARY")
205   endforeach(ARG ${BOOST_TEST_DEPENDS})
206
207   # Setup the SOURCES variables. If no sources are specified, use the
208   # name of the test.cpp
209   if (BOOST_TEST_DEFAULT_ARGS)
210     set(BOOST_TEST_SOURCES ${BOOST_TEST_DEFAULT_ARGS})
211   else (BOOST_TEST_DEFAULT_ARGS)
212     set(BOOST_TEST_SOURCES "${testname}.cpp")
213   endif (BOOST_TEST_DEFAULT_ARGS)
214
215   set(BOOST_TEST_TESTNAME "${BOOST_PROJECT_NAME}-${testname}")
216   #message("testname: ${BOOST_TEST_TESTNAME}")
217   # If testing is turned off, this test is not okay
218 endmacro(boost_test_parse_args)
219
220 # This macro attaches a the "known-failure" label to the given test
221 # target if the build name matches any of the declared, known
222 # failures.
223 macro(boost_test_known_failures TEST)
224   foreach(PATTERN ${ARGN})
225     if (${BUILDNAME} MATCHES ${PATTERN})
226       set_tests_properties("${BOOST_PROJECT_NAME}-${TEST}"
227         PROPERTIES 
228         LABELS "${BOOST_PROJECT_NAME};known-failure"
229         WILL_FAIL TRUE
230         )
231     endif()
232   endforeach()
233 endmacro(boost_test_known_failures)
234
235
236 # This macro creates a Boost regression test that will be executed. If
237 # the test can be built, executed, and exits with a return code of
238 # zero, it will be considered to have passed.
239 #
240 #   boost_test_run(testname 
241 #                  [source1 source2 ...]
242 #                  [ARGS arg1 arg2... ]
243 #                  [COMPILE_FLAGS compileflags]
244 #                  [LINK_FLAGS linkflags]
245 #                  [LINK_LIBS linklibs]
246 #                  [DEPENDS libdepend1 libdepend2 ...]
247 #                  [EXTRA_OPTIONS option1 option2 ...])
248 #
249 # testname is the name of the test. source1, source2, etc. are the
250 # source files that will be built and linked into the test
251 # executable. If no source files are provided, the file "testname.cpp"
252 # will be used instead.
253 #
254 # There are several optional arguments to control how the regression
255 # test is built and executed:
256 #
257 #   ARGS: Provides additional arguments that will be passed to the
258 #   test executable when it is run.
259 #
260 #   COMPILE_FLAGS: Provides additional compilation flags that will be
261 #   used when building this test. For example, one might want to add
262 #   "-DBOOST_SIGNALS_ASSERT=1" to turn on assertions within the library.
263 #
264 #   LINK_FLAGS: Provides additional flags that will be passed to the
265 #   linker when linking the test excecutable. This option should not
266 #   be used to link in additional libraries; see LINK_LIBS and
267 #   DEPENDS.
268 #
269 #   LINK_LIBS: Provides additional libraries against which the test
270 #   executable will be linked. For example, one might provide "expat"
271 #   as options to LINK_LIBS, to state that this executable should be
272 #   linked against the external "expat" library. Use LINK_LIBS for
273 #   libraries external to Boost; for Boost libraries, use DEPENDS.
274 #
275 #   DEPENDS: States that this test executable depends on and links
276 #   against another Boost library. The argument to DEPENDS should be
277 #   the name of a particular variant of a Boost library, e.g.,
278 #   boost_signals-static.
279 #
280 #   EXTRA_OPTIONS: Provide extra options that will be passed on to 
281 #   boost_add_executable.
282 #
283 # Example:
284 #   boost_test_run(signal_test DEPENDS boost_signals)
285 macro(boost_test_run testname)
286   boost_test_parse_args(${testname} ${ARGN} RUN)
287   #
288   # On windows, tests have to go in the same directory as
289   # DLLs.  
290   # 
291   if (NOT CMAKE_HOST_WIN32)
292     set(OUTPUT_NAME tests/${BOOST_PROJECT_NAME}/${testname})
293   else()
294     set(OUTPUT_NAME ${BOOST_PROJECT_NAME}-${testname})
295   endif()
296   if (BOOST_TEST_OKAY)  
297
298     boost_add_executable(${testname} ${BOOST_TEST_SOURCES}
299       OUTPUT_NAME ${OUTPUT_NAME}
300       DEPENDS "${BOOST_TEST_DEPENDS}"
301       LINK_LIBS ${BOOST_TEST_LINK_LIBS}
302       LINK_FLAGS ${BOOST_TEST_LINK_FLAGS}
303       COMPILE_FLAGS ${BOOST_TEST_COMPILE_FLAGS}
304       NO_INSTALL 
305       ${BOOST_TEST_EXTRA_OPTIONS})
306
307     if (THIS_EXE_OKAY)
308       #
309       # Fixup path for visual studio per instructions from Brad King:  
310       #
311       get_target_property(THIS_TEST_LOCATION ${BOOST_TEST_TESTNAME}
312         LOCATION)
313       string(REGEX REPLACE "\\$\\(.*\\)" "\${CTEST_CONFIGURATION_TYPE}"
314         THIS_TEST_LOCATION "${THIS_TEST_LOCATION}")
315
316       add_test (${BOOST_TEST_TESTNAME} 
317         ${THIS_TEST_LOCATION}
318         ${BOOST_TEST_ARGS})
319
320       set_tests_properties(${BOOST_TEST_TESTNAME}
321         PROPERTIES
322         LABELS "${BOOST_PROJECT_NAME}"
323         )
324       boost_test_known_failures(${testname} ${BOOST_TEST_KNOWN_FAILURES})
325
326       if (BOOST_TEST_FAIL)
327         set_tests_properties(${BOOST_TEST_TESTNAME} PROPERTIES WILL_FAIL ON)
328       endif ()
329     endif(THIS_EXE_OKAY)
330   endif (BOOST_TEST_OKAY)
331 endmacro(boost_test_run)
332
333
334 # This macro creates a boost regression test that will be run but is
335 # expected to fail (exit with nonzero return code).
336 # See boost_test_run()
337
338 macro(boost_test_run_fail testname)
339   boost_test_run(${testname} ${ARGN} FAIL)
340 endmacro(boost_test_run_fail)
341
342 # This macro creates a Boost regression test that will be compiled,
343 # but not linked or executed. If the test can be compiled with no
344 # failures, the test passes.
345 #
346 #   boost_test_compile(testname 
347 #                      [source1]
348 #                      [COMPILE_FLAGS compileflags])
349 #
350 # testname is the name of the test. source1 is the name of the source
351 # file that will be built. If no source file is provided, the file
352 # "testname.cpp" will be used instead.
353 #
354 # The COMPILE_FLAGS argument provides additional arguments that will
355 # be passed to the compiler when building this test.
356
357 # Example:
358 #   boost_test_compile(advance)
359 macro(boost_test_compile testname)
360   boost_test_parse_args(${testname} ${ARGN} COMPILE)
361
362   set (test_pass "PASSED")
363   if (BOOST_TEST_FAIL)
364     set (test_pass "FAILED")
365   endif(BOOST_TEST_FAIL)
366   if (BOOST_TEST_OKAY)
367   
368     # Determine the include directories to pass along to the underlying
369     # project.
370     # works but not great
371     get_directory_property(BOOST_TEST_INCLUDE_DIRS INCLUDE_DIRECTORIES)
372     set(BOOST_TEST_INCLUDES "")
373     foreach(DIR ${BOOST_TEST_INCLUDE_DIRS})
374       set(BOOST_TEST_INCLUDES "${BOOST_TEST_INCLUDES};${DIR}")
375     endforeach(DIR ${BOOST_TEST_INCLUDE_DIRS})
376
377     add_test(${BOOST_TEST_TESTNAME}
378       ${CMAKE_CTEST_COMMAND}
379       --build-and-test
380       ${Boost_SOURCE_DIR}/tools/build/CMake/CompileTest
381       ${Boost_BINARY_DIR}/tools/build/CMake/CompileTest
382       --build-generator ${CMAKE_GENERATOR}
383       --build-makeprogram ${CMAKE_MAKE_PROGRAM}
384       --build-project CompileTest
385       --build-options 
386       "-DSOURCE:STRING=${CMAKE_CURRENT_SOURCE_DIR}/${BOOST_TEST_SOURCES}"
387       "-DINCLUDES:STRING=${BOOST_TEST_INCLUDES}"
388       "-DCOMPILE_FLAGS:STRING=${BOOST_TEST_COMPILE_FLAGS}"
389       )
390
391     set_tests_properties(${BOOST_TEST_TESTNAME}
392       PROPERTIES
393       LABELS "${BOOST_PROJECT_NAME}"
394       )
395
396     boost_test_known_failures(${testname} ${BOOST_TEST_KNOWN_FAILURES})
397
398     if (BOOST_TEST_FAIL)
399       set_tests_properties(${BOOST_TEST_TESTNAME} PROPERTIES WILL_FAIL ON)      
400     endif ()
401   endif(BOOST_TEST_OKAY)
402 endmacro(boost_test_compile)
403
404 #
405 # This macro creates a Boost regression test that is expected to 
406 # *fail* to compile.   See boost_test_compile()
407 #
408 macro(boost_test_compile_fail testname)
409   boost_test_compile(${testname} ${ARGN} FAIL)
410 endmacro(boost_test_compile_fail)
411
412
413
414
415 #
416 # boost_test_link:
417 #
418 #
419 # Each library "exports" itself to
420 # ${CMAKE_BINARY_DIR}/exports/<variantname>.cmake
421 #
422 # The list of 'depends' for these libraries has to match one of those
423 # files, this way the export mechanism works.  The generated
424 # cmakelists will include() those exported .cmake files, for each
425 # DEPENDS.
426 #
427 #
428 macro(boost_test_link testname)
429   boost_test_parse_args(${testname} ${ARGN} LINK)
430   if(BOOST_TEST_OKAY)
431     # Determine the include directories to pass along to the underlying
432     # project.
433     # works but not great
434     get_directory_property(BOOST_TEST_INCLUDE_DIRS INCLUDE_DIRECTORIES)
435     set(BOOST_TEST_INCLUDES "")
436     foreach(DIR ${BOOST_TEST_INCLUDE_DIRS})
437       set(BOOST_TEST_INCLUDES "${BOOST_TEST_INCLUDES};${DIR}")
438     endforeach(DIR ${BOOST_TEST_INCLUDE_DIRS})
439
440     add_test(${BOOST_TEST_TESTNAME}
441       ${CMAKE_CTEST_COMMAND}
442       -VV
443       --build-and-test
444       ${Boost_SOURCE_DIR}/tools/build/CMake/LinkTest
445       ${Boost_BINARY_DIR}/tools/build/CMake/LinkTest
446       --build-generator ${CMAKE_GENERATOR}
447       --build-makeprogram ${CMAKE_MAKE_PROGRAM}
448       --build-project LinkTest
449       --build-options 
450       "-DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}"
451       "-DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}"
452       "-DBOOST_EXPORTS_DIR:FILEPATH=${CMAKE_BINARY_DIR}/exports"
453       "-DSOURCE:STRING=${CMAKE_CURRENT_SOURCE_DIR}/${BOOST_TEST_SOURCES}"
454       "-DINCLUDES:STRING=${BOOST_TEST_INCLUDES}"
455       "-DCOMPILE_FLAGS:STRING=${BOOST_TEST_COMPILE_FLAGS}"
456       "-DLINK_LIBS:STRING=${BOOST_TEST_LINK_LIBS}"
457       "-DDEPENDS:STRING=${BOOST_TEST_DEPENDS}"
458       )
459
460     set_tests_properties(${BOOST_TEST_TESTNAME}
461       PROPERTIES
462       LABELS "${BOOST_PROJECT_NAME}"
463       )
464
465     boost_test_known_failures(${testname} ${BOOST_TEST_KNOWN_FAILURES})
466
467     if (BOOST_TEST_FAIL)
468       set_tests_properties(${BOOST_TEST_TESTNAME} PROPERTIES WILL_FAIL ON)      
469     endif ()
470   endif(BOOST_TEST_OKAY)
471 endmacro(boost_test_link)
472