T73268: Link C/C++ unit tests into single executable

This commit introduces a new way to build unit tests. It is now possible
for each module to generate its own test library. The tests in these
libraries are then bundled into a single executable.

The test executable can be run with `ctest`. Even though the tests
reside in a single executable, they are still exposed as individual
tests to `ctest`, and thus can be selected via its `-R` argument.

Not yet ported tests still build & run as before.

The following rules apply:

- Test code should reside in the same directory as the code under test.
- Tests that target functionality in `somefile.{c,cc}` should reside in
  `somefile_test.cc`.
- The namespace for tests is the `tests` sub-namespace of the code under
  test. For example, tests for `blender::bke` should be in
  `blender::bke:tests`.
- The test files should be listed in the module's `CMakeLists.txt` in a
  `blender_add_test_lib()` call. See the `blenkernel` module for an
  example.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D7649
master
Sybren A. Stüvel 4 years ago
parent 065a00ee3e
commit 56aa5b0d8c

@ -1628,10 +1628,6 @@ endif()
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# Libraries # Libraries
if(WITH_GTESTS)
include(GTestTesting)
endif()
if(WITH_BLENDER) if(WITH_BLENDER)
add_subdirectory(intern) add_subdirectory(intern)
add_subdirectory(extern) add_subdirectory(extern)

@ -37,6 +37,11 @@ macro(BLENDER_SRC_GTEST_EX)
if(WIN32) if(WIN32)
set(MANIFEST "${CMAKE_BINARY_DIR}/tests.exe.manifest") set(MANIFEST "${CMAKE_BINARY_DIR}/tests.exe.manifest")
endif() endif()
add_definitions(-DBLENDER_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
add_definitions(${GFLAGS_DEFINES})
add_definitions(${GLOG_DEFINES})
add_executable(${TARGET_NAME} ${ARG_SRC} ${MANIFEST}) add_executable(${TARGET_NAME} ${ARG_SRC} ${MANIFEST})
target_include_directories(${TARGET_NAME} PUBLIC "${TEST_INC}") target_include_directories(${TARGET_NAME} PUBLIC "${TEST_INC}")
target_include_directories(${TARGET_NAME} SYSTEM PUBLIC "${TEST_INC_SYS}") target_include_directories(${TARGET_NAME} SYSTEM PUBLIC "${TEST_INC_SYS}")

@ -354,6 +354,42 @@ function(blender_add_lib
set_property(GLOBAL APPEND PROPERTY BLENDER_LINK_LIBS ${name}) set_property(GLOBAL APPEND PROPERTY BLENDER_LINK_LIBS ${name})
endfunction() endfunction()
# blender_add_test_lib() is used to define a test library. It is intended to be
# called in tandem with blender_add_lib(). The test library will be linked into
# the bf_gtest_runner_test executable (see tests/gtests/CMakeLists.txt).
function(blender_add_test_lib
name
sources
includes
includes_sys
library_deps
)
add_cc_flags_custom_test(${name} PARENT_SCOPE)
# Otherwise external projects will produce warnings that we cannot fix.
remove_strict_flags()
# This duplicates logic that's also in GTestTesting.cmake, macro BLENDER_SRC_GTEST_EX.
# TODO(Sybren): deduplicate after the general approach in D7649 has been approved.
LIST(APPEND includes
${CMAKE_SOURCE_DIR}/tests/gtests
)
LIST(APPEND includes_sys
${GLOG_INCLUDE_DIRS}
${GFLAGS_INCLUDE_DIRS}
${CMAKE_SOURCE_DIR}/extern/gtest/include
${CMAKE_SOURCE_DIR}/extern/gmock/include
)
add_definitions(-DBLENDER_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
add_definitions(${GFLAGS_DEFINES})
add_definitions(${GLOG_DEFINES})
blender_add_lib__impl(${name} "${sources}" "${includes}" "${includes_sys}" "${library_deps}")
set_property(GLOBAL APPEND PROPERTY BLENDER_TEST_LIBS ${name})
endfunction()
# Ninja only: assign 'heavy pool' to some targets that are especially RAM-consuming to build. # Ninja only: assign 'heavy pool' to some targets that are especially RAM-consuming to build.
function(setup_heavy_lib_pool) function(setup_heavy_lib_pool)
if(WITH_NINJA_POOL_JOBS AND NINJA_MAX_NUM_PARALLEL_COMPILE_HEAVY_JOBS) if(WITH_NINJA_POOL_JOBS AND NINJA_MAX_NUM_PARALLEL_COMPILE_HEAVY_JOBS)

@ -212,6 +212,8 @@ if(WITH_LIBMV)
if(WITH_GTESTS) if(WITH_GTESTS)
include(GTestTesting)
blender_add_lib(libmv_test_dataset "./libmv/multiview/test_data_sets.cc" "" "" "") blender_add_lib(libmv_test_dataset "./libmv/multiview/test_data_sets.cc" "" "" "")
BLENDER_SRC_GTEST("libmv_predict_tracks" "./libmv/autotrack/predict_tracks_test.cc" "libmv_test_dataset;bf_intern_libmv;extern_ceres") BLENDER_SRC_GTEST("libmv_predict_tracks" "./libmv/autotrack/predict_tracks_test.cc" "libmv_test_dataset;bf_intern_libmv;extern_ceres")

@ -701,3 +701,16 @@ blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# Needed so we can use dna_type_offsets.h for defaults initialization. # Needed so we can use dna_type_offsets.h for defaults initialization.
add_dependencies(bf_blenkernel bf_dna) add_dependencies(bf_blenkernel bf_dna)
if(WITH_GTESTS)
set(TEST_SRC
intern/armature_test.cc
intern/fcurve_test.cc
)
set(TEST_INC
../editors/include
)
include(GTestTesting)
blender_add_test_lib(bf_blenkernel_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB}")
endif()

@ -23,6 +23,8 @@
#include "testing/testing.h" #include "testing/testing.h"
namespace blender::bke::tests {
static const float FLOAT_EPSILON = 1.2e-7; static const float FLOAT_EPSILON = 1.2e-7;
TEST(mat3_vec_to_roll, UnitMatrix) TEST(mat3_vec_to_roll, UnitMatrix)
@ -87,3 +89,5 @@ TEST(mat3_vec_to_roll, Rotationmatrix)
EXPECT_NEAR(0.57158958f, roll, FLOAT_EPSILON); EXPECT_NEAR(0.57158958f, roll, FLOAT_EPSILON);
} }
} }
} // namespace blender::bke::tests

@ -27,6 +27,8 @@ extern "C" {
#include "DNA_anim_types.h" #include "DNA_anim_types.h"
} }
namespace blender::bke::tests {
// Epsilon for floating point comparisons. // Epsilon for floating point comparisons.
static const float EPSILON = 1e-7f; static const float EPSILON = 1e-7f;
@ -209,3 +211,5 @@ TEST(evaluate_fcurve, ExtrapolationBezierKeys)
BKE_fcurve_free(fcu); BKE_fcurve_free(fcu);
} }
} // namespace blender::bke::tests

@ -1,18 +1,13 @@
# GTest
if(WITH_GTESTS) if(WITH_GTESTS)
include(GTestTesting)
add_definitions(${GFLAGS_DEFINES})
add_definitions(${GLOG_DEFINES})
add_definitions(-DBLENDER_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
# Otherwise we get warnings here that we cant fix in external projects # Otherwise we get warnings here that we cant fix in external projects
remove_strict_flags() remove_strict_flags()
# Build common test runner
add_subdirectory(runner)
# Build tests not yet ported to the common runner
add_subdirectory(testing) add_subdirectory(testing)
add_subdirectory(blenkernel)
add_subdirectory(blenlib) add_subdirectory(blenlib)
add_subdirectory(blenloader) add_subdirectory(blenloader)
add_subdirectory(guardedalloc) add_subdirectory(guardedalloc)

@ -1,44 +0,0 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2020, Blender Foundation
# All rights reserved.
# ***** END GPL LICENSE BLOCK *****
set(INC
.
..
../../../source/blender/blenkernel
../../../source/blender/blenlib
../../../source/blender/editors/include
../../../source/blender/makesdna
../../../source/blender/makesrna
../../../intern/guardedalloc
../../../intern/atomic
)
setup_libdirs()
include_directories(${INC})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}")
if(WITH_BUILDINFO)
set(BUILDINFO buildinfoobj)
endif()
BLENDER_TEST(BKE_armature "bf_blenloader;bf_blenkernel;bf_blenlib;${BUILDINFO}")
BLENDER_TEST(BKE_fcurve "bf_blenloader;bf_blenkernel;bf_editor_animation;${BUILDINFO}")

@ -0,0 +1,63 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2020, Blender Foundation
# All rights reserved.
# ***** END GPL LICENSE BLOCK *****
# Build the test runner. This runner takes care of running all GTests, i.e.
# the code that was built using the blender_add_test_lib() CMake macro (see
# macros.cmake).
set(SRC
blender_test.cc
)
if(WITH_BUILDINFO)
list(APPEND SRC
"$<TARGET_OBJECTS:buildinfoobj>"
)
endif()
# Test libraries need to be linked "whole archive", because they're not
# directly referenced from other code.
get_property(_test_libs GLOBAL PROPERTY BLENDER_TEST_LIBS)
if(WIN32)
list(APPEND TEST_LIBS ${_test_libs})
elseif(APPLE)
list(APPEND TEST_LIBS "-Wl,-force_load" ${_test_libs})
elseif(UNIX)
list(APPEND TEST_LIBS "-Wl,--whole-archive" ${_test_libs} "-Wl,--no-whole-archive")
else()
message(FATAL_ERROR "Unknown how to link whole-archive with your compiler ${CMAKE_CXX_COMPILER_ID}")
endif()
unset(_test_libs)
# This builds `bin/tests/blender_test`, but does not add it as a single test.
setup_libdirs()
BLENDER_SRC_GTEST_EX(
NAME blender
SRC "${SRC}"
EXTRA_LIBS "${TEST_LIBS}"
SKIP_ADD_TEST
)
setup_liblinks(blender_test)
# This runs the blender_test executable with `--gtest_list_tests`, then
# exposes those tests individually to the ctest runner.
# See https://cmake.org/cmake/help/v3.18/module/GoogleTest.html
include(GoogleTest)
gtest_discover_tests(blender_test)

@ -0,0 +1,25 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2020 Blender Foundation.
* All rights reserved.
*/
/* This file is intentionally left blank. It is necessary for CMake to have a source file for each
* executable. However, the blender_tests test runner only comprises of statically linked library
* files, including its main function.
*
* See source/blender/blenkernel/CMakeLists.txt for an example of how to add unit tests to the test
* runner. */

@ -18,6 +18,10 @@
# All rights reserved. # All rights reserved.
# ***** END GPL LICENSE BLOCK ***** # ***** END GPL LICENSE BLOCK *****
add_definitions(${GFLAGS_DEFINES})
add_definitions(${GLOG_DEFINES})
add_definitions(-DBLENDER_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
set(INC set(INC
. .
.. ..

Loading…
Cancel
Save