Skip to content

Commit

Permalink
Made cudftestutil header-only and removed GTest dependency (#16839)
Browse files Browse the repository at this point in the history
This merge request follows up on #16658.
It removes the dependency on GTest by cudftestutil.  It satisfies the requirement that we only need API compatibility with the GTest API and we don't expose the GTest symbols to our consumers nor ship any binary artifact.
The source files defining the symbols are late-binded to the resulting executable (via library INTERFACE sources).
The user has to link to manually link the GTest and GMock libraries to the final executable as illustrated below.

Closes #16658

### Usage

CMakeLists.txt:

```cmake
add_executable(test1 test1.cpp)
target_link_libraries(test1 PRIVATE GTest::gtest GTest::gmock GTest::gtest_main cudf::cudftestutil cudf::cudftestutil_impl)
```

Authors:
  - Basit Ayantunde (https://github.com/lamarrr)

Approvers:
  - Vyas Ramasubramani (https://github.com/vyasr)
  - Robert Maynard (https://github.com/robertmaynard)
  - David Wendt (https://github.com/davidwendt)
  - Mike Sarahan (https://github.com/msarahan)

URL: #16839
  • Loading branch information
lamarrr authored Oct 14, 2024
1 parent 4dbb8a3 commit 3bee678
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 72 deletions.
65 changes: 41 additions & 24 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -863,15 +863,7 @@ if(CUDF_BUILD_TESTUTIL)

add_library(cudf::cudftest_default_stream ALIAS cudftest_default_stream)

add_library(
cudftestutil SHARED
tests/io/metadata_utilities.cpp
tests/utilities/column_utilities.cu
tests/utilities/debug_utilities.cu
tests/utilities/random_seed.cpp
tests/utilities/table_utilities.cu
tests/utilities/tdigest_utilities.cu
)
add_library(cudftestutil INTERFACE)

set_target_properties(
cudftestutil
Expand All @@ -880,32 +872,56 @@ if(CUDF_BUILD_TESTUTIL)
# set target compile options
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_VISIBILITY_PRESET hidden
CUDA_STANDARD 17
CUDA_STANDARD_REQUIRED ON
CUDA_VISIBILITY_PRESET hidden
POSITION_INDEPENDENT_CODE ON
INTERFACE_POSITION_INDEPENDENT_CODE ON
)

target_compile_options(
cudftestutil PUBLIC "$<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:CXX>:${CUDF_CXX_FLAGS}>>"
"$<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:CUDA>:${CUDF_CUDA_FLAGS}>>"
cudftestutil INTERFACE "$<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:CXX>:${CUDF_CXX_FLAGS}>>"
"$<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:CUDA>:${CUDF_CUDA_FLAGS}>>"
)

target_link_libraries(
cudftestutil
PUBLIC Threads::Threads cudf cudftest_default_stream
PRIVATE GTest::gmock GTest::gtest $<TARGET_NAME_IF_EXISTS:conda_env>
cudftestutil INTERFACE Threads::Threads cudf cudftest_default_stream
$<TARGET_NAME_IF_EXISTS:conda_env>
)

target_include_directories(
cudftestutil PUBLIC "$<BUILD_INTERFACE:${CUDF_SOURCE_DIR}>"
"$<BUILD_INTERFACE:${CUDF_SOURCE_DIR}/src>"
cudftestutil INTERFACE "$<BUILD_INTERFACE:${CUDF_SOURCE_DIR}>"
"$<BUILD_INTERFACE:${CUDF_SOURCE_DIR}/src>"
)
rapids_cuda_set_runtime(cudftestutil USE_STATIC ${CUDA_STATIC_RUNTIME})
add_library(cudf::cudftestutil ALIAS cudftestutil)

add_library(cudftestutil_impl INTERFACE)
add_library(cudf::cudftestutil_impl ALIAS cudftestutil_impl)
target_sources(
cudftestutil_impl
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tests/io/metadata_utilities.cpp>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tests/utilities/column_utilities.cu>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tests/utilities/debug_utilities.cu>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tests/utilities/random_seed.cpp>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tests/utilities/table_utilities.cu>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tests/utilities/tdigest_utilities.cu>
$<INSTALL_INTERFACE:src/cudftestutil/io/metadata_utilities.cpp>
$<INSTALL_INTERFACE:src/cudftestutil/utilities/column_utilities.cu>
$<INSTALL_INTERFACE:src/cudftestutil/utilities/debug_utilities.cu>
$<INSTALL_INTERFACE:src/cudftestutil/utilities/random_seed.cpp>
$<INSTALL_INTERFACE:src/cudftestutil/utilities/table_utilities.cu>
$<INSTALL_INTERFACE:src/cudftestutil/utilities/tdigest_utilities.cu>
)
target_link_libraries(cudftestutil_impl INTERFACE cudf::cudftestutil)

install(FILES tests/io/metadata_utilities.cpp DESTINATION src/cudftestutil/io)
install(
FILES tests/utilities/column_utilities.cu
tests/utilities/debug_utilities.cu
tests/utilities/random_seed.cpp
tests/utilities/table_utilities.cu
tests/utilities/tdigest_utilities.cu
DESTINATION src/cudftestutil/utilities
)

endif()

# * build cudf_identify_stream_usage --------------------------------------------------------------
Expand Down Expand Up @@ -1006,7 +1022,7 @@ install(
set(_components_export_string)
if(TARGET cudftestutil)
install(
TARGETS cudftest_default_stream cudftestutil
TARGETS cudftest_default_stream cudftestutil cudftestutil_impl
DESTINATION ${lib_dir}
EXPORT cudf-testing-exports
)
Expand Down Expand Up @@ -1046,14 +1062,15 @@ targets:
This module offers an optional testing component which defines the
following IMPORTED GLOBAL targets:

cudf::cudftestutil - The main cudf testing library
cudf::cudftestutil - The main cudf testing library
cudf::cudftestutil_impl - C++ and CUDA sources to compile for definitions in cudf::cudftestutil
]=]
)

rapids_export(
INSTALL cudf
EXPORT_SET cudf-exports ${_components_export_string}
GLOBAL_TARGETS cudf cudftestutil
GLOBAL_TARGETS cudf cudftestutil cudftestutil_impl
NAMESPACE cudf::
DOCUMENTATION doc_string
)
Expand All @@ -1074,7 +1091,7 @@ endif()
rapids_export(
BUILD cudf
EXPORT_SET cudf-exports ${_components_export_string}
GLOBAL_TARGETS cudf cudftestutil
GLOBAL_TARGETS cudf cudftestutil cudftestutil_impl
NAMESPACE cudf::
DOCUMENTATION doc_string
FINAL_CODE_BLOCK build_code_string
Expand Down
25 changes: 13 additions & 12 deletions cpp/benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ target_compile_options(
target_link_libraries(
cudf_datagen
PUBLIC GTest::gmock GTest::gtest benchmark::benchmark nvbench::nvbench Threads::Threads cudf
cudftestutil nvtx3::nvtx3-cpp
cudf::cudftestutil nvtx3::nvtx3-cpp
PRIVATE $<TARGET_NAME_IF_EXISTS:conda_env>
)

Expand All @@ -49,7 +49,7 @@ target_compile_options(

target_link_libraries(
ndsh_data_generator
PUBLIC cudf cudftestutil nvtx3::nvtx3-cpp
PUBLIC cudf GTest::gmock GTest::gtest cudf::cudftestutil nvtx3::nvtx3-cpp
PRIVATE $<TARGET_NAME_IF_EXISTS:conda_env>
)

Expand All @@ -65,14 +65,14 @@ target_include_directories(
# Use an OBJECT library so we only compile these helper source files only once
add_library(
cudf_benchmark_common OBJECT
"${CUDF_SOURCE_DIR}/tests/utilities/random_seed.cpp"
synchronization/synchronization.cpp
io/cuio_common.cpp
common/table_utilities.cpp
common/benchmark_utilities.cpp
common/nvbench_utilities.cpp
synchronization/synchronization.cpp io/cuio_common.cpp common/table_utilities.cpp
common/benchmark_utilities.cpp common/nvbench_utilities.cpp
)
target_link_libraries(cudf_benchmark_common PRIVATE cudf_datagen $<TARGET_NAME_IF_EXISTS:conda_env>)
target_link_libraries(
cudf_benchmark_common PRIVATE cudf_datagen $<TARGET_NAME_IF_EXISTS:conda_env> GTest::gmock
GTest::gtest
)

add_custom_command(
OUTPUT CUDF_BENCHMARKS
COMMAND echo Running benchmarks
Expand All @@ -99,7 +99,7 @@ function(ConfigureBench CMAKE_BENCH_NAME)
)
target_link_libraries(
${CMAKE_BENCH_NAME} PRIVATE cudf_benchmark_common cudf_datagen benchmark::benchmark_main
$<TARGET_NAME_IF_EXISTS:conda_env>
cudf::cudftestutil_impl $<TARGET_NAME_IF_EXISTS:conda_env>
)
add_custom_command(
OUTPUT CUDF_BENCHMARKS
Expand Down Expand Up @@ -127,8 +127,9 @@ function(ConfigureNVBench CMAKE_BENCH_NAME)
INSTALL_RPATH "\$ORIGIN/../../../lib"
)
target_link_libraries(
${CMAKE_BENCH_NAME} PRIVATE cudf_benchmark_common ndsh_data_generator cudf_datagen
nvbench::nvbench $<TARGET_NAME_IF_EXISTS:conda_env>
${CMAKE_BENCH_NAME}
PRIVATE cudf_benchmark_common ndsh_data_generator cudf_datagen nvbench::nvbench
$<TARGET_NAME_IF_EXISTS:conda_env> cudf::cudftestutil_impl
)
install(
TARGETS ${CMAKE_BENCH_NAME}
Expand Down
67 changes: 45 additions & 22 deletions cpp/include/cudf_test/testing_main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#pragma once

#include <cudf_test/cudf_gtest.hpp>
#include <cudf_test/cxxopts.hpp>
#include <cudf_test/stream_checking_resource_adaptor.hpp>

Expand All @@ -36,6 +37,12 @@
namespace CUDF_EXPORT cudf {
namespace test {

struct config {
std::string rmm_mode;
std::string stream_mode;
std::string stream_error_mode;
};

/// MR factory functions
inline auto make_cuda() { return std::make_shared<rmm::mr::cuda_memory_resource>(); }

Expand Down Expand Up @@ -157,10 +164,9 @@ inline auto parse_cudf_test_opts(int argc, char** argv)
* @param cmd_opts Command line options returned by parse_cudf_test_opts
* @return Memory resource adaptor
*/
inline auto make_memory_resource_adaptor(cxxopts::ParseResult const& cmd_opts)
inline auto make_memory_resource_adaptor(cudf::test::config const& config)
{
auto const rmm_mode = cmd_opts["rmm_mode"].as<std::string>();
auto resource = cudf::test::create_memory_resource(rmm_mode);
auto resource = cudf::test::create_memory_resource(config.rmm_mode);
cudf::set_current_device_resource(resource.get());
return resource;
}
Expand All @@ -176,37 +182,54 @@ inline auto make_memory_resource_adaptor(cxxopts::ParseResult const& cmd_opts)
* @param cmd_opts Command line options returned by parse_cudf_test_opts
* @return Memory resource adaptor
*/
inline auto make_stream_mode_adaptor(cxxopts::ParseResult const& cmd_opts)
inline auto make_stream_mode_adaptor(cudf::test::config const& config)
{
auto resource = cudf::get_current_device_resource_ref();
auto const stream_mode = cmd_opts["stream_mode"].as<std::string>();
auto const stream_error_mode = cmd_opts["stream_error_mode"].as<std::string>();
auto const error_on_invalid_stream = (stream_error_mode == "error");
auto const check_default_stream = (stream_mode == "new_cudf_default");
auto const error_on_invalid_stream = (config.stream_error_mode == "error");
auto const check_default_stream = (config.stream_mode == "new_cudf_default");
auto adaptor = cudf::test::stream_checking_resource_adaptor(
resource, error_on_invalid_stream, check_default_stream);
if ((stream_mode == "new_cudf_default") || (stream_mode == "new_testing_default")) {
if ((config.stream_mode == "new_cudf_default") || (config.stream_mode == "new_testing_default")) {
cudf::set_current_device_resource(&adaptor);
}
return adaptor;
}

/**
* @brief Should be called in every test program that uses rmm allocators since it maintains the
* lifespan of the rmm default memory resource. this function parses the command line to customize
* test behavior, like the allocation mode used for creating the default memory resource.
*
*/
inline void init_cudf_test(int argc, char** argv, cudf::test::config const& config_override = {})
{
// static lifetime to keep rmm resource alive till tests end
auto const cmd_opts = parse_cudf_test_opts(argc, argv);
cudf::test::config config = config_override;
if (config.rmm_mode.empty()) { config.rmm_mode = cmd_opts["rmm_mode"].as<std::string>(); }

if (config.stream_mode.empty()) {
config.stream_mode = cmd_opts["stream_mode"].as<std::string>();
}

if (config.stream_error_mode.empty()) {
config.stream_error_mode = cmd_opts["stream_error_mode"].as<std::string>();
}

[[maybe_unused]] static auto mr = make_memory_resource_adaptor(config);
[[maybe_unused]] static auto adaptor = make_stream_mode_adaptor(config);
}

/**
* @brief Macro that defines main function for gtest programs that use rmm
*
* Should be included in every test program that uses rmm allocators since
* it maintains the lifespan of the rmm default memory resource.
* This `main` function is a wrapper around the google test generated `main`,
* maintaining the original functionality. In addition, this custom `main`
* function parses the command line to customize test behavior, like the
* allocation mode used for creating the default memory resource.
* maintaining the original functionality.
*/
#define CUDF_TEST_PROGRAM_MAIN() \
int main(int argc, char** argv) \
{ \
::testing::InitGoogleTest(&argc, argv); \
auto const cmd_opts = parse_cudf_test_opts(argc, argv); \
[[maybe_unused]] auto mr = make_memory_resource_adaptor(cmd_opts); \
[[maybe_unused]] auto adaptor = make_stream_mode_adaptor(cmd_opts); \
return RUN_ALL_TESTS(); \
#define CUDF_TEST_PROGRAM_MAIN() \
int main(int argc, char** argv) \
{ \
::testing::InitGoogleTest(&argc, argv); \
init_cudf_test(argc, argv); \
return RUN_ALL_TESTS(); \
}
11 changes: 9 additions & 2 deletions cpp/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,15 @@ function(ConfigureTest CMAKE_TEST_NAME)

target_link_libraries(
${CMAKE_TEST_NAME}
PRIVATE cudftestutil GTest::gmock GTest::gmock_main GTest::gtest GTest::gtest_main
nvtx3::nvtx3-cpp $<TARGET_NAME_IF_EXISTS:conda_env> "${_CUDF_TEST_EXTRA_LIBS}"
PRIVATE cudf::cudftestutil
cudf::cudftestutil_impl
GTest::gmock
GTest::gmock_main
GTest::gtest
GTest::gtest_main
nvtx3::nvtx3-cpp
$<TARGET_NAME_IF_EXISTS:conda_env>
"${_CUDF_TEST_EXTRA_LIBS}"
)
rapids_cuda_set_runtime(${CMAKE_TEST_NAME} USE_STATIC ${CUDA_STATIC_RUNTIME})
rapids_test_add(
Expand Down
5 changes: 2 additions & 3 deletions cpp/tests/io/metadata_utilities.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022, NVIDIA CORPORATION.
* Copyright (c) 2021-2024, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,10 +14,9 @@
* limitations under the License.
*/

#include <cudf_test/cudf_gtest.hpp>
#include <cudf_test/io_metadata_utilities.hpp>

#include <gmock/gmock.h>

namespace cudf::test {

void expect_metadata_equal(cudf::io::table_input_metadata in_meta,
Expand Down
9 changes: 3 additions & 6 deletions cpp/tests/large_strings/large_strings_fixture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,9 @@ LargeStringsData* StringsLargeTest::g_ls_data = nullptr;
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
auto const cmd_opts = parse_cudf_test_opts(argc, argv);
// hardcoding the CUDA memory resource to keep from exceeding the pool
auto mr = cudf::test::make_cuda();
cudf::set_current_device_resource(mr.get());
auto adaptor = make_stream_mode_adaptor(cmd_opts);

cudf::test::config config;
config.rmm_mode = "cuda";
init_cudf_test(argc, argv, config);
// create object to automatically be destroyed at the end of main()
auto lsd = cudf::test::StringsLargeTest::get_ls_data();

Expand Down
5 changes: 2 additions & 3 deletions cpp/tests/utilities/table_utilities.cu
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022, NVIDIA CORPORATION.
* Copyright (c) 2019-2024, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,10 +15,9 @@
*/

#include <cudf_test/column_utilities.hpp>
#include <cudf_test/cudf_gtest.hpp>
#include <cudf_test/table_utilities.hpp>

#include <gmock/gmock.h>

namespace cudf::test::detail {
void expect_table_properties_equal(cudf::table_view lhs, cudf::table_view rhs)
{
Expand Down

0 comments on commit 3bee678

Please sign in to comment.