diff --git a/src/lib/gui/MainWindow.cpp b/src/lib/gui/MainWindow.cpp index 2a39f4675..78b3a6c69 100644 --- a/src/lib/gui/MainWindow.cpp +++ b/src/lib/gui/MainWindow.cpp @@ -293,8 +293,10 @@ void MainWindow::connectSlots() connect(&m_serverConnection, &ServerConnection::configureClient, this, &MainWindow::serverConnectionConfigureClient); connect(&m_serverConnection, &ServerConnection::clientsChanged, this, &MainWindow::serverClientsChanged); + connect( + &m_serverConnection, &ServerConnection::requestNewClientPrompt, this, &MainWindow::handleNewClientPromptRequest + ); - connect(&m_serverConnection, &ServerConnection::messageShowing, this, &MainWindow::showAndActivate); connect(&m_clientConnection, &ClientConnection::requestShowError, this, &MainWindow::showClientError); connect(ui->btnToggleCore, &QPushButton::clicked, m_actionStartCore, &QAction::trigger, Qt::UniqueConnection); @@ -1237,3 +1239,10 @@ void MainWindow::showClientError(deskflow::client::ErrorType error, const QStrin showAndActivate(); m_clientErrorVisible = false; } + +void MainWindow::handleNewClientPromptRequest(const QString &clientName, bool usePeerAuth) +{ + showAndActivate(); + bool result = deskflow::gui::messages::showNewClientPrompt(this, clientName, usePeerAuth); + m_serverConnection.handleNewClientResult(clientName, result); +} diff --git a/src/lib/gui/MainWindow.h b/src/lib/gui/MainWindow.h index a0c3240fe..9aad00b30 100644 --- a/src/lib/gui/MainWindow.h +++ b/src/lib/gui/MainWindow.h @@ -151,7 +151,7 @@ private: void daemonIpcClientConnectionFailed(); void toggleCanRunCore(bool enableButtons); void remoteHostChanged(const QString &newRemoteHost); - + void handleNewClientPromptRequest(const QString &clientName, bool usePeerAuth); /** * @brief showClientError * @param error Error Type diff --git a/src/lib/gui/core/ServerConnection.cpp b/src/lib/gui/core/ServerConnection.cpp index 17b0e6915..922481d08 100644 --- a/src/lib/gui/core/ServerConnection.cpp +++ b/src/lib/gui/core/ServerConnection.cpp @@ -1,12 +1,12 @@ /* * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers * SPDX-FileCopyrightText: (C) 2021 Symless Ltd. * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ #include "ServerConnection.h" -#include "Messages.h" #include "ServerMessage.h" #include "common/Settings.h" @@ -15,25 +15,9 @@ namespace deskflow::gui { -// -// ServerConnection::Deps -// - -bool ServerConnection::Deps::showNewClientPrompt( - QWidget *parent, const QString &clientName, bool serverRequiresPeerAuth -) const -{ - return messages::showNewClientPrompt(parent, clientName, serverRequiresPeerAuth); -} - -// -// ServerConnection -// - -ServerConnection::ServerConnection(QWidget *parent, IServerConfig &serverConfig, std::shared_ptr deps) +ServerConnection::ServerConnection(QWidget *parent, IServerConfig &serverConfig) : m_pParent(parent), - m_serverConfig(serverConfig), - m_pDeps(deps) + m_serverConfig(serverConfig) { } @@ -93,15 +77,17 @@ void ServerConnection::handleNewClient(const QString &clientName) return; } - Q_EMIT messageShowing(); - m_messageShowing = true; const bool tlsEnabled = Settings::value(Settings::Security::TlsEnabled).toBool(); const bool requireCerts = Settings::value(Settings::Security::CheckPeers).toBool(); - const auto result = m_pDeps->showNewClientPrompt(m_pParent, clientName, tlsEnabled && requireCerts); + Q_EMIT requestNewClientPrompt(clientName, tlsEnabled && requireCerts); +} + +void ServerConnection::handleNewClientResult(const QString &clientName, bool acceptClient) +{ m_messageShowing = false; - if (result) { + if (acceptClient) { qDebug("accepted dialog, adding client: %s", qPrintable(clientName)); Q_EMIT configureClient(clientName); } else { diff --git a/src/lib/gui/core/ServerConnection.h b/src/lib/gui/core/ServerConnection.h index f9e8ed21f..fc28b427e 100644 --- a/src/lib/gui/core/ServerConnection.h +++ b/src/lib/gui/core/ServerConnection.h @@ -1,5 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers * SPDX-FileCopyrightText: (C) 2021 Symless Ltd. * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ @@ -19,16 +20,7 @@ class ServerConnection : public QObject using IServerConfig = deskflow::gui::IServerConfig; public: - struct Deps - { - virtual ~Deps() = default; - virtual bool - showNewClientPrompt(QWidget *parent, const QString &clientName, bool serverRequiresPeerAuth = false) const; - }; - - explicit ServerConnection( - QWidget *parent, IServerConfig &serverConfig, std::shared_ptr deps = std::make_shared() - ); + explicit ServerConnection(QWidget *parent, IServerConfig &serverConfig); void handleLogLine(const QString &logLine); void serverConfigDialogVisible(bool visible) { @@ -36,9 +28,10 @@ public: } QStringList connectedClients() const; + void handleNewClientResult(const QString &clientName, bool acceptClient); Q_SIGNALS: - void messageShowing(); + void requestNewClientPrompt(const QString &clientName, bool peerAuthRequired); void configureClient(const QString &clientName); void clientsChanged(const QStringList &clients); @@ -47,7 +40,6 @@ private: QWidget *m_pParent; IServerConfig &m_serverConfig; - std::shared_ptr m_pDeps; QSet m_connectedClients; bool m_messageShowing = false; bool m_serverConfigDialogVisible = false; diff --git a/src/unittests/gui/core/CMakeLists.txt b/src/unittests/gui/core/CMakeLists.txt index 15abad75e..77645e5ef 100644 --- a/src/unittests/gui/core/CMakeLists.txt +++ b/src/unittests/gui/core/CMakeLists.txt @@ -14,3 +14,10 @@ create_test( SOURCE ClientConnectionTests.cpp WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/gui" ) + +create_test( + NAME ServerConnectionTests + DEPENDS gui + SOURCE ServerConnectionTests.cpp + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/gui" +) diff --git a/src/unittests/gui/core/ServerConnectionTests.cpp b/src/unittests/gui/core/ServerConnectionTests.cpp new file mode 100644 index 000000000..a40c5583f --- /dev/null +++ b/src/unittests/gui/core/ServerConnectionTests.cpp @@ -0,0 +1,101 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-FileCopyrightText: (C) 2024 Symless Ltd. + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#include "ServerConnectionTests.h" + +#include "gui/config/ServerConfig.h" +#include "gui/core/ServerConnection.h" +#include + +#include + +using namespace deskflow::gui; + +class FullServerConfig : public ServerConfig +{ +public: + bool isFull() const override + { + return true; + } +}; + +class ScreenExistsServerConfig : public ServerConfig +{ +public: + bool screenExists(const QString &screenName) const override + { + return true; + } +}; + +void ServerConnectionTests::initTestCase() +{ + QDir dir; + QVERIFY(dir.mkpath(m_settingsPath)); + + QFile oldSettings(m_settingsFile); + if (oldSettings.exists()) + oldSettings.remove(); + + Settings::setSettingsFile(m_settingsFile); + Settings::setStateFile(m_stateFile); +} + +void ServerConnectionTests::handleLogLine_newClient_shouldShowPrompt() +{ + ServerConfig m_serverConfig; + ServerConnection serverConnection(nullptr, m_serverConfig); + + QString clientName = "test client"; + + QSignalSpy spy(&serverConnection, &ServerConnection::requestNewClientPrompt); + QVERIFY(spy.isValid()); + + serverConnection.handleLogLine(R"(unrecognised client name "test client")"); + QCOMPARE(spy.count(), 1); +} + +void ServerConnectionTests::handleLogLine_ignoredClient_shouldNotShowPrompt() +{ + ServerConfig m_serverConfig; + ServerConnection serverConnection(nullptr, m_serverConfig); + QString clientName = "test client"; + serverConnection.handleNewClientResult(clientName, false); + + QSignalSpy spy(&serverConnection, &ServerConnection::requestNewClientPrompt); + QVERIFY(spy.isValid()); + + serverConnection.handleLogLine(R"(unrecognised client name "test client")"); + QCOMPARE(spy.count(), 0); +} + +void ServerConnectionTests::handleLogLine_serverConfigFull_shouldNotShowPrompt() +{ + FullServerConfig m_serverConfig; + ServerConnection serverConnection(nullptr, m_serverConfig); + + QSignalSpy spy(&serverConnection, &ServerConnection::requestNewClientPrompt); + QVERIFY(spy.isValid()); + + serverConnection.handleLogLine(R"(unrecognised client name "test client")"); + QCOMPARE(spy.count(), 0); +} + +void ServerConnectionTests::handleLogLine_screenExists_shouldNotShowPrompt() +{ + ScreenExistsServerConfig m_serverConfig; + ServerConnection serverConnection(nullptr, m_serverConfig); + + QSignalSpy spy(&serverConnection, &ServerConnection::requestNewClientPrompt); + QVERIFY(spy.isValid()); + + serverConnection.handleLogLine(R"(unrecognised client name "test client")"); + QCOMPARE(spy.count(), 0); +} + +QTEST_MAIN(ServerConnectionTests) diff --git a/src/unittests/gui/core/ServerConnectionTests.h b/src/unittests/gui/core/ServerConnectionTests.h new file mode 100644 index 000000000..558775a25 --- /dev/null +++ b/src/unittests/gui/core/ServerConnectionTests.h @@ -0,0 +1,24 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#include + +class ServerConnectionTests : public QObject +{ + Q_OBJECT +private Q_SLOTS: + // Test are run in order top to bottom + void initTestCase(); + void handleLogLine_newClient_shouldShowPrompt(); + void handleLogLine_ignoredClient_shouldNotShowPrompt(); + void handleLogLine_serverConfigFull_shouldNotShowPrompt(); + void handleLogLine_screenExists_shouldNotShowPrompt(); + +private: + inline static const QString m_settingsPath = QStringLiteral("tmp/test"); + inline static const QString m_settingsFile = QStringLiteral("%1/Deskflow.conf").arg(m_settingsPath); + inline static const QString m_stateFile = QStringLiteral("%1/Deskflow.state").arg(m_settingsPath); +}; diff --git a/src/unittests/legacytests/legacytests/gui/core/ServerConnectionTests.cpp b/src/unittests/legacytests/legacytests/gui/core/ServerConnectionTests.cpp deleted file mode 100644 index c8d2e0123..000000000 --- a/src/unittests/legacytests/legacytests/gui/core/ServerConnectionTests.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2024 Symless Ltd. - * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception - */ - -#include "gui/core/ServerConnection.h" - -#include "unittests/legacytests/shared/gui/mocks/ServerConfigMock.h" - -#include "gmock/gmock.h" -#include -#include - -using testing::_; -using testing::NiceMock; -using namespace deskflow::gui; - -class QWidget; - -namespace { - -struct DepsMock : public ServerConnection::Deps -{ - MOCK_METHOD( - bool, showNewClientPrompt, (QWidget * parent, const QString &clientName, bool previousyAccepted), - (const, override) - ); -}; - -} // namespace - -class ServerConnectionTests : public testing::Test -{ -public: - std::shared_ptr m_pDeps = std::make_shared>(); - NiceMock m_serverConfig; -}; - -TEST_F(ServerConnectionTests, handleLogLine_newClient_shouldShowPrompt) -{ - ServerConnection serverConnection(nullptr, m_serverConfig, m_pDeps); - - QString clientName = "test client"; - EXPECT_CALL(*m_pDeps, showNewClientPrompt(_, clientName, true)).Times(0); - - serverConnection.handleLogLine(R"(unrecognised client name "test client")"); -} - -TEST_F(ServerConnectionTests, handleLogLine_ignoredClient_shouldNotShowPrompt) -{ - ServerConnection serverConnection(nullptr, m_serverConfig, m_pDeps); - ON_CALL(*m_pDeps, showNewClientPrompt(_, _, false)).WillByDefault(testing::Return(false)); - serverConnection.handleLogLine(R"(unrecognised client name "stub")"); - - EXPECT_CALL(*m_pDeps, showNewClientPrompt(_, _, false)).Times(0); - - serverConnection.handleLogLine(R"(unrecognised client name "stub")"); -} - -TEST_F(ServerConnectionTests, handleLogLine_serverConfigFull_shouldNotShowPrompt) -{ - ServerConnection serverConnection(nullptr, m_serverConfig, m_pDeps); - ON_CALL(m_serverConfig, isFull()).WillByDefault(testing::Return(true)); - - EXPECT_CALL(*m_pDeps, showNewClientPrompt(_, _, false)).Times(0); - - serverConnection.handleLogLine(R"(unrecognised client name "test client")"); -} - -TEST_F(ServerConnectionTests, handleLogLine_screenExists_shouldNotShowPrompt) -{ - ServerConnection serverConnection(nullptr, m_serverConfig, m_pDeps); - ON_CALL(m_serverConfig, screenExists(_)).WillByDefault(testing::Return(true)); - - EXPECT_CALL(*m_pDeps, showNewClientPrompt(_, _, false)).Times(0); - - serverConnection.handleLogLine(R"(unrecognised client name "test client")"); -} diff --git a/src/unittests/legacytests/legacytests/main.cpp b/src/unittests/legacytests/legacytests/main.cpp index 717f6b908..e348c37c2 100644 --- a/src/unittests/legacytests/legacytests/main.cpp +++ b/src/unittests/legacytests/legacytests/main.cpp @@ -7,14 +7,12 @@ #include "arch/Arch.h" #include "base/Log.h" -#include "common/Settings.h" #include "unittests/legacytests/shared/ExitTimeout.h" #if SYSAPI_WIN32 #include "arch/win32/ArchMiscWindows.h" #endif -#include #include using deskflow::test::ExitTimeout; @@ -23,13 +21,6 @@ const auto testDir = "tmp/test"; int main(int argc, char **argv) { - // HACK: Unit tests should not use the filesystem. - std::filesystem::create_directories(testDir); - - Settings::setSettingsFile("tmp/test/settings.ini"); - Settings::setStateFile("tmp/test/Deskflow.state"); - Settings::setValue(Settings::Server::ExternalConfig, true); - ExitTimeout exitTimeout(1, "Unit tests"); #if SYSAPI_WIN32