From 09dc9e4c35bb1e7ea766b7a68b222ecd4eb1aea6 Mon Sep 17 00:00:00 2001
From: Dave Lane <42013603+ReenigneArcher@users.noreply.github.com>
Date: Tue, 30 Jun 2026 19:12:10 -0400
Subject: [PATCH] chore: use lizardbyte-common in c++ (#5356)
Co-authored-by: Kishi <41839133+Kishi85@users.noreply.github.com>
---
.gitmodules | 4 --
README.md | 21 +++---
cmake/compile_definitions/common.cmake | 1 +
cmake/dependencies/common.cmake | 5 ++
docs/Doxyfile | 2 +-
src/platform/common.h | 15 ----
src/platform/linux/input/inputtino_seat.cpp | 10 ++-
src/platform/linux/kwingrab.cpp | 23 +++----
src/platform/linux/misc.cpp | 68 ++++---------------
src/platform/linux/wayland.cpp | 11 +--
src/platform/macos/misc.mm | 8 ---
src/platform/windows/display_base.cpp | 6 +-
src/platform/windows/misc.cpp | 8 ---
tests/CMakeLists.txt | 8 ++-
tests/integration/test_config_consistency.cpp | 3 +-
tests/integration/test_external_commands.cpp | 3 +-
tests/integration/test_locale_consistency.cpp | 2 +-
tests/tests_common.h | 4 +-
tests/tests_events.h | 41 +++--------
tests/unit/platform/test_common.cpp | 42 ------------
.../unit/platform/windows/test_utf_utils.cpp | 2 +-
tests/unit/test_audio.cpp | 1 +
tests/unit/test_confighttp.cpp | 5 +-
tests/unit/test_display_device.cpp | 2 +-
tests/unit/test_file_handler.cpp | 6 +-
tests/unit/test_http_pairing.cpp | 2 +-
tests/unit/test_httpcommon.cpp | 6 +-
tests/unit/test_logging.cpp | 2 +-
tests/unit/test_mouse.cpp | 2 +
tests/unit/test_network.cpp | 6 +-
tests/unit/test_process.cpp | 4 +-
tests/unit/test_video.cpp | 3 +-
third-party/googletest | 1 -
third-party/lizardbyte-common | 2 +-
34 files changed, 103 insertions(+), 226 deletions(-)
delete mode 160000 third-party/googletest
diff --git a/.gitmodules b/.gitmodules
index 373fc9258..e1b90b926 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -13,10 +13,6 @@
[submodule "third-party/glad"]
path = third-party/glad
url = https://github.com/Dav1dde/glad.git
-[submodule "third-party/googletest"]
- path = third-party/googletest
- url = https://github.com/google/googletest.git
- branch = main
[submodule "third-party/inputtino"]
path = third-party/inputtino
url = https://github.com/games-on-whales/inputtino.git
diff --git a/README.md b/README.md
index b9563661c..deb149dcd 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,9 @@
-

+
Sunshine
Self-hosted game stream host for Moonlight.
@@ -8,16 +12,15 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
## ℹ️ About
diff --git a/cmake/compile_definitions/common.cmake b/cmake/compile_definitions/common.cmake
index 204a668eb..8f32cb5c6 100644
--- a/cmake/compile_definitions/common.cmake
+++ b/cmake/compile_definitions/common.cmake
@@ -150,6 +150,7 @@ list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
${CMAKE_THREAD_LIBS_INIT}
enet
libdisplaydevice::display_device
+ lizardbyte::common
nlohmann_json::nlohmann_json
${Opus_LIBRARY}
${FFMPEG_LIBRARIES}
diff --git a/cmake/dependencies/common.cmake b/cmake/dependencies/common.cmake
index ba20980f0..dc6886776 100644
--- a/cmake/dependencies/common.cmake
+++ b/cmake/dependencies/common.cmake
@@ -16,6 +16,11 @@ add_subdirectory("${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/enet")
# web server
add_subdirectory("${CMAKE_SOURCE_DIR}/third-party/Simple-Web-Server")
+# lizardbyte common helpers
+set(LIZARDBYTE_COMMON_BUILD_TEST_SUPPORT ${BUILD_TESTS}
+ CACHE BOOL "Build lizardbyte-common GoogleTest support helpers" FORCE)
+add_subdirectory("${CMAKE_SOURCE_DIR}/third-party/lizardbyte-common")
+
# libdisplaydevice
add_subdirectory("${CMAKE_SOURCE_DIR}/third-party/libdisplaydevice")
diff --git a/docs/Doxyfile b/docs/Doxyfile
index 0c84d823d..74b3f3815 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -26,7 +26,7 @@ DOCSET_BUNDLE_ID = dev.lizardbyte.Sunshine
DOCSET_PUBLISHER_ID = dev.lizardbyte.Sunshine.documentation
PROJECT_BRIEF = "Self-hosted game stream host for Moonlight."
PROJECT_ICON = ../sunshine.ico
-PROJECT_LOGO = ../sunshine.png
+PROJECT_LOGO = ../sunshine.svg
PROJECT_NAME = Sunshine
# project specific settings
diff --git a/src/platform/common.h b/src/platform/common.h
index 2bbcee8ff..24da9f53c 100644
--- a/src/platform/common.h
+++ b/src/platform/common.h
@@ -953,21 +953,6 @@ namespace platf {
void restart();
- /**
- * @brief Set an environment variable.
- * @param name The name of the environment variable.
- * @param value The value to set the environment variable to.
- * @return 0 on success, non-zero on failure.
- */
- int set_env(const std::string &name, const std::string &value);
-
- /**
- * @brief Unset an environment variable.
- * @param name The name of the environment variable.
- * @return 0 on success, non-zero on failure.
- */
- int unset_env(const std::string &name);
-
/**
* @brief Platform buffer pointer and size for batched socket sends.
*/
diff --git a/src/platform/linux/input/inputtino_seat.cpp b/src/platform/linux/input/inputtino_seat.cpp
index beb380838..e4f2a2101 100644
--- a/src/platform/linux/input/inputtino_seat.cpp
+++ b/src/platform/linux/input/inputtino_seat.cpp
@@ -2,8 +2,8 @@
* @file src/platform/linux/input/inputtino_seat.cpp
* @brief Implementation for multi-seat naming (udev-only).
*/
-// standard includes
-#include
+// lib includes
+#include
// local includes
#include "inputtino_seat.h"
@@ -11,10 +11,8 @@
namespace platf::inputtino_seat {
std::string get_target_seat() {
- if (const char *seat = std::getenv("XDG_SEAT")) {
- if (seat[0] != '\0') {
- return seat;
- }
+ if (std::string seat; lizardbyte::common::get_env("XDG_SEAT", seat) && !seat.empty()) {
+ return seat;
}
return {};
diff --git a/src/platform/linux/kwingrab.cpp b/src/platform/linux/kwingrab.cpp
index fd3124870..6e0ba02f7 100644
--- a/src/platform/linux/kwingrab.cpp
+++ b/src/platform/linux/kwingrab.cpp
@@ -21,6 +21,7 @@
#include
// lib includes
+#include
#include
#include
#include
@@ -55,7 +56,7 @@ namespace kwin {
* @return True when KWin reports that the permission system is disabled.
*/
static bool is_permission_system_deactivated() {
- return getenvstr("KWIN_WAYLAND_NO_PERMISSION_CHECKS") == "1";
+ return lizardbyte::common::get_env("KWIN_WAYLAND_NO_PERMISSION_CHECKS") == "1";
}
/**
@@ -160,17 +161,9 @@ namespace kwin {
static inline bool initialized = false;
static inline bool create_file = true;
- static std::string getenvstr(std::string const &key) {
- char const *val = std::getenv(key.c_str());
- if (!val) {
- return "";
- }
- return val;
- }
-
static std::filesystem::path get_home_dir() {
// Check HOME environment variable
- if (std::string homedir = getenvstr("HOME"); !homedir.empty()) {
+ if (std::string homedir = lizardbyte::common::get_env("HOME"); !homedir.empty()) {
return homedir;
}
// Fall back to home directory from NSS passwd
@@ -182,7 +175,7 @@ namespace kwin {
// Follow the XDG base directory specification for user data home:
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
std::filesystem::path xdg_data_home;
- if (std::string dir = getenvstr("XDG_DATA_HOME"); !dir.empty()) {
+ if (std::string dir = lizardbyte::common::get_env("XDG_DATA_HOME"); !dir.empty()) {
xdg_data_home = std::filesystem::path(dir);
} else {
const auto homedir = get_home_dir();
@@ -222,7 +215,7 @@ namespace kwin {
static bool check_kwin_system_permissions(const std::string_view &filenameprefix, const std::string_view &executablepath) {
// Find data dirs to check from XDG_DATA_DIRS
std::vector xdg_data_dirs;
- if (const std::string e = getenvstr("XDG_DATA_DIRS"); !e.empty()) {
+ if (const std::string e = lizardbyte::common::get_env("XDG_DATA_DIRS"); !e.empty()) {
std::stringstream ss(e);
std::string item;
@@ -322,13 +315,13 @@ namespace kwin {
screencast_permission_helper_t::setup();
}
- const char *wl_name = std::getenv("WAYLAND_DISPLAY");
- if (!wl_name) {
+ std::string wl_name;
+ if (!lizardbyte::common::get_env("WAYLAND_DISPLAY", wl_name)) {
BOOST_LOG(error) << "[kwingrab] WAYLAND_DISPLAY not set"sv;
return -1;
}
- wl_display = wl_display_connect(wl_name);
+ wl_display = wl_display_connect(wl_name.c_str());
if (!wl_display) {
BOOST_LOG(error) << "[kwingrab] cannot connect to Wayland display: "sv << wl_name;
return -1;
diff --git a/src/platform/linux/misc.cpp b/src/platform/linux/misc.cpp
index 1965e9f20..dae271d33 100644
--- a/src/platform/linux/misc.cpp
+++ b/src/platform/linux/misc.cpp
@@ -44,6 +44,7 @@
#include
#include
#include
+#include
#include
#ifdef SUNSHINE_BUILD_DRM
@@ -179,38 +180,35 @@ namespace platf {
std::call_once(migration_flag, []() {
bool found = false;
bool migrate_config = true;
- const char *dir;
- const char *homedir;
- const char *migrate_envvar;
+ fs::path homedir {lizardbyte::common::get_env("HOME")};
// Get the home directory
- if ((homedir = getenv("HOME")) == nullptr || strlen(homedir) == 0) {
+ if (homedir.empty()) {
// If HOME is empty or not set, use the current user's home directory
homedir = getpwuid(geteuid())->pw_dir;
}
// May be set if running under a systemd service with the ConfigurationDirectory= option set.
- if ((dir = getenv("CONFIGURATION_DIRECTORY")) != nullptr && strlen(dir) > 0) {
+ if (std::string dir; lizardbyte::common::get_env("CONFIGURATION_DIRECTORY", dir) && !dir.empty()) {
found = true;
config_path = fs::path(dir) / "sunshine"sv;
}
// Otherwise, follow the XDG base directory specification:
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
- if (!found && (dir = getenv("XDG_CONFIG_HOME")) != nullptr && strlen(dir) > 0) {
+ if (std::string dir; !found && lizardbyte::common::get_env("XDG_CONFIG_HOME", dir) && !dir.empty()) {
found = true;
config_path = fs::path(dir) / "sunshine"sv;
}
// As a last resort, use the home directory
if (!found) {
migrate_config = false;
- config_path = fs::path(homedir) / ".config/sunshine"sv;
+ config_path = homedir / ".config" / "sunshine";
}
// migrate from the old config location if necessary
- migrate_envvar = getenv("SUNSHINE_MIGRATE_CONFIG");
- if (migrate_config && found && migrate_envvar && strcmp(migrate_envvar, "1") == 0) {
+ if (std::string migrate_envvar; migrate_config && found && lizardbyte::common::get_env("SUNSHINE_MIGRATE_CONFIG", migrate_envvar) && migrate_envvar == "1") {
std::error_code ec;
- fs::path old_config_path = fs::path(homedir) / ".config/sunshine"sv;
+ fs::path old_config_path = homedir / ".config" / "sunshine";
if (old_config_path != config_path && fs::exists(old_config_path, ec)) {
if (!fs::exists(config_path, ec)) {
std::cout << "Migrating config from "sv << old_config_path << " to "sv << config_path << std::endl;
@@ -365,7 +363,7 @@ namespace platf {
*/
void open_url(const std::string &url) {
// set working dir to user home directory
- auto working_dir = boost::filesystem::path(std::getenv("HOME"));
+ auto working_dir = boost::filesystem::path(lizardbyte::common::get_env("HOME"));
std::string cmd = R"(xdg-open ")" + url + R"(")";
boost::process::v1::environment _env = boost::this_process::environment();
@@ -506,42 +504,6 @@ namespace platf {
lifetime::exit_sunshine(0, true);
}
- /**
- * @brief Read an environment variable as an optional string.
- *
- * @param name Human-readable name to assign.
- * @return Environment variable value, or an empty string when unset.
- */
- std::string get_env(const std::string &name) {
- if (const auto value = getenv(name.c_str()); value != nullptr) {
- return value;
- }
- return "";
- }
-
- int set_env(const std::string &name, const std::string &value) {
- return setenv(name.c_str(), value.c_str(), 1);
- }
-
- /**
- * @brief Append a value to a separator-delimited environment variable.
- *
- * @param name Human-readable name to assign.
- * @param value Entry to add when it is not already present.
- * @param separator Character used to join or split the value.
- * @return Result from updating the environment variable.
- */
- int append_env(const std::string &name, const std::string &value, const std::string &separator) {
- if (const std::string old_value = get_env(name); !old_value.contains(value)) {
- return set_env(name, old_value.empty() ? value : old_value + separator + value);
- }
- return 0;
- }
-
- int unset_env(const std::string &name) {
- return unsetenv(name.c_str());
- }
-
bool request_process_group_exit(std::uintptr_t native_handle) {
if (kill(-((pid_t) native_handle), SIGTERM) == 0 || errno == ESRCH) {
BOOST_LOG(debug) << "Successfully sent SIGTERM to process group: "sv << native_handle;
@@ -1267,25 +1229,25 @@ namespace platf {
std::unique_ptr init() {
// enable low latency mode for AMD
// https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30039
- set_env("AMD_DEBUG", "lowlatencyenc");
+ lizardbyte::common::set_env("AMD_DEBUG", "lowlatencyenc");
// enable Vulkan video extensions for AMD RADV
- set_env("RADV_PERFTEST", "video_encode");
+ lizardbyte::common::set_env("RADV_PERFTEST", "video_encode");
// Above is deprecated on Mesa 26.1+ and replaced by (keep both to ensure best compatibility):
- append_env("RADV_EXPERIMENTAL", "video_encode", ",");
+ lizardbyte::common::append_env("RADV_EXPERIMENTAL", "video_encode", ",");
// These are allowed to fail.
gbm::init();
window_system = window_system_e::NONE;
#ifdef SUNSHINE_BUILD_WAYLAND
- if (std::getenv("WAYLAND_DISPLAY")) {
+ if (std::string v; lizardbyte::common::get_env("WAYLAND_DISPLAY", v)) {
window_system = window_system_e::WAYLAND;
}
#endif
#if defined(SUNSHINE_BUILD_X11) || defined(SUNSHINE_BUILD_CUDA)
- if (std::getenv("DISPLAY") && window_system != window_system_e::WAYLAND) {
- if (std::getenv("WAYLAND_DISPLAY")) {
+ if (std::string v; lizardbyte::common::get_env("DISPLAY", v) && window_system != window_system_e::WAYLAND) {
+ if (lizardbyte::common::get_env("WAYLAND_DISPLAY", v)) {
BOOST_LOG(warning) << "Wayland detected, yet sunshine will use X11 for screencasting, screencasting will only work on XWayland applications"sv;
}
diff --git a/src/platform/linux/wayland.cpp b/src/platform/linux/wayland.cpp
index cdef9ae78..1be18e12d 100644
--- a/src/platform/linux/wayland.cpp
+++ b/src/platform/linux/wayland.cpp
@@ -2,9 +2,6 @@
* @file src/platform/linux/wayland.cpp
* @brief Definitions for Wayland capture.
*/
-// standard includes
-#include
-
// platform includes
#include
#include
@@ -15,6 +12,9 @@
#include
#include
+// lib includes
+#include
+
// local includes
#include "graphics.h"
#include "src/logging.h"
@@ -53,8 +53,11 @@ namespace wl {
};
int display_t::init(const char *display_name) {
+ std::string env_display_name;
if (!display_name) {
- display_name = std::getenv("WAYLAND_DISPLAY");
+ if (lizardbyte::common::get_env("WAYLAND_DISPLAY", env_display_name)) {
+ display_name = env_display_name.c_str();
+ }
}
if (!display_name) {
diff --git a/src/platform/macos/misc.mm b/src/platform/macos/misc.mm
index 56fca1340..7699556d4 100644
--- a/src/platform/macos/misc.mm
+++ b/src/platform/macos/misc.mm
@@ -296,14 +296,6 @@ namespace platf {
lifetime::exit_sunshine(0, true);
}
- int set_env(const std::string &name, const std::string &value) {
- return setenv(name.c_str(), value.c_str(), 1);
- }
-
- int unset_env(const std::string &name) {
- return unsetenv(name.c_str());
- }
-
bool request_process_group_exit(std::uintptr_t native_handle) {
if (killpg((pid_t) native_handle, SIGTERM) == 0 || errno == ESRCH) {
BOOST_LOG(debug) << "Successfully sent SIGTERM to process group: "sv << native_handle;
diff --git a/src/platform/windows/display_base.cpp b/src/platform/windows/display_base.cpp
index 071efc355..00b4abf8c 100644
--- a/src/platform/windows/display_base.cpp
+++ b/src/platform/windows/display_base.cpp
@@ -520,8 +520,7 @@ namespace platf::dxgi {
height = desc.DesktopCoordinates.bottom - offset_y;
display_rotation = desc.Rotation;
- if (display_rotation == DXGI_MODE_ROTATION_ROTATE90 ||
- display_rotation == DXGI_MODE_ROTATION_ROTATE270) {
+ if (display_rotation == DXGI_MODE_ROTATION_ROTATE90 || display_rotation == DXGI_MODE_ROTATION_ROTATE270) {
width_before_rotation = height;
height_before_rotation = width;
} else {
@@ -621,8 +620,7 @@ namespace platf::dxgi {
HANDLE token;
LUID val;
- if (OpenProcessToken(GetCurrentProcess(), flags, &token) &&
- !!LookupPrivilegeValue(nullptr, SE_INC_BASE_PRIORITY_NAME, &val)) {
+ if (OpenProcessToken(GetCurrentProcess(), flags, &token) && !!LookupPrivilegeValue(nullptr, SE_INC_BASE_PRIORITY_NAME, &val)) {
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = val;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
diff --git a/src/platform/windows/misc.cpp b/src/platform/windows/misc.cpp
index ee2ec7af5..25f509981 100644
--- a/src/platform/windows/misc.cpp
+++ b/src/platform/windows/misc.cpp
@@ -1324,14 +1324,6 @@ namespace platf {
lifetime::exit_sunshine(0, true);
}
- int set_env(const std::string &name, const std::string &value) {
- return _putenv_s(name.c_str(), value.c_str());
- }
-
- int unset_env(const std::string &name) {
- return _putenv_s(name.c_str(), "");
- }
-
/**
* @brief Stores state while enumerating top-level Windows windows.
*/
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index c38547f4d..1ebeea959 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -15,10 +15,12 @@ include_directories("${CMAKE_SOURCE_DIR}")
enable_testing()
# Add GoogleTest directory to the project
-set(GTEST_SOURCE_DIR "${CMAKE_SOURCE_DIR}/third-party/googletest")
+set(GTEST_SOURCE_DIR "${CMAKE_SOURCE_DIR}/third-party/lizardbyte-common/third-party/googletest")
set(INSTALL_GTEST OFF)
set(INSTALL_GMOCK OFF)
-add_subdirectory("${GTEST_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/googletest")
+if(NOT TARGET gtest)
+ add_subdirectory("${GTEST_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/googletest")
+endif()
include_directories("${GTEST_SOURCE_DIR}/googletest/include" "${GTEST_SOURCE_DIR}")
# coverage
@@ -167,7 +169,7 @@ add_dependencies(${PROJECT_NAME} sync_locale_files)
# Build the list of libraries to link
set(TEST_LINK_LIBRARIES
${SUNSHINE_EXTERNAL_LIBRARIES}
- gtest
+ lizardbyte::test_support
${PLATFORM_LIBRARIES}
)
diff --git a/tests/integration/test_config_consistency.cpp b/tests/integration/test_config_consistency.cpp
index 821c5923d..412db71f5 100644
--- a/tests/integration/test_config_consistency.cpp
+++ b/tests/integration/test_config_consistency.cpp
@@ -20,9 +20,10 @@
// local includes
#include "src/file_handler.h"
-class ConfigConsistencyTest: public ::testing::Test {
+class ConfigConsistencyTest: public BaseTest {
protected:
void SetUp() override {
+ BaseTest::SetUp();
// Define the expected mapping between documentation sections and UI tabs
expectedDocToTabMapping = {
{"General", "general"},
diff --git a/tests/integration/test_external_commands.cpp b/tests/integration/test_external_commands.cpp
index 92ec159e3..bbf2bb23f 100644
--- a/tests/integration/test_external_commands.cpp
+++ b/tests/integration/test_external_commands.cpp
@@ -37,9 +37,10 @@ struct ExternalCommandTestData {
xfail_reason(std::move(xfail_rsn)) {}
};
-class ExternalCommandTest: public ::testing::TestWithParam {
+class ExternalCommandTest: public BaseTest, public ::testing::WithParamInterface {
protected:
void SetUp() override {
+ BaseTest::SetUp();
if constexpr (IS_WINDOWS) {
current_platform = "windows";
} else if constexpr (IS_MACOS) {
diff --git a/tests/integration/test_locale_consistency.cpp b/tests/integration/test_locale_consistency.cpp
index 3fdc7ef49..c842e3174 100644
--- a/tests/integration/test_locale_consistency.cpp
+++ b/tests/integration/test_locale_consistency.cpp
@@ -23,7 +23,7 @@
namespace fs = std::filesystem;
-class LocaleConsistencyTest: public ::testing::Test {
+class LocaleConsistencyTest: public BaseTest {
protected:
// Extract locale options from config.cpp
static std::set> extractConfigCppLocales() {
diff --git a/tests/tests_common.h b/tests/tests_common.h
index fe4ce1a03..5025943fe 100644
--- a/tests/tests_common.h
+++ b/tests/tests_common.h
@@ -12,7 +12,7 @@
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
-#include
+#include
#include
#include
#include
@@ -146,7 +146,7 @@ namespace test_utils {
#define IS_FREEBSD false
#endif
-struct PlatformTestSuite: testing::Test {
+struct PlatformTestSuite: BaseTest {
static void SetUpTestSuite() {
ASSERT_FALSE(platf_deinit);
BOOST_LOG(tests) << "Setting up platform test suite";
diff --git a/tests/tests_events.h b/tests/tests_events.h
index 63c27c160..be649f084 100644
--- a/tests/tests_events.h
+++ b/tests/tests_events.h
@@ -5,7 +5,7 @@
#pragma once
#include "tests_common.h"
-struct SunshineEventListener: testing::EmptyTestEventListener {
+struct SunshineEventListener: BufferedTestEventListener {
SunshineEventListener() {
sink = boost::make_shared();
sink_buffer = boost::make_shared();
@@ -14,51 +14,30 @@ struct SunshineEventListener: testing::EmptyTestEventListener {
}
void OnTestProgramStart(const testing::UnitTest &unit_test) override {
+ static_cast(unit_test);
boost::log::core::get()->add_sink(sink);
}
void OnTestProgramEnd(const testing::UnitTest &unit_test) override {
+ static_cast(unit_test);
boost::log::core::get()->remove_sink(sink);
}
- void OnTestStart(const testing::TestInfo &test_info) override {
- BOOST_LOG(tests) << "From " << test_info.file() << ":" << test_info.line();
- BOOST_LOG(tests) << " " << test_info.test_suite_name() << "/" << test_info.name() << " started";
+protected:
+ void logTestEvent(const std::string &message) override {
+ BOOST_LOG(tests) << message;
}
- void OnTestPartResult(const testing::TestPartResult &test_part_result) override {
- std::string file = test_part_result.file_name();
- BOOST_LOG(tests) << "At " << file << ":" << test_part_result.line_number();
-
- auto result_text = test_part_result.passed() ? "Success" :
- test_part_result.nonfatally_failed() ? "Non-fatal failure" :
- test_part_result.fatally_failed() ? "Failure" :
- "Skip";
-
- std::string summary = test_part_result.summary();
- std::string message = test_part_result.message();
- BOOST_LOG(tests) << " " << result_text << ": " << summary;
- if (message != summary) {
- BOOST_LOG(tests) << " " << message;
- }
+ [[nodiscard]] std::string bufferedTestOutput() const override {
+ return sink_buffer->str();
}
- void OnTestEnd(const testing::TestInfo &test_info) override {
- auto &result = *test_info.result();
-
- auto result_text = result.Passed() ? "passed" :
- result.Skipped() ? "skipped" :
- "failed";
- BOOST_LOG(tests) << test_info.test_suite_name() << "/" << test_info.name() << " " << result_text;
-
- if (result.Failed()) {
- std::cout << sink_buffer->str();
- }
-
+ void clearBufferedTestOutput() override {
sink_buffer->str("");
sink_buffer->clear();
}
+private:
using sink_t = boost::log::sinks::synchronous_sink;
boost::shared_ptr sink;
boost::shared_ptr sink_buffer;
diff --git a/tests/unit/platform/test_common.cpp b/tests/unit/platform/test_common.cpp
index ff7372088..b497d3581 100644
--- a/tests/unit/platform/test_common.cpp
+++ b/tests/unit/platform/test_common.cpp
@@ -7,48 +7,6 @@
#include
#include
-struct SetEnvTest: ::testing::TestWithParam> {
-protected:
- void TearDown() override {
- // Clean up environment variable after each test
- const auto &[name, value, expected] = GetParam();
- platf::unset_env(name);
- }
-};
-
-TEST_P(SetEnvTest, SetEnvironmentVariableTests) {
- const auto &[name, value, expected] = GetParam();
- platf::set_env(name, value);
-
- const char *env_value = std::getenv(name.c_str());
- if (expected == 0 && !value.empty()) {
- ASSERT_NE(env_value, nullptr);
- ASSERT_EQ(std::string(env_value), value);
- } else {
- ASSERT_EQ(env_value, nullptr);
- }
-}
-
-TEST_P(SetEnvTest, UnsetEnvironmentVariableTests) {
- const auto &[name, value, expected] = GetParam();
- platf::unset_env(name);
-
- const char *env_value = std::getenv(name.c_str());
- if (expected == 0) {
- ASSERT_EQ(env_value, nullptr);
- }
-}
-
-INSTANTIATE_TEST_SUITE_P(
- SetEnvTests,
- SetEnvTest,
- ::testing::Values(
- std::make_tuple("SUNSHINE_UNIT_TEST_ENV_VAR", "test_value_0", 0),
- std::make_tuple("SUNSHINE_UNIT_TEST_ENV_VAR", "test_value_1", 0),
- std::make_tuple("", "test_value", -1)
- )
-);
-
TEST(HostnameTests, TestAsioEquality) {
// These should be equivalent on all platforms for ASCII hostnames
ASSERT_EQ(platf::get_host_name(), boost::asio::ip::host_name());
diff --git a/tests/unit/platform/windows/test_utf_utils.cpp b/tests/unit/platform/windows/test_utf_utils.cpp
index d7afc41b1..bd62218ef 100644
--- a/tests/unit/platform/windows/test_utf_utils.cpp
+++ b/tests/unit/platform/windows/test_utf_utils.cpp
@@ -16,7 +16,7 @@
/**
* @brief Test fixture for utf_utils namespace functions
*/
-class UtfUtilsTest: public testing::Test {};
+class UtfUtilsTest: public BaseTest {};
TEST_F(UtfUtilsTest, FromUtf8WithEmptyString) {
const std::string empty_string = "";
diff --git a/tests/unit/test_audio.cpp b/tests/unit/test_audio.cpp
index 648b838ea..9b894112b 100644
--- a/tests/unit/test_audio.cpp
+++ b/tests/unit/test_audio.cpp
@@ -10,6 +10,7 @@ using namespace audio;
struct AudioTest: PlatformTestSuite, testing::WithParamInterface, config_t>> {
void SetUp() override {
+ BaseTest::SetUp();
m_config = std::get<1>(GetParam());
m_mail = std::make_shared();
}
diff --git a/tests/unit/test_confighttp.cpp b/tests/unit/test_confighttp.cpp
index 195a666c2..a633ae3b5 100644
--- a/tests/unit/test_confighttp.cpp
+++ b/tests/unit/test_confighttp.cpp
@@ -89,7 +89,7 @@ X4wnh1bwdiidqpcgyuKossLOPxbS786WmsesaAWPnpoY6M8aija+ALwNNuWWmyMg
*
* This fixture creates a real server to test the actual confighttp functions.
*/
-class ConfigHttpTest: public ::testing::Test { // NOSONAR(cpp:S3656) - protected members are intentional for test fixture subclassing
+class ConfigHttpTest: public BaseTest { // NOSONAR(cpp:S3656) - protected members are intentional for test fixture subclassing
protected:
std::unique_ptr> server;
std::unique_ptr> client;
@@ -107,6 +107,7 @@ protected:
std::filesystem::path web_dir_test_file;
void SetUp() override {
+ BaseTest::SetUp();
// Save current config
saved_username = config::sunshine.username;
saved_password = config::sunshine.password;
@@ -354,6 +355,7 @@ protected:
if (std::filesystem::exists(test_web_dir)) {
std::filesystem::remove_all(test_web_dir);
}
+ BaseTest::TearDown();
}
static std::string create_auth_header(const std::string &username, const std::string &password) {
@@ -1251,7 +1253,6 @@ TEST_F(BrowseDirectoryTest, IsBrowsableExecutable_LinuxGroupExecBit_ReturnsTrue)
TEST_F(BrowseDirectoryTest, BuildBrowseEntries_TypeAny_ReturnsAllEntries) {
const auto entries = confighttp::build_browse_entries(browse_test_dir, "any");
ASSERT_TRUE(entries.is_array());
- // subdir_a, subdir_b, file_alpha.txt, file_beta.txt, test_exec[.exe] = 5
ASSERT_EQ(entries.size(), 5u);
}
diff --git a/tests/unit/test_display_device.cpp b/tests/unit/test_display_device.cpp
index 5fd00d31f..9b20f876b 100644
--- a/tests/unit/test_display_device.cpp
+++ b/tests/unit/test_display_device.cpp
@@ -43,7 +43,7 @@ namespace {
const std::string max_uint_string {std::to_string(std::numeric_limits::max())};
template
- struct DisplayDeviceConfigTest: testing::TestWithParam {};
+ struct DisplayDeviceConfigTest: BaseTest, testing::WithParamInterface {};
} // namespace
using ParseDeviceId = DisplayDeviceConfigTest>;
diff --git a/tests/unit/test_file_handler.cpp b/tests/unit/test_file_handler.cpp
index cf5b8a1f5..4ec53f2e9 100644
--- a/tests/unit/test_file_handler.cpp
+++ b/tests/unit/test_file_handler.cpp
@@ -7,7 +7,7 @@
#include
#include
-struct FileHandlerParentDirectoryTest: testing::TestWithParam> {};
+struct FileHandlerParentDirectoryTest: BaseTest, testing::WithParamInterface> {};
TEST_P(FileHandlerParentDirectoryTest, Run) {
auto [input, expected] = GetParam();
@@ -24,7 +24,7 @@ INSTANTIATE_TEST_SUITE_P(
)
);
-struct FileHandlerMakeDirectoryTest: testing::TestWithParam> {};
+struct FileHandlerMakeDirectoryTest: BaseTest, testing::WithParamInterface> {};
TEST_P(FileHandlerMakeDirectoryTest, Run) {
auto [input, expected, remove] = GetParam();
@@ -52,7 +52,7 @@ INSTANTIATE_TEST_SUITE_P(
)
);
-struct FileHandlerTests: testing::TestWithParam> {};
+struct FileHandlerTests: BaseTest, testing::WithParamInterface> {};
INSTANTIATE_TEST_SUITE_P(
TestFiles,
diff --git a/tests/unit/test_http_pairing.cpp b/tests/unit/test_http_pairing.cpp
index 0b75e32b4..b9a06768a 100644
--- a/tests/unit/test_http_pairing.cpp
+++ b/tests/unit/test_http_pairing.cpp
@@ -76,7 +76,7 @@ X4wnh1bwdiidqpcgyuKossLOPxbS786WmsesaAWPnpoY6M8aija+ALwNNuWWmyMg
9SVDV76xJzM36Uq7Kg3QJYTlY04WmPIdJHkCtXWf9g==
-----END CERTIFICATE-----)";
-struct PairingTest: testing::TestWithParam> {};
+struct PairingTest: BaseTest, testing::WithParamInterface> {};
TEST_P(PairingTest, Run) {
auto [input, expected] = GetParam();
diff --git a/tests/unit/test_httpcommon.cpp b/tests/unit/test_httpcommon.cpp
index a5a6c4886..2f7af0c58 100644
--- a/tests/unit/test_httpcommon.cpp
+++ b/tests/unit/test_httpcommon.cpp
@@ -11,7 +11,7 @@
// local imports
#include
-struct UrlEscapeTest: testing::TestWithParam> {};
+struct UrlEscapeTest: BaseTest, testing::WithParamInterface> {};
TEST_P(UrlEscapeTest, Run) {
const auto &[input, expected] = GetParam();
@@ -28,7 +28,7 @@ INSTANTIATE_TEST_SUITE_P(
)
);
-struct UrlGetHostTest: testing::TestWithParam> {};
+struct UrlGetHostTest: BaseTest, testing::WithParamInterface> {};
TEST_P(UrlGetHostTest, Run) {
const auto &[input, expected] = GetParam();
@@ -45,7 +45,7 @@ INSTANTIATE_TEST_SUITE_P(
)
);
-struct DownloadFileTest: testing::TestWithParam> {};
+struct DownloadFileTest: BaseTest, testing::WithParamInterface> {};
TEST_P(DownloadFileTest, Run) {
const auto &[url, filename] = GetParam();
diff --git a/tests/unit/test_logging.cpp b/tests/unit/test_logging.cpp
index cc6388598..e1ffb6adc 100644
--- a/tests/unit/test_logging.cpp
+++ b/tests/unit/test_logging.cpp
@@ -22,7 +22,7 @@ namespace {
constexpr auto log_file = "test_sunshine.log";
} // namespace
-struct LogLevelsTest: testing::TestWithParam {};
+struct LogLevelsTest: BaseTest, testing::WithParamInterface {};
INSTANTIATE_TEST_SUITE_P(
Logging,
diff --git a/tests/unit/test_mouse.cpp b/tests/unit/test_mouse.cpp
index c2935e54b..eda5fd02e 100644
--- a/tests/unit/test_mouse.cpp
+++ b/tests/unit/test_mouse.cpp
@@ -8,6 +8,7 @@
struct MouseHIDTest: PlatformTestSuite, testing::WithParamInterface {
void SetUp() override {
+ BaseTest::SetUp();
#ifdef _WIN32
// TODO: Windows tests are failing, `get_mouse_loc` seems broken and `platf::abs_mouse` too
// the alternative `platf::abs_mouse` method seem to work better during tests,
@@ -21,6 +22,7 @@ struct MouseHIDTest: PlatformTestSuite, testing::WithParamInterface
-struct MdnsInstanceNameTest: testing::TestWithParam> {};
+struct MdnsInstanceNameTest: BaseTest, testing::WithParamInterface> {};
TEST_P(MdnsInstanceNameTest, Run) {
auto [input, expected] = GetParam();
@@ -30,11 +30,12 @@ INSTANTIATE_TEST_SUITE_P(
/**
* @brief Test fixture for bind_address tests with setup/teardown
*/
-class BindAddressTest: public ::testing::Test {
+class BindAddressTest: public BaseTest {
protected:
std::string original_bind_address;
void SetUp() override {
+ BaseTest::SetUp();
// Save the original bind_address config
original_bind_address = config::sunshine.bind_address;
}
@@ -42,6 +43,7 @@ protected:
void TearDown() override {
// Restore the original bind_address config
config::sunshine.bind_address = original_bind_address;
+ BaseTest::TearDown();
}
};
diff --git a/tests/unit/test_process.cpp b/tests/unit/test_process.cpp
index 14ac6924c..0e4caf525 100644
--- a/tests/unit/test_process.cpp
+++ b/tests/unit/test_process.cpp
@@ -14,9 +14,10 @@
namespace fs = std::filesystem;
-class ProcessPNGTest: public ::testing::Test {
+class ProcessPNGTest: public BaseTest {
protected:
void SetUp() override {
+ BaseTest::SetUp();
// Create test directory
test_dir = fs::temp_directory_path() / "sunshine_process_png_test"; // NOSONAR(cpp:S5443) - safe for tests
fs::create_directories(test_dir);
@@ -27,6 +28,7 @@ protected:
if (fs::exists(test_dir)) {
fs::remove_all(test_dir);
}
+ BaseTest::TearDown();
}
// Helper function to create a file with specific content
diff --git a/tests/unit/test_video.cpp b/tests/unit/test_video.cpp
index e71fb1d8f..b9c926bf8 100644
--- a/tests/unit/test_video.cpp
+++ b/tests/unit/test_video.cpp
@@ -8,6 +8,7 @@
struct EncoderTest: PlatformTestSuite, testing::WithParamInterface {
void SetUp() override {
+ BaseTest::SetUp();
auto &encoder = *GetParam();
if (!video::validate_encoder(encoder, false)) {
// Encoder failed validation,
@@ -49,7 +50,7 @@ TEST_P(EncoderTest, ValidateEncoder) {
// todo:: test something besides fixture setup
}
-struct FramerateX100Test: testing::TestWithParam> {};
+struct FramerateX100Test: BaseTest, testing::WithParamInterface> {};
TEST_P(FramerateX100Test, Run) {
const auto &[x100, expected] = GetParam();
diff --git a/third-party/googletest b/third-party/googletest
deleted file mode 160000
index 52eb8108c..000000000
--- a/third-party/googletest
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 52eb8108c5bdec04579160ae17225d66034bd723
diff --git a/third-party/lizardbyte-common b/third-party/lizardbyte-common
index bd1b0bb88..06cd442b8 160000
--- a/third-party/lizardbyte-common
+++ b/third-party/lizardbyte-common
@@ -1 +1 @@
-Subproject commit bd1b0bb88d47f953875170151d86ae464a7175e8
+Subproject commit 06cd442b808f02f1674f3192a84d25b9a503c482