build: remove google tests and remaining gtest

This commit is contained in:
sithlord48 2026-07-19 08:35:17 -04:00 committed by Nick Bolton
parent 63c83b8640
commit 9981910814
17 changed files with 12 additions and 942 deletions

View file

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2024 Chris Rizzitello <sithlord48@gmail.com> # SPDX-FileCopyrightText: (C) 2024 - 2026 Chris Rizzitello <sithlord48@gmail.com>
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
name: "Install dependencies for deskflow" name: "Install dependencies for deskflow"
@ -30,29 +30,27 @@ runs:
if: ${{ runner.os != 'Windows' }} if: ${{ runner.os != 'Windows' }}
run: | run: |
if [ "$RUNNER_OS" == "macOS" ]; then if [ "$RUNNER_OS" == "macOS" ]; then
brew install googletest openssl doxygen --quiet brew install openssl doxygen --quiet
elif [ "$RUNNER_OS" == "Linux" ]; then elif [ "$RUNNER_OS" == "Linux" ]; then
if [ ${{inputs.like}} == "debian" ]; then if [ ${{inputs.like}} == "debian" ]; then
apt update -qqq > /dev/null apt update -qqq > /dev/null
apt install -qqq cmake build-essential ninja-build \ apt install -qqq cmake build-essential ninja-build \
xorg-dev libx11-dev libxtst-dev libssl-dev \ xorg-dev libx11-dev libxtst-dev libssl-dev \
libglib2.0-dev libxkbfile-dev qt6-base-dev qt6-tools-dev \ libglib2.0-dev libxkbfile-dev qt6-base-dev qt6-tools-dev \
libgtk-3-dev libgtest-dev libgmock-dev \ libgtk-3-dev libei-dev libportal-dev help2man doxygen -y >/dev/null
libei-dev libportal-dev help2man doxygen -y >/dev/null
elif [ ${{inputs.like}} == "fedora" ]; then elif [ ${{inputs.like}} == "fedora" ]; then
dnf install -y cmake make ninja-build gcc-c++ rpm-build openssl-devel \ dnf install -y cmake make ninja-build gcc-c++ rpm-build openssl-devel \
glib2-devel libXtst-devel libxkbfile-devel qt6-qtbase-devel qt6-qttools-devel \ glib2-devel libXtst-devel libxkbfile-devel qt6-qtbase-devel qt6-qttools-devel \
gtk3-devel gtest-devel gmock-devel libei-devel libportal-devel help2man doxygen gtk3-devel libei-devel libportal-devel help2man doxygen
elif [ ${{inputs.like}} == "suse" ]; then elif [ ${{inputs.like}} == "suse" ]; then
zypper refresh zypper refresh
zypper install -y --force-resolution \ zypper install -y --force-resolution \
cmake make ninja gcc-c++ rpm-build libopenssl-devel \ cmake make ninja gcc-c++ rpm-build libopenssl-devel \
glib2-devel libXtst-devel libxkbfile-devel qt6-base-devel qt6-tools-devel \ glib2-devel libXtst-devel libxkbfile-devel qt6-base-devel qt6-tools-devel \
qt6-linguist-devel gtk3-devel doxygen \ qt6-linguist-devel gtk3-devel doxygen libei-devel libportal-devel help2man
googletest-devel googlemock-devel libei-devel libportal-devel help2man
elif [ ${{ inputs.like }} == "arch" ]; then elif [ ${{ inputs.like }} == "arch" ]; then
pacman -Syu --noconfirm base-devel cmake ninja \ pacman -Syu --noconfirm base-devel cmake ninja \
gcc openssl glib2 libxtst libxkbfile gtest libei libportal \ gcc openssl glib2 libxtst libxkbfile libei libportal \
qt6-base qt6-tools qt6-svg qt6-translations qt6-declarative gtk3 help2man doxygen graphviz rsync qt6-base qt6-tools qt6-svg qt6-translations qt6-declarative gtk3 help2man doxygen graphviz rsync
else else
echo "Unknown like" echo "Unknown like"
@ -77,7 +75,7 @@ runs:
id: vcpkg id: vcpkg
uses: johnwason/vcpkg-action@v8 uses: johnwason/vcpkg-action@v8
with: with:
pkgs: gtest openssl pkgs: openssl
extra-args: --classic --host-triplet=${{inputs.vcpkg-triplet}} extra-args: --classic --host-triplet=${{inputs.vcpkg-triplet}}
triplet: ${{inputs.vcpkg-triplet}} triplet: ${{inputs.vcpkg-triplet}}
token: ${{ github.token }} token: ${{ github.token }}

View file

@ -29,31 +29,14 @@ runs:
shell: bash shell: bash
continue-on-error: true continue-on-error: true
- name: Legacy Tests
id: legacy-tests
env:
QT_QPA_PLATFORM: offscreen
run: |
./${{ inputs.bin-dir }}/legacytests
result=$?
if [ $result -ne 0 ]; then
echo "Legacy tests failed with code: $result" >> $GITHUB_STEP_SUMMARY
fi
shell: bash
continue-on-error: true
- name: Get test results - name: Get test results
id: results id: results
run: | run: |
pass="✅ Pass" pass="✅ Pass"
fail="❌ Fail" fail="❌ Fail"
unit_tests_outcome="${{ steps.unit-tests.outcome }}" unit_tests_outcome="${{ steps.unit-tests.outcome }}"
legacy_tests_outcome="${{ steps.legacy-tests.outcome }}"
unit_tests=$( [ "$unit_tests_outcome" = "success" ] && echo $pass || echo $fail ) unit_tests=$( [ "$unit_tests_outcome" = "success" ] && echo $pass || echo $fail )
legacy_tests=$( [ "$legacy_tests_outcome" = "success" ] && echo $pass || echo $fail )
echo "unit-tests=$unit_tests" >> $GITHUB_OUTPUT echo "unit-tests=$unit_tests" >> $GITHUB_OUTPUT
echo "legacy-tests=$legacy_tests" >> $GITHUB_OUTPUT
shell: bash shell: bash
- name: Summary row - name: Summary row
@ -64,7 +47,6 @@ runs:
row="" row=""
row+="| ${{ inputs.job }} " row+="| ${{ inputs.job }} "
row+="| ${{ steps.results.outputs.unit-tests }} " row+="| ${{ steps.results.outputs.unit-tests }} "
row+="| ${{ steps.results.outputs.legacy-tests }} "
echo "$row" > $file echo "$row" > $file
echo "file=$file" > $GITHUB_OUTPUT echo "file=$file" > $GITHUB_OUTPUT
@ -77,7 +59,7 @@ runs:
path: ${{ steps.row.outputs.file }} path: ${{ steps.row.outputs.file }}
- name: Check test outcome - name: Check test outcome
if: (steps.unit-tests.outcome != 'success' || steps.legacy-tests.outcome != 'success') if: (steps.unit-tests.outcome != 'success')
run: | run: |
echo "Tests failed" echo "Tests failed"
exit 1 exit 1

View file

@ -359,9 +359,9 @@ jobs:
release: "14.4" release: "14.4"
run: | run: |
pkg install -y cmake ninja gmake gcc12 openssl glib \ pkg install -y cmake ninja gmake gcc12 openssl \
libX11 libXtst libxkbfile qt6-base qt6-tools gtk3 \ glib libX11 libXtst libxkbfile qt6-base qt6-tools \
googletest pkgconf libei libportal doxygen gtk3 pkgconf libei libportal doxygen
${{env.CMAKE_CONFIGURE}} -G Ninja ${{env.CMAKE_CONFIGURE}} -G Ninja
cmake --build build -j16 cmake --build build -j16
flatpak: flatpak:

View file

@ -5,7 +5,6 @@
"version": "@DESKFLOW_VERSION_MAJOR@.@DESKFLOW_VERSION_MINOR@.@DESKFLOW_VERSION_PATCH@.@DESKFLOW_VERSION_TWEAK@", "version": "@DESKFLOW_VERSION_MAJOR@.@DESKFLOW_VERSION_MINOR@.@DESKFLOW_VERSION_PATCH@.@DESKFLOW_VERSION_TWEAK@",
"builtin-baseline": "d5ec528843d29e3a52d745a64b469f810b2cedbf", "builtin-baseline": "d5ec528843d29e3a52d745a64b469f810b2cedbf",
"dependencies": [ "dependencies": [
"gtest",
"openssl" "openssl"
@QT_LIBS@ @QT_LIBS@
] ]

View file

@ -67,18 +67,6 @@ modules:
url: https://github.com/flatpak/libportal.git url: https://github.com/flatpak/libportal.git
tag: 0.10.0 tag: 0.10.0
commit: c23024018c8eb076549a1517fcb2d7f80d3e2ed5 commit: c23024018c8eb076549a1517fcb2d7f80d3e2ed5
- name: gtest
buildsystem: cmake-ninja
sources:
- type: git
url: https://github.com/google/googletest.git
tag: v1.17.0
commit: 52eb8108c5bdec04579160ae17225d66034bd723
x-checker-data:
type: git
tag-pattern: ^([\\d.]+)$
cleanup:
- '*'
- name: deskflow - name: deskflow
buildsystem: cmake-ninja buildsystem: cmake-ninja
config-opts: config-opts:

View file

@ -6,7 +6,6 @@ To build Deskflow you will a minimum of:
- [openssl] 3.0+ - [openssl] 3.0+
- [libportal] 0.9.1+ (linux, bsd) - [libportal] 0.9.1+ (linux, bsd)
- [libei] 1.3+ (linux, bsd) - [libei] 1.3+ (linux, bsd)
- [google_test] ^
> ^ Will be fetched if not found on the host system. > ^ Will be fetched if not found on the host system.
@ -25,7 +24,7 @@ Deskflow supports the following CMake options:
| BUILD_USER_DOCS | Build user documentation | DOXYGEN_FOUND | `Doxygen` | | BUILD_USER_DOCS | Build user documentation | DOXYGEN_FOUND | `Doxygen` |
| BUILD_DEV_DOCS | Build development documentation | OFF | `Doxygen` | | BUILD_DEV_DOCS | Build development documentation | OFF | `Doxygen` |
| BUILD_INSTALLER | Build installers/packages | ON | | | BUILD_INSTALLER | Build installers/packages | ON | |
| BUILD_TESTS | Build unit tests and legacy tests | ON | `gtest`| | BUILD_TESTS | Build unit tests and legacy tests | ON | |
| BUILD_X11_SUPPORT | Build X11 backend (Linux and BSD only) | ON | `x11 libs`| | BUILD_X11_SUPPORT | Build X11 backend (Linux and BSD only) | ON | `x11 libs`|
| BUILD_OSX_BUNDLE | Build an app bundle (macOS only) | ON | | | BUILD_OSX_BUNDLE | Build an app bundle (macOS only) | ON | |
| ENABLE_COVERAGE | Enable test coverage | OFF | `gcov` | | ENABLE_COVERAGE | Enable test coverage | OFF | `gcov` |
@ -105,6 +104,5 @@ After configuring you should be able to run make to build all targets.
[doxygen]:http://www.stack.nl/~dimitri/doxygen/ [doxygen]:http://www.stack.nl/~dimitri/doxygen/
[cmake]:https://cmake.org/ [cmake]:https://cmake.org/
[openssl]:https://www.openssl.org/ [openssl]:https://www.openssl.org/
[google_test]:https://github.com/google/googletest
[libei]:https://gitlab.freedesktop.org/libinput/libei [libei]:https://gitlab.freedesktop.org/libinput/libei
[libportal]:https://github.com/flatpak/libportal [libportal]:https://github.com/flatpak/libportal

View file

@ -61,7 +61,6 @@ add_subdirectory(client)
add_subdirectory(common) add_subdirectory(common)
add_subdirectory(deskflow) add_subdirectory(deskflow)
add_subdirectory(gui) add_subdirectory(gui)
add_subdirectory(legacytests)
add_subdirectory(net) add_subdirectory(net)
add_subdirectory(platform) add_subdirectory(platform)
add_subdirectory(server) add_subdirectory(server)

View file

@ -1,145 +0,0 @@
# SPDX-FileCopyrightText: (C) 2024 Deskflow Developers
# SPDX-FileCopyrightText: (C) 2012 - 2024 Symless Ltd
# SPDX-FileCopyrightText: (C) 2009 - 2012 Nick Bolton
# SPDX-License-Identifier: MIT
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG b514bdc898e2951020cbdca1304b75f5950d1f59 # release-1.15.2
GIT_SHALLOW 1
FIND_PACKAGE_ARGS NAMES GTest
)
FetchContent_MakeAvailable(googletest)
macro(config_all_tests)
set(base_dir ${PROJECT_SOURCE_DIR})
set(src_dir ${base_dir}/src)
set(test_base_dir ${src_dir}/unittests/legacytests)
set(gui_dir ${src_dir}/gui/src)
config_test_deps()
add_subdirectory(legacytests)
endmacro()
macro(config_test)
include_directories(
${test_base_dir}
${src_dir}
${src_dir}/lib
${gui_dir}
${ext_dir})
set_sources()
endmacro()
macro(set_sources)
file(GLOB_RECURSE headers ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
file(GLOB_RECURSE sources ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE shared_headers ${test_base_dir}/shared/*.h)
file(GLOB_RECURSE shared_sources ${test_base_dir}/shared/*.cpp)
list(APPEND headers ${shared_headers})
list(APPEND sources ${shared_sources})
file(GLOB_RECURSE mock_headers ${test_base_dir}/mock/*.h)
file(GLOB_RECURSE mock_sources ${test_base_dir}/mock/*.cpp)
list(APPEND headers ${mock_headers})
list(APPEND sources ${mock_sources})
if(ADD_HEADERS_TO_SOURCES)
list(APPEND sources ${headers})
endif()
list(APPEND sources ${PROJECT_SOURCE_DIR}/src/apps/res/deskflow.qrc)
replace_platform_sources()
replace_arch_sources()
endmacro()
macro(replace_platform_sources)
set(platform_dir ${CMAKE_CURRENT_SOURCE_DIR}/platform)
# Remove platform files so that specific platform files can be added later.
# This is a bit weird, but it's simpler to include everything, remove all
# platform files, then only include the platforms we need.
file(GLOB_RECURSE all_platform_files ${platform_dir}/*)
list(REMOVE_ITEM headers ${all_platform_files})
list(REMOVE_ITEM sources ${all_platform_files})
if(WIN32)
file(GLOB platform_sources ${platform_dir}/MSWindows*.cpp)
file(GLOB platform_headers ${platform_dir}/MSWindows*.h)
elseif(APPLE)
file(GLOB platform_sources ${platform_dir}/OSX*.cpp)
file(GLOB platform_headers ${platform_dir}/OSX*.h)
elseif(UNIX)
file(GLOB platform_sources ${platform_dir}/XWindows*.cpp)
file(GLOB platform_headers ${platform_dir}/XWindows*.h)
endif()
list(APPEND sources ${platform_sources})
list(APPEND headers ${platform_headers})
endmacro()
macro(replace_arch_sources)
set(arch_dir ${CMAKE_CURRENT_SOURCE_DIR}/arch)
# Remove arch files so that specific arch files can be added later.
# This is a bit weird, but it's simpler to include everything, remove all
# arch files, then only include the archs we need.
file(GLOB_RECURSE all_arch_files ${arch_dir}/*)
list(REMOVE_ITEM headers ${all_arch_files})
list(REMOVE_ITEM sources ${all_arch_files})
if(WIN32)
file(GLOB arch_sources ${arch_dir}/win32/*.cpp)
file(GLOB arch_headers ${arch_dir}/win32/*.h)
elseif(UNIX)
file(GLOB arch_sources ${arch_dir}/unix/*.cpp)
file(GLOB arch_headers ${arch_dir}/unix/*.h)
endif()
list(APPEND sources ${arch_sources})
list(APPEND headers ${arch_headers})
endmacro()
macro(config_test_deps)
# gui library autogen headers:
# qt doesn't seem to auto include the autogen headers for libraries.
include_directories(${PROJECT_BINARY_DIR}/src/lib/gui/gui_autogen/include)
set(test_libs
arch
base
client
server
io
net
platform
server
app
mt
gui
GTest::gtest
GTest::gmock
${libs})
endmacro()
config_all_tests()

View file

@ -1,21 +0,0 @@
# SPDX-FileCopyrightText: (C) 2012 - 2024 Symless Ltd
# SPDX-FileCopyrightText: (C) 2009 - 2012 Nick Bolton
# SPDX-License-Identifier: MIT
config_test()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(target legacytests)
add_executable(${target} ${sources} ${headers})
target_link_libraries(${target} ${test_libs} common)
if(ENABLE_COVERAGE)
set(test_exclude subprojects/* build/* src/unittests/*)
set(test_src ${PROJECT_SOURCE_DIR}/src)
setup_target_for_coverage_gcovr_xml(
NAME coverage-${target}
EXECUTABLE ${target}
BASE_DIRECTORY ${test_src}
EXCLUDE ${test_exclude}
)
endif()

View file

@ -1,210 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2014 - 2016 Synergy App Ltd
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "arch/IArchNetwork.h"
#include "lib/arch/unix/ArchNetworkBSD.h"
#include "lib/arch/ArchException.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <memory>
#include <netinet/in.h>
#include <sys/types.h>
using ::testing::_;
using ::testing::NiceMock;
using PollEntries = std::vector<IArchNetwork::PollEntry>;
using PollFD = struct pollfd[];
namespace {
struct MockDeps : public ArchNetworkBSD::Deps
{
std::shared_ptr<PollFD> m_pollFD;
MockDeps()
{
ON_CALL(*this, makePollFD(_)).WillByDefault([this](nfds_t n) {
m_pollFD = ArchNetworkBSD::Deps::makePollFD(n);
return m_pollFD;
});
}
static std::shared_ptr<NiceMock<MockDeps>> makeNice()
{
return std::make_shared<NiceMock<MockDeps>>();
}
MOCK_METHOD(void, sleep, (double), (override));
MOCK_METHOD(int, poll, (struct pollfd *, nfds_t, int), (override));
MOCK_METHOD(std::shared_ptr<PollFD>, makePollFD, (nfds_t), (override));
MOCK_METHOD(ssize_t, read, (int, void *, size_t), (override));
MOCK_METHOD(void, testCancelThread, (), (override));
};
} // namespace
TEST(ArchNetworkBSDTests, pollSocket_zeroEntries_callsSleep)
{
auto deps = MockDeps::makeNice();
ArchNetworkBSD networkBSD(deps);
EXPECT_CALL(*deps, sleep(1)).Times(1);
auto result = networkBSD.pollSocket(nullptr, 0, 1);
EXPECT_EQ(result, 0);
}
TEST(ArchNetworkBSDTests, pollSocket_mockAccessError_throws)
{
auto deps = MockDeps::makeNice();
ON_CALL(*deps, poll(_, _, _)).WillByDefault([]() {
errno = EACCES;
return -1;
});
ArchNetworkBSD networkBSD(deps);
PollEntries entries{{nullptr, 0, 0}};
const auto f = [&] { networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1); };
EXPECT_THROW({ f(); }, ArchNetworkAccessException);
}
TEST(ArchNetworkBSDTests, pollSocket_pfdHasRevents_copiedToEntries)
{
auto deps = MockDeps::makeNice();
ON_CALL(*deps, poll(_, _, _)).WillByDefault([](auto pfd, auto, auto) {
pfd[0].revents = POLLIN | POLLOUT | POLLERR | POLLNVAL;
return 0;
});
ArchNetworkBSD networkBSD(deps);
PollEntries entries{{nullptr, 0, 0}};
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
const auto expect = IArchNetwork::PollEventMask::In | IArchNetwork::PollEventMask::Out |
IArchNetwork::PollEventMask::Error | IArchNetwork::PollEventMask::Invalid;
EXPECT_EQ(entries[0].m_revents, expect);
}
TEST(ArchNetworkBSDTests, pollSocket_nullSocket_fdIsNegativeOne)
{
auto deps = MockDeps::makeNice();
ArchNetworkBSD networkBSD(deps);
PollEntries entries{{nullptr, 0, 0}};
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
EXPECT_EQ(deps->m_pollFD[0].fd, -1);
}
TEST(ArchNetworkBSDTests, pollSocket_socketSet_fdWasSet)
{
auto deps = MockDeps::makeNice();
ArchNetworkBSD networkBSD(deps);
ArchSocketImpl socket{1, 0};
PollEntries entries{{&socket, 0, 0}};
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
EXPECT_EQ(deps->m_pollFD[0].fd, 1);
}
TEST(ArchNetworkBSDTests, pollSocket_eventHasPollInBit_bitWasSet)
{
auto deps = MockDeps::makeNice();
ArchNetworkBSD networkBSD(deps);
ArchSocketImpl socket{1, 0};
PollEntries entries{{&socket, IArchNetwork::PollEventMask::In, 0}};
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
EXPECT_EQ(deps->m_pollFD[0].events, POLLIN);
}
TEST(ArchNetworkBSDTests, pollSocket_eventHasPollOutBit_bitWasSet)
{
auto deps = MockDeps::makeNice();
ArchNetworkBSD networkBSD(deps);
ArchSocketImpl socket{1, 0};
PollEntries entries{{&socket, IArchNetwork::PollEventMask::Out, 0}};
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
EXPECT_EQ(deps->m_pollFD[0].events, POLLOUT);
}
TEST(ArchNetworkBSDTests, pollSocket_nullSocket_unblockPipeAppended)
{
auto deps = MockDeps::makeNice();
ArchNetworkBSD networkBSD(deps);
PollEntries entries{{nullptr, 0, 0}};
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
// interesting: unblock pipe fd comes from `getNetworkDataForThread` which
// seems to differ depending on linux distro.
EXPECT_GT(deps->m_pollFD[1].fd, -1);
}
TEST(ArchNetworkBSDTests, pollSocket_unblockPipeReventsError_readCalled)
{
const auto unblockPipeIndex = 1;
auto deps = MockDeps::makeNice();
ON_CALL(*deps, poll(_, _, _)).WillByDefault([](auto pfd, auto, auto) {
pfd[unblockPipeIndex].revents = POLLIN;
return 1;
});
ON_CALL(*deps, read(_, _, _)).WillByDefault([]() {
errno = EAGAIN;
return 0;
});
ArchNetworkBSD networkBSD(deps);
PollEntries entries{{nullptr, 0, 0}};
EXPECT_CALL(*deps, read(_, _, _)).Times(1);
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
}
TEST(ArchNetworkBSDTests, pollSocket_interruptSystemCall_testCancelThread)
{
auto deps = MockDeps::makeNice();
ON_CALL(*deps, poll(_, _, _)).WillByDefault([]() {
errno = EINTR;
return -1;
});
ArchNetworkBSD networkBSD(deps);
PollEntries entries{{nullptr, 0, 0}};
EXPECT_CALL(*deps, testCancelThread()).Times(1);
networkBSD.pollSocket(entries.data(), static_cast<int>(entries.size()), 1);
}
TEST(ArchNetworkBSDTests, isAnyAddr_goodAddress_returnsTrue)
{
auto deps = MockDeps::makeNice();
ArchNetworkBSD networkBSD(deps);
std::unique_ptr<ArchNetAddressImpl> addr;
addr.reset(networkBSD.newAnyAddr(IArchNetwork::AddressFamily::INet6));
auto result = networkBSD.isAnyAddr(addr.get());
EXPECT_TRUE(result);
}
TEST(ArchNetworkBSDTests, isAnyAddr_badAddress_returnsFalse)
{
auto deps = MockDeps::makeNice();
ArchNetworkBSD networkBSD(deps);
std::unique_ptr<ArchNetAddressImpl> addr;
addr.reset(networkBSD.newAnyAddr(IArchNetwork::AddressFamily::INet6));
auto scratch = (char *)&addr->m_addr;
std::string badAddr = "badaddr";
std::ranges::copy(badAddr, scratch + 2);
auto result = networkBSD.isAnyAddr(addr.get());
EXPECT_FALSE(result);
}

View file

@ -1,283 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
* SPDX-FileCopyrightText: (C) 2011 Nick Bolton
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "unittests/legacytests/mock/deskflow/MockEventQueue.h"
#include "unittests/legacytests/mock/deskflow/MockKeyMap.h"
#include "unittests/legacytests/mock/deskflow/MockKeyState.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using ::testing::_;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::Return;
void stubPollPressedKeys(IKeyState::KeyButtonSet &pressedKeys);
void assertMaskIsOne(ForeachKeyCallback, void *userData);
const deskflow::KeyMap::KeyItem *stubMapKey(
deskflow::KeyMap::Keystrokes &keys, KeyID id, int32_t group, deskflow::KeyMap::ModifierToKeys &activeModifiers,
KeyModifierMask &currentState, KeyModifierMask desiredMask, bool isAutoRepeat, const std::string &lang
);
deskflow::KeyMap::Keystroke s_stubKeystroke(1, false, false);
deskflow::KeyMap::KeyItem s_stubKeyItem;
TEST(KeyStateTests, sendKeyEvent_halfDuplexAndRepeat_addEventNotCalled)
{
NiceMock<MockKeyMap> keyMap;
NiceMock<MockEventQueue> eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
ON_CALL(keyMap, isHalfDuplex(_, _)).WillByDefault(Return(true));
EXPECT_CALL(eventQueue, addEvent(_)).Times(0);
keyState.sendKeyEvent(nullptr, false, true, kKeyCapsLock, 0, 0, 0);
}
TEST(KeyStateTests, updateKeyMap_mockKeyMap_keyMapGotMock)
{
NiceMock<MockKeyMap> keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
// key map member gets a new key map via swap()
EXPECT_CALL(keyMap, swap(_));
keyState.updateKeyMap();
}
TEST(KeyStateTests, updateKeyState_activeModifiers_maskSet)
{
NiceMock<MockKeyMap> keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
ON_CALL(keyState, pollActiveModifiers()).WillByDefault(Return(KeyModifierAlt));
keyState.updateKeyState();
KeyModifierMask actual = keyState.getActiveModifiers();
ASSERT_EQ(KeyModifierAlt, actual);
}
TEST(KeyStateTests, updateKeyState_activeModifiers_keyMapGotModifers)
{
MockKeyMap keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
ON_CALL(keyState, pollActiveModifiers()).WillByDefault(Return(1));
ON_CALL(keyMap, foreachKey(_, _)).WillByDefault(Invoke(assertMaskIsOne));
// key map gets new modifiers via foreachKey()
EXPECT_CALL(keyMap, foreachKey(_, _));
keyState.updateKeyState();
}
TEST(KeyStateTests, setHalfDuplexMask_capsLock_halfDuplexCapsLockAdded)
{
MockKeyMap keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
EXPECT_CALL(keyMap, addHalfDuplexModifier(kKeyCapsLock));
keyState.setHalfDuplexMask(KeyModifierCapsLock);
}
TEST(KeyStateTests, setHalfDuplexMask_numLock_halfDuplexNumLockAdded)
{
MockKeyMap keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
EXPECT_CALL(keyMap, addHalfDuplexModifier(kKeyNumLock));
keyState.setHalfDuplexMask(KeyModifierNumLock);
}
TEST(KeyStateTests, setHalfDuplexMask_scrollLock_halfDuplexScollLockAdded)
{
MockKeyMap keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
EXPECT_CALL(keyMap, addHalfDuplexModifier(kKeyScrollLock));
keyState.setHalfDuplexMask(KeyModifierScrollLock);
}
TEST(KeyStateTests, fakeKeyDown_serverKeyAlreadyDown_fakeKeyCalledTwice)
{
NiceMock<MockKeyMap> keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
s_stubKeyItem.m_client = 0;
s_stubKeyItem.m_button = 1;
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Invoke(stubMapKey));
// 2 calls to fakeKeyDown should still call fakeKey, even though
// repeated keys are handled differently.
EXPECT_CALL(keyState, fakeKey(_)).Times(2);
// call twice to simulate server key already down (a misreported autorepeat).
keyState.fakeKeyDown(1, 0, 0, "en");
keyState.fakeKeyDown(1, 0, 0, "en");
}
TEST(KeyStateTests, fakeKeyDown_isIgnoredKey_fakeKeyNotCalled)
{
MockKeyMap keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
EXPECT_CALL(keyState, fakeKey(_)).Times(0);
keyState.fakeKeyDown(kKeyCapsLock, 0, 0, "en");
}
TEST(KeyStateTests, fakeKeyDown_mapReturnsKeystrokes_fakeKeyCalled)
{
NiceMock<MockKeyMap> keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
s_stubKeyItem.m_button = 0;
s_stubKeyItem.m_client = 0;
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Invoke(stubMapKey));
EXPECT_CALL(keyState, fakeKey(_)).Times(1);
keyState.fakeKeyDown(1, 0, 0, "en");
}
TEST(KeyStateTests, fakeKeyRepeat_nullKey_returnsFalse)
{
NiceMock<MockKeyMap> keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
// set the key to down (we need to make mapKey return a valid key to do this).
deskflow::KeyMap::KeyItem keyItem;
keyItem.m_client = 0;
keyItem.m_button = 1;
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Return(&keyItem));
keyState.fakeKeyDown(1, 0, 0, "en");
// change mapKey to return nullptr so that fakeKeyRepeat exits early.
deskflow::KeyMap::KeyItem *nullKeyItem = nullptr;
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Return(nullKeyItem));
bool actual = keyState.fakeKeyRepeat(1, 0, 0, 0, "en");
ASSERT_FALSE(actual);
}
TEST(KeyStateTests, fakeKeyRepeat_invalidButton_returnsFalse)
{
NiceMock<MockKeyMap> keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
// set the key to down (we need to make mapKey return a valid key to do this).
deskflow::KeyMap::KeyItem keyItem;
keyItem.m_client = 0;
keyItem.m_button = 1; // set to 1 to make fakeKeyDown work.
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Return(&keyItem));
keyState.fakeKeyDown(1, 0, 0, "en");
// change button to 0 so that fakeKeyRepeat will return early.
keyItem.m_button = 0;
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Return(&keyItem));
bool actual = keyState.fakeKeyRepeat(1, 0, 0, 0, "en");
ASSERT_FALSE(actual);
}
TEST(KeyStateTests, fakeKeyRepeat_validKey_returnsTrue)
{
NiceMock<MockKeyMap> keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
s_stubKeyItem.m_client = 0;
s_stubKeystroke.m_type = deskflow::KeyMap::Keystroke::KeyType::Button;
s_stubKeystroke.m_data.m_button.m_button = 2;
// set the button to 1 for fakeKeyDown call
s_stubKeyItem.m_button = 1;
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Invoke(stubMapKey));
keyState.fakeKeyDown(1, 0, 0, "en");
// change the button to 2
s_stubKeyItem.m_button = 2;
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Invoke(stubMapKey));
bool actual = keyState.fakeKeyRepeat(1, 0, 0, 0, "en");
ASSERT_TRUE(actual);
}
TEST(KeyStateTests, fakeKeyUp_buttonAlreadyDown_returnsTrue)
{
NiceMock<MockKeyMap> keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
// press alt down so we get full coverage.
ON_CALL(keyState, pollActiveModifiers()).WillByDefault(Return(KeyModifierAlt));
keyState.updateKeyState();
// press button 1 down.
s_stubKeyItem.m_button = 1;
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Invoke(stubMapKey));
keyState.fakeKeyDown(1, 0, 1, "en");
// this takes the button id, which is the 3rd arg of fakeKeyDown
bool actual = keyState.fakeKeyUp(1);
ASSERT_TRUE(actual);
}
TEST(KeyStateTests, fakeAllKeysUp_keysWereDown_keysAreUp)
{
NiceMock<MockKeyMap> keyMap;
MockEventQueue eventQueue;
KeyStateImpl keyState(eventQueue, keyMap);
// press button 1 down.
s_stubKeyItem.m_button = 1;
ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Invoke(stubMapKey));
keyState.fakeKeyDown(1, 0, 1, "en");
// method under test
keyState.fakeAllKeysUp();
bool actual = keyState.isKeyDown(1);
ASSERT_FALSE(actual);
}
void stubPollPressedKeys(IKeyState::KeyButtonSet &pressedKeys)
{
pressedKeys.insert(1);
}
void assertMaskIsOne(ForeachKeyCallback, void *userData)
{
ASSERT_EQ(1, ((KeyState::AddActiveModifierContext *)userData)->m_mask);
}
const deskflow::KeyMap::KeyItem *stubMapKey(
deskflow::KeyMap::Keystrokes &keys, KeyID, int32_t, deskflow::KeyMap::ModifierToKeys &, KeyModifierMask &,
KeyModifierMask, bool, const std::string &
)
{
keys.push_back(s_stubKeystroke);
return &s_stubKeyItem;
}

View file

@ -1,43 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2012 Synergy App Ltd
* SPDX-FileCopyrightText: (C) 2011 Nick Bolton
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "arch/Arch.h"
#include "base/Log.h"
#include "unittests/legacytests/shared/ExitTimeout.h"
#if defined(Q_OS_WIN)
#include "arch/win32/ArchMiscWindows.h"
#endif
#include <gtest/gtest.h>
using deskflow::test::ExitTimeout;
const auto testDir = "tmp/test";
int main(int argc, char **argv)
{
ExitTimeout exitTimeout(1, "Unit tests");
#if defined(Q_OS_WIN)
// HACK: shouldn't be needed, but logging fails without this.
ArchMiscWindows::setInstanceWin32(GetModuleHandle(nullptr));
#endif
Arch arch;
arch.init();
Log log;
log.setFilter(LogLevel::Level::Verbose);
::testing::GTEST_FLAG(throw_on_failure) = true;
testing::InitGoogleTest(&argc, argv);
// return code 1 means the test failed.
// any other non-zero code is probably a memory error.
return RUN_ALL_TESTS();
}

View file

@ -1,31 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
* SPDX-FileCopyrightText: (C) 2011 Nick Bolton
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include "base/IEventQueue.h"
#include <gmock/gmock.h>
class MockEventQueue : public IEventQueue
{
public:
MOCK_METHOD(int, loop, (), (override));
MOCK_METHOD(EventQueueTimer *, newOneShotTimer, (double, void *), (override));
MOCK_METHOD(EventQueueTimer *, newTimer, (double, void *), (override));
MOCK_METHOD(bool, getEvent, (Event &, double), (override));
MOCK_METHOD(void, adoptBuffer, (IEventQueueBuffer *), (override));
MOCK_METHOD(void, removeHandlers, (void *), (override));
MOCK_METHOD(EventTypes, registerType, (const char *));
MOCK_METHOD(void, addHandler, (EventTypes, void *, const EventHandler &), (override));
MOCK_METHOD(void, addEvent, (Event &&), (override));
MOCK_METHOD(void, removeHandler, (EventTypes, void *), (override));
MOCK_METHOD(bool, dispatchEvent, (const Event &), (override));
MOCK_METHOD(void, deleteTimer, (EventQueueTimer *), (override));
MOCK_METHOD(void *, getSystemTarget, (), (override));
MOCK_METHOD(void, waitForReady, (), (const, override));
};

View file

@ -1,26 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
* SPDX-FileCopyrightText: (C) 2011 Nick Bolton
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include "deskflow/KeyMap.h"
#include <gmock/gmock.h>
class MockKeyMap : public deskflow::KeyMap
{
public:
MOCK_METHOD(void, swap, (KeyMap &), (noexcept));
MOCK_METHOD(void, finish, (), (override));
MOCK_METHOD(void, foreachKey, (ForeachKeyCallback, void *), (override));
MOCK_METHOD(void, addHalfDuplexModifier, (KeyID), (override));
MOCK_METHOD(bool, isHalfDuplex, (KeyID, KeyButton), (const, override));
MOCK_METHOD(
const KeyMap::KeyItem *, mapKey,
(Keystrokes &, KeyID, int32_t, ModifierToKeys &, KeyModifierMask &, KeyModifierMask, bool, const std::string &),
(const, override)
);
};

View file

@ -1,44 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
* SPDX-FileCopyrightText: (C) 2011 Nick Bolton
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include "deskflow/KeyState.h"
#include <gmock/gmock.h>
class MockKeyMap;
class MockEventQueue;
// NOTE: do not mock methods that are not pure virtual. this mock exists only
// to provide an implementation of the KeyState abstract class.
class MockKeyState : public KeyState
{
public:
MockKeyState(const MockEventQueue &eventQueue) : KeyState((IEventQueue *)&eventQueue, {"en"}, true)
{
}
MockKeyState(const MockEventQueue &eventQueue, const deskflow::KeyMap &keyMap)
: KeyState((IEventQueue *)&eventQueue, (deskflow::KeyMap &)keyMap, {"en"}, true)
{
}
MOCK_METHOD(int32_t, pollActiveGroup, (), (const, override));
MOCK_METHOD(KeyModifierMask, pollActiveModifiers, (), (const, override));
MOCK_METHOD(bool, fakeCtrlAltDel, (), (override));
MOCK_METHOD(void, getKeyMap, (deskflow::KeyMap &), (override));
MOCK_METHOD(void, fakeKey, (const Keystroke &), (override));
MOCK_METHOD(bool, fakeMediaKey, (KeyID), (override));
MOCK_METHOD(void, pollPressedKeys, (KeyButtonSet &), (const, override));
};
typedef ::testing::NiceMock<MockKeyState> KeyStateImpl;
using KeyID = uint32_t;
typedef void (*ForeachKeyCallback)(KeyID, int32_t group, deskflow::KeyMap::KeyItem &, void *userData);

View file

@ -1,54 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Synergy App Ltd
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "ExitTimeout.h"
#include <chrono>
#include <iostream>
#include <memory>
#include <string_view>
#include <thread>
namespace deskflow::test {
const auto checkMilliseconds = std::chrono::milliseconds(100);
using std::chrono::duration_cast;
using std::chrono::steady_clock;
bool timeoutReached(const steady_clock::time_point &start, const int minutes)
{
auto now = steady_clock::now();
auto duration = duration_cast<std::chrono::minutes>(now - start);
return duration.count() >= minutes;
}
ExitTimeout::ExitTimeout(const int minutes, const std::string_view &name)
: m_minutes(minutes),
m_name(name),
m_thread(std::make_unique<std::thread>([this]() { run(); }))
{
}
ExitTimeout::~ExitTimeout()
{
m_running = false;
m_thread->join();
}
void ExitTimeout::run() const
{
auto start = steady_clock::now();
while (m_running) {
std::this_thread::sleep_for(checkMilliseconds);
if (timeoutReached(start, m_minutes)) {
std::cerr << m_name << " timed out after " << m_minutes << " minute(s)" << std::endl;
std::exit(EXIT_FAILURE);
}
}
}
} // namespace deskflow::test

View file

@ -1,37 +0,0 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2024 Synergy App Ltd
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#pragma once
#include <string_view>
#include <thread>
namespace deskflow::test {
/**
* @brief Exits the program after a specified timeout, unless destroyed.
*
* The `std::thread` class is used instead of `std::jthread` as Apple Clang has
* no `std::jthread` support: https://en.cppreference.com/w/cpp/compiler_support
*
* TODO: Switch to regular Clang instead of Apple Clang:
* https://symless.atlassian.net/browse/S1-1754
*/
class ExitTimeout
{
public:
ExitTimeout(const int minutes, const std::string_view &name);
~ExitTimeout();
void run() const;
private:
bool m_running = true;
int m_minutes = 0;
std::string_view m_name;
std::unique_ptr<std::thread> m_thread;
};
} // namespace deskflow::test