0
votes

I am traing to use cmake and gtest first time. I have written one test. But this test is not running. I have read the docs https://cmake.org/cmake/help/latest/module/GoogleTest.html

Files in my project: CMakeLists.txt func1.h func.cpp main.cpp mTest.cpp

CMakeLists.txt:

cmake_minimum_required(VERSION 3.0.0)
project(t1 VERSION 0.1.0)

enable_testing()
find_package(GTest REQUIRED)

add_executable(t1 main.cpp)

add_library(func STATIC func.cpp)
add_library(mTest STATIC mTest.cpp) 

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

target_link_libraries(t1 func mTest gtest  gtest_main pthread)

gtest_discover_tests(t1)

main.cpp:

#include <iostream>
#include "func1.h"
#include "gtest/gtest.h"


int main(int argc, char** argv) 
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

mTest.cpp:

#include <vector>
#include "func1.h"
#include "gtest/gtest.h"

TEST(prime_mumbers, calc_n_prime_numbers_test) 
{
    std::vector<size_t> prime_numbers = 
    {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 57, 53, 59, 61, 67, 71, 73};
    size_t n = prime_numbers.size();
    std::vector<size_t> res(n);
    calc_n_prime_numbers(n, res.data());
    EXPECT_EQ(prime_numbers,res);
}

Result:

[==========] Running 0 tests from 0 test suites.
[==========] 0 tests from 0 test suites ran. (0 ms total)
[  PASSED  ] 0 tests.
[1] + Done                       "/usr/bin/gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-9jep64np.x0l" 1>"/tmp/Microsoft-MIEngine-Out-qcr0fwol.v1o"
2

2 Answers

0
votes

The linker might exclude you tests because you do not use any symbol from the static library with tests in you main file. The solution is forcing the whole library to be linked.

cmake_minimum_required(VERSION 3.0.0)
project(t1 VERSION 0.1.0)

enable_testing()
find_package(GTest REQUIRED)

add_executable(t1 main.cpp)

add_library(func STATIC func.cpp)
add_library(mTest STATIC mTest.cpp) 

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

target_link_options(t1 --whole-archive) # <--
target_link_libraries(t1 func mTest gtest  gtest_main pthread)

gtest_discover_tests(t1)

If you don't want to force whole library for other libraries, you can do it for 'mTest' library only.

cmake_minimum_required(VERSION 3.0.0)
project(t1 VERSION 0.1.0)

enable_testing()
find_package(GTest REQUIRED)

add_executable(t1 main.cpp)

add_library(func STATIC func.cpp)
add_library(mTest STATIC mTest.cpp) 

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

target_link_libraries(t1 func -Wl,--whole-archive mtest -Wl,--no-whole-archive gtest gtest_main pthread)
#                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

gtest_discover_tests(t1)
0
votes

@S.M. has identified the issue correctly: The linker is discarding the globals whose initialization is used to register the tests (check out e.g. Bartłomiej Filipek's blog to see how self-registration of tests works under the hood).

However, there are several better ways to solve the issue than to fiddle with the linker flags (which is platform-specific).

If your main function doesn't do anything special (yours currently doesn't), then you can get rid of the source file defining main, make mTest the executable and link against gtest_main instead

cmake_minimum_required(VERSION 3.0.0)
project(t1 VERSION 0.1.0)

enable_testing()
find_package(GTest REQUIRED)

add_library(func STATIC func.cpp)
add_executable(mTest mTest.cpp) 

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

find_package(Threads REQUIRED)

target_link_libraries(mTest PRIVATE func gest_main Threads::Threads)

gtest_discover_tests(t1)

If your main function does do something different, the typical approach is to put main into its own static library and to link that into the test executables instead of gtest_main:

cmake_minimum_required(VERSION 3.0.0)
project(t1 VERSION 0.1.0)

enable_testing()
find_package(GTest REQUIRED)

add_library(func STATIC func.cpp)
add_library(test_main STATIC main.cpp)
target_link_libraries(test_main PRIVATE gtest)
add_executable(mTest mTest.cpp) 

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

find_package(Threads REQUIRED)

target_link_libraries(mTest PRIVATE func test_main gtest Threads::Threads)

gtest_discover_tests(t1)