Combine all tests in a single executable to speed up the build

This commit is contained in:
Mike Gelfand 2021-08-16 04:45:50 +03:00
parent 647c171636
commit 407201c207
9 changed files with 172 additions and 144 deletions

View File

@ -1,10 +1,6 @@
#set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
include_directories(
SYSTEM
${CMAKE_SOURCE_DIR}/third-party/googletest/googletest/include
${CMAKE_SOURCE_DIR}/third-party/googletest/googletest
)
include_directories(SYSTEM
${THIRD_PARTY_DIR}/googletest/googletest/include
${THIRD_PARTY_DIR}/googletest/googletest)
add_subdirectory(gtest)
add_subdirectory(libtransmission)

View File

@ -1,6 +1,3 @@
add_library(
gtestall
STATIC
${CMAKE_SOURCE_DIR}/third-party/googletest/googletest/src/gtest-all.cc
${CMAKE_SOURCE_DIR}/third-party/googletest/googletest/src/gtest_main.cc
)
add_library(gtestall STATIC
${THIRD_PARTY_DIR}/googletest/googletest/src/gtest-all.cc
${THIRD_PARTY_DIR}/googletest/googletest/src/gtest_main.cc)

View File

@ -1,47 +1,77 @@
set(crypto-test_ADD_SOURCES crypto-test-ref.h)
set(subprocess-test_ADD_SOURCES subprocess-test.cmd)
add_executable(libtransmission-test
bitfield-test.cc
blocklist-test.cc
clients-test.cc
copy-test.cc
crypto-test-ref.h
crypto-test.cc
error-test.cc
file-test.cc
getopt-test.cc
history-test.cc
json-test.cc
magnet-test.cc
makemeta-test.cc
metainfo-test.cc
move-test.cc
peer-msgs-test.cc
quark-test.cc
rename-test.cc
rpc-test.cc
session-test.cc
subprocess-test-script.cmd
subprocess-test.cc
test-fixtures.h
utils-test.cc
variant-test.cc
watchdir-test.cc)
add_compile_options(
${CXX_WARNING_FLAGS}
)
target_compile_definitions(libtransmission-test
PRIVATE
__TRANSMISSION__)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
# patches welcomed
add_compile_options(-Wno-sign-compare)
endif()
target_include_directories(libtransmission-test
PRIVATE
${CMAKE_SOURCE_DIR}/libtransmission
${CMAKE_BINARY_DIR}/libtransmission)
add_definitions(
-D__TRANSMISSION__
)
target_include_directories(libtransmission-test SYSTEM
PRIVATE
${CURL_INCLUDE_DIRS}
${EVENT2_INCLUDE_DIRS})
include_directories(
${CMAKE_SOURCE_DIR}/libtransmission
${CMAKE_SOURCE_DIR}/tests/libtransmission
${CMAKE_BINARY_DIR}/libtransmission
)
include_directories(
SYSTEM
${CURL_INCLUDE_DIRS}
${EVENT2_INCLUDE_DIRS}
)
target_compile_options(libtransmission-test
PRIVATE
${CXX_WARNING_FLAGS}
$<$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>>:-Wno-sign-compare>) # patches welcomed
set_property(DIRECTORY PROPERTY FOLDER "UnitTests")
set_property(DIRECTORY PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
target_link_libraries(libtransmission-test
PRIVATE
${TR_NAME}
gtestall)
foreach(T bitfield blocklist clients copy crypto error file getopt
history json magnet makemeta metainfo move peer-msgs
quark rename rpc session subprocess utils variant watchdir)
set(TP libtransmission-test-${T})
add_executable(${TP} ${T}-test.cc)
target_link_libraries(${TP} gtestall ${TR_NAME})
add_test(NAME ${TP} COMMAND ${TP})
endforeach()
add_test(
NAME libtransmission-test
COMMAND libtransmission-test)
add_custom_command(
TARGET libtransmission-test-subprocess
PRE_BUILD
COMMAND
${CMAKE_COMMAND} -E copy_if_different
${PROJECT_SOURCE_DIR}/tests/libtransmission/subprocess-test.cmd
$<TARGET_FILE_DIR:libtransmission-test-subprocess>/libtransmission-test-subprocess.cmd
)
TARGET libtransmission-test
PRE_BUILD
COMMAND
${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/subprocess-test-script.cmd
$<TARGET_FILE_DIR:libtransmission-test>/subprocess-test.cmd)
add_executable(subprocess-test
subprocess-test-program.cc)
target_include_directories(subprocess-test
PRIVATE
${CMAKE_SOURCE_DIR}/libtransmission)
target_link_libraries(subprocess-test
PRIVATE
${TR_NAME})
add_dependencies(libtransmission-test
subprocess-test)

View File

@ -53,6 +53,11 @@ TEST(Session, peerId)
TEST(Session, sessionId)
{
#ifdef __sun
// FIXME: File locking doesn't work as expected
GTEST_SKIP();
#endif
EXPECT_FALSE(tr_session_id_is_local(nullptr));
EXPECT_FALSE(tr_session_id_is_local(""));
EXPECT_FALSE(tr_session_id_is_local("test"));

View File

@ -0,0 +1,71 @@
/*
* This file Copyright (C) 2017 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
*/
#include "transmission.h"
#include "file.h"
#include "subprocess.h"
#include "utils.h"
#include <memory>
#include <string>
int main(int argc, char** argv)
{
if (argc < 3)
{
return 1;
}
auto const result_path = std::string{ argv[1] };
auto const test_action = std::string{ argv[2] };
auto const tmp_result_path = result_path + ".tmp";
auto fd = tr_sys_file_open(
tmp_result_path.data(), // NOLINT
TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE,
0644,
nullptr);
if (fd == TR_BAD_SYS_FILE)
{
return 1;
}
if (test_action == "--dump-args")
{
for (size_t i = 3; i < argc; ++i)
{
tr_sys_file_write_line(fd, argv[i], nullptr);
}
}
else if (test_action == "--dump-env")
{
for (size_t i = 3; i < argc; ++i)
{
char* const value = tr_env_get_string(argv[i], "<null>");
tr_sys_file_write_line(fd, value, nullptr);
tr_free(value);
}
}
else if (test_action == "--dump-cwd")
{
char* const value = tr_sys_dir_get_current(nullptr);
tr_sys_file_write_line(fd, value != nullptr ? value : "<null>", nullptr);
tr_free(value);
}
else
{
tr_sys_file_close(fd, nullptr);
tr_sys_path_remove(tmp_result_path.data(), nullptr);
return 1;
}
tr_sys_file_close(fd, nullptr);
tr_sys_path_rename(tmp_result_path.data(), result_path.data(), nullptr);
return 0;
}

View File

@ -9,6 +9,7 @@
#include "transmission.h"
#include "error.h"
#include "file.h"
#include "platform.h"
#include "subprocess.h"
#include "utils.h"
@ -31,20 +32,11 @@ namespace libtransmission
namespace test
{
std::string getSelfPath()
std::string getTestProgramPath(std::string const& filename)
{
auto const exec = ::testing::internal::GetArgvs().front();
return makeString(tr_sys_path_resolve(exec.data(), nullptr));
}
std::string getCmdSelfPath()
{
auto const new_suffix = std::string{ ".cmd" };
auto exec = getSelfPath();
// replace ".exe" suffix with ".cmd"
exec.resize(exec.size() - new_suffix.size());
exec.append(new_suffix.data(), new_suffix.size());
return exec;
auto const exe_path = makeString(tr_sys_path_resolve(testing::internal::GetArgvs().front().data(), nullptr));
auto const exe_dir = makeString(tr_sys_path_dirname(exe_path.data(), nullptr));
return exe_dir + TR_PATH_DELIMITER + filename;
}
class SubprocessTest
@ -76,67 +68,6 @@ protected:
std::string self_path_;
// If command-line args were passed in, then this test is being
// invoked as a subprocess: it should dump the info requested by
// the command-line flags and then exit without running tests.
// FIXME: cleanup does not happen when we exit(). move this all
// to a standalone file similar to the .cmd file on Windows
void processCommandLineArgs() const
{
auto const argv = ::testing::internal::GetArgvs();
if (argv.size() < 3)
{
return;
}
auto const& result_path = argv[1];
auto const& test_action = argv[2];
auto const tmp_result_path = result_path + ".tmp";
auto fd = tr_sys_file_open(
tmp_result_path.data(), // NOLINT
TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE,
0644,
nullptr);
if (fd == TR_BAD_SYS_FILE)
{
exit(1);
}
if (test_action == arg_dump_args_)
{
for (size_t i = 3; i < argv.size(); ++i)
{
tr_sys_file_write_line(fd, argv[i].data(), nullptr);
}
}
else if (test_action == arg_dump_env_)
{
for (size_t i = 3; i < argv.size(); ++i)
{
auto const value = makeString(tr_env_get_string(argv[i].data(), "<null>"));
tr_sys_file_write_line(fd, value.data(), nullptr);
}
}
else if (test_action == arg_dump_cwd_)
{
char* const value = tr_sys_dir_get_current(nullptr);
tr_sys_file_write_line(fd, value != nullptr ? value : "<null>", nullptr);
tr_free(value);
}
else
{
tr_sys_file_close(fd, nullptr);
tr_sys_path_remove(tmp_result_path.data(), nullptr);
exit(1);
}
tr_sys_file_close(fd, nullptr);
tr_sys_path_rename(tmp_result_path.data(), result_path.data(), nullptr);
exit(0);
}
void waitForFileToExist(std::string const& path)
{
auto const test = [path]()
@ -148,7 +79,6 @@ protected:
void SetUp() override
{
processCommandLineArgs();
self_path_ = GetParam();
}
};
@ -395,20 +325,15 @@ TEST_P(SubprocessTest, SpawnAsyncCwdMissing)
tr_error_clear(&error);
}
#ifdef _WIN32
INSTANTIATE_TEST_SUITE_P( //
INSTANTIATE_TEST_SUITE_P(
Subprocess,
SubprocessTest,
::testing::Values( //
getSelfPath(),
getCmdSelfPath()));
#else
INSTANTIATE_TEST_SUITE_P( //
Subprocess,
SubprocessTest,
::testing::Values( //
getSelfPath()));
#endif
TR_IF_WIN32(
::testing::Values( //
getTestProgramPath("subprocess-test.exe"),
getTestProgramPath("subprocess-test.cmd")),
::testing::Values( //
getTestProgramPath("subprocess-test"))));
} // namespace test

View File

@ -6,6 +6,8 @@
*
*/
#pragma once
#include "crypto-utils.h" // tr_base64_decode_str()
#include "error.h"
#include "file.h" // tr_sys_file_*()
@ -31,14 +33,14 @@ namespace libtransmission
namespace test
{
auto const makeString = [](char*&& s)
inline std::string makeString(char*&& s)
{
auto const ret = std::string(s != nullptr ? s : "");
tr_free(s);
return ret;
};
}
bool waitFor(std::function<bool()> const& test, int msec)
inline bool waitFor(std::function<bool()> const& test, int msec)
{
auto const deadline = std::chrono::milliseconds{ msec };
auto const begin = std::chrono::steady_clock::now();
@ -256,7 +258,7 @@ private:
Sandbox sandbox_;
};
void ensureFormattersInited()
inline void ensureFormattersInited()
{
static constexpr int MEM_K = 1024;
static char const constexpr* const MEM_K_STR = "KiB";
@ -477,8 +479,9 @@ protected:
virtual void SetUp() override
{
session_ = sessionInit(settings());
SandboxedTest::SetUp();
session_ = sessionInit(settings());
}
virtual void TearDown() override

View File

@ -446,6 +446,7 @@ TEST_F(VariantTest, stackSmash)
// confirm that we can serialize it back again
size_t len;
auto* saved = tr_variantToStr(&val, TR_VARIANT_FMT_BENC, &len);
EXPECT_NE(nullptr, saved);
EXPECT_EQ(in, std::string(saved, len));
tr_free(saved);