From dba77c01333810a9676ad1d537f0a82ea3b51f1d Mon Sep 17 00:00:00 2001 From: FrogTheFrog Date: Sun, 28 Apr 2024 12:56:57 +0300 Subject: [PATCH 01/10] feat: Modernize cmake --- CMakeLists.txt | 71 +++++++------------ cmake/linux.cmake | 3 - cmake/macos.cmake | 3 - cmake/windows.cmake | 3 - src/CMakeLists.txt | 19 +++++ src/common/CMakeLists.txt | 11 +++ .../include/libdisplaydevice}/logging.h | 0 src/{ => common}/logging.cpp | 2 +- src/displaydevice/CMakeLists.txt | 14 ++++ .../libdisplaydevice/libddplaceholder.h | 0 src/displaydevice/libddplaceholder.cpp | 9 +++ src/platf/CMakeLists.txt | 28 ++++++++ .../libdisplaydevice/libplatfplaceholder.h | 3 + src/platf/libplatfplaceholder.cpp | 12 ++++ src/windows/CMakeLists.txt | 14 ++++ .../libdisplaydevice}/windows/winapilayer.h | 0 .../windows/winapilayerinterface.h | 0 src/{platf => }/windows/winapilayer.cpp | 4 +- 18 files changed, 137 insertions(+), 59 deletions(-) delete mode 100644 cmake/linux.cmake delete mode 100644 cmake/macos.cmake delete mode 100644 cmake/windows.cmake create mode 100644 src/CMakeLists.txt create mode 100644 src/common/CMakeLists.txt rename src/{ => common/include/libdisplaydevice}/logging.h (100%) rename src/{ => common}/logging.cpp (98%) create mode 100644 src/displaydevice/CMakeLists.txt create mode 100644 src/displaydevice/include/libdisplaydevice/libddplaceholder.h create mode 100644 src/displaydevice/libddplaceholder.cpp create mode 100644 src/platf/CMakeLists.txt create mode 100644 src/platf/include/libdisplaydevice/libplatfplaceholder.h create mode 100644 src/platf/libplatfplaceholder.cpp create mode 100644 src/windows/CMakeLists.txt rename src/{platf => windows/include/libdisplaydevice}/windows/winapilayer.h (100%) rename src/{platf => windows/include/libdisplaydevice}/windows/winapilayerinterface.h (100%) rename src/{platf => }/windows/winapilayer.cpp (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90c291f..9629640 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,67 +1,44 @@ +# +# Project configuration +# cmake_minimum_required(VERSION 3.13) # todo: what is the minimum version required? - project(libdisplaydevice DESCRIPTION "Library to modify display devices." - HOMEPAGE_URL "https://app.lizardbyte.dev") + HOMEPAGE_URL "https://app.lizardbyte.dev" + LANGUAGES CXX) set(PROJECT_LICENSE "GPL-3.0") +set(CMAKE_CXX_STANDARD 20) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Release' as none was specified.") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE) endif() -set(CMAKE_CXX_STANDARD 20) - -# set the module path, used for includes -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") - -# options +# +# Project optional configuration +# option(BUILD_TESTS "Build tests" ON) option(CODE_QL_ANALYSIS "Build is for codeql analysis" OFF) -# auto-set CODE_QL_ANALYSIS based on env variable -if(DEFINED ENV{GITHUB_CODEQL_BUILD}) - set(CODE_QL_ANALYSIS ON) -endif() - -# include directories (for including header files) -include_directories("${CMAKE_SOURCE_DIR}") - -# glob src files, excluding platf directory -file(GLOB_RECURSE DD_COMMON_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/*.cpp") -list(FILTER DD_COMMON_TARGET_FILES EXCLUDE REGEX ".*/platf/.*") - -if(WIN32) - file(GLOB_RECURSE DD_PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platf/windows/*.cpp") - include(${CMAKE_MODULE_PATH}/windows.cmake) -elseif(APPLE) - if(NOT CODE_QL_ANALYSIS) - message(FATAL_ERROR "MacOS is not supported yet.") +# +# Only do these if this is the main project, and not if it is included through add_subdirectory +# +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + # auto-set CODE_QL_ANALYSIS based on env variable + if(DEFINED ENV{GITHUB_CODEQL_BUILD}) + set(CODE_QL_ANALYSIS ON) endif() - file(GLOB_RECURSE DD_PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platf/macos/*.cpp") - include(${CMAKE_MODULE_PATH}/macos.cmake) -elseif(UNIX) - if(NOT CODE_QL_ANALYSIS) - message(FATAL_ERROR "Linux is not supported yet.") - endif() - file(GLOB_RECURSE DD_PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platf/linux/*.cpp") - include(${CMAKE_MODULE_PATH}/linux.cmake) -else() - message(FATAL_ERROR "Unsupported platform") endif() -message(STATUS "Common source files: ${DD_COMMON_TARGET_FILES}") -message(STATUS "Platform source files: ${DD_PLATFORM_TARGET_FILES}") - -# Combine common and platform-specific source files -set(DD_TARGET_FILES ${DD_COMMON_TARGET_FILES} ${DD_PLATFORM_TARGET_FILES}) +# +# Library code is located here +# +add_subdirectory(src) -# tests -if(BUILD_TESTS) +# +# Testing only available if this is the main project +# +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) add_subdirectory(tests) endif() - -# lib -add_library(${PROJECT_NAME} ${DD_TARGET_FILES}) -target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/cmake/linux.cmake b/cmake/linux.cmake deleted file mode 100644 index addf2c1..0000000 --- a/cmake/linux.cmake +++ /dev/null @@ -1,3 +0,0 @@ -# Linux specific setup -file(GLOB_RECURSE DD_TARGET_FILES - "${CMAKE_SOURCE_DIR}/src/platf/linux/*.cpp") diff --git a/cmake/macos.cmake b/cmake/macos.cmake deleted file mode 100644 index e1c5e94..0000000 --- a/cmake/macos.cmake +++ /dev/null @@ -1,3 +0,0 @@ -# macOS specific setup -file(GLOB_RECURSE DD_TARGET_FILES - "${CMAKE_SOURCE_DIR}/src/platf/macos/*.cpp") diff --git a/cmake/windows.cmake b/cmake/windows.cmake deleted file mode 100644 index 606fc02..0000000 --- a/cmake/windows.cmake +++ /dev/null @@ -1,3 +0,0 @@ -# Windows specific setup -file(GLOB_RECURSE DD_TARGET_FILES - "${CMAKE_SOURCE_DIR}/src/platf/windows/*.cpp") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..984f6ef --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,19 @@ +# This a shared common library for other libraries +add_subdirectory(common) + +# This is a platform-specific library +if(WIN32) + add_subdirectory(windows) +elseif(APPLE) + message(WARNING "MacOS is not supported yet.") +elseif(UNIX) + message(WARNING "Linux is not supported yet.") +else() + message(FATAL_ERROR "Unsupported platform") +endif() + +# This is a platform-specific library that loads the correct library for the OS +add_subdirectory(platf) + +# This is the main library +add_subdirectory(displaydevice) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 0000000..83fac6e --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# A global identifier for the library +set(MODULE libcommon) + +# Globing headers here so that they appear in some IDEs +file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/libdisplaydevice/*.h") + +# Automatic library - will be static or dynamic based on user setting +add_library(${MODULE} ${HEADER_LIST} logging.cpp) + +# Provide the includes together with this library +target_include_directories(${MODULE} PUBLIC include) diff --git a/src/logging.h b/src/common/include/libdisplaydevice/logging.h similarity index 100% rename from src/logging.h rename to src/common/include/libdisplaydevice/logging.h diff --git a/src/logging.cpp b/src/common/logging.cpp similarity index 98% rename from src/logging.cpp rename to src/common/logging.cpp index f78d46e..7ddba55 100644 --- a/src/logging.cpp +++ b/src/common/logging.cpp @@ -1,5 +1,5 @@ // class header include -#include "logging.h" +#include "libdisplaydevice/logging.h" // system includes #include diff --git a/src/displaydevice/CMakeLists.txt b/src/displaydevice/CMakeLists.txt new file mode 100644 index 0000000..78fb3fa --- /dev/null +++ b/src/displaydevice/CMakeLists.txt @@ -0,0 +1,14 @@ +# A global identifier for the library +set(MODULE libdisplaydevice) + +# Globing headers here so that they appear in some IDEs +file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/libdisplaydevice/*.h") + +# Automatic library - will be static or dynamic based on user setting +add_library(${MODULE} ${HEADER_LIST} libddplaceholder.cpp) + +# Provide the includes together with this library +target_include_directories(${MODULE} PUBLIC include) + +# Required libraries +target_link_libraries(${MODULE} PRIVATE libplatf libcommon) diff --git a/src/displaydevice/include/libdisplaydevice/libddplaceholder.h b/src/displaydevice/include/libdisplaydevice/libddplaceholder.h new file mode 100644 index 0000000..e69de29 diff --git a/src/displaydevice/libddplaceholder.cpp b/src/displaydevice/libddplaceholder.cpp new file mode 100644 index 0000000..857efb3 --- /dev/null +++ b/src/displaydevice/libddplaceholder.cpp @@ -0,0 +1,9 @@ + +#include "libdisplaydevice/libddplaceholder.h" +#include "libdisplaydevice/libplatfplaceholder.h" +#include "libdisplaydevice/logging.h" + +int ddplaceholder() +{ + return 0; +} diff --git a/src/platf/CMakeLists.txt b/src/platf/CMakeLists.txt new file mode 100644 index 0000000..934cc88 --- /dev/null +++ b/src/platf/CMakeLists.txt @@ -0,0 +1,28 @@ +# A global identifier for the library +set(MODULE libplatf) + +# Globing headers here so that they appear in some IDEs +file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/libdisplaydevice/*.h") + +# Automatic library - will be static or dynamic based on user setting +add_library(${MODULE} ${HEADER_LIST} libplatfplaceholder.cpp) + +# Provide the includes together with this library +target_include_directories(${MODULE} PUBLIC include) + +# Shared libraries between platforms +target_link_libraries(${MODULE} PRIVATE libcommon) + +# Link the platform specific library privately +if(WIN32) + target_link_libraries(${MODULE} PRIVATE libwindows) + target_compile_definitions(${MODULE} PUBLIC DD_WIN) +elseif(APPLE) + message(WARNING "MacOS is not supported yet.") + target_compile_definitions(${MODULE} PUBLIC DD_APPLE) +elseif(UNIX) + message(WARNING "Linux is not supported yet.") + target_compile_definitions(${MODULE} PUBLIC DD_UNIX) +else() + message(FATAL_ERROR "Unsupported platform") +endif() diff --git a/src/platf/include/libdisplaydevice/libplatfplaceholder.h b/src/platf/include/libdisplaydevice/libplatfplaceholder.h new file mode 100644 index 0000000..45dcbb0 --- /dev/null +++ b/src/platf/include/libdisplaydevice/libplatfplaceholder.h @@ -0,0 +1,3 @@ +#pragma once + + diff --git a/src/platf/libplatfplaceholder.cpp b/src/platf/libplatfplaceholder.cpp new file mode 100644 index 0000000..a75be5b --- /dev/null +++ b/src/platf/libplatfplaceholder.cpp @@ -0,0 +1,12 @@ +#include "libdisplaydevice/libplatfplaceholder.h" + +#ifdef DD_WIN + #include "libdisplaydevice/windows/winapilayerinterface.h" +#else +static_assert(false, "LOL"); +#endif + +int +plaftplaceholder() { + return 0; +} diff --git a/src/windows/CMakeLists.txt b/src/windows/CMakeLists.txt new file mode 100644 index 0000000..99e293f --- /dev/null +++ b/src/windows/CMakeLists.txt @@ -0,0 +1,14 @@ +# A global identifier for the library +set(MODULE libwindows) + +# Globing headers here so that they appear in some IDEs +file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/libdisplaydevice/windows/*.h") + +# Automatic library - will be static or dynamic based on user setting +add_library(${MODULE} ${HEADER_LIST} winapilayer.cpp) + +# Provide the includes together with this library +target_include_directories(${MODULE} PUBLIC include) + +# Link the additional libraries +target_link_libraries(${MODULE} PRIVATE libcommon) diff --git a/src/platf/windows/winapilayer.h b/src/windows/include/libdisplaydevice/windows/winapilayer.h similarity index 100% rename from src/platf/windows/winapilayer.h rename to src/windows/include/libdisplaydevice/windows/winapilayer.h diff --git a/src/platf/windows/winapilayerinterface.h b/src/windows/include/libdisplaydevice/windows/winapilayerinterface.h similarity index 100% rename from src/platf/windows/winapilayerinterface.h rename to src/windows/include/libdisplaydevice/windows/winapilayerinterface.h diff --git a/src/platf/windows/winapilayer.cpp b/src/windows/winapilayer.cpp similarity index 99% rename from src/platf/windows/winapilayer.cpp rename to src/windows/winapilayer.cpp index 49a762b..147488a 100644 --- a/src/platf/windows/winapilayer.cpp +++ b/src/windows/winapilayer.cpp @@ -1,11 +1,11 @@ // class header include -#include "winapilayer.h" +#include "libdisplaydevice/windows/winapilayer.h" // system includes #include // local includes -#include "src/logging.h" +#include "libdisplaydevice/logging.h" namespace display_device { namespace { From 8d38828953aebdb9150575c9b8ac1106ec63bb0c Mon Sep 17 00:00:00 2001 From: FrogTheFrog Date: Thu, 2 May 2024 01:34:13 +0300 Subject: [PATCH 02/10] plz work? --- .github/workflows/ci.yml | 4 +- .gitignore | 3 + CMakeLists.txt | 2 +- src/displaydevice/CMakeLists.txt | 2 +- tests/CMakeLists.txt | 102 ++++------ tests/conftest.cpp | 177 ------------------ tests/fixtures/CMakeLists.txt | 14 ++ tests/fixtures/fixtures.cpp | 115 ++++++++++++ tests/fixtures/fixtures.h | 74 ++++++++ tests/{ => fixtures}/utils.cpp | 0 tests/{ => fixtures}/utils.h | 0 tests/unit/CMakeLists.txt | 13 ++ tests/unit/general/CMakeLists.txt | 5 + tests/unit/{ => general}/test_logging.cpp | 3 +- tests/unit/{ => general}/test_sample.cpp | 3 +- tests/unit/platf/linux/test_linux_sample.cpp | 1 - tests/unit/platf/macos/test_macos_sample.cpp | 1 - tests/unit/windows/CMakeLists.txt | 7 + .../{platf => }/windows/test_winapilayer.cpp | 4 +- 19 files changed, 279 insertions(+), 251 deletions(-) delete mode 100644 tests/conftest.cpp create mode 100644 tests/fixtures/CMakeLists.txt create mode 100644 tests/fixtures/fixtures.cpp create mode 100644 tests/fixtures/fixtures.h rename tests/{ => fixtures}/utils.cpp (100%) rename tests/{ => fixtures}/utils.h (100%) create mode 100644 tests/unit/CMakeLists.txt create mode 100644 tests/unit/general/CMakeLists.txt rename tests/unit/{ => general}/test_logging.cpp (99%) rename tests/unit/{ => general}/test_sample.cpp (84%) delete mode 100644 tests/unit/platf/linux/test_linux_sample.cpp delete mode 100644 tests/unit/platf/macos/test_macos_sample.cpp create mode 100644 tests/unit/windows/CMakeLists.txt rename tests/unit/{platf => }/windows/test_winapilayer.cpp (98%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da8a1b6..976b843 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,9 +121,9 @@ jobs: - name: Run tests id: test shell: msys2 {0} - working-directory: build/tests + working-directory: build run: | - ./test_libdisplaydevice.exe --gtest_color=yes + ctest - name: Generate gcov report # any except canceled or skipped diff --git a/.gitignore b/.gitignore index 5073c82..c75a6b1 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,6 @@ # build directories build/ cmake-*/ + +# CTest +Testing/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 9629640..e6be331 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,6 @@ add_subdirectory(src) # # Testing only available if this is the main project # -if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTS) add_subdirectory(tests) endif() diff --git a/src/displaydevice/CMakeLists.txt b/src/displaydevice/CMakeLists.txt index 78fb3fa..c879d3a 100644 --- a/src/displaydevice/CMakeLists.txt +++ b/src/displaydevice/CMakeLists.txt @@ -11,4 +11,4 @@ add_library(${MODULE} ${HEADER_LIST} libddplaceholder.cpp) target_include_directories(${MODULE} PUBLIC include) # Required libraries -target_link_libraries(${MODULE} PRIVATE libplatf libcommon) +target_link_libraries(${MODULE} PUBLIC libcommon PRIVATE libplatf) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8cbf236..b712bcc 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,75 +1,49 @@ -cmake_minimum_required(VERSION 3.13) -# https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md#foundational-c-support - -project(test_libdisplaydevice) - -include_directories("${CMAKE_SOURCE_DIR}") - +# +# Setup google test +# enable_testing() - -# Add GoogleTest directory to the project -set(GTEST_SOURCE_DIR "${CMAKE_SOURCE_DIR}/third-party/googletest") set(INSTALL_GTEST OFF) set(INSTALL_GMOCK OFF) -add_subdirectory("${GTEST_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/googletest") -include_directories("${GTEST_SOURCE_DIR}/googletest/include" "${GTEST_SOURCE_DIR}") - -# coverage +include(GoogleTest) +add_subdirectory("${PROJECT_SOURCE_DIR}/third-party/googletest" "third-party/googletest") + +# A helper function to setup the test executables +function(add_dd_tests) + set(options "") + set(oneValueArgs "") + set(multiValueArgs TESTS LIBRARIES) + cmake_parse_arguments(FN_VARS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + foreach(test ${FN_VARS_TESTS}) + add_executable(${test} ${test}.cpp) + target_link_libraries(${test} + gtest + gtest_main # if we use this we don't need our own main function + libdisplaydevice # we are always testing at least the public API so it's safe to always link this + libfixtures # these are our fixtures/helpers for the tests + ${FN_VARS_LIBRARIES} # additional libraries if needed + ) + + # Adds the test to CTest + gtest_discover_tests(${test}) + endforeach() +endfunction() + +# +# Add subdirectories +# +add_subdirectory(fixtures) +add_subdirectory(unit) + +# +# Additional setup for coverage # https://gcovr.com/en/stable/guide/compiling.html#compiler-options +# set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage -O1") set(CMAKE_C_FLAGS "-fprofile-arcs -ftest-coverage -O1") -# if windows +# TODO: why is this needed? if (WIN32) # For Windows: Prevent overriding the parent project's compiler/linker settings set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # cmake-lint: disable=C0103 endif () - -set(TEST_PATTERNS test_* mock_*) -file(GLOB_RECURSE TEST_SOURCES - "${CMAKE_SOURCE_DIR}/tests/conftest.cpp" - "${CMAKE_SOURCE_DIR}/tests/utils.cpp") -set(TEST_PLATFORM_SOURCES) - -foreach(pattern ${TEST_PATTERNS}) - file(GLOB_RECURSE CURRENT_TEST_SOURCES - "${CMAKE_SOURCE_DIR}/tests/${pattern}.cpp") - list(APPEND TEST_SOURCES ${CURRENT_TEST_SOURCES}) - - if(WIN32) - file(GLOB_RECURSE CURRENT_TEST_PLATFORM_SOURCES - "${CMAKE_SOURCE_DIR}/tests/*/platf/windows/${pattern}.cpp") - elseif(__APPLE__) - file(GLOB_RECURSE CURRENT_TEST_PLATFORM_SOURCES - "${CMAKE_SOURCE_DIR}/tests/*/platf/macos/${pattern}.cpp") - elseif(UNIX) - file(GLOB_RECURSE CURRENT_TEST_PLATFORM_SOURCES - "${CMAKE_SOURCE_DIR}/tests/*/platf/linux/${pattern}.cpp") - else() - message(FATAL_ERROR "Unsupported platform") - endif() - - list(APPEND TEST_PLATFORM_SOURCES ${CURRENT_TEST_PLATFORM_SOURCES}) -endforeach() - -list(FILTER TEST_SOURCES EXCLUDE REGEX ".*/platf/.*") -message(STATUS "Common Test source files: ${TEST_SOURCES}") -message(STATUS "Platform Test source files: ${TEST_PLATFORM_SOURCES}") - -set(DD_SOURCES - ${DD_TARGET_FILES}) - -add_executable(${PROJECT_NAME} - ${TEST_SOURCES} - ${TEST_PLATFORM_SOURCES} - ${DD_SOURCES}) -set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 20) -target_link_libraries(${PROJECT_NAME} - ${DD_EXTERNAL_LIBRARIES} - gtest - gtest_main) # if we use this we don't need our own main function -target_compile_definitions(${PROJECT_NAME} PUBLIC ${DD_DEFINITIONS} ${TEST_DEFINITIONS}) -target_compile_options(${PROJECT_NAME} PRIVATE $<$:${DD_COMPILE_OPTIONS}> -std=c++20) -target_link_options(${PROJECT_NAME} PRIVATE) - -add_test(NAME ${PROJECT_NAME} COMMAND libdisplaydevice_test) diff --git a/tests/conftest.cpp b/tests/conftest.cpp deleted file mode 100644 index f06eca1..0000000 --- a/tests/conftest.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// system includes -#include -#include - -// local includes -#include "src/logging.h" -#include "tests/utils.h" - -// Undefine the original TEST macro -#undef TEST - -// Redefine TEST to use our BaseTest class, to automatically use our BaseTest fixture -#define TEST(test_case_name, test_name) \ - GTEST_TEST_(test_case_name, test_name, ::BaseTest, \ - ::testing::internal::GetTypeId<::BaseTest>()) - -/** - * @brief Base class for tests. - * - * This class provides a base test fixture for all tests. - * - * ``cout``, ``stderr``, and ``stdout`` are redirected to a buffer, and the buffer is printed if the test fails. - * - * @todo Retain the color of the original output. - */ -class BaseTest: public ::testing::Test { -protected: - // https://stackoverflow.com/a/58369622/11214013 - - // we can possibly use some internal googletest functions to capture stdout and stderr, but I have not tested this - // https://stackoverflow.com/a/33186201/11214013 - - BaseTest(): - sbuf { nullptr }, pipe_stdout { nullptr }, pipe_stderr { nullptr } { - // intentionally empty - } - - ~BaseTest() override = default; - - void - SetUp() override { - // todo: only run this one time, instead of every time a test is run - // see: https://stackoverflow.com/questions/2435277/googletest-accessing-the-environment-from-a-test - // get command line args from the test executable - testArgs = ::testing::internal::GetArgvs(); - - // then get the directory of the test executable - // std::string path = ::testing::internal::GetArgvs()[0]; - testBinary = testArgs[0]; - - // get the directory of the test executable - testBinaryDir = std::filesystem::path(testBinary).parent_path(); - - // If testBinaryDir is empty or `.` then set it to the current directory - // maybe some better options here: https://stackoverflow.com/questions/875249/how-to-get-current-directory - if (testBinaryDir.empty() || testBinaryDir.string() == ".") { - testBinaryDir = std::filesystem::current_path(); - } - - sbuf = std::cout.rdbuf(); // save cout buffer (std::cout) - std::cout.rdbuf(cout_buffer.rdbuf()); // redirect cout to buffer (std::cout) - - // Default to the verbose level in case some test fails - display_device::logger_t::get().set_log_level(display_device::logger_t::log_level_e::verbose); - } - - void - TearDown() override { - display_device::logger_t::get().set_custom_callback(nullptr); // restore the default callback to avoid potential leaks - std::cout.rdbuf(sbuf); // restore cout buffer - - // get test info - const ::testing::TestInfo *const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); - - if (test_info->result()->Failed()) { - std::cout << std::endl - << "Test failed: " << test_info->name() << std::endl - << std::endl - << "Captured cout:" << std::endl - << cout_buffer.str() << std::endl - << "Captured stdout:" << std::endl - << stdout_buffer.str() << std::endl - << "Captured stderr:" << std::endl - << stderr_buffer.str() << std::endl; - } - - sbuf = nullptr; // clear sbuf - if (pipe_stdout) { - pclose(pipe_stdout); - pipe_stdout = nullptr; - } - if (pipe_stderr) { - pclose(pipe_stderr); - pipe_stderr = nullptr; - } - } - - // functions and variables - std::vector testArgs; // CLI arguments used - std::filesystem::path testBinary; // full path of this binary - std::filesystem::path testBinaryDir; // full directory of this binary - std::stringstream cout_buffer; // declare cout_buffer - std::stringstream stdout_buffer; // declare stdout_buffer - std::stringstream stderr_buffer; // declare stderr_buffer - std::streambuf *sbuf; - FILE *pipe_stdout; - FILE *pipe_stderr; - - int - exec(const char *cmd) { - std::array buffer {}; - pipe_stdout = popen((std::string(cmd) + " 2>&1").c_str(), "r"); - pipe_stderr = popen((std::string(cmd) + " 2>&1").c_str(), "r"); - if (!pipe_stdout || !pipe_stderr) { - throw std::runtime_error("popen() failed!"); - } - while (fgets(buffer.data(), buffer.size(), pipe_stdout) != nullptr) { - stdout_buffer << buffer.data(); - } - while (fgets(buffer.data(), buffer.size(), pipe_stderr) != nullptr) { - stderr_buffer << buffer.data(); - } - int returnCode = pclose(pipe_stdout); - pipe_stdout = nullptr; - if (returnCode != 0) { - std::cout << "Error: " << stderr_buffer.str() << std::endl - << "Return code: " << returnCode << std::endl; - } - return returnCode; - } -}; - -class LinuxTest: public BaseTest { -protected: - void - SetUp() override { -#ifndef __linux__ - GTEST_SKIP_("Skipping, this test is for Linux only."); -#endif - } - - void - TearDown() override { - BaseTest::TearDown(); - } -}; - -class MacOSTest: public BaseTest { -protected: - void - SetUp() override { -#if !defined(__APPLE__) || !defined(__MACH__) - GTEST_SKIP_("Skipping, this test is for macOS only."); -#endif - } - - void - TearDown() override { - BaseTest::TearDown(); - } -}; - -class WindowsTest: public BaseTest { -protected: - void - SetUp() override { -#ifndef _WIN32 - GTEST_SKIP_("Skipping, this test is for Windows only."); -#endif - BaseTest::SetUp(); - } - - void - TearDown() override { - BaseTest::TearDown(); - } -}; diff --git a/tests/fixtures/CMakeLists.txt b/tests/fixtures/CMakeLists.txt new file mode 100644 index 0000000..34e58b2 --- /dev/null +++ b/tests/fixtures/CMakeLists.txt @@ -0,0 +1,14 @@ +# A global identifier for the library +set(MODULE libfixtures) + +# Globing headers here so that they appear in some IDEs +file(GLOB HEADER_LIST CONFIGURE_DEPENDS "*.h") + +# Automatic library - will be static or dynamic based on user setting +add_library(${MODULE} ${HEADER_LIST} utils.cpp fixtures.cpp) + +# Provide the includes together with this library +target_include_directories(${MODULE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +# Link the additional libraries +target_link_libraries(${MODULE} PRIVATE gtest libcommon) diff --git a/tests/fixtures/fixtures.cpp b/tests/fixtures/fixtures.cpp new file mode 100644 index 0000000..3eaa12c --- /dev/null +++ b/tests/fixtures/fixtures.cpp @@ -0,0 +1,115 @@ +// header include +#include "fixtures.h" + +// local includes +#include "libdisplaydevice/logging.h" + +BaseTest::BaseTest(): + sbuf { nullptr }, pipe_stdout { nullptr }, pipe_stderr { nullptr } { + // intentionally empty +} + +void +BaseTest::SetUp() { + // todo: only run this one time, instead of every time a test is run + // see: https://stackoverflow.com/questions/2435277/googletest-accessing-the-environment-from-a-test + // get command line args from the test executable + testArgs = ::testing::internal::GetArgvs(); + + // then get the directory of the test executable + // std::string path = ::testing::internal::GetArgvs()[0]; + testBinary = testArgs[0]; + + // get the directory of the test executable + testBinaryDir = std::filesystem::path(testBinary).parent_path(); + + // If testBinaryDir is empty or `.` then set it to the current directory + // maybe some better options here: https://stackoverflow.com/questions/875249/how-to-get-current-directory + if (testBinaryDir.empty() || testBinaryDir.string() == ".") { + testBinaryDir = std::filesystem::current_path(); + } + + sbuf = std::cout.rdbuf(); // save cout buffer (std::cout) + std::cout.rdbuf(cout_buffer.rdbuf()); // redirect cout to buffer (std::cout) + + // Default to the verbose level in case some test fails + display_device::logger_t::get().set_log_level(display_device::logger_t::log_level_e::verbose); +} + +void +BaseTest::TearDown() { + display_device::logger_t::get().set_custom_callback(nullptr); // restore the default callback to avoid potential leaks + std::cout.rdbuf(sbuf); // restore cout buffer + + // get test info + const ::testing::TestInfo *const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); + + if (test_info->result()->Failed()) { + std::cout << std::endl + << "Test failed: " << test_info->name() << std::endl + << std::endl + << "Captured cout:" << std::endl + << cout_buffer.str() << std::endl + << "Captured stdout:" << std::endl + << stdout_buffer.str() << std::endl + << "Captured stderr:" << std::endl + << stderr_buffer.str() << std::endl; + } + + sbuf = nullptr; // clear sbuf + if (pipe_stdout) { + pclose(pipe_stdout); + pipe_stdout = nullptr; + } + if (pipe_stderr) { + pclose(pipe_stderr); + pipe_stderr = nullptr; + } +} + +int +BaseTest::exec(const char *cmd) { + std::array buffer {}; + pipe_stdout = popen((std::string(cmd) + " 2>&1").c_str(), "r"); + pipe_stderr = popen((std::string(cmd) + " 2>&1").c_str(), "r"); + if (!pipe_stdout || !pipe_stderr) { + throw std::runtime_error("popen() failed!"); + } + while (fgets(buffer.data(), buffer.size(), pipe_stdout) != nullptr) { + stdout_buffer << buffer.data(); + } + while (fgets(buffer.data(), buffer.size(), pipe_stderr) != nullptr) { + stderr_buffer << buffer.data(); + } + int returnCode = pclose(pipe_stdout); + pipe_stdout = nullptr; + if (returnCode != 0) { + std::cout << "Error: " << stderr_buffer.str() << std::endl + << "Return code: " << returnCode << std::endl; + } + return returnCode; +} + +void +LinuxTest::SetUp() { +#ifndef __linux__ + GTEST_SKIP_("Skipping, this test is for Linux only."); +#endif + BaseTest::SetUp(); +} + +void +MacOSTest::SetUp() { +#if !defined(__APPLE__) || !defined(__MACH__) + GTEST_SKIP_("Skipping, this test is for macOS only."); +#endif + BaseTest::SetUp(); +} + +void +WindowsTest::SetUp() { +#ifndef _WIN32 + GTEST_SKIP_("Skipping, this test is for Windows only."); +#endif + BaseTest::SetUp(); +} diff --git a/tests/fixtures/fixtures.h b/tests/fixtures/fixtures.h new file mode 100644 index 0000000..2d6d58b --- /dev/null +++ b/tests/fixtures/fixtures.h @@ -0,0 +1,74 @@ +#pragma once + +// system includes +#include +#include + +// local includes +#include "utils.h" + +// Undefine the original TEST macro +#undef TEST + +// Redefine TEST to use our BaseTest class, to automatically use our BaseTest fixture +#define TEST(test_case_name, test_name) \ + GTEST_TEST_(test_case_name, test_name, ::BaseTest, \ + ::testing::internal::GetTypeId<::BaseTest>()) + +/** + * @brief Base class for tests. + * + * This class provides a base test fixture for all tests. + * + * ``cout``, ``stderr``, and ``stdout`` are redirected to a buffer, and the buffer is printed if the test fails. + * + * @todo Retain the color of the original output. + */ +class BaseTest: public ::testing::Test { +protected: + // https://stackoverflow.com/a/58369622/11214013 + + // we can possibly use some internal googletest functions to capture stdout and stderr, but I have not tested this + // https://stackoverflow.com/a/33186201/11214013 + + BaseTest(); + ~BaseTest() override = default; + + void + SetUp() override; + + void + TearDown() override; + + int + exec(const char *cmd); + + // functions and variables + std::vector testArgs; // CLI arguments used + std::filesystem::path testBinary; // full path of this binary + std::filesystem::path testBinaryDir; // full directory of this binary + std::stringstream cout_buffer; // declare cout_buffer + std::stringstream stdout_buffer; // declare stdout_buffer + std::stringstream stderr_buffer; // declare stderr_buffer + std::streambuf *sbuf; + FILE *pipe_stdout; + FILE *pipe_stderr; +}; + +class LinuxTest: public BaseTest { +protected: + void + SetUp() override; +}; + +class MacOSTest: public BaseTest { +protected: + void + SetUp() override; +}; + +class WindowsTest: public BaseTest { +protected: + void + SetUp() override; +}; diff --git a/tests/utils.cpp b/tests/fixtures/utils.cpp similarity index 100% rename from tests/utils.cpp rename to tests/fixtures/utils.cpp diff --git a/tests/utils.h b/tests/fixtures/utils.h similarity index 100% rename from tests/utils.h rename to tests/fixtures/utils.h diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt new file mode 100644 index 0000000..7ec2ea8 --- /dev/null +++ b/tests/unit/CMakeLists.txt @@ -0,0 +1,13 @@ +# General platform-agnostic tests +add_subdirectory(general) + +# Platform specific tests +if(WIN32) + add_subdirectory(windows) +elseif(APPLE) + message(WARNING "MacOS is not supported yet.") +elseif(UNIX) + message(WARNING "Linux is not supported yet.") +else() + message(FATAL_ERROR "Unsupported platform") +endif() diff --git a/tests/unit/general/CMakeLists.txt b/tests/unit/general/CMakeLists.txt new file mode 100644 index 0000000..65cd506 --- /dev/null +++ b/tests/unit/general/CMakeLists.txt @@ -0,0 +1,5 @@ +add_dd_tests( + TESTS + test_logging + test_sample +) diff --git a/tests/unit/test_logging.cpp b/tests/unit/general/test_logging.cpp similarity index 99% rename from tests/unit/test_logging.cpp rename to tests/unit/general/test_logging.cpp index d312df7..e6c822f 100644 --- a/tests/unit/test_logging.cpp +++ b/tests/unit/general/test_logging.cpp @@ -1,5 +1,6 @@ // local includes -#include "tests/conftest.cpp" +#include "fixtures.h" +#include "libdisplaydevice/logging.h" TEST(LoggingTest, LogLevelVerbose) { using level = display_device::logger_t::log_level_e; diff --git a/tests/unit/test_sample.cpp b/tests/unit/general/test_sample.cpp similarity index 84% rename from tests/unit/test_sample.cpp rename to tests/unit/general/test_sample.cpp index 0fbd3a2..c494f28 100644 --- a/tests/unit/test_sample.cpp +++ b/tests/unit/general/test_sample.cpp @@ -1,4 +1,5 @@ -#include +// local includes +#include "fixtures.h" TEST(HelloWorldTest, HelloWorld) { EXPECT_TRUE(true); diff --git a/tests/unit/platf/linux/test_linux_sample.cpp b/tests/unit/platf/linux/test_linux_sample.cpp deleted file mode 100644 index b186cfc..0000000 --- a/tests/unit/platf/linux/test_linux_sample.cpp +++ /dev/null @@ -1 +0,0 @@ -// TODO: remove this file diff --git a/tests/unit/platf/macos/test_macos_sample.cpp b/tests/unit/platf/macos/test_macos_sample.cpp deleted file mode 100644 index b186cfc..0000000 --- a/tests/unit/platf/macos/test_macos_sample.cpp +++ /dev/null @@ -1 +0,0 @@ -// TODO: remove this file diff --git a/tests/unit/windows/CMakeLists.txt b/tests/unit/windows/CMakeLists.txt new file mode 100644 index 0000000..4b42060 --- /dev/null +++ b/tests/unit/windows/CMakeLists.txt @@ -0,0 +1,7 @@ +add_dd_tests( + TESTS + test_winapilayer + + LIBRARIES + libwindows +) diff --git a/tests/unit/platf/windows/test_winapilayer.cpp b/tests/unit/windows/test_winapilayer.cpp similarity index 98% rename from tests/unit/platf/windows/test_winapilayer.cpp rename to tests/unit/windows/test_winapilayer.cpp index 0f92c37..2db2c89 100644 --- a/tests/unit/platf/windows/test_winapilayer.cpp +++ b/tests/unit/windows/test_winapilayer.cpp @@ -1,6 +1,6 @@ // local includes -#include "src/platf/windows/winapilayer.h" -#include "tests/conftest.cpp" +#include "fixtures.h" +#include "libdisplaydevice/windows/winapilayer.h" TEST(LoggingTest, GetErrorString) { const display_device::WinApiLayer layer; From dc1416f39f060071eb8a8b3265424e18dd6ca9d4 Mon Sep 17 00:00:00 2001 From: FrogTheFrog Date: Thu, 2 May 2024 01:46:24 +0300 Subject: [PATCH 03/10] plz work? --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 976b843..378ea69 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,6 +123,7 @@ jobs: shell: msys2 {0} working-directory: build run: | + cd build ctest - name: Generate gcov report From a6699b006356e5c5ff951a607f19f56a57a2603b Mon Sep 17 00:00:00 2001 From: FrogTheFrog Date: Thu, 2 May 2024 01:49:40 +0300 Subject: [PATCH 04/10] hmmm --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 378ea69..21aa8e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,7 +123,8 @@ jobs: shell: msys2 {0} working-directory: build run: | - cd build + pwd + ls ctest - name: Generate gcov report From 78b81919f6a442f9688c393350c862d106a8bfa2 Mon Sep 17 00:00:00 2001 From: FrogTheFrog Date: Thu, 2 May 2024 01:56:47 +0300 Subject: [PATCH 05/10] hmmm --- .github/workflows/ci.yml | 6 ++---- tests/unit/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21aa8e1..28e2b06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,11 +121,9 @@ jobs: - name: Run tests id: test shell: msys2 {0} - working-directory: build + working-directory: build/tests run: | - pwd - ls - ctest + ctest --extra-verbose - name: Generate gcov report # any except canceled or skipped diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 7ec2ea8..20e84f5 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,4 +1,4 @@ -# General platform-agnostic tests +# General platform-agnostic tests (or without hard platform dependencies) add_subdirectory(general) # Platform specific tests From bc3551ecdbee00e75d1884ce25d328903cf6c14f Mon Sep 17 00:00:00 2001 From: FrogTheFrog Date: Thu, 2 May 2024 17:55:04 +0300 Subject: [PATCH 06/10] hmmm --- .github/workflows/ci.yml | 2 +- CMakeLists.txt | 1 + src/common/CMakeLists.txt | 7 ++- .../logging.h | 0 src/common/logging.cpp | 2 +- src/displaydevice/CMakeLists.txt | 7 ++- .../libddplaceholder.h | 0 src/displaydevice/libddplaceholder.cpp | 5 +- src/platf/CMakeLists.txt | 10 ++- .../displaydevice/libplatfplaceholder.h | 0 .../libdisplaydevice/libplatfplaceholder.h | 3 - src/platf/libplatfplaceholder.cpp | 8 +-- src/windows/CMakeLists.txt | 5 +- .../windows/winapilayer.h | 0 .../windows/winapilayerinterface.h | 0 src/windows/winapilayer.cpp | 4 +- tests/CMakeLists.txt | 62 ++++++++++++------- tests/fixtures/CMakeLists.txt | 5 +- tests/fixtures/fixtures.cpp | 29 ++++++++- tests/fixtures/fixtures.h | 9 +++ tests/unit/general/CMakeLists.txt | 7 +-- tests/unit/general/test_logging.cpp | 2 +- tests/unit/windows/CMakeLists.txt | 9 +-- tests/unit/windows/test_winapilayer.cpp | 10 +-- 24 files changed, 111 insertions(+), 76 deletions(-) rename src/common/include/{libdisplaydevice => displaydevice}/logging.h (100%) rename src/displaydevice/include/{libdisplaydevice => displaydevice}/libddplaceholder.h (100%) create mode 100644 src/platf/include/displaydevice/libplatfplaceholder.h delete mode 100644 src/platf/include/libdisplaydevice/libplatfplaceholder.h rename src/windows/include/{libdisplaydevice => displaydevice}/windows/winapilayer.h (100%) rename src/windows/include/{libdisplaydevice => displaydevice}/windows/winapilayerinterface.h (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28e2b06..0b542b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,7 +121,7 @@ jobs: - name: Run tests id: test shell: msys2 {0} - working-directory: build/tests + working-directory: build run: | ctest --extra-verbose diff --git a/CMakeLists.txt b/CMakeLists.txt index e6be331..1378cd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,5 +40,6 @@ add_subdirectory(src) # Testing only available if this is the main project # if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTS) + enable_testing() add_subdirectory(tests) endif() diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 83fac6e..01afea8 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,11 +1,12 @@ # A global identifier for the library set(MODULE libcommon) -# Globing headers here so that they appear in some IDEs -file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/libdisplaydevice/*.h") +# Globing headers (so that they appear in some IDEs) and sources +file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/displaydevice/*.h") +file(GLOB SOURCE_LIST CONFIGURE_DEPENDS "*.cpp") # Automatic library - will be static or dynamic based on user setting -add_library(${MODULE} ${HEADER_LIST} logging.cpp) +add_library(${MODULE} ${HEADER_LIST} ${SOURCE_LIST}) # Provide the includes together with this library target_include_directories(${MODULE} PUBLIC include) diff --git a/src/common/include/libdisplaydevice/logging.h b/src/common/include/displaydevice/logging.h similarity index 100% rename from src/common/include/libdisplaydevice/logging.h rename to src/common/include/displaydevice/logging.h diff --git a/src/common/logging.cpp b/src/common/logging.cpp index 7ddba55..2b54ad1 100644 --- a/src/common/logging.cpp +++ b/src/common/logging.cpp @@ -1,5 +1,5 @@ // class header include -#include "libdisplaydevice/logging.h" +#include "displaydevice/logging.h" // system includes #include diff --git a/src/displaydevice/CMakeLists.txt b/src/displaydevice/CMakeLists.txt index c879d3a..223d660 100644 --- a/src/displaydevice/CMakeLists.txt +++ b/src/displaydevice/CMakeLists.txt @@ -1,11 +1,12 @@ # A global identifier for the library set(MODULE libdisplaydevice) -# Globing headers here so that they appear in some IDEs -file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/libdisplaydevice/*.h") +# Globing headers (so that they appear in some IDEs) and sources +file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/displaydevice/*.h") +file(GLOB SOURCE_LIST CONFIGURE_DEPENDS "*.cpp") # Automatic library - will be static or dynamic based on user setting -add_library(${MODULE} ${HEADER_LIST} libddplaceholder.cpp) +add_library(${MODULE} ${HEADER_LIST} ${SOURCE_LIST}) # Provide the includes together with this library target_include_directories(${MODULE} PUBLIC include) diff --git a/src/displaydevice/include/libdisplaydevice/libddplaceholder.h b/src/displaydevice/include/displaydevice/libddplaceholder.h similarity index 100% rename from src/displaydevice/include/libdisplaydevice/libddplaceholder.h rename to src/displaydevice/include/displaydevice/libddplaceholder.h diff --git a/src/displaydevice/libddplaceholder.cpp b/src/displaydevice/libddplaceholder.cpp index 857efb3..c117747 100644 --- a/src/displaydevice/libddplaceholder.cpp +++ b/src/displaydevice/libddplaceholder.cpp @@ -1,7 +1,4 @@ - -#include "libdisplaydevice/libddplaceholder.h" -#include "libdisplaydevice/libplatfplaceholder.h" -#include "libdisplaydevice/logging.h" +#include "displaydevice/libddplaceholder.h" int ddplaceholder() { diff --git a/src/platf/CMakeLists.txt b/src/platf/CMakeLists.txt index 934cc88..be702ce 100644 --- a/src/platf/CMakeLists.txt +++ b/src/platf/CMakeLists.txt @@ -1,11 +1,12 @@ # A global identifier for the library set(MODULE libplatf) -# Globing headers here so that they appear in some IDEs -file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/libdisplaydevice/*.h") +# Globing headers (so that they appear in some IDEs) and sources +file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/displaydevice/*.h") +file(GLOB SOURCE_LIST CONFIGURE_DEPENDS "*.cpp") # Automatic library - will be static or dynamic based on user setting -add_library(${MODULE} ${HEADER_LIST} libplatfplaceholder.cpp) +add_library(${MODULE} ${HEADER_LIST} ${SOURCE_LIST}) # Provide the includes together with this library target_include_directories(${MODULE} PUBLIC include) @@ -16,13 +17,10 @@ target_link_libraries(${MODULE} PRIVATE libcommon) # Link the platform specific library privately if(WIN32) target_link_libraries(${MODULE} PRIVATE libwindows) - target_compile_definitions(${MODULE} PUBLIC DD_WIN) elseif(APPLE) message(WARNING "MacOS is not supported yet.") - target_compile_definitions(${MODULE} PUBLIC DD_APPLE) elseif(UNIX) message(WARNING "Linux is not supported yet.") - target_compile_definitions(${MODULE} PUBLIC DD_UNIX) else() message(FATAL_ERROR "Unsupported platform") endif() diff --git a/src/platf/include/displaydevice/libplatfplaceholder.h b/src/platf/include/displaydevice/libplatfplaceholder.h new file mode 100644 index 0000000..e69de29 diff --git a/src/platf/include/libdisplaydevice/libplatfplaceholder.h b/src/platf/include/libdisplaydevice/libplatfplaceholder.h deleted file mode 100644 index 45dcbb0..0000000 --- a/src/platf/include/libdisplaydevice/libplatfplaceholder.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - - diff --git a/src/platf/libplatfplaceholder.cpp b/src/platf/libplatfplaceholder.cpp index a75be5b..8754fc4 100644 --- a/src/platf/libplatfplaceholder.cpp +++ b/src/platf/libplatfplaceholder.cpp @@ -1,10 +1,4 @@ -#include "libdisplaydevice/libplatfplaceholder.h" - -#ifdef DD_WIN - #include "libdisplaydevice/windows/winapilayerinterface.h" -#else -static_assert(false, "LOL"); -#endif +#include "displaydevice/libplatfplaceholder.h" int plaftplaceholder() { diff --git a/src/windows/CMakeLists.txt b/src/windows/CMakeLists.txt index 99e293f..2af2f2f 100644 --- a/src/windows/CMakeLists.txt +++ b/src/windows/CMakeLists.txt @@ -1,11 +1,12 @@ # A global identifier for the library set(MODULE libwindows) -# Globing headers here so that they appear in some IDEs +# Globing headers (so that they appear in some IDEs) and sources file(GLOB HEADER_LIST CONFIGURE_DEPENDS "include/libdisplaydevice/windows/*.h") +file(GLOB SOURCE_LIST CONFIGURE_DEPENDS "*.cpp") # Automatic library - will be static or dynamic based on user setting -add_library(${MODULE} ${HEADER_LIST} winapilayer.cpp) +add_library(${MODULE} ${HEADER_LIST} ${SOURCE_LIST}) # Provide the includes together with this library target_include_directories(${MODULE} PUBLIC include) diff --git a/src/windows/include/libdisplaydevice/windows/winapilayer.h b/src/windows/include/displaydevice/windows/winapilayer.h similarity index 100% rename from src/windows/include/libdisplaydevice/windows/winapilayer.h rename to src/windows/include/displaydevice/windows/winapilayer.h diff --git a/src/windows/include/libdisplaydevice/windows/winapilayerinterface.h b/src/windows/include/displaydevice/windows/winapilayerinterface.h similarity index 100% rename from src/windows/include/libdisplaydevice/windows/winapilayerinterface.h rename to src/windows/include/displaydevice/windows/winapilayerinterface.h diff --git a/src/windows/winapilayer.cpp b/src/windows/winapilayer.cpp index 147488a..dbc1da4 100644 --- a/src/windows/winapilayer.cpp +++ b/src/windows/winapilayer.cpp @@ -1,11 +1,11 @@ // class header include -#include "libdisplaydevice/windows/winapilayer.h" +#include "displaydevice/windows/winapilayer.h" // system includes #include // local includes -#include "libdisplaydevice/logging.h" +#include "displaydevice/logging.h" namespace display_device { namespace { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b712bcc..b5be41d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,32 +1,36 @@ # # Setup google test # -enable_testing() set(INSTALL_GTEST OFF) set(INSTALL_GMOCK OFF) include(GoogleTest) add_subdirectory("${PROJECT_SOURCE_DIR}/third-party/googletest" "third-party/googletest") -# A helper function to setup the test executables -function(add_dd_tests) +if (WIN32) + # For Windows: Prevent overriding the parent project's compiler/linker settings + set(gtest_force_shared_crt ON CACHE BOOL "Always use msvcrt.dll" FORCE) # cmake-lint: disable=C0103 +endif () + +# A helper function to setup the dependencies for the test executable +function(add_dd_test_dir) set(options "") set(oneValueArgs "") - set(multiValueArgs TESTS LIBRARIES) + set(multiValueArgs ADDITIONAL_LIBRARIES) cmake_parse_arguments(FN_VARS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - foreach(test ${FN_VARS_TESTS}) - add_executable(${test} ${test}.cpp) - target_link_libraries(${test} - gtest - gtest_main # if we use this we don't need our own main function - libdisplaydevice # we are always testing at least the public API so it's safe to always link this - libfixtures # these are our fixtures/helpers for the tests - ${FN_VARS_LIBRARIES} # additional libraries if needed - ) - - # Adds the test to CTest - gtest_discover_tests(${test}) - endforeach() + # Get the current sources and libraries + get_property(sources GLOBAL PROPERTY DD_TEST_SOURCES) + get_property(libraries GLOBAL PROPERTY DD_TEST_LIBRARIES) + + # Gather new data + file(GLOB test_files CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/test_*.cpp") + + list(APPEND sources ${test_files}) + list(APPEND libraries ${FN_VARS_ADDITIONAL_LIBRARIES}) + + # Update the global variables + set_property(GLOBAL PROPERTY DD_TEST_SOURCES "${sources}") + set_property(GLOBAL PROPERTY DD_TEST_LIBRARIES "${libraries}") endfunction() # @@ -35,15 +39,27 @@ endfunction() add_subdirectory(fixtures) add_subdirectory(unit) +# +# Setup the final test binary +# +set(TEST_BINARY test_libdisplaydevice) +get_property(sources GLOBAL PROPERTY DD_TEST_SOURCES) +get_property(libraries GLOBAL PROPERTY DD_TEST_LIBRARIES) + +add_executable(${TEST_BINARY} ${sources}) +target_link_libraries(${TEST_BINARY} + gtest_main # if we use this we don't need our own main function + libdisplaydevice # we are always testing at least the public API so it's safe to always link this + libfixtures # these are our fixtures/helpers for the tests + ${libraries} # additional libraries if needed +) + +# Add the test to CTest +gtest_discover_tests(${TEST_BINARY}) + # # Additional setup for coverage # https://gcovr.com/en/stable/guide/compiling.html#compiler-options # set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage -O1") set(CMAKE_C_FLAGS "-fprofile-arcs -ftest-coverage -O1") - -# TODO: why is this needed? -if (WIN32) - # For Windows: Prevent overriding the parent project's compiler/linker settings - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # cmake-lint: disable=C0103 -endif () diff --git a/tests/fixtures/CMakeLists.txt b/tests/fixtures/CMakeLists.txt index 34e58b2..dd70433 100644 --- a/tests/fixtures/CMakeLists.txt +++ b/tests/fixtures/CMakeLists.txt @@ -1,11 +1,12 @@ # A global identifier for the library set(MODULE libfixtures) -# Globing headers here so that they appear in some IDEs +# Globing headers (so that they appear in some IDEs) and sources file(GLOB HEADER_LIST CONFIGURE_DEPENDS "*.h") +file(GLOB SOURCE_LIST CONFIGURE_DEPENDS "*.cpp") # Automatic library - will be static or dynamic based on user setting -add_library(${MODULE} ${HEADER_LIST} utils.cpp fixtures.cpp) +add_library(${MODULE} ${HEADER_LIST} ${SOURCE_LIST}) # Provide the includes together with this library target_include_directories(${MODULE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/fixtures/fixtures.cpp b/tests/fixtures/fixtures.cpp index 3eaa12c..8f78815 100644 --- a/tests/fixtures/fixtures.cpp +++ b/tests/fixtures/fixtures.cpp @@ -2,7 +2,7 @@ #include "fixtures.h" // local includes -#include "libdisplaydevice/logging.h" +#include "displaydevice/logging.h" BaseTest::BaseTest(): sbuf { nullptr }, pipe_stdout { nullptr }, pipe_stderr { nullptr } { @@ -98,6 +98,15 @@ LinuxTest::SetUp() { BaseTest::SetUp(); } +void +LinuxTest::TearDown() { +#ifndef __linux__ + // This a noop case to skip the teardown + return; +#endif + BaseTest::TearDown(); +} + void MacOSTest::SetUp() { #if !defined(__APPLE__) || !defined(__MACH__) @@ -106,6 +115,15 @@ MacOSTest::SetUp() { BaseTest::SetUp(); } +void +MacOSTest::TearDown() { +#if !defined(__APPLE__) || !defined(__MACH__) + // This a noop case to skip the teardown + return; +#endif + BaseTest::TearDown(); +} + void WindowsTest::SetUp() { #ifndef _WIN32 @@ -113,3 +131,12 @@ WindowsTest::SetUp() { #endif BaseTest::SetUp(); } + +void +WindowsTest::TearDown() { +#ifndef _WIN32 + // This a noop case to skip the teardown + return; +#endif + BaseTest::TearDown(); +} diff --git a/tests/fixtures/fixtures.h b/tests/fixtures/fixtures.h index 2d6d58b..ced4276 100644 --- a/tests/fixtures/fixtures.h +++ b/tests/fixtures/fixtures.h @@ -59,16 +59,25 @@ class LinuxTest: public BaseTest { protected: void SetUp() override; + + void + TearDown() override; }; class MacOSTest: public BaseTest { protected: void SetUp() override; + + void + TearDown() override; }; class WindowsTest: public BaseTest { protected: void SetUp() override; + + void + TearDown() override; }; diff --git a/tests/unit/general/CMakeLists.txt b/tests/unit/general/CMakeLists.txt index 65cd506..39a9a07 100644 --- a/tests/unit/general/CMakeLists.txt +++ b/tests/unit/general/CMakeLists.txt @@ -1,5 +1,2 @@ -add_dd_tests( - TESTS - test_logging - test_sample -) +# Add the test files in this directory +add_dd_test_dir() diff --git a/tests/unit/general/test_logging.cpp b/tests/unit/general/test_logging.cpp index e6c822f..f99f0df 100644 --- a/tests/unit/general/test_logging.cpp +++ b/tests/unit/general/test_logging.cpp @@ -1,6 +1,6 @@ // local includes +#include "displaydevice/logging.h" #include "fixtures.h" -#include "libdisplaydevice/logging.h" TEST(LoggingTest, LogLevelVerbose) { using level = display_device::logger_t::log_level_e; diff --git a/tests/unit/windows/CMakeLists.txt b/tests/unit/windows/CMakeLists.txt index 4b42060..11ab7f0 100644 --- a/tests/unit/windows/CMakeLists.txt +++ b/tests/unit/windows/CMakeLists.txt @@ -1,7 +1,2 @@ -add_dd_tests( - TESTS - test_winapilayer - - LIBRARIES - libwindows -) +# Add the test files in this directory +add_dd_test_dir(ADDITIONAL_LIBRARIES libwindows) diff --git a/tests/unit/windows/test_winapilayer.cpp b/tests/unit/windows/test_winapilayer.cpp index 2db2c89..bee9d91 100644 --- a/tests/unit/windows/test_winapilayer.cpp +++ b/tests/unit/windows/test_winapilayer.cpp @@ -1,8 +1,8 @@ // local includes +#include "displaydevice/windows/winapilayer.h" #include "fixtures.h" -#include "libdisplaydevice/windows/winapilayer.h" -TEST(LoggingTest, GetErrorString) { +TEST(WinApiLayer, GetErrorString) { const display_device::WinApiLayer layer; EXPECT_TRUE(test_regex(layer.get_error_string(ERROR_INVALID_PARAMETER), R"(\[code: ERROR_INVALID_PARAMETER, .+?\])")); @@ -14,7 +14,7 @@ TEST(LoggingTest, GetErrorString) { EXPECT_TRUE(test_regex(layer.get_error_string(ERROR_ACCOUNT_DISABLED), R"(\[code: )" + std::to_string(ERROR_ACCOUNT_DISABLED) + R"(, .+?\])")); } -TEST(LoggingTest, QueryDisplayConfigPathAndModeCount) { +TEST(WinApiLayer, QueryDisplayConfigPathAndModeCount) { const display_device::WinApiLayer layer; const auto active_devices { layer.query_display_config(display_device::WinApiLayer::query_type_e::Active) }; @@ -29,7 +29,7 @@ TEST(LoggingTest, QueryDisplayConfigPathAndModeCount) { EXPECT_TRUE(all_devices->modes.size() == active_devices->modes.size()); } -TEST(LoggingTest, QueryDisplayConfigPathActivePaths) { +TEST(WinApiLayer, QueryDisplayConfigPathActivePaths) { const display_device::WinApiLayer layer; const auto active_devices { layer.query_display_config(display_device::WinApiLayer::query_type_e::Active) }; @@ -40,7 +40,7 @@ TEST(LoggingTest, QueryDisplayConfigPathActivePaths) { } } -TEST(LoggingTest, QueryDisplayConfigModeIndexValidity) { +TEST(WinApiLayer, QueryDisplayConfigModeIndexValidity) { // The MS docs is not clear when to access the index union struct or not. It appears that union struct is available, // whenever QDC_VIRTUAL_MODE_AWARE is specified when querying (always in our case). // From a1c3f60a801a161f30df45b57077d580f083399e Mon Sep 17 00:00:00 2001 From: FrogTheFrog Date: Thu, 2 May 2024 17:57:23 +0300 Subject: [PATCH 07/10] hmmm --- CMakeLists.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1378cd2..8947e6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,17 +19,6 @@ endif() # Project optional configuration # option(BUILD_TESTS "Build tests" ON) -option(CODE_QL_ANALYSIS "Build is for codeql analysis" OFF) - -# -# Only do these if this is the main project, and not if it is included through add_subdirectory -# -if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) - # auto-set CODE_QL_ANALYSIS based on env variable - if(DEFINED ENV{GITHUB_CODEQL_BUILD}) - set(CODE_QL_ANALYSIS ON) - endif() -endif() # # Library code is located here From 3b0d5bdb5df14cbb635f77757703799493174634 Mon Sep 17 00:00:00 2001 From: FrogTheFrog Date: Thu, 2 May 2024 18:04:19 +0300 Subject: [PATCH 08/10] format --- src/displaydevice/libddplaceholder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displaydevice/libddplaceholder.cpp b/src/displaydevice/libddplaceholder.cpp index c117747..d1f244d 100644 --- a/src/displaydevice/libddplaceholder.cpp +++ b/src/displaydevice/libddplaceholder.cpp @@ -1,6 +1,6 @@ #include "displaydevice/libddplaceholder.h" -int ddplaceholder() -{ +int +ddplaceholder() { return 0; } From cf5cc4aa062d9e9af797dc670237e7b248b38fba Mon Sep 17 00:00:00 2001 From: Lukas Senionis Date: Thu, 2 May 2024 19:20:51 +0300 Subject: [PATCH 09/10] Update tests/CMakeLists.txt Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b5be41d..e314595 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory("${PROJECT_SOURCE_DIR}/third-party/googletest" "third-party/goo if (WIN32) # For Windows: Prevent overriding the parent project's compiler/linker settings - set(gtest_force_shared_crt ON CACHE BOOL "Always use msvcrt.dll" FORCE) # cmake-lint: disable=C0103 + set(gtest_force_shared_crt ON CACHE BOOL "Always use msvcrt.dll" FORCE) # cmake-lint: disable=C0103 endif () # A helper function to setup the dependencies for the test executable From 9133c382655982ad8f15d42c018b3108278c1a4f Mon Sep 17 00:00:00 2001 From: Lukas Senionis Date: Thu, 2 May 2024 19:21:00 +0300 Subject: [PATCH 10/10] Update .github/workflows/ci.yml Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b542b1..4607212 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,7 +123,7 @@ jobs: shell: msys2 {0} working-directory: build run: | - ctest --extra-verbose + ./tests/test_libdisplaydevice --gtest_color=yes - name: Generate gcov report # any except canceled or skipped