From 0c9b3d5fbebb30ae37ab450ccb91d454d69e406d Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 4 Mar 2026 13:37:17 +0200 Subject: [PATCH 01/53] fix: AUTOMOC and AUTOUIC added --- client/tests/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index e541a4e6f..e7496f978 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -5,7 +5,9 @@ project(AmneziaVPN_Tests) find_package(Qt6 REQUIRED COMPONENTS Test) +set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) qt6_add_resources(TEST_QRC ${CLIENT_ROOT_DIR}/server_scripts/serverScripts.qrc From fb402eb9c82822f1c8665df0cf71f8176360449f Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Fri, 13 Mar 2026 11:15:36 +0200 Subject: [PATCH 02/53] update: native exports test --- client/core/controllers/coreController.h | 2 + client/tests/CMakeLists.txt | 10 ++ client/tests/testMultipleExports.cpp | 167 +++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 client/tests/testMultipleExports.cpp diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 1fb178f0f..a78b720d8 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -87,6 +87,7 @@ class TestComplexOperations; class TestSettingsSignals; class TestUiServersModelAndController; class TestSelfHostedServerSetup; +class TestMultipleExports; class CoreController : public QObject { @@ -104,6 +105,7 @@ class CoreController : public QObject friend class TestSettingsSignals; friend class TestUiServersModelAndController; friend class TestSelfHostedServerSetup; + friend class TestMultipleExports; public: explicit CoreController(const QSharedPointer &vpnConnection, SecureQSettings* settings, diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index e7496f978..bed52a677 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -142,6 +142,15 @@ target_link_libraries(test_self_hosted_server_setup PRIVATE test_common ) +add_executable(test_exports + testMultipleExports.cpp +) + +target_link_libraries(test_exports PRIVATE + Qt6::Test + test_common +) + enable_testing() add_test(NAME ImportExportTest COMMAND test_import_export) add_test(NAME MultipleImportsTest COMMAND test_multiple_imports) @@ -155,3 +164,4 @@ add_test(NAME ComplexOperationsTest COMMAND test_complex_operations) add_test(NAME SettingsSignalsTest COMMAND test_settings_signals) add_test(NAME UiServersModelAndControllerTest COMMAND test_ui_servers_model_and_controller) add_test(NAME SelfHostedServerSetupTest COMMAND test_self_hosted_server_setup) +add_test(NAME MultipleExportsTest COMMAND test_exports) diff --git a/client/tests/testMultipleExports.cpp b/client/tests/testMultipleExports.cpp new file mode 100644 index 000000000..2e254ee9f --- /dev/null +++ b/client/tests/testMultipleExports.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "ui/models/containerProps.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestMultipleExports : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + + QString getSHAdminConfig() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_SELF_HOSTED_CONFIG_EMPTY"); + } + + void ExportWithContainer(DockerContainer container) + { + + ContainerProps props; + + int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + auto port = m_coreController->m_installUiController->defaultPort(props.defaultProtocol(container)); + auto transportProto = m_coreController->m_installUiController->defaultTransportProto(props.defaultProtocol(container)); + + m_coreController->m_installUiController->install( + container, port, + static_cast(transportProto), + serverIndex); + + qDebug() << "CONTAINER INSTALLED\n"; + + qDebug() << m_coreController->m_serversUiController->getProcessedContainerIndex(); + + QString clientName = "MultipleExports Test Client"; + + auto exportResult = [&]() { + switch (container) { + case DockerContainer::Awg: + case DockerContainer::Awg2: + return m_coreController->m_exportController->generateAwgConfig(serverIndex, clientName); + case DockerContainer::WireGuard: + return m_coreController->m_exportController->generateWireGuardConfig(serverIndex, clientName); + case DockerContainer::OpenVpn: + return m_coreController->m_exportController->generateOpenVpnConfig(serverIndex, clientName); + case DockerContainer::Xray: + return m_coreController->m_exportController->generateXrayConfig(serverIndex, clientName); + } + }(); + + QVERIFY2(exportResult.errorCode == ErrorCode::NoError, "\nExport should succeed"); + QVERIFY2(!exportResult.config.isEmpty(), "Exported config should not be empty\n"); + + /* + QString fileName = ""; + QString configFileName = "amnezia_config"; + QString configExtension = ".vpn"; + +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + fileName = configFileName + configExtension; +#else + fileName = m_coreController->m_systemController->getFileName( + "Save AmneziaVPN config", "Config files (*" + configExtension + ")", + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/" + configFileName, true, + configExtension); +#endif + if (fileName != "") + m_coreController->m_exportUiController->exportConfig(fileName); + */ + + qDebug() << "\nEXPORTED CONFIG:\n" << exportResult.config << "\n"; + + QString exportedConfig = exportResult.config; + + auto reimportResult = m_coreController->m_importCoreController->extractConfigFromData(exportedConfig); + QVERIFY2(reimportResult.errorCode == ErrorCode::NoError, "Re-import should succeed"); + + QString reimportedJson = QJsonDocument(reimportResult.config).toJson(QJsonDocument::Compact); + + qDebug() << "\nEXPORTED JSON:\n" << exportedConfig << "\n"; + qDebug() << "REIMPORTED JSON:\n" << reimportedJson << "\n"; + + QCOMPARE(reimportedJson, exportedConfig); + + // TODO: remove only client for test + // m_coreController->m_exportController->revokeConfig(clientIndex, serverIndex, processedContainerIndex); + + m_coreController->m_installController->clearCachedProfile(serverIndex, container); + } + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + + QString vpnKey = getSHAdminConfig(); + QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; + + m_coreController->m_importCoreController->importConfig(importedConfig); + + qDebug() << "SELF-HOSTED ADMIN SERVER IMPORTED\n"; + } + + void cleanupTestCase() + { + int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + m_coreController->m_installController->removeAllContainers(serverIndex); + m_coreController->m_serversController->removeServer(serverIndex); + + qDebug() << "SERVER CLEARED AND REMOVED\n"; + + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void testExportAwgConfig() + { + ExportWithContainer(DockerContainer::Awg2); + } + + void testExportWireGuardConfig() + { + ExportWithContainer(DockerContainer::WireGuard); + } + + void testExportOpenVpnConfig() + { + ExportWithContainer(DockerContainer::OpenVpn); + } + + void testExportXrayConfig() + { + ExportWithContainer(DockerContainer::Xray); + } + +}; + +QTEST_MAIN(TestMultipleExports) +#include "testMultipleExports.moc" From 42532721541ef4cb95db6f330255fe4d934a2987 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 30 Mar 2026 14:16:54 +0300 Subject: [PATCH 03/53] update: export test --- client/tests/testMultipleExports.cpp | 139 ++++++++++----------------- 1 file changed, 49 insertions(+), 90 deletions(-) diff --git a/client/tests/testMultipleExports.cpp b/client/tests/testMultipleExports.cpp index 2e254ee9f..e84708b9d 100644 --- a/client/tests/testMultipleExports.cpp +++ b/client/tests/testMultipleExports.cpp @@ -8,7 +8,6 @@ #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" -#include "ui/models/containerProps.h" #include "secureQSettings.h" #include "vpnConnection.h" @@ -25,81 +24,7 @@ private: QString getSHAdminConfig() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_SELF_HOSTED_CONFIG_EMPTY"); - } - - void ExportWithContainer(DockerContainer container) - { - - ContainerProps props; - - int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); - auto port = m_coreController->m_installUiController->defaultPort(props.defaultProtocol(container)); - auto transportProto = m_coreController->m_installUiController->defaultTransportProto(props.defaultProtocol(container)); - - m_coreController->m_installUiController->install( - container, port, - static_cast(transportProto), - serverIndex); - - qDebug() << "CONTAINER INSTALLED\n"; - - qDebug() << m_coreController->m_serversUiController->getProcessedContainerIndex(); - - QString clientName = "MultipleExports Test Client"; - - auto exportResult = [&]() { - switch (container) { - case DockerContainer::Awg: - case DockerContainer::Awg2: - return m_coreController->m_exportController->generateAwgConfig(serverIndex, clientName); - case DockerContainer::WireGuard: - return m_coreController->m_exportController->generateWireGuardConfig(serverIndex, clientName); - case DockerContainer::OpenVpn: - return m_coreController->m_exportController->generateOpenVpnConfig(serverIndex, clientName); - case DockerContainer::Xray: - return m_coreController->m_exportController->generateXrayConfig(serverIndex, clientName); - } - }(); - - QVERIFY2(exportResult.errorCode == ErrorCode::NoError, "\nExport should succeed"); - QVERIFY2(!exportResult.config.isEmpty(), "Exported config should not be empty\n"); - - /* - QString fileName = ""; - QString configFileName = "amnezia_config"; - QString configExtension = ".vpn"; - -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - fileName = configFileName + configExtension; -#else - fileName = m_coreController->m_systemController->getFileName( - "Save AmneziaVPN config", "Config files (*" + configExtension + ")", - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/" + configFileName, true, - configExtension); -#endif - if (fileName != "") - m_coreController->m_exportUiController->exportConfig(fileName); - */ - - qDebug() << "\nEXPORTED CONFIG:\n" << exportResult.config << "\n"; - - QString exportedConfig = exportResult.config; - - auto reimportResult = m_coreController->m_importCoreController->extractConfigFromData(exportedConfig); - QVERIFY2(reimportResult.errorCode == ErrorCode::NoError, "Re-import should succeed"); - - QString reimportedJson = QJsonDocument(reimportResult.config).toJson(QJsonDocument::Compact); - - qDebug() << "\nEXPORTED JSON:\n" << exportedConfig << "\n"; - qDebug() << "REIMPORTED JSON:\n" << reimportedJson << "\n"; - - QCOMPARE(reimportedJson, exportedConfig); - - // TODO: remove only client for test - // m_coreController->m_exportController->revokeConfig(clientIndex, serverIndex, processedContainerIndex); - - m_coreController->m_installController->clearCachedProfile(serverIndex, container); + return env.value("TEST_SELF_HOSTED_CONFIG"); } private slots: @@ -123,10 +48,9 @@ private slots: void cleanupTestCase() { int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); - m_coreController->m_installController->removeAllContainers(serverIndex); m_coreController->m_serversController->removeServer(serverIndex); - qDebug() << "SERVER CLEARED AND REMOVED\n"; + qDebug() << "SERVER REMOVED\n"; m_settings->clearSettings(); delete m_coreController; @@ -141,24 +65,59 @@ private slots: } } - void testExportAwgConfig() + void testMultipleExports() { - ExportWithContainer(DockerContainer::Awg2); + int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + + QString clientName = "MultipleExports Test Client"; + + for (int containerIndex = 1; containerIndex < 7; ++containerIndex) { + + QString containerName; + + switch (containerIndex) { + case 1: containerName = "AwgLegacy"; break; + case 2: containerName = "Awg2"; break; + case 3: containerName = "WireGuard"; break; + case 4: containerName = "OpenVPN"; break; + case 5: continue; break; // skipping IPsec + case 6: containerName = "XRay"; break; + } + + if (!m_coreController->m_containersModel->data(containerIndex, ContainersModel::Roles::IsInstalledRole).toBool()) { + qDebug() << QStringLiteral("%1: Not installed").arg(containerName).toUtf8().constData(); + continue; + } + + auto exportResult = m_coreController->m_exportController->generateConnectionConfig(serverIndex, containerIndex, clientName); + + QVERIFY2(exportResult.errorCode == ErrorCode::NoError, + QStringLiteral("\n%1: Export should succeed").arg(containerName).toUtf8().constData()); + QVERIFY2(!exportResult.config.isEmpty(), + QStringLiteral("%1: Exported config should not be empty\n").arg(containerName).toUtf8().constData()); + } } - void testExportWireGuardConfig() + void testMultipleExportsNative() { - ExportWithContainer(DockerContainer::WireGuard); - } + int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); - void testExportOpenVpnConfig() - { - ExportWithContainer(DockerContainer::OpenVpn); - } + QString clientName = "MultipleExports Test Client"; - void testExportXrayConfig() - { - ExportWithContainer(DockerContainer::Xray); + auto exportResultAwg = m_coreController->m_exportController->generateAwgConfig(serverIndex, clientName); + auto exportResultWg = m_coreController->m_exportController->generateWireGuardConfig(serverIndex, clientName); + auto exportResultOvpn = m_coreController->m_exportController->generateOpenVpnConfig(serverIndex, clientName); + auto exportResultXray = m_coreController->m_exportController->generateXrayConfig(serverIndex, clientName); + + QVERIFY2(exportResultAwg.errorCode == ErrorCode::NoError, "\nAwg (native): Export should succeed"); + QVERIFY2(exportResultWg.errorCode == ErrorCode::NoError, "\nWg (native): Export should succeed"); + QVERIFY2(exportResultOvpn.errorCode == ErrorCode::NoError, "\nOvpn (native): Export should succeed"); + QVERIFY2(exportResultXray.errorCode == ErrorCode::NoError, "\nXray (native): Export should succeed"); + + QVERIFY2(!exportResultAwg.config.isEmpty(), "Awg (native): Exported config should not be empty\n"); + QVERIFY2(!exportResultWg.config.isEmpty(), "Wg (native): Exported config should not be empty\n"); + QVERIFY2(!exportResultOvpn.config.isEmpty(), "Ovpn (native): Exported config should not be empty\n"); + QVERIFY2(!exportResultXray.config.isEmpty(), "Xray (native): Exported config should not be empty\n"); } }; From 40a3f615323901c891bb9d3a8be43a6ba4c52d44 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 31 Mar 2026 13:16:51 +0300 Subject: [PATCH 04/53] update: vless serialization/deserialization test added --- client/core/controllers/coreController.h | 2 + client/tests/CMakeLists.txt | 10 ++ client/tests/testSerialization.cpp | 169 +++++++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 client/tests/testSerialization.cpp diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index a78b720d8..f32a4db2f 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -88,6 +88,7 @@ class TestSettingsSignals; class TestUiServersModelAndController; class TestSelfHostedServerSetup; class TestMultipleExports; +class TestSerialization; class CoreController : public QObject { @@ -106,6 +107,7 @@ class CoreController : public QObject friend class TestUiServersModelAndController; friend class TestSelfHostedServerSetup; friend class TestMultipleExports; + friend class TestSerialization; public: explicit CoreController(const QSharedPointer &vpnConnection, SecureQSettings* settings, diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index bed52a677..4a36adffd 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -151,6 +151,15 @@ target_link_libraries(test_exports PRIVATE test_common ) +add_executable(test_serialization + testSerialization.cpp +) + +target_link_libraries(test_serialization PRIVATE + Qt6::Test + test_common +) + enable_testing() add_test(NAME ImportExportTest COMMAND test_import_export) add_test(NAME MultipleImportsTest COMMAND test_multiple_imports) @@ -165,3 +174,4 @@ add_test(NAME SettingsSignalsTest COMMAND test_settings_signals) add_test(NAME UiServersModelAndControllerTest COMMAND test_ui_servers_model_and_controller) add_test(NAME SelfHostedServerSetupTest COMMAND test_self_hosted_server_setup) add_test(NAME MultipleExportsTest COMMAND test_exports) +add_test(NAME SerializationTest COMMAND test_serialization) diff --git a/client/tests/testSerialization.cpp b/client/tests/testSerialization.cpp new file mode 100644 index 000000000..89caad87c --- /dev/null +++ b/client/tests/testSerialization.cpp @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "core/utils/serialization/serialization.h" +#include "core/utils/utilities.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestSerialization : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + + QString getSHAdminConfig() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_SELF_HOSTED_CONFIG"); + } + + QJsonObject extractXrayConfig(const QString &data, ConfigTypes configType, const QString &description = "") const + { + QJsonParseError parserErr; + QJsonDocument jsonConf = QJsonDocument::fromJson(data.toLocal8Bit(), &parserErr); + + QJsonObject xrayVpnConfig; + xrayVpnConfig[configKey::config] = jsonConf.toJson().constData(); + QJsonObject lastConfig; + lastConfig[configKey::lastConfig] = jsonConf.toJson().constData(); + lastConfig[configKey::isThirdPartyConfig] = true; + + QJsonObject containers; + if (configType == ConfigTypes::ShadowSocks) { + containers.insert(configKey::ssxray, QJsonValue(lastConfig)); + containers.insert(configKey::container, QJsonValue(configKey::amneziaSsxray)); + } else { + containers.insert(configKey::container, QJsonValue(configKey::amneziaXray)); + containers.insert(configKey::xray, QJsonValue(lastConfig)); + } + + QJsonArray arr; + arr.push_back(containers); + + QString hostName; + + const static QRegularExpression hostNameRegExp("\"address\":\\s*\"([^\"]+)"); + QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(data); + if (hostNameMatch.hasMatch()) { + hostName = hostNameMatch.captured(1); + } + + QJsonObject config; + config[configKey::containers] = arr; + config[configKey::defaultContainer] = + (configType == ConfigTypes::ShadowSocks) ? configKey::amneziaSsxray : configKey::amneziaXray; + if (description.isEmpty()) { + config[configKey::description] = m_coreController->m_appSettingsRepository->nextAvailableServerName(); + } else { + config[configKey::description] = description; + } + config[configKey::hostName] = hostName; + + return config; + } + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + + QString vpnKey = getSHAdminConfig(); + QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; + + m_coreController->m_importCoreController->importConfig(importedConfig); + + qDebug() << "SELF-HOSTED ADMIN SERVER IMPORTED\n"; + } + + void cleanupTestCase() + { + int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + m_coreController->m_serversController->removeServer(serverIndex); + + qDebug() << "SERVER REMOVED\n"; + + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void testVless() + { + int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + + QString clientName = "Serialization Test Client"; + + auto exportResult = m_coreController->m_exportController->generateXrayConfig(serverIndex, clientName); + + ImportController::ImportResult importResult; + + QString config = exportResult.config; + QString prefix; + QString errormsg; + ConfigTypes configType = ConfigTypes::Invalid; + + if (config.startsWith("vless://")) { + configType = ConfigTypes::Xray; + importResult.config = extractXrayConfig(Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), + QJsonDocument::JsonFormat::Compact), configType, prefix); + QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + } else { + QSKIP("Config not starts with vless://"); + } + + QCOMPARE(importResult.config, exportResult.config); + } + + void testVmessNew() + { + QSKIP("test not completed"); + } + + void testVmess() + { + QSKIP("test not completed"); + } + + void testTrojan() + { + QSKIP("test not completed"); + } + + void testSS() + { + QSKIP("test not completed"); + } + + void testSSd() + { + QSKIP("test not completed"); + } +}; + +QTEST_MAIN(TestSerialization) +#include "testSerialization.moc" From 7a84f42d5c979514129104c2090107e565d63bd6 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 6 Apr 2026 14:45:06 +0300 Subject: [PATCH 05/53] update: language model and controller test --- client/core/controllers/coreController.h | 2 + client/tests/CMakeLists.txt | 10 ++ client/tests/testSitesModel.cpp | 75 +++++++++++++++ .../testUiLanguageModelAndController.cpp | 91 +++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 client/tests/testSitesModel.cpp create mode 100644 client/tests/testUiLanguageModelAndController.cpp diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index f32a4db2f..792cb7792 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -89,6 +89,7 @@ class TestUiServersModelAndController; class TestSelfHostedServerSetup; class TestMultipleExports; class TestSerialization; +class TestUiLanguageModelAndController; class CoreController : public QObject { @@ -108,6 +109,7 @@ class CoreController : public QObject friend class TestSelfHostedServerSetup; friend class TestMultipleExports; friend class TestSerialization; + friend class TestUiLanguageModelAndController; public: explicit CoreController(const QSharedPointer &vpnConnection, SecureQSettings* settings, diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index 4a36adffd..37b57bdd8 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -160,6 +160,15 @@ target_link_libraries(test_serialization PRIVATE test_common ) +add_executable(test_ui_language_model_and_controller + testUiLanguageModelAndController.cpp +) + +target_link_libraries(test_ui_language_model_and_controller PRIVATE + Qt6::Test + test_common +) + enable_testing() add_test(NAME ImportExportTest COMMAND test_import_export) add_test(NAME MultipleImportsTest COMMAND test_multiple_imports) @@ -175,3 +184,4 @@ add_test(NAME UiServersModelAndControllerTest COMMAND test_ui_servers_model_and_ add_test(NAME SelfHostedServerSetupTest COMMAND test_self_hosted_server_setup) add_test(NAME MultipleExportsTest COMMAND test_exports) add_test(NAME SerializationTest COMMAND test_serialization) +add_test(NAME UiLanguageModelAndControllerTest COMMAND test_ui_language_model_and_controller) diff --git a/client/tests/testSitesModel.cpp b/client/tests/testSitesModel.cpp new file mode 100644 index 000000000..e7cf8211c --- /dev/null +++ b/client/tests/testSitesModel.cpp @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestSerialization : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + + QString getSHAdminConfig() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_SELF_HOSTED_CONFIG"); + } + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + + QString vpnKey = getSHAdminConfig(); + QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; + + m_coreController->m_importCoreController->importConfig(importedConfig); + + qDebug() << "SELF-HOSTED ADMIN SERVER IMPORTED\n"; + } + + void cleanupTestCase() + { + int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + m_coreController->m_serversController->removeServer(serverIndex); + + qDebug() << "SERVER REMOVED\n"; + + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void test() + { + + } +}; + +QTEST_MAIN(TestSerialization) +#include "testSerialization.moc" diff --git a/client/tests/testUiLanguageModelAndController.cpp b/client/tests/testUiLanguageModelAndController.cpp new file mode 100644 index 000000000..521c68b54 --- /dev/null +++ b/client/tests/testUiLanguageModelAndController.cpp @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestUiLanguageModelAndController : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + } + + void cleanupTestCase() + { + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void testChangeLanguage() + { + QVERIFY(m_coreController->m_languageModel->rowCount() > 0, "Language model should not be empty"); + + QSignalSpy updateTranslationsSpy(m_coreController->m_languageUiController, &LanguageUiController::updateTranslations); + QSignalSpy translationsUpdatedSpy(m_coreController->m_languageUiController, &LanguageUiController::translationsUpdated); + + m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::China_cn); + QVERIFY(updateTranslationsSpy.count() == 1, "updateTranslations signal should be emitted"); + QVERIFY(translationsUpdatedSpy.count() == 1, "translationsUpdated signal should be emitted"); + + m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::English); + QVERIFY(updateTranslationsSpy.count() == 2, "updateTranslations signal should be emitted"); + QVERIFY(translationsUpdatedSpy.count() == 2, "translationsUpdated signal should be emitted"); + } + + void testUrl() + { + m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::Russian); + QString siteRU = m_coreController->m_languageUiController->getCurrentSiteUrl("test_path"); + QString docsRU = m_coreController->m_languageUiController->getCurrentDocsUrl("test_path"); + + m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::English); + QString siteEN = m_coreController->m_languageUiController->getCurrentSiteUrl("test_path"); + QString docsEN = m_coreController->m_languageUiController->getCurrentDocsUrl("test_path"); + + QVERIFY(siteRU != siteEN, "site url's should not be same"); + QVERIFY(docsRU != docsEN, "docs url's should not be same"); + } + + void testLineHeight() + { + m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::Burmese); + QVERIFY(m_coreController->m_languageUiController->getLineHeightAppend() == 10, "line height should be 10"); + + m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::English); + QVERIFY(m_coreController->m_languageUiController->getLineHeightAppend() == 0, "line height should be 0"); + } +}; + +QTEST_MAIN(TestUiLanguageModelAndController) +#include "testUiLanguageModelAndController.moc" From bccf9f5fbfc3d25fffa1c478f25903e56f9db966 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 6 Apr 2026 17:53:20 +0300 Subject: [PATCH 06/53] update: sites UiController and Model test --- client/core/controllers/coreController.h | 2 + client/tests/CMakeLists.txt | 10 ++ client/tests/testSitesModel.cpp | 75 ------------ .../tests/testUiSitesModelAndController.cpp | 110 ++++++++++++++++++ 4 files changed, 122 insertions(+), 75 deletions(-) delete mode 100644 client/tests/testSitesModel.cpp create mode 100644 client/tests/testUiSitesModelAndController.cpp diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 792cb7792..2ec3aac93 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -90,6 +90,7 @@ class TestSelfHostedServerSetup; class TestMultipleExports; class TestSerialization; class TestUiLanguageModelAndController; +class TestUiSitesModelAndController; class CoreController : public QObject { @@ -110,6 +111,7 @@ class CoreController : public QObject friend class TestMultipleExports; friend class TestSerialization; friend class TestUiLanguageModelAndController; + friend class TestUiSitesModelAndController; public: explicit CoreController(const QSharedPointer &vpnConnection, SecureQSettings* settings, diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index 37b57bdd8..2de98c842 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -169,6 +169,15 @@ target_link_libraries(test_ui_language_model_and_controller PRIVATE test_common ) +add_executable(test_ui_sites_model_and_controller + testUiSitesModelAndController.cpp +) + +target_link_libraries(test_ui_sites_model_and_controller PRIVATE + Qt6::Test + test_common +) + enable_testing() add_test(NAME ImportExportTest COMMAND test_import_export) add_test(NAME MultipleImportsTest COMMAND test_multiple_imports) @@ -185,3 +194,4 @@ add_test(NAME SelfHostedServerSetupTest COMMAND test_self_hosted_server_setup) add_test(NAME MultipleExportsTest COMMAND test_exports) add_test(NAME SerializationTest COMMAND test_serialization) add_test(NAME UiLanguageModelAndControllerTest COMMAND test_ui_language_model_and_controller) +add_test(NAME UiSitesModelAndControllerTest COMMAND test_ui_sites_model_and_controller) diff --git a/client/tests/testSitesModel.cpp b/client/tests/testSitesModel.cpp deleted file mode 100644 index e7cf8211c..000000000 --- a/client/tests/testSitesModel.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "core/controllers/coreController.h" -#include "core/models/serverConfig.h" -#include "secureQSettings.h" -#include "vpnConnection.h" - -using namespace amnezia; - -class TestSerialization : public QObject -{ - Q_OBJECT - -private: - CoreController *m_coreController; - SecureQSettings *m_settings; - - QString getSHAdminConfig() - { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_SELF_HOSTED_CONFIG"); - } - -private slots: - void initTestCase() - { - QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); - m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); - - auto vpnConnection = QSharedPointer::create(nullptr, nullptr); - - m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); - - QString vpnKey = getSHAdminConfig(); - QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; - - m_coreController->m_importCoreController->importConfig(importedConfig); - - qDebug() << "SELF-HOSTED ADMIN SERVER IMPORTED\n"; - } - - void cleanupTestCase() - { - int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); - m_coreController->m_serversController->removeServer(serverIndex); - - qDebug() << "SERVER REMOVED\n"; - - m_settings->clearSettings(); - delete m_coreController; - delete m_settings; - } - - void init() - { - m_settings->clearSettings(); - if (m_coreController->m_serversModel) { - m_coreController->m_serversModel->updateModel(QVector(), -1, false); - } - } - - void test() - { - - } -}; - -QTEST_MAIN(TestSerialization) -#include "testSerialization.moc" diff --git a/client/tests/testUiSitesModelAndController.cpp b/client/tests/testUiSitesModelAndController.cpp new file mode 100644 index 000000000..7af547729 --- /dev/null +++ b/client/tests/testUiSitesModelAndController.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestUiSitesModelAndController : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + + QString getSHAdminConfig() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_SELF_HOSTED_CONFIG"); + } + + QString normalizeHostname(const QString &hostname) const + { + QString normalized = hostname; + normalized.replace("https://", ""); + normalized.replace("http://", ""); + normalized.replace("ftp://", ""); + normalized = normalized.split("/", Qt::SkipEmptyParts).first(); + return normalized; + } + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + + QString vpnKey = getSHAdminConfig(); + QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; + + m_coreController->m_importCoreController->importConfig(importedConfig); + + qDebug() << "SELF-HOSTED ADMIN SERVER IMPORTED\n"; + } + + void cleanupTestCase() + { + int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + m_coreController->m_serversController->removeServer(serverIndex); + + qDebug() << "SERVER REMOVED\n"; + + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void testRoles() + { + QSignalSpy finishedSpy(m_coreController->m_sitesUiController, &SitesUiController::finished); + + m_coreController->m_sitesUiController->addSite("2ip.io"); + m_coreController->m_sitesUiController->addSite("whatismyipaddress.com"); + m_coreController->m_sitesUiController->updateModel(); + QVERIFY(finishedSpy.count() == 2, "finished signal should be emitted 2 times"); + QVERIFY(m_coreController->m_sitesModel->rowCount() == 2, "SitesModel should have 2 rows"); + + QModelIndex siteModelIndex = m_coreController->m_sitesModel->index(0, 0); + QVERIFY2(siteModelIndex.isValid(), "Site model index should be valid"); + + auto siteUrl = m_coreController->m_sitesModel->data(siteModelIndex, SitesModel::UrlRole); + QVERIFY(siteUrl == normalizeHostname("2ip.io"), QString("site url should be %1, got %2").arg(normalizeHostname("2ip.io"), siteUrl)); + + // auto siteIp = m_coreController->m_sitesModel->data(siteModelIndex, SitesModel::IpRole); + // QVERIFY(siteIp != "", "site ip should not be empty"); + + m_coreController->m_sitesUiController->removeSite(0); + m_coreController->m_sitesUiController->updateModel(); + QVERIFY(finishedSpy.count() == 3, "finished signal should be emitted"); + QVERIFY(m_coreController->m_sitesModel->rowCount() == 1, "SitesModel should have 1 row"); + + m_coreController->m_sitesUiController->removeSites(); + m_coreController->m_sitesUiController->updateModel(); + QVERIFY(finishedSpy.count() == 4, "finished signal should be emitted"); + QVERIFY(m_coreController->m_sitesModel->rowCount() == 0, "SitesModel should have 0 rows"); + } +}; + +QTEST_MAIN(TestUiSitesModelAndController) +#include "testUiSitesModelAndController.moc" From 2ee792d08803b0133599e34b0057dc903761bb60 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 7 Apr 2026 16:30:28 +0300 Subject: [PATCH 07/53] update: sites test --- .../tests/testUiSitesModelAndController.cpp | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/client/tests/testUiSitesModelAndController.cpp b/client/tests/testUiSitesModelAndController.cpp index 7af547729..0429c61d3 100644 --- a/client/tests/testUiSitesModelAndController.cpp +++ b/client/tests/testUiSitesModelAndController.cpp @@ -27,6 +27,18 @@ private: return env.value("TEST_SELF_HOSTED_CONFIG"); } + QString getSitesList() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_SITES_LIST"); + } + + QString getExportPath() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_SITES_LIST_EXPORT"); + } + QString normalizeHostname(const QString &hostname) const { QString normalized = hostname; @@ -60,7 +72,7 @@ private slots: int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); m_coreController->m_serversController->removeServer(serverIndex); - qDebug() << "SERVER REMOVED\n"; + qDebug() << "\nSERVER REMOVED\n"; m_settings->clearSettings(); delete m_coreController; @@ -75,11 +87,23 @@ private slots: } } - void testRoles() + void testRolesAndSignals() { QSignalSpy finishedSpy(m_coreController->m_sitesUiController, &SitesUiController::finished); + QSignalSpy errorOccurredSpy(m_coreController->m_sitesUiController, &SitesUiController::errorOccurred); + QSignalSpy isSplitTunnelingChangedSpy(m_coreController->m_sitesUiController, &SitesUiController::isTunnelingEnabledChanged); - m_coreController->m_sitesUiController->addSite("2ip.io"); + m_coreController->m_sitesUiController->toggleSplitTunneling(true); + QVERIFY(isSplitTunnelingChangedSpy.count() == 1, "isSplitTunnelingChangedSpy signal should be emitted"); + QVERIFY(m_coreController->m_sitesUiController->isTunnelingEnabled() == true, "SiteSplitTunneling should be enabled"); + + m_coreController->m_sitesUiController->toggleSplitTunneling(false); + QVERIFY(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); + QVERIFY(m_coreController->m_sitesUiController->isTunnelingEnabled() == false, "SiteSplitTunneling should be disabled"); + + QString site = "2ip.io"; + + m_coreController->m_sitesUiController->addSite(site); m_coreController->m_sitesUiController->addSite("whatismyipaddress.com"); m_coreController->m_sitesUiController->updateModel(); QVERIFY(finishedSpy.count() == 2, "finished signal should be emitted 2 times"); @@ -89,19 +113,28 @@ private slots: QVERIFY2(siteModelIndex.isValid(), "Site model index should be valid"); auto siteUrl = m_coreController->m_sitesModel->data(siteModelIndex, SitesModel::UrlRole); - QVERIFY(siteUrl == normalizeHostname("2ip.io"), QString("site url should be %1, got %2").arg(normalizeHostname("2ip.io"), siteUrl)); + QCOMPARE(siteUrl, normalizeHostname(site)); - // auto siteIp = m_coreController->m_sitesModel->data(siteModelIndex, SitesModel::IpRole); - // QVERIFY(siteIp != "", "site ip should not be empty"); + auto siteIp = m_coreController->m_sitesModel->data(siteModelIndex, SitesModel::IpRole); + QVERIFY(siteIp.isNull() == false, "site ip should not be empty"); m_coreController->m_sitesUiController->removeSite(0); m_coreController->m_sitesUiController->updateModel(); QVERIFY(finishedSpy.count() == 3, "finished signal should be emitted"); QVERIFY(m_coreController->m_sitesModel->rowCount() == 1, "SitesModel should have 1 row"); + m_coreController->m_sitesUiController->importSites(getSitesList(), true); + m_coreController->m_sitesUiController->updateModel(); + QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY(finishedSpy.count() == 4, "finished signal should be emitted"); + QVERIFY(m_coreController->m_sitesModel->rowCount() > 1, "SitesModel should have more than 1 row"); + + m_coreController->m_sitesUiController->exportSites(getExportPath() + "test_sites_export.json"); + QVERIFY(finishedSpy.count() == 5, "finished signal should be emitted"); + m_coreController->m_sitesUiController->removeSites(); m_coreController->m_sitesUiController->updateModel(); - QVERIFY(finishedSpy.count() == 4, "finished signal should be emitted"); + QVERIFY(finishedSpy.count() == 6, "finished signal should be emitted"); QVERIFY(m_coreController->m_sitesModel->rowCount() == 0, "SitesModel should have 0 rows"); } }; From ddb522a8d3b37b3f5ed71b6639757c62929ff34a Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 7 Apr 2026 16:31:09 +0300 Subject: [PATCH 08/53] update: app ui model and controller test --- client/core/controllers/coreController.h | 2 + client/tests/CMakeLists.txt | 10 ++ .../tests/testUiAppSTModelAndController.cpp | 120 ++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 client/tests/testUiAppSTModelAndController.cpp diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 2ec3aac93..442ec2322 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -91,6 +91,7 @@ class TestMultipleExports; class TestSerialization; class TestUiLanguageModelAndController; class TestUiSitesModelAndController; +class TestUiAppSTModelAndController; class CoreController : public QObject { @@ -112,6 +113,7 @@ class CoreController : public QObject friend class TestSerialization; friend class TestUiLanguageModelAndController; friend class TestUiSitesModelAndController; + friend class TestUiAppSTModelAndController; public: explicit CoreController(const QSharedPointer &vpnConnection, SecureQSettings* settings, diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index 2de98c842..d7d56f3ae 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -178,6 +178,15 @@ target_link_libraries(test_ui_sites_model_and_controller PRIVATE test_common ) +add_executable(test_ui_app_st_model_and_controller + testUiAppSTModelAndController.cpp +) + +target_link_libraries(test_ui_app_st_model_and_controller PRIVATE + Qt6::Test + test_common +) + enable_testing() add_test(NAME ImportExportTest COMMAND test_import_export) add_test(NAME MultipleImportsTest COMMAND test_multiple_imports) @@ -195,3 +204,4 @@ add_test(NAME MultipleExportsTest COMMAND test_exports) add_test(NAME SerializationTest COMMAND test_serialization) add_test(NAME UiLanguageModelAndControllerTest COMMAND test_ui_language_model_and_controller) add_test(NAME UiSitesModelAndControllerTest COMMAND test_ui_sites_model_and_controller) +add_test(NAME UiAppSTModelAndControllerTest COMMAND test_ui_app_st_model_and_controller) diff --git a/client/tests/testUiAppSTModelAndController.cpp b/client/tests/testUiAppSTModelAndController.cpp new file mode 100644 index 000000000..0c80cb424 --- /dev/null +++ b/client/tests/testUiAppSTModelAndController.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestUiAppSTModelAndController : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + + QString getSHAdminConfig() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_SELF_HOSTED_CONFIG"); + } + + QString getAppPath() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_APP_PATH"); + } + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + + QString vpnKey = getSHAdminConfig(); + QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; + + m_coreController->m_importCoreController->importConfig(importedConfig); + + qDebug() << "SELF-HOSTED ADMIN SERVER IMPORTED\n"; + } + + void cleanupTestCase() + { + int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + m_coreController->m_serversController->removeServer(serverIndex); + + qDebug() << "\nSERVER REMOVED\n"; + + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void testRolesAndSignals() + { + QSignalSpy finishedSpy(m_coreController->m_appSplitTunnelingUiController, &AppSplitTunnelingUiController::finished); + QSignalSpy errorOccurredSpy(m_coreController->m_appSplitTunnelingUiController, &AppSplitTunnelingUiController::errorOccurred); + QSignalSpy isSplitTunnelingChangedSpy(m_coreController->m_appSplitTunnelingUiController, &AppSplitTunnelingUiController::isTunnelingEnabledChanged); + + m_coreController->m_appSplitTunnelingUiController->toggleSplitTunneling(true); + QVERIFY(isSplitTunnelingChangedSpy.count() == 1, "isSplitTunnelingChangedSpy signal should be emitted"); + QVERIFY(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == true, "AppSplitTunneling should be enabled"); + + m_coreController->m_appSplitTunnelingUiController->toggleSplitTunneling(false); + QVERIFY(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); + QVERIFY(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == false, "AppSplitTunneling should be disabled"); + + QString app = getAppPath(); + + m_coreController->m_appSplitTunnelingUiController->addApp(app); + m_coreController->m_appSplitTunnelingUiController->updateModel(); + QVERIFY(finishedSpy.count() == 1, "finished signal should be emitted"); + QVERIFY(m_coreController->m_appSplitTunnelingModel->rowCount() == 1, "AppSplitTunnelingModel should have 1 row"); + + QModelIndex appSTModelIndex = m_coreController->m_appSplitTunnelingModel->index(0, 0); + QVERIFY2(appSTModelIndex.isValid(), "Site model index should be valid"); + + auto appPath = m_coreController->m_appSplitTunnelingModel->data(appSTModelIndex, AppSplitTunnelingModel::AppPathRole); + QVERIFY(app.contains(appPath.toString()) == true, QString("app path should be %1, got %2").arg(app, appPath)); + + auto pkgAppName = m_coreController->m_appSplitTunnelingModel->data(appSTModelIndex, AppSplitTunnelingModel::PackageAppNameRole); + QVERIFY(pkgAppName == true, "app name should be set"); + + auto pkgAppIcon = m_coreController->m_appSplitTunnelingModel->data(appSTModelIndex, AppSplitTunnelingModel::PackageAppIconRole); + QVERIFY(pkgAppIcon == true, "app image should be set"); + + m_coreController->m_appSplitTunnelingUiController->addApp(app); + m_coreController->m_appSplitTunnelingUiController->updateModel(); + QVERIFY(errorOccurredSpy.count() == 1, "errorOccurred signal should be emitted"); + QVERIFY(m_coreController->m_appSplitTunnelingModel->rowCount() == 1, "AppSplitTunnelingModel should have 3 rows (same app should not be added)"); + + m_coreController->m_appSplitTunnelingUiController->removeApp(0); + m_coreController->m_appSplitTunnelingUiController->updateModel(); + QVERIFY(finishedSpy.count() == 2, "finished signal should be emitted"); + QVERIFY(m_coreController->m_appSplitTunnelingModel->rowCount() == 0, "AppSplitTunnelingModel should have 0 rows"); + } +}; + +QTEST_MAIN(TestUiAppSTModelAndController) +#include "testUiAppSTModelAndController.moc" From 23f993e2e52e44882052a20ed0a29692c7d12fa3 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 8 Apr 2026 12:00:49 +0300 Subject: [PATCH 09/53] update: allowed dns ui model and controller test --- client/core/controllers/coreController.h | 2 + client/tests/CMakeLists.txt | 10 ++ .../testUiAllowedDnsModelAndController.cpp | 100 ++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 client/tests/testUiAllowedDnsModelAndController.cpp diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 442ec2322..0091ca10e 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -92,6 +92,7 @@ class TestSerialization; class TestUiLanguageModelAndController; class TestUiSitesModelAndController; class TestUiAppSTModelAndController; +class TestUiAllowedDnsModelAndController; class CoreController : public QObject { @@ -114,6 +115,7 @@ class CoreController : public QObject friend class TestUiLanguageModelAndController; friend class TestUiSitesModelAndController; friend class TestUiAppSTModelAndController; + friend class TestUiAllowedDnsModelAndController; public: explicit CoreController(const QSharedPointer &vpnConnection, SecureQSettings* settings, diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index d7d56f3ae..743a5b38e 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -187,6 +187,15 @@ target_link_libraries(test_ui_app_st_model_and_controller PRIVATE test_common ) +add_executable(test_ui_allowed_dns_model_and_controller + testUiAllowedDnsModelAndController.cpp +) + +target_link_libraries(test_ui_allowed_dns_model_and_controller PRIVATE + Qt6::Test + test_common +) + enable_testing() add_test(NAME ImportExportTest COMMAND test_import_export) add_test(NAME MultipleImportsTest COMMAND test_multiple_imports) @@ -205,3 +214,4 @@ add_test(NAME SerializationTest COMMAND test_serialization) add_test(NAME UiLanguageModelAndControllerTest COMMAND test_ui_language_model_and_controller) add_test(NAME UiSitesModelAndControllerTest COMMAND test_ui_sites_model_and_controller) add_test(NAME UiAppSTModelAndControllerTest COMMAND test_ui_app_st_model_and_controller) +add_test(NAME UiAllowedDnsModelAndControllerTest COMMAND test_ui_allowed_dns_model_and_controller) diff --git a/client/tests/testUiAllowedDnsModelAndController.cpp b/client/tests/testUiAllowedDnsModelAndController.cpp new file mode 100644 index 000000000..7e48aea73 --- /dev/null +++ b/client/tests/testUiAllowedDnsModelAndController.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestUiAllowedDnsModelAndController : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + + QString getFilePath() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_FILE_PATH"); + } + + QString getExportPath() + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_SITES_LIST_EXPORT"); + } + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + } + + void cleanupTestCase() + { + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void testRolesAndSignals() + { + QSignalSpy finishedSpy(m_coreController->m_allowedDnsUiController, &AllowedDnsUiController::finished); + QSignalSpy errorOccurredSpy(m_coreController->m_allowedDnsUiController, &AllowedDnsUiController::errorOccurred); + + QString ip = "188.40.167.81"; + + m_coreController->m_allowedDnsUiController->addDns(ip); + m_coreController->m_allowedDnsUiController->updateModel(); + QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY(finishedSpy.count() == 1, "finished signal should be emitted"); + QVERIFY(m_coreController->m_allowedDnsModel->rowCount() == 1, "AllowedDnsModel should have 1 row"); + + QModelIndex allowedDnsModelIndex = m_coreController->m_allowedDnsModel->index(0, 0); + QVERIFY2(allowedDnsModelIndex.isValid(), "Site model index should be valid"); + + auto dnsIp = m_coreController->m_allowedDnsModel->data(allowedDnsModelIndex, AllowedDnsModel::IpRole); + QVERIFY(dnsIp == ip, QString("app path should be %1, got %2").arg(ip, appPath)); + + m_coreController->m_allowedDnsUiController->importDns(getFilePath(), true); + m_coreController->m_allowedDnsUiController->updateModel(); + QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY(finishedSpy.count() == 2, "finished signal should be emitted"); + QVERIFY(m_coreController->m_allowedDnsModel->rowCount() > 1, "AllowedDnsModel should have more than 1 row"); + + m_coreController->m_allowedDnsUiController->exportDns(getExportPath() + "test_dns_export.json"); + QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY(finishedSpy.count() == 3, "finished signal should be emitted"); + + m_coreController->m_allowedDnsUiController->removeDns(0); + m_coreController->m_allowedDnsUiController->updateModel(); + QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY(finishedSpy.count() == 4, "finished signal should be emitted"); + QVERIFY(m_coreController->m_allowedDnsModel->rowCount() == 0, "AllowedDnsModel should have 0 rows"); + } +}; + +QTEST_MAIN(TestUiAllowedDnsModelAndController) +#include "testUiAllowedDnsModelAndController.moc" From 87c5f2a284d07347ff22bf10be9196568322bcd7 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 8 Apr 2026 12:04:58 +0300 Subject: [PATCH 10/53] update: env vars and removed some lines --- .../testUiAllowedDnsModelAndController.cpp | 8 +++--- .../tests/testUiAppSTModelAndController.cpp | 24 +++-------------- .../tests/testUiSitesModelAndController.cpp | 26 +++---------------- 3 files changed, 11 insertions(+), 47 deletions(-) diff --git a/client/tests/testUiAllowedDnsModelAndController.cpp b/client/tests/testUiAllowedDnsModelAndController.cpp index 7e48aea73..8e600b042 100644 --- a/client/tests/testUiAllowedDnsModelAndController.cpp +++ b/client/tests/testUiAllowedDnsModelAndController.cpp @@ -21,16 +21,16 @@ private: CoreController *m_coreController; SecureQSettings *m_settings; - QString getFilePath() + QString getPath() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_FILE_PATH"); + return env.value("TEST_PATH"); } QString getExportPath() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_SITES_LIST_EXPORT"); + return env.value("TEST_EXPORT_PATH"); } private slots: @@ -78,7 +78,7 @@ private slots: auto dnsIp = m_coreController->m_allowedDnsModel->data(allowedDnsModelIndex, AllowedDnsModel::IpRole); QVERIFY(dnsIp == ip, QString("app path should be %1, got %2").arg(ip, appPath)); - m_coreController->m_allowedDnsUiController->importDns(getFilePath(), true); + m_coreController->m_allowedDnsUiController->importDns(getPath(), true); m_coreController->m_allowedDnsUiController->updateModel(); QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); QVERIFY(finishedSpy.count() == 2, "finished signal should be emitted"); diff --git a/client/tests/testUiAppSTModelAndController.cpp b/client/tests/testUiAppSTModelAndController.cpp index 0c80cb424..761d11806 100644 --- a/client/tests/testUiAppSTModelAndController.cpp +++ b/client/tests/testUiAppSTModelAndController.cpp @@ -21,16 +21,10 @@ private: CoreController *m_coreController; SecureQSettings *m_settings; - QString getSHAdminConfig() + QString getPath() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_SELF_HOSTED_CONFIG"); - } - - QString getAppPath() - { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_APP_PATH"); + return env.value("TEST_PATH"); } private slots: @@ -42,22 +36,10 @@ private slots: auto vpnConnection = QSharedPointer::create(nullptr, nullptr); m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); - - QString vpnKey = getSHAdminConfig(); - QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; - - m_coreController->m_importCoreController->importConfig(importedConfig); - - qDebug() << "SELF-HOSTED ADMIN SERVER IMPORTED\n"; } void cleanupTestCase() { - int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); - m_coreController->m_serversController->removeServer(serverIndex); - - qDebug() << "\nSERVER REMOVED\n"; - m_settings->clearSettings(); delete m_coreController; delete m_settings; @@ -85,7 +67,7 @@ private slots: QVERIFY(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); QVERIFY(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == false, "AppSplitTunneling should be disabled"); - QString app = getAppPath(); + QString app = getPath(); m_coreController->m_appSplitTunnelingUiController->addApp(app); m_coreController->m_appSplitTunnelingUiController->updateModel(); diff --git a/client/tests/testUiSitesModelAndController.cpp b/client/tests/testUiSitesModelAndController.cpp index 0429c61d3..aa815aff8 100644 --- a/client/tests/testUiSitesModelAndController.cpp +++ b/client/tests/testUiSitesModelAndController.cpp @@ -21,22 +21,16 @@ private: CoreController *m_coreController; SecureQSettings *m_settings; - QString getSHAdminConfig() + QString getPath() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_SELF_HOSTED_CONFIG"); - } - - QString getSitesList() - { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_SITES_LIST"); + return env.value("TEST_PATH"); } QString getExportPath() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_SITES_LIST_EXPORT"); + return env.value("TEST_EXPORT_PATH"); } QString normalizeHostname(const QString &hostname) const @@ -58,22 +52,10 @@ private slots: auto vpnConnection = QSharedPointer::create(nullptr, nullptr); m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); - - QString vpnKey = getSHAdminConfig(); - QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; - - m_coreController->m_importCoreController->importConfig(importedConfig); - - qDebug() << "SELF-HOSTED ADMIN SERVER IMPORTED\n"; } void cleanupTestCase() { - int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); - m_coreController->m_serversController->removeServer(serverIndex); - - qDebug() << "\nSERVER REMOVED\n"; - m_settings->clearSettings(); delete m_coreController; delete m_settings; @@ -123,7 +105,7 @@ private slots: QVERIFY(finishedSpy.count() == 3, "finished signal should be emitted"); QVERIFY(m_coreController->m_sitesModel->rowCount() == 1, "SitesModel should have 1 row"); - m_coreController->m_sitesUiController->importSites(getSitesList(), true); + m_coreController->m_sitesUiController->importSites(getPath(), true); m_coreController->m_sitesUiController->updateModel(); QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); QVERIFY(finishedSpy.count() == 4, "finished signal should be emitted"); From 545e751d33392b4a21ff5e595858287f1266c366 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 13 Apr 2026 12:18:33 +0300 Subject: [PATCH 11/53] update: news ui model and controller test (incomplete) --- client/core/controllers/coreController.h | 2 + client/tests/CMakeLists.txt | 10 ++ .../api/testUiNewsModelAndController.cpp | 97 +++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 client/tests/api/testUiNewsModelAndController.cpp diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 0091ca10e..007ead86f 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -93,6 +93,7 @@ class TestUiLanguageModelAndController; class TestUiSitesModelAndController; class TestUiAppSTModelAndController; class TestUiAllowedDnsModelAndController; +class TestUiNewsModelAndController; class CoreController : public QObject { @@ -116,6 +117,7 @@ class CoreController : public QObject friend class TestUiSitesModelAndController; friend class TestUiAppSTModelAndController; friend class TestUiAllowedDnsModelAndController; + friend class TestUiNewsModelAndController; public: explicit CoreController(const QSharedPointer &vpnConnection, SecureQSettings* settings, diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index 743a5b38e..006083a21 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -196,6 +196,15 @@ target_link_libraries(test_ui_allowed_dns_model_and_controller PRIVATE test_common ) +add_executable(test_ui_news_model_and_controller + api/testUiNewsModelAndController.cpp +) + +target_link_libraries(test_ui_news_model_and_controller PRIVATE + Qt6::Test + test_common +) + enable_testing() add_test(NAME ImportExportTest COMMAND test_import_export) add_test(NAME MultipleImportsTest COMMAND test_multiple_imports) @@ -215,3 +224,4 @@ add_test(NAME UiLanguageModelAndControllerTest COMMAND test_ui_language_model_an add_test(NAME UiSitesModelAndControllerTest COMMAND test_ui_sites_model_and_controller) add_test(NAME UiAppSTModelAndControllerTest COMMAND test_ui_app_st_model_and_controller) add_test(NAME UiAllowedDnsModelAndControllerTest COMMAND test_ui_allowed_dns_model_and_controller) +add_test(NAME UiNewsModelAndControllerTest COMMAND test_ui_news_model_and_controller) diff --git a/client/tests/api/testUiNewsModelAndController.cpp b/client/tests/api/testUiNewsModelAndController.cpp new file mode 100644 index 000000000..95c81c450 --- /dev/null +++ b/client/tests/api/testUiNewsModelAndController.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestUiNewsModelAndController : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + + // TODO: add env vars for api + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + } + + void cleanupTestCase() + { + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void testRolesAndSignals() + { + QSignalSpy fetchNewsFinishedSpy(m_coreController->m_apiNewsUiController, &ApiNewsUiController::fetchNewsFinished); + QSignalSpy errorOccurredSpy(m_coreController->m_apiNewsUiController, &ApiNewsUiController::errorOccurred); + QSignalSpy processedIndexChangedSpy(m_coreController->m_newsModel, &NewsModel::processedIndexChanged); + QSignalSpy hasUnreadChangedSpy(m_coreController->m_newsModel, &NewsModel::hasUnreadChanged); + + /* TODO: + m_coreController->m_apiNewsUiController->fetchNews(false); + QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY(fetchNewsFinishedSpy.count() == 1, "fetchNewsFinished signal should be emitted"); + + m_coreController->m_newsModel->updateModel(); + QVERIFY(hasUnreadChangedSpy.count() == 1, "hasUnreadChanged signal should be emitted"); + + QModelIndex newsModelIndex = m_coreController->m_newsModel->index(0, 0); + QVERIFY2(newsModelIndex.isValid(), "News model index should be valid"); + + auto newsId = m_coreController->m_newsModel->data(newsModelIndex, NewsModel::IdRole); + QCOMPARE(newsId, ); + + auto newsTitle = m_coreController->m_newsModel->data(newsModelIndex, NewsModel::TitleRole); + QCOMPARE(newsTitle, ); + + auto newsContent = m_coreController->m_newsModel->data(newsModelIndex, NewsModel::ContentRole); + QCOMPARE(newsContent, ); + + auto newsTimestamp = m_coreController->m_newsModel->data(newsModelIndex, NewsModel::TimestampRole); + QCOMPARE(newsTimestamp, ); + + auto newsIsRead = m_coreController->m_newsModel->data(newsModelIndex, NewsModel::IsReadRole); + QCOMPARE(newsIsRead, false); + + auto newsIsProcessed = m_coreController->m_newsModel->data(newsModelIndex, NewsModel::IsProcessedRole); + QCOMPARE(newsIsProcessed, ); + + m_coreController->m_newsModel->markAsRead(0); + ? m_coreController->m_newsModel->updateModel(); ? + QVERIFY(hasUnreadChangedSpy.count() == 2, "hasUnreadChanged signal should be emitted"); + QCOMPARE(newsIsRead, true); + */ + } +}; + +QTEST_MAIN(TestUiNewsModelAndController) +#include "testUiNewsModelAndController.moc" From f6ca964ff88fed054a623dc9b4a5a9a8a48ea6ea Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 13 Apr 2026 14:52:13 +0300 Subject: [PATCH 12/53] update: api services ui model and controller test (incompleted) --- client/core/controllers/coreController.h | 2 + client/tests/CMakeLists.txt | 10 ++ .../testUiApiServicesModelAndController.cpp | 97 +++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 client/tests/api/testUiApiServicesModelAndController.cpp diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 007ead86f..eb38eb217 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -94,6 +94,7 @@ class TestUiSitesModelAndController; class TestUiAppSTModelAndController; class TestUiAllowedDnsModelAndController; class TestUiNewsModelAndController; +class TestUiApiServicesModelAndController; class CoreController : public QObject { @@ -118,6 +119,7 @@ class CoreController : public QObject friend class TestUiAppSTModelAndController; friend class TestUiAllowedDnsModelAndController; friend class TestUiNewsModelAndController; + friend class TestUiApiServicesModelAndController; public: explicit CoreController(const QSharedPointer &vpnConnection, SecureQSettings* settings, diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index 006083a21..3f57cc76b 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -196,6 +196,15 @@ target_link_libraries(test_ui_allowed_dns_model_and_controller PRIVATE test_common ) +add_executable(test_ui_api_services_model_and_controller + api/testUiApiServicesModelAndController.cpp +) + +target_link_libraries(test_ui_api_services_model_and_controller PRIVATE + Qt6::Test + test_common +) + add_executable(test_ui_news_model_and_controller api/testUiNewsModelAndController.cpp ) @@ -224,4 +233,5 @@ add_test(NAME UiLanguageModelAndControllerTest COMMAND test_ui_language_model_an add_test(NAME UiSitesModelAndControllerTest COMMAND test_ui_sites_model_and_controller) add_test(NAME UiAppSTModelAndControllerTest COMMAND test_ui_app_st_model_and_controller) add_test(NAME UiAllowedDnsModelAndControllerTest COMMAND test_ui_allowed_dns_model_and_controller) +add_test(NAME UiApiServicesModelAndControllerTest COMMAND test_ui_api_services_model_and_controller) add_test(NAME UiNewsModelAndControllerTest COMMAND test_ui_news_model_and_controller) diff --git a/client/tests/api/testUiApiServicesModelAndController.cpp b/client/tests/api/testUiApiServicesModelAndController.cpp new file mode 100644 index 000000000..50d3d8ae1 --- /dev/null +++ b/client/tests/api/testUiApiServicesModelAndController.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestUiApiServicesModelAndController : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + + // TODO: add env vars for api + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + } + + void cleanupTestCase() + { + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void testRolesAndSignals() + { + QSignalSpy errorOccurredSpy(m_coreController->m_servicesCatalogUiController, &ServicesCatalogUiController::errorOccurred); + + /* TODO: + m_coreController->m_servicesCatalogUiController->fillAvailableServices(); + QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + + QModelIndex serviceModelIndex = m_coreController->m_apiServicesModel->index(0, 0); + QVERIFY2(serviceModelIndex.isValid(), "Service model index should be valid"); + + auto serviceName = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::NameRole); + QCOMPARE(serviceName, ); + + auto serviceCardDescription = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::CardDescriptionRole); + QCOMPARE(serviceCardDescription, ); + + auto isServiceAvailable = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::IsServiceAvailableRole); + QCOMPARE(isServiceAvailable, ); + + auto serviceSpeed = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::SpeedRole); + QCOMPARE(serviceSpeed, ); + + auto serviceTimeLimit = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::TimeLimitRole); + QCOMPARE(serviceTimeLimit, ); + + auto serviceRegion = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::RegionRole); + QCOMPARE(serviceRegion, ); + + auto serviceFeatures = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::FeaturesRole); + QCOMPARE(serviceFeatures, ); + + auto servicePrice = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::PriceRole); + QCOMPARE(servicePrice, ); + + auto serviceEndDate = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::EndDateRole); + QCOMPARE(serviceEndDate, ); + + auto serviceOrder = m_coreController->m_apiServicesModel->data(serviceModelIndex, ApiServicesModel::OrderRole); + QCOMPARE(serviceOrder, ); + */ + } +}; + +QTEST_MAIN(TestUiApiServicesModelAndController) +#include "testUiApiServicesModelAndController.moc" From a51b0736928718bc161cc4b7227e62d6eb3cf762 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Fri, 17 Apr 2026 18:07:27 +0300 Subject: [PATCH 13/53] update: job for tests (Linux) --- .github/workflows/deploy.yml | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 669552a7d..5dea20760 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -735,3 +735,40 @@ jobs: run: | echo "Pull request:" >> $GITHUB_STEP_SUMMARY echo "[[#${{ fromJSON(steps.pull_request.outputs.data)[0].number }}] ${{ fromJSON(steps.pull_request.outputs.data)[0].title }}](${{ fromJSON(steps.pull_request.outputs.data)[0].html_url }})" >> $GITHUB_STEP_SUMMARY + +# ------------------------------------------------------ + + Test-Linux: + runs-on: ubuntu-latest + + needs: Build-Linux-Ubuntu + + steps: + - uses: actions/checkout@v4 + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: linux-build + path: build/AppDir + + - name: Install Qt + uses: jurplel/install-qt-action@v3 + with: + version: ${{ env.QT_VERSION }} + host: 'linux' + target: 'desktop' + arch: 'linux_gcc_64' + modules: 'qtremoteobjects qt5compat qtshadertools' + dir: ${{ runner.temp }} + setup-python: 'true' + tools: 'tools_ifw' + set-env: 'true' + aqtversion: '==3.3.0' + py7zrversion: '==0.22.*' + extra: '--base ${{ env.QT_MIRROR }}' + + - name: Run tests + run: | + cd build + ctest --output-on-failure \ No newline at end of file From ee09913cead7eda8103075e6f1699c17b12bad64 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Fri, 17 Apr 2026 18:27:19 +0300 Subject: [PATCH 14/53] update: job for tests (Windows) --- .github/workflows/deploy.yml | 42 ++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5dea20760..b8b552eb5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -750,7 +750,7 @@ jobs: uses: actions/download-artifact@v4 with: name: linux-build - path: build/AppDir + path: build/ - name: Install Qt uses: jurplel/install-qt-action@v3 @@ -771,4 +771,42 @@ jobs: - name: Run tests run: | cd build - ctest --output-on-failure \ No newline at end of file + ctest --output-on-failure + +# ------------------------------------------------------ + + Test-Windows: + runs-on: windows-latest + + needs: Build-Windows + + steps: + - uses: actions/checkout@v4 + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: windows-build + path: build + + - name: Install Qt + uses: jurplel/install-qt-action@v3 + with: + version: ${{ env.QT_VERSION }} + host: 'windows' + target: 'desktop' + arch: 'win64_msvc2019_64' + modules: 'qtremoteobjects qt5compat qtshadertools' + dir: ${{ runner.temp }} + setup-python: 'true' + tools: 'tools_ifw' + set-env: 'true' + aqtversion: '==3.3.0' + py7zrversion: '==0.22.*' + extra: '--base ${{ env.QT_MIRROR }}' + + - name: Run tests + shell: bash + run: | + cd build + ctest --output-on-failure From fbde1aab005d5a6714a66f342e812063717d52a3 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 20 Apr 2026 10:57:25 +0300 Subject: [PATCH 15/53] update: proper artifact names --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b8b552eb5..80f859391 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -749,7 +749,7 @@ jobs: - name: Download build artifacts uses: actions/download-artifact@v4 with: - name: linux-build + name: AmneziaVPN_${{ env.VERSION }}_linux_x64.tar.zip path: build/ - name: Install Qt @@ -786,7 +786,7 @@ jobs: - name: Download build artifacts uses: actions/download-artifact@v4 with: - name: windows-build + name: AmneziaVPN_${{ env.VERSION }}_x64.exe path: build - name: Install Qt From 631d4c7fd01d22fb482e1dcb034f8da4b8a9e186 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 20 Apr 2026 11:39:07 +0300 Subject: [PATCH 16/53] update: added envs --- .github/workflows/deploy.yml | 45 ++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 80f859391..04dc494f3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -743,15 +743,12 @@ jobs: needs: Build-Linux-Ubuntu + env: + QT_VERSION: 6.10.1 + steps: - uses: actions/checkout@v4 - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: AmneziaVPN_${{ env.VERSION }}_linux_x64.tar.zip - path: build/ - - name: Install Qt uses: jurplel/install-qt-action@v3 with: @@ -768,6 +765,19 @@ jobs: py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' + - name: 'Get version from CMakeLists.txt' + id: get_version + run: | + VERSION=$(grep 'set(AMNEZIAVPN_VERSION' CMakeLists.txt | sed -E 's/.*AMNEZIAVPN_VERSION ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\)/\1/') + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "Version: $VERSION" + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: AmneziaVPN_${{ env.VERSION }}_linux_x64.tar.zip + path: build/ + - name: Run tests run: | cd build @@ -780,15 +790,12 @@ jobs: needs: Build-Windows + env: + QT_VERSION: 6.10.1 + steps: - uses: actions/checkout@v4 - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: AmneziaVPN_${{ env.VERSION }}_x64.exe - path: build - - name: Install Qt uses: jurplel/install-qt-action@v3 with: @@ -805,6 +812,20 @@ jobs: py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' + - name: 'Get version from CMakeLists.txt' + id: get_version + shell: bash + run: | + VERSION=$(grep 'set(AMNEZIAVPN_VERSION' CMakeLists.txt | sed -E 's/.*AMNEZIAVPN_VERSION ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\)/\1/') + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "Version: $VERSION" + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: AmneziaVPN_${{ env.VERSION }}_x64.exe + path: build + - name: Run tests shell: bash run: | From 6c7d414a645ef26e6c61f1fb4c38e25dc64b4355 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 20 Apr 2026 12:30:38 +0300 Subject: [PATCH 17/53] update: added 'get sources' and changed steps order --- .github/workflows/deploy.yml | 66 +++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 04dc494f3..609e85bf8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -748,6 +748,25 @@ jobs: steps: - uses: actions/checkout@v4 + + - name: 'Get sources' + uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 10 + + - name: 'Get version from CMakeLists.txt' + id: get_version + run: | + VERSION=$(grep 'set(AMNEZIAVPN_VERSION' CMakeLists.txt | sed -E 's/.*AMNEZIAVPN_VERSION ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\)/\1/') + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "Version: $VERSION" + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: AmneziaVPN_${{ env.VERSION }}_linux_x64.tar.zip + path: build/ - name: Install Qt uses: jurplel/install-qt-action@v3 @@ -765,19 +784,6 @@ jobs: py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - - name: 'Get version from CMakeLists.txt' - id: get_version - run: | - VERSION=$(grep 'set(AMNEZIAVPN_VERSION' CMakeLists.txt | sed -E 's/.*AMNEZIAVPN_VERSION ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\)/\1/') - echo "VERSION=$VERSION" >> $GITHUB_ENV - echo "Version: $VERSION" - - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: AmneziaVPN_${{ env.VERSION }}_linux_x64.tar.zip - path: build/ - - name: Run tests run: | cd build @@ -795,6 +801,26 @@ jobs: steps: - uses: actions/checkout@v4 + + - name: 'Get sources' + uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 10 + + - name: 'Get version from CMakeLists.txt' + id: get_version + shell: bash + run: | + VERSION=$(grep 'set(AMNEZIAVPN_VERSION' CMakeLists.txt | sed -E 's/.*AMNEZIAVPN_VERSION ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\)/\1/') + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "Version: $VERSION" + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: AmneziaVPN_${{ env.VERSION }}_x64.exe + path: build - name: Install Qt uses: jurplel/install-qt-action@v3 @@ -812,20 +838,6 @@ jobs: py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - - name: 'Get version from CMakeLists.txt' - id: get_version - shell: bash - run: | - VERSION=$(grep 'set(AMNEZIAVPN_VERSION' CMakeLists.txt | sed -E 's/.*AMNEZIAVPN_VERSION ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\)/\1/') - echo "VERSION=$VERSION" >> $GITHUB_ENV - echo "Version: $VERSION" - - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: AmneziaVPN_${{ env.VERSION }}_x64.exe - path: build - - name: Run tests shell: bash run: | From e2944b1794dbd88eef57fa847672b75b0b09ea44 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 20 Apr 2026 13:26:53 +0300 Subject: [PATCH 18/53] update: tests jobs remake --- .github/workflows/deploy.yml | 142 +++++++++++++++-------------------- 1 file changed, 62 insertions(+), 80 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 609e85bf8..1d568328f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -741,105 +741,87 @@ jobs: Test-Linux: runs-on: ubuntu-latest - needs: Build-Linux-Ubuntu - env: QT_VERSION: 6.10.1 steps: - - uses: actions/checkout@v4 - - - name: 'Get sources' - uses: actions/checkout@v4 - with: - submodules: 'true' - fetch-depth: 10 + - name: 'Get sources' + uses: actions/checkout@v4 - - name: 'Get version from CMakeLists.txt' - id: get_version - run: | - VERSION=$(grep 'set(AMNEZIAVPN_VERSION' CMakeLists.txt | sed -E 's/.*AMNEZIAVPN_VERSION ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\)/\1/') - echo "VERSION=$VERSION" >> $GITHUB_ENV - echo "Version: $VERSION" + - name: 'Install Qt' + uses: jurplel/install-qt-action@v3 + with: + version: ${{ env.QT_VERSION }} + host: 'linux' + target: 'desktop' + arch: 'linux_gcc_64' + modules: 'qtremoteobjects qt5compat qtshadertools' + dir: ${{ runner.temp }} + set-env: 'true' - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: AmneziaVPN_${{ env.VERSION }}_linux_x64.tar.zip - path: build/ + - name: 'Install dependencies' + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build libxkbcommon-x11-0 - - name: Install Qt - uses: jurplel/install-qt-action@v3 - with: - version: ${{ env.QT_VERSION }} - host: 'linux' - target: 'desktop' - arch: 'linux_gcc_64' - modules: 'qtremoteobjects qt5compat qtshadertools' - dir: ${{ runner.temp }} - setup-python: 'true' - tools: 'tools_ifw' - set-env: 'true' - aqtversion: '==3.3.0' - py7zrversion: '==0.22.*' - extra: '--base ${{ env.QT_MIRROR }}' + - name: 'Configure' + run: | + cmake -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_TESTING=ON - - name: Run tests - run: | - cd build - ctest --output-on-failure + - name: 'Build' + run: cmake --build build + + - name: 'Run QTest binaries' + run: | + ./build/client/tests/testSettingsSignals + ./build/client/tests/testSignalOrder # ------------------------------------------------------ Test-Windows: runs-on: windows-latest - needs: Build-Windows - env: QT_VERSION: 6.10.1 steps: - - uses: actions/checkout@v4 - - - name: 'Get sources' - uses: actions/checkout@v4 - with: - submodules: 'true' - fetch-depth: 10 + - name: 'Get sources' + uses: actions/checkout@v4 - - name: 'Get version from CMakeLists.txt' - id: get_version - shell: bash - run: | - VERSION=$(grep 'set(AMNEZIAVPN_VERSION' CMakeLists.txt | sed -E 's/.*AMNEZIAVPN_VERSION ([0-9]+.[0-9]+.[0-9]+.[0-9]+)\)/\1/') - echo "VERSION=$VERSION" >> $GITHUB_ENV - echo "Version: $VERSION" + - name: 'Install Qt' + uses: jurplel/install-qt-action@v3 + with: + version: ${{ env.QT_VERSION }} + host: 'windows' + target: 'desktop' + arch: 'win64_msvc2022_64' + modules: 'qtremoteobjects qt5compat qtshadertools' + dir: ${{ runner.temp }} + set-env: 'true' - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - name: AmneziaVPN_${{ env.VERSION }}_x64.exe - path: build + - name: 'Setup MSVC' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: 'x64' - - name: Install Qt - uses: jurplel/install-qt-action@v3 - with: - version: ${{ env.QT_VERSION }} - host: 'windows' - target: 'desktop' - arch: 'win64_msvc2019_64' - modules: 'qtremoteobjects qt5compat qtshadertools' - dir: ${{ runner.temp }} - setup-python: 'true' - tools: 'tools_ifw' - set-env: 'true' - aqtversion: '==3.3.0' - py7zrversion: '==0.22.*' - extra: '--base ${{ env.QT_MIRROR }}' + - name: 'Install dependencies' + shell: bash + run: | + choco install ninja -y - - name: Run tests - shell: bash - run: | - cd build - ctest --output-on-failure + - name: 'Configure' + run: | + cmake -B build -G Ninja ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DBUILD_TESTING=ON + + - name: 'Build' + run: cmake --build build + + - name: 'Run QTest binaries' + shell: cmd + run: | + build/client/tests/testSettingsSignals.exe + build/client/tests/testSignalOrder.exe From e9ec3d673436c7c0d94f31da0c052e06688feb30 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 20 Apr 2026 14:31:33 +0300 Subject: [PATCH 19/53] update: 'get sources' step and windows shell --- .github/workflows/deploy.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1d568328f..1288f3b4e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -747,6 +747,9 @@ jobs: steps: - name: 'Get sources' uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 10 - name: 'Install Qt' uses: jurplel/install-qt-action@v3 @@ -789,6 +792,9 @@ jobs: steps: - name: 'Get sources' uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 10 - name: 'Install Qt' uses: jurplel/install-qt-action@v3 @@ -812,10 +818,11 @@ jobs: choco install ninja -y - name: 'Configure' + shell: cmd run: | cmake -B build -G Ninja ^ - -DCMAKE_BUILD_TYPE=Release ^ - -DBUILD_TESTING=ON + -DCMAKE_BUILD_TYPE=Release ^ + -DBUILD_TESTING=ON - name: 'Build' run: cmake --build build From 93e70e8d9f43ec493a58f6c37b18ab8dac7fc830 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 20 Apr 2026 15:25:34 +0300 Subject: [PATCH 20/53] update: using ctest --- .github/workflows/deploy.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1288f3b4e..24d4d5e99 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -827,8 +827,7 @@ jobs: - name: 'Build' run: cmake --build build - - name: 'Run QTest binaries' - shell: cmd + - name: 'Run tests' run: | - build/client/tests/testSettingsSignals.exe - build/client/tests/testSignalOrder.exe + cd build + ctest --output-on-failure From b2d7b3e686662463a9ee21ae5ae59c80873b527e Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 21 Apr 2026 15:42:17 +0300 Subject: [PATCH 21/53] search for exe files --- .github/workflows/deploy.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 24d4d5e99..8d7dfc9c4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -824,10 +824,17 @@ jobs: -DCMAKE_BUILD_TYPE=Release ^ -DBUILD_TESTING=ON - - name: 'Build' - run: cmake --build build + - name: Deploy Qt dependencies + shell: cmd + run: | + for %%f in (build\client\tests\*.exe) do (windeployqt %%f) + + - name: Find all exe files + shell: cmd + run: | + dir build /s *.exe - name: 'Run tests' run: | - cd build + cd build\client\tests ctest --output-on-failure From ffb1e556b11984359cd12759358e7a197b30c7c8 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 21 Apr 2026 15:52:02 +0300 Subject: [PATCH 22/53] changed path to run tests --- .github/workflows/deploy.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8d7dfc9c4..7f2ade715 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -827,14 +827,9 @@ jobs: - name: Deploy Qt dependencies shell: cmd run: | - for %%f in (build\client\tests\*.exe) do (windeployqt %%f) - - - name: Find all exe files - shell: cmd - run: | - dir build /s *.exe + for %%f in (out\build\client\tests\*.exe) do (windeployqt %%f) - name: 'Run tests' run: | - cd build\client\tests + cd out\build\client\tests ctest --output-on-failure From 3426ea4e269931677b62773b14fda0d9955f83aa Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 21 Apr 2026 16:30:07 +0300 Subject: [PATCH 23/53] update: 'Build' step --- .github/workflows/deploy.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7f2ade715..cb80ed9fe 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -824,12 +824,18 @@ jobs: -DCMAKE_BUILD_TYPE=Release ^ -DBUILD_TESTING=ON + - name: 'Build' + shell: cmd + run: cmake --build build --config Release + - name: Deploy Qt dependencies shell: cmd run: | - for %%f in (out\build\client\tests\*.exe) do (windeployqt %%f) + for %%f in (build\client\tests\*.exe) do (windeployqt %%f) - name: 'Run tests' run: | - cd out\build\client\tests + dir build\client\tests + dir build\client + cd build\client\tests ctest --output-on-failure From 5a7c7c9df9765228d1b7f5a1176eb62a0b3aeb94 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 21 Apr 2026 16:56:30 +0300 Subject: [PATCH 24/53] update: changed path to deploy qt dependencies --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cb80ed9fe..838fa16bd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -828,10 +828,10 @@ jobs: shell: cmd run: cmake --build build --config Release - - name: Deploy Qt dependencies + - name: 'Deploy Qt dependencies' shell: cmd run: | - for %%f in (build\client\tests\*.exe) do (windeployqt %%f) + for %%f in (build\client\*.exe) do (windeployqt %%f) - name: 'Run tests' run: | From 3b8adf3b6a38cc36d384f5ae800388771885ba99 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 21 Apr 2026 17:14:31 +0300 Subject: [PATCH 25/53] update: dependencies only for tests executables --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 838fa16bd..56c4e8b00 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -831,7 +831,7 @@ jobs: - name: 'Deploy Qt dependencies' shell: cmd run: | - for %%f in (build\client\*.exe) do (windeployqt %%f) + for %%f in (build\client\test_*.exe) do (windeployqt %%f) - name: 'Run tests' run: | From eb6f7a58703873d3ab47a2aac0efa98c6983d43e Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 21 Apr 2026 18:01:58 +0300 Subject: [PATCH 26/53] update: ctest dir --- .github/workflows/deploy.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 56c4e8b00..3081584ef 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -834,8 +834,6 @@ jobs: for %%f in (build\client\test_*.exe) do (windeployqt %%f) - name: 'Run tests' + shell: cmd run: | - dir build\client\tests - dir build\client - cd build\client\tests - ctest --output-on-failure + ctest --test-dir build --output-on-failure From 72a8b15ac8d6cfbb3389fdd997cfe74cf2355430 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 21 Apr 2026 18:45:11 +0300 Subject: [PATCH 27/53] update: include ctest --- client/tests/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index 3f57cc76b..e11849695 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -4,6 +4,8 @@ project(AmneziaVPN_Tests) find_package(Qt6 REQUIRED COMPONENTS Test) +include(CTest) +enable_testing() set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) From ea5e76e8c8e4e7ccaca169a4a472b8e3e9f83b8d Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 22 Apr 2026 11:31:27 +0300 Subject: [PATCH 28/53] update: set dir for tests exe --- .github/workflows/deploy.yml | 3 +- client/tests/CMakeLists.txt | 64 +++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3081584ef..7b11247c4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -836,4 +836,5 @@ jobs: - name: 'Run tests' shell: cmd run: | - ctest --test-dir build --output-on-failure + dir build\client\tests /s | findstr CTestTestfile.cmake + ctest --test-dir build\client\tests --output-on-failure diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index e11849695..0de100dca 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -5,7 +5,6 @@ project(AmneziaVPN_Tests) find_package(Qt6 REQUIRED COMPONENTS Test) include(CTest) -enable_testing() set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) @@ -216,6 +215,69 @@ target_link_libraries(test_ui_news_model_and_controller PRIVATE test_common ) +if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE) + set_target_properties(test_import_export PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_multiple_imports PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_server_edit PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_default_server_change PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_server_edge_cases PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_signal_order PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_servers_model_sync PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_gateway_stacks PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_complex_operations PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_settings_signals PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_ui_servers_model_and_controller PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_self_hosted_server_setup PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_exports PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_serialization PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_ui_language_model_and_controller PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_ui_sites_model_and_controller PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_ui_app_st_model_and_controller PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_ui_allowed_dns_model_and_controller PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_ui_api_services_model_and_controller PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) + set_target_properties(test_ui_news_model_and_controller PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" + ) +endif() + enable_testing() add_test(NAME ImportExportTest COMMAND test_import_export) add_test(NAME MultipleImportsTest COMMAND test_multiple_imports) From a02419e229d8ff4502115f09981dce5907a91105 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 22 Apr 2026 12:27:08 +0300 Subject: [PATCH 29/53] update: qt path --- .github/workflows/deploy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7b11247c4..1849743e3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -836,5 +836,7 @@ jobs: - name: 'Run tests' shell: cmd run: | + dir build\client\tests\*.dll + set PATH=%PATH%;%Qt6_DIR%\..\..\bin dir build\client\tests /s | findstr CTestTestfile.cmake ctest --test-dir build\client\tests --output-on-failure From 703384445bf75b376c09f88808a3ac19c18b7c9d Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 22 Apr 2026 14:28:52 +0300 Subject: [PATCH 30/53] update: serialization test --- client/tests/testSerialization.cpp | 138 ++++++++++++++++++++++++++--- 1 file changed, 128 insertions(+), 10 deletions(-) diff --git a/client/tests/testSerialization.cpp b/client/tests/testSerialization.cpp index 89caad87c..1a32b5a23 100644 --- a/client/tests/testSerialization.cpp +++ b/client/tests/testSerialization.cpp @@ -29,6 +29,12 @@ private: return env.value("TEST_SELF_HOSTED_CONFIG"); } + QString getKey(QString name) + { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + return env.value("TEST_KEY_" + name); + } + QJsonObject extractXrayConfig(const QString &data, ConfigTypes configType, const QString &description = "") const { QJsonParseError parserErr; @@ -116,9 +122,9 @@ private slots: { int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); - QString clientName = "Serialization Test Client"; + QString clientName = "Test Client (vless (de)serialization)"; - auto exportResult = m_coreController->m_exportController->generateXrayConfig(serverIndex, clientName); + ExportController::ExportResult exportResult = m_coreController->m_exportController->generateXrayConfig(serverIndex, clientName); ImportController::ImportResult importResult; @@ -129,39 +135,151 @@ private slots: if (config.startsWith("vless://")) { configType = ConfigTypes::Xray; - importResult.config = extractXrayConfig(Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), - QJsonDocument::JsonFormat::Compact), configType, prefix); + importResult.config = extractXrayConfig( + Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), + configType, prefix); QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); } else { QSKIP("Config not starts with vless://"); } - QCOMPARE(importResult.config, exportResult.config); + QCOMPARE(importResult.config, config); } void testVmessNew() { - QSKIP("test not completed"); + QString clientName = "Test Client (vmess_new deserialization)"; + + ImportController::ImportResult importResult; + + m_coreController->m_importController->extractConfigFromData(getKey("VMESS_NEW")); + + QString config = m_coreController->m_importController->getConfig(); + QString prefix; + QString errormsg; + ConfigTypes configType = ConfigTypes::Invalid; + + if (config.startsWith("vmess://") && config.contains("@")) { + configType = ConfigTypes::Xray; + importResult.config = extractXrayConfig( + Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), + configType, prefix); + QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + } else { + QSKIP("Config not starts with vmess:// or not contain @"); + } + + QCOMPARE(importResult.config, config); } void testVmess() { - QSKIP("test not completed"); + QString clientName = "Test Client (vmess deserialization)"; + + ImportController::ImportResult importResult; + + m_coreController->m_importController->extractConfigFromData(getKey("VMESS")); + + QString config = m_coreController->m_importController->getConfig(); + QString prefix; + QString errormsg; + ConfigTypes configType = ConfigTypes::Invalid; + + if (config.startsWith("vmess://")) { + configType = ConfigTypes::Xray; + importResult.config = extractXrayConfig( + Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), + configType, prefix); + QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + } else { + QSKIP("Config not starts with vmess://"); + } + + QCOMPARE(importResult.config, config); } void testTrojan() { - QSKIP("test not completed"); + QString clientName = "Test Client (trojan deserialization)"; + + ImportController::ImportResult importResult; + + m_coreController->m_importController->extractConfigFromData(getKey("TROJAN")); + + QString config = m_coreController->m_importController->getConfig(); + QString prefix; + QString errormsg; + ConfigTypes configType = ConfigTypes::Invalid; + + if (config.startsWith("trojan://")) { + configType = ConfigTypes::Xray; + importResult.config = extractXrayConfig( + Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), + configType, prefix); + QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + } else { + QSKIP("Config not starts with trojan://"); + } + + QCOMPARE(importResult.config, config); } void testSS() { - QSKIP("test not completed"); + QString clientName = "Test Client (ss deserialization)"; + + ImportController::ImportResult importResult; + + m_coreController->m_importController->extractConfigFromData(getKey("SS")); + + QString config = m_coreController->m_importController->getConfig(); + QString prefix; + QString errormsg; + ConfigTypes configType = ConfigTypes::Invalid; + + if (config.startsWith("ss://") && !config.contains("plugin=")) { + configType = ConfigTypes::ShadowSocks; + importResult.config = extractXrayConfig( + Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), + configType, prefix); + QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + } else { + QSKIP("Config not starts with ss:// or contain plugin="); + } + + QCOMPARE(importResult.config, config); } void testSSd() { - QSKIP("test not completed"); + QString clientName = "Test Client (ssd deserialization)"; + + ImportController::ImportResult importResult; + + m_coreController->m_importController->extractConfigFromData(getKey("SSD")); + + QString config = m_coreController->m_importController->getConfig(); + QString prefix; + QString errormsg; + ConfigTypes configType = ConfigTypes::Invalid; + + if (config.startsWith("ssd://")) { + QStringList tmp; + QList> servers = serialization::ssd::Deserialize(config, &prefix, &tmp); + configType = ConfigTypes::ShadowSocks; + // Took only first config from list + if (!servers.isEmpty()) { + importResult.config = extractXrayConfig(servers.first().first, configType); + } + if (!importResult.config.empty()) { + importResult.configType = configType; + } + QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + } else { + QSKIP("Config not starts with ssd://"); + } + + QCOMPARE(importResult.config, config); } }; From a58b05214f01a412c9179af7b524ec590a2a5d5b Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 22 Apr 2026 14:31:43 +0300 Subject: [PATCH 31/53] update: removed api tests from cmake --- client/tests/CMakeLists.txt | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index 0de100dca..342dfad5e 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -206,15 +206,6 @@ target_link_libraries(test_ui_api_services_model_and_controller PRIVATE test_common ) -add_executable(test_ui_news_model_and_controller - api/testUiNewsModelAndController.cpp -) - -target_link_libraries(test_ui_news_model_and_controller PRIVATE - Qt6::Test - test_common -) - if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE) set_target_properties(test_import_export PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" @@ -270,12 +261,6 @@ if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE) set_target_properties(test_ui_allowed_dns_model_and_controller PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" ) - set_target_properties(test_ui_api_services_model_and_controller PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_ui_news_model_and_controller PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) endif() enable_testing() @@ -297,5 +282,3 @@ add_test(NAME UiLanguageModelAndControllerTest COMMAND test_ui_language_model_an add_test(NAME UiSitesModelAndControllerTest COMMAND test_ui_sites_model_and_controller) add_test(NAME UiAppSTModelAndControllerTest COMMAND test_ui_app_st_model_and_controller) add_test(NAME UiAllowedDnsModelAndControllerTest COMMAND test_ui_allowed_dns_model_and_controller) -add_test(NAME UiApiServicesModelAndControllerTest COMMAND test_ui_api_services_model_and_controller) -add_test(NAME UiNewsModelAndControllerTest COMMAND test_ui_news_model_and_controller) From 562858c9df4ef907da944712b80c3fa2fc3ca79d Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Thu, 23 Apr 2026 11:08:28 +0300 Subject: [PATCH 32/53] update: changed tests dir --- .github/workflows/deploy.yml | 5 ++-- client/tests/CMakeLists.txt | 57 ------------------------------------ 2 files changed, 2 insertions(+), 60 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1849743e3..3b3a7734d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -836,7 +836,6 @@ jobs: - name: 'Run tests' shell: cmd run: | - dir build\client\tests\*.dll set PATH=%PATH%;%Qt6_DIR%\..\..\bin - dir build\client\tests /s | findstr CTestTestfile.cmake - ctest --test-dir build\client\tests --output-on-failure + dir build\client /s | findstr CTestTestfile.cmake + ctest --test-dir build\client --output-on-failure diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index 342dfad5e..9c3ac6f86 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -206,63 +206,6 @@ target_link_libraries(test_ui_api_services_model_and_controller PRIVATE test_common ) -if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE) - set_target_properties(test_import_export PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_multiple_imports PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_server_edit PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_default_server_change PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_server_edge_cases PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_signal_order PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_servers_model_sync PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_gateway_stacks PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_complex_operations PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_settings_signals PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_ui_servers_model_and_controller PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_self_hosted_server_setup PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_exports PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_serialization PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_ui_language_model_and_controller PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_ui_sites_model_and_controller PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_ui_app_st_model_and_controller PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) - set_target_properties(test_ui_allowed_dns_model_and_controller PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/client/tests" - ) -endif() - enable_testing() add_test(NAME ImportExportTest COMMAND test_import_export) add_test(NAME MultipleImportsTest COMMAND test_multiple_imports) From 63f33bff83b2a156b5987619ce1b9703d41c5e33 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Thu, 23 Apr 2026 11:09:05 +0300 Subject: [PATCH 33/53] added ctest to client cmake --- client/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 42e9ad566..029485902 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -233,6 +233,8 @@ if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE) ) endif() +include(CTest) + if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE) add_subdirectory(tests) endif() From 3885013829501b6ee673c55677dbb8a80473cabc Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Fri, 24 Apr 2026 12:53:53 +0300 Subject: [PATCH 34/53] update: installing msvc and additional checks --- .github/workflows/deploy.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3b3a7734d..cffe19958 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -837,5 +837,4 @@ jobs: shell: cmd run: | set PATH=%PATH%;%Qt6_DIR%\..\..\bin - dir build\client /s | findstr CTestTestfile.cmake ctest --test-dir build\client --output-on-failure From d37c616d3dae46cd9cb7e33d60428d34832b0471 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Fri, 24 Apr 2026 13:15:28 +0300 Subject: [PATCH 35/53] removed mcvs install --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cffe19958..02212ba3d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -836,5 +836,5 @@ jobs: - name: 'Run tests' shell: cmd run: | - set PATH=%PATH%;%Qt6_DIR%\..\..\bin + set PATH=%PATH%;%Qt6_DIR%\..\..\..\bin ctest --test-dir build\client --output-on-failure From a3cff2099fbdd5023c6b488843d65c8f53e32223 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 27 Apr 2026 11:43:08 +0300 Subject: [PATCH 36/53] update: path to ssh.dll --- .github/workflows/deploy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 02212ba3d..e018d847c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -836,5 +836,7 @@ jobs: - name: 'Run tests' shell: cmd run: | + set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x6 set PATH=%PATH%;%Qt6_DIR%\..\..\..\bin + where ssh.dll ctest --test-dir build\client --output-on-failure From a5deb30abb598f69a0c9488a123cc154f0d34a90 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 27 Apr 2026 12:04:07 +0300 Subject: [PATCH 37/53] fixed issue with ssh path --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e018d847c..ea32ce14f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -836,7 +836,7 @@ jobs: - name: 'Run tests' shell: cmd run: | - set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x6 + set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x64 set PATH=%PATH%;%Qt6_DIR%\..\..\..\bin where ssh.dll ctest --test-dir build\client --output-on-failure From ae763187b9923b4ef7fad0a88c9e8a9caa7824a7 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 27 Apr 2026 12:27:24 +0300 Subject: [PATCH 38/53] update: removed unneccessary step and line --- .github/workflows/deploy.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ea32ce14f..52ba229ee 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -838,5 +838,4 @@ jobs: run: | set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x64 set PATH=%PATH%;%Qt6_DIR%\..\..\..\bin - where ssh.dll ctest --test-dir build\client --output-on-failure From 4c6cf9f2d4bc38ed8c2141e2e4adfaeeacaa85b9 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 27 Apr 2026 12:32:02 +0300 Subject: [PATCH 39/53] update: linux job step 'Run tests' --- .github/workflows/deploy.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 52ba229ee..aa0ddde2f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -776,10 +776,15 @@ jobs: - name: 'Build' run: cmake --build build - - name: 'Run QTest binaries' + - name: 'Run tests' run: | - ./build/client/tests/testSettingsSignals - ./build/client/tests/testSignalOrder + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:\ + ${{ env.Qt6_DIR }}/../../../lib:\ + $PWD/client/3rd-prebuilt/deploy-prebuilt/linux/x64 + + ldd build/client/tests/testSettingsSignals || true + + ctest --test-dir build/client --output-on-failure # ------------------------------------------------------ From 2f9f0ee50d369609e788dc8a2db1c4aa42b47725 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 27 Apr 2026 12:48:51 +0300 Subject: [PATCH 40/53] update: linux 'Install dependencies' --- .github/workflows/deploy.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index aa0ddde2f..9206fe983 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -765,7 +765,11 @@ jobs: - name: 'Install dependencies' run: | sudo apt-get update - sudo apt-get install -y cmake ninja-build libxkbcommon-x11-0 + sudo apt-get install -y \ + cmake \ + ninja-build \ + libxkbcommon-x11-0 \ + libsecret-1-dev - name: 'Configure' run: | From c965aba61db92a701d863ebb02c20a7bce8ab7fe Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 27 Apr 2026 13:42:31 +0300 Subject: [PATCH 41/53] update: modified qtest include --- client/tests/testAdminSelfHostedExport.cpp | 7 ++++++- client/tests/testComplexOperations.cpp | 7 ++++++- client/tests/testDefaultServerChange.cpp | 7 ++++++- client/tests/testGatewayStacks.cpp | 7 ++++++- client/tests/testMultipleExports.cpp | 7 ++++++- client/tests/testMultipleImports.cpp | 7 ++++++- client/tests/testSelfHostedServerSetup.cpp | 7 ++++++- client/tests/testSerialization.cpp | 7 ++++++- client/tests/testServerEdgeCases.cpp | 7 ++++++- client/tests/testServerEdit.cpp | 7 ++++++- client/tests/testServersModelSync.cpp | 7 ++++++- client/tests/testSettingsSignals.cpp | 7 ++++++- client/tests/testSignalOrder.cpp | 7 ++++++- client/tests/testUiAllowedDnsModelAndController.cpp | 7 ++++++- client/tests/testUiAppSTModelAndController.cpp | 7 ++++++- client/tests/testUiLanguageModelAndController.cpp | 7 ++++++- client/tests/testUiServersModelAndController.cpp | 7 ++++++- client/tests/testUiSitesModelAndController.cpp | 7 ++++++- 18 files changed, 108 insertions(+), 18 deletions(-) diff --git a/client/tests/testAdminSelfHostedExport.cpp b/client/tests/testAdminSelfHostedExport.cpp index 9cd8a6976..439a93b27 100644 --- a/client/tests/testAdminSelfHostedExport.cpp +++ b/client/tests/testAdminSelfHostedExport.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,6 +6,12 @@ #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "vpnConnection.h" diff --git a/client/tests/testComplexOperations.cpp b/client/tests/testComplexOperations.cpp index 878a12510..931f6a51b 100644 --- a/client/tests/testComplexOperations.cpp +++ b/client/tests/testComplexOperations.cpp @@ -1,9 +1,14 @@ -#include #include #include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "vpnConnection.h" diff --git a/client/tests/testDefaultServerChange.cpp b/client/tests/testDefaultServerChange.cpp index adffde62f..675a8fa1e 100644 --- a/client/tests/testDefaultServerChange.cpp +++ b/client/tests/testDefaultServerChange.cpp @@ -1,9 +1,14 @@ -#include #include #include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "ui/models/serversModel.h" diff --git a/client/tests/testGatewayStacks.cpp b/client/tests/testGatewayStacks.cpp index acffe39bb..2271f07f1 100644 --- a/client/tests/testGatewayStacks.cpp +++ b/client/tests/testGatewayStacks.cpp @@ -1,9 +1,14 @@ -#include #include #include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "vpnConnection.h" diff --git a/client/tests/testMultipleExports.cpp b/client/tests/testMultipleExports.cpp index e84708b9d..c88af391e 100644 --- a/client/tests/testMultipleExports.cpp +++ b/client/tests/testMultipleExports.cpp @@ -2,10 +2,15 @@ #include #include #include -#include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "secureQSettings.h" diff --git a/client/tests/testMultipleImports.cpp b/client/tests/testMultipleImports.cpp index 44a0acd3c..e4ad96d3c 100644 --- a/client/tests/testMultipleImports.cpp +++ b/client/tests/testMultipleImports.cpp @@ -1,10 +1,15 @@ -#include #include #include #include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "vpnConnection.h" diff --git a/client/tests/testSelfHostedServerSetup.cpp b/client/tests/testSelfHostedServerSetup.cpp index a44725556..184b40e32 100644 --- a/client/tests/testSelfHostedServerSetup.cpp +++ b/client/tests/testSelfHostedServerSetup.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -6,6 +5,12 @@ #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "core/models/selfhosted/selfHostedServerConfig.h" diff --git a/client/tests/testSerialization.cpp b/client/tests/testSerialization.cpp index 1a32b5a23..edd8b74f3 100644 --- a/client/tests/testSerialization.cpp +++ b/client/tests/testSerialization.cpp @@ -3,9 +3,14 @@ #include #include #include -#include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "core/utils/serialization/serialization.h" diff --git a/client/tests/testServerEdgeCases.cpp b/client/tests/testServerEdgeCases.cpp index 53c358d20..82e0b6ee6 100644 --- a/client/tests/testServerEdgeCases.cpp +++ b/client/tests/testServerEdgeCases.cpp @@ -1,9 +1,14 @@ -#include #include #include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "vpnConnection.h" diff --git a/client/tests/testServerEdit.cpp b/client/tests/testServerEdit.cpp index 57f18ef12..45009dc1c 100644 --- a/client/tests/testServerEdit.cpp +++ b/client/tests/testServerEdit.cpp @@ -1,9 +1,14 @@ -#include #include #include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "ui/models/serversModel.h" diff --git a/client/tests/testServersModelSync.cpp b/client/tests/testServersModelSync.cpp index a1e63ccce..773d720b9 100644 --- a/client/tests/testServersModelSync.cpp +++ b/client/tests/testServersModelSync.cpp @@ -1,9 +1,14 @@ -#include #include #include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "ui/models/serversModel.h" diff --git a/client/tests/testSettingsSignals.cpp b/client/tests/testSettingsSignals.cpp index e0308a56c..eef42b54c 100644 --- a/client/tests/testSettingsSignals.cpp +++ b/client/tests/testSettingsSignals.cpp @@ -1,10 +1,15 @@ -#include #include #include #include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "ui/controllers/settingsUiController.h" diff --git a/client/tests/testSignalOrder.cpp b/client/tests/testSignalOrder.cpp index 97b7cb29e..61304dd19 100644 --- a/client/tests/testSignalOrder.cpp +++ b/client/tests/testSignalOrder.cpp @@ -1,9 +1,14 @@ -#include #include #include #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "vpnConnection.h" diff --git a/client/tests/testUiAllowedDnsModelAndController.cpp b/client/tests/testUiAllowedDnsModelAndController.cpp index 8e600b042..07ee6ce2c 100644 --- a/client/tests/testUiAllowedDnsModelAndController.cpp +++ b/client/tests/testUiAllowedDnsModelAndController.cpp @@ -3,9 +3,14 @@ #include #include #include -#include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "secureQSettings.h" diff --git a/client/tests/testUiAppSTModelAndController.cpp b/client/tests/testUiAppSTModelAndController.cpp index 761d11806..26c1f2aef 100644 --- a/client/tests/testUiAppSTModelAndController.cpp +++ b/client/tests/testUiAppSTModelAndController.cpp @@ -3,9 +3,14 @@ #include #include #include -#include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "secureQSettings.h" diff --git a/client/tests/testUiLanguageModelAndController.cpp b/client/tests/testUiLanguageModelAndController.cpp index 521c68b54..699e14902 100644 --- a/client/tests/testUiLanguageModelAndController.cpp +++ b/client/tests/testUiLanguageModelAndController.cpp @@ -3,9 +3,14 @@ #include #include #include -#include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "secureQSettings.h" diff --git a/client/tests/testUiServersModelAndController.cpp b/client/tests/testUiServersModelAndController.cpp index 16039e988..9cb500e93 100644 --- a/client/tests/testUiServersModelAndController.cpp +++ b/client/tests/testUiServersModelAndController.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,6 +6,12 @@ #include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "core/controllers/selfhosted/importController.h" diff --git a/client/tests/testUiSitesModelAndController.cpp b/client/tests/testUiSitesModelAndController.cpp index aa815aff8..4734e0f52 100644 --- a/client/tests/testUiSitesModelAndController.cpp +++ b/client/tests/testUiSitesModelAndController.cpp @@ -3,9 +3,14 @@ #include #include #include -#include #include +#ifdef Q_OS_WIN + #include +#else + #include +#endif + #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" #include "secureQSettings.h" From c3ea4f5ee6f79d6a44879a64a43ebae28d3e8080 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 27 Apr 2026 14:08:26 +0300 Subject: [PATCH 42/53] update: changed QVERIFY to QVERIFY2 --- client/tests/testSerialization.cpp | 12 ++++---- .../testUiAllowedDnsModelAndController.cpp | 24 +++++++-------- .../tests/testUiAppSTModelAndController.cpp | 26 ++++++++-------- .../testUiLanguageModelAndController.cpp | 18 +++++------ .../tests/testUiSitesModelAndController.cpp | 30 +++++++++---------- 5 files changed, 55 insertions(+), 55 deletions(-) diff --git a/client/tests/testSerialization.cpp b/client/tests/testSerialization.cpp index edd8b74f3..86717f3b9 100644 --- a/client/tests/testSerialization.cpp +++ b/client/tests/testSerialization.cpp @@ -143,7 +143,7 @@ private slots: importResult.config = extractXrayConfig( Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), configType, prefix); - QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + QVERIFY2(!importResult.config.empty(), "Config shouldn't be empty"); } else { QSKIP("Config not starts with vless://"); } @@ -169,7 +169,7 @@ private slots: importResult.config = extractXrayConfig( Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), configType, prefix); - QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + QVERIFY2(!importResult.config.empty(), "Config shouldn't be empty"); } else { QSKIP("Config not starts with vmess:// or not contain @"); } @@ -195,7 +195,7 @@ private slots: importResult.config = extractXrayConfig( Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), configType, prefix); - QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + QVERIFY2(!importResult.config.empty(), "Config shouldn't be empty"); } else { QSKIP("Config not starts with vmess://"); } @@ -221,7 +221,7 @@ private slots: importResult.config = extractXrayConfig( Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), configType, prefix); - QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + QVERIFY2(!importResult.config.empty(), "Config shouldn't be empty"); } else { QSKIP("Config not starts with trojan://"); } @@ -247,7 +247,7 @@ private slots: importResult.config = extractXrayConfig( Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), configType, prefix); - QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + QVERIFY2(!importResult.config.empty(), "Config shouldn't be empty"); } else { QSKIP("Config not starts with ss:// or contain plugin="); } @@ -279,7 +279,7 @@ private slots: if (!importResult.config.empty()) { importResult.configType = configType; } - QVERIFY(!importResult.config.empty(), "Config shouldn't be empty"); + QVERIFY2(!importResult.config.empty(), "Config shouldn't be empty"); } else { QSKIP("Config not starts with ssd://"); } diff --git a/client/tests/testUiAllowedDnsModelAndController.cpp b/client/tests/testUiAllowedDnsModelAndController.cpp index 07ee6ce2c..46aee886b 100644 --- a/client/tests/testUiAllowedDnsModelAndController.cpp +++ b/client/tests/testUiAllowedDnsModelAndController.cpp @@ -73,31 +73,31 @@ private slots: m_coreController->m_allowedDnsUiController->addDns(ip); m_coreController->m_allowedDnsUiController->updateModel(); - QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); - QVERIFY(finishedSpy.count() == 1, "finished signal should be emitted"); - QVERIFY(m_coreController->m_allowedDnsModel->rowCount() == 1, "AllowedDnsModel should have 1 row"); + QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY2(finishedSpy.count() == 1, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_allowedDnsModel->rowCount() == 1, "AllowedDnsModel should have 1 row"); QModelIndex allowedDnsModelIndex = m_coreController->m_allowedDnsModel->index(0, 0); QVERIFY2(allowedDnsModelIndex.isValid(), "Site model index should be valid"); auto dnsIp = m_coreController->m_allowedDnsModel->data(allowedDnsModelIndex, AllowedDnsModel::IpRole); - QVERIFY(dnsIp == ip, QString("app path should be %1, got %2").arg(ip, appPath)); + QVERIFY2(dnsIp == ip, QString("app path should be %1, got %2").arg(ip, appPath)); m_coreController->m_allowedDnsUiController->importDns(getPath(), true); m_coreController->m_allowedDnsUiController->updateModel(); - QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); - QVERIFY(finishedSpy.count() == 2, "finished signal should be emitted"); - QVERIFY(m_coreController->m_allowedDnsModel->rowCount() > 1, "AllowedDnsModel should have more than 1 row"); + QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY2(finishedSpy.count() == 2, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_allowedDnsModel->rowCount() > 1, "AllowedDnsModel should have more than 1 row"); m_coreController->m_allowedDnsUiController->exportDns(getExportPath() + "test_dns_export.json"); - QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); - QVERIFY(finishedSpy.count() == 3, "finished signal should be emitted"); + QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY2(finishedSpy.count() == 3, "finished signal should be emitted"); m_coreController->m_allowedDnsUiController->removeDns(0); m_coreController->m_allowedDnsUiController->updateModel(); - QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); - QVERIFY(finishedSpy.count() == 4, "finished signal should be emitted"); - QVERIFY(m_coreController->m_allowedDnsModel->rowCount() == 0, "AllowedDnsModel should have 0 rows"); + QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY2(finishedSpy.count() == 4, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_allowedDnsModel->rowCount() == 0, "AllowedDnsModel should have 0 rows"); } }; diff --git a/client/tests/testUiAppSTModelAndController.cpp b/client/tests/testUiAppSTModelAndController.cpp index 26c1f2aef..b36926274 100644 --- a/client/tests/testUiAppSTModelAndController.cpp +++ b/client/tests/testUiAppSTModelAndController.cpp @@ -65,41 +65,41 @@ private slots: QSignalSpy isSplitTunnelingChangedSpy(m_coreController->m_appSplitTunnelingUiController, &AppSplitTunnelingUiController::isTunnelingEnabledChanged); m_coreController->m_appSplitTunnelingUiController->toggleSplitTunneling(true); - QVERIFY(isSplitTunnelingChangedSpy.count() == 1, "isSplitTunnelingChangedSpy signal should be emitted"); - QVERIFY(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == true, "AppSplitTunneling should be enabled"); + QVERIFY2(isSplitTunnelingChangedSpy.count() == 1, "isSplitTunnelingChangedSpy signal should be emitted"); + QVERIFY2(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == true, "AppSplitTunneling should be enabled"); m_coreController->m_appSplitTunnelingUiController->toggleSplitTunneling(false); - QVERIFY(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); - QVERIFY(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == false, "AppSplitTunneling should be disabled"); + QVERIFY2(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); + QVERIFY2(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == false, "AppSplitTunneling should be disabled"); QString app = getPath(); m_coreController->m_appSplitTunnelingUiController->addApp(app); m_coreController->m_appSplitTunnelingUiController->updateModel(); - QVERIFY(finishedSpy.count() == 1, "finished signal should be emitted"); - QVERIFY(m_coreController->m_appSplitTunnelingModel->rowCount() == 1, "AppSplitTunnelingModel should have 1 row"); + QVERIFY2(finishedSpy.count() == 1, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_appSplitTunnelingModel->rowCount() == 1, "AppSplitTunnelingModel should have 1 row"); QModelIndex appSTModelIndex = m_coreController->m_appSplitTunnelingModel->index(0, 0); QVERIFY2(appSTModelIndex.isValid(), "Site model index should be valid"); auto appPath = m_coreController->m_appSplitTunnelingModel->data(appSTModelIndex, AppSplitTunnelingModel::AppPathRole); - QVERIFY(app.contains(appPath.toString()) == true, QString("app path should be %1, got %2").arg(app, appPath)); + QVERIFY2(app.contains(appPath.toString()) == true, QString("app path should be %1, got %2").arg(app, appPath)); auto pkgAppName = m_coreController->m_appSplitTunnelingModel->data(appSTModelIndex, AppSplitTunnelingModel::PackageAppNameRole); - QVERIFY(pkgAppName == true, "app name should be set"); + QVERIFY2(pkgAppName == true, "app name should be set"); auto pkgAppIcon = m_coreController->m_appSplitTunnelingModel->data(appSTModelIndex, AppSplitTunnelingModel::PackageAppIconRole); - QVERIFY(pkgAppIcon == true, "app image should be set"); + QVERIFY2(pkgAppIcon == true, "app image should be set"); m_coreController->m_appSplitTunnelingUiController->addApp(app); m_coreController->m_appSplitTunnelingUiController->updateModel(); - QVERIFY(errorOccurredSpy.count() == 1, "errorOccurred signal should be emitted"); - QVERIFY(m_coreController->m_appSplitTunnelingModel->rowCount() == 1, "AppSplitTunnelingModel should have 3 rows (same app should not be added)"); + QVERIFY2(errorOccurredSpy.count() == 1, "errorOccurred signal should be emitted"); + QVERIFY2(m_coreController->m_appSplitTunnelingModel->rowCount() == 1, "AppSplitTunnelingModel should have 3 rows (same app should not be added)"); m_coreController->m_appSplitTunnelingUiController->removeApp(0); m_coreController->m_appSplitTunnelingUiController->updateModel(); - QVERIFY(finishedSpy.count() == 2, "finished signal should be emitted"); - QVERIFY(m_coreController->m_appSplitTunnelingModel->rowCount() == 0, "AppSplitTunnelingModel should have 0 rows"); + QVERIFY2(finishedSpy.count() == 2, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_appSplitTunnelingModel->rowCount() == 0, "AppSplitTunnelingModel should have 0 rows"); } }; diff --git a/client/tests/testUiLanguageModelAndController.cpp b/client/tests/testUiLanguageModelAndController.cpp index 699e14902..539d7a333 100644 --- a/client/tests/testUiLanguageModelAndController.cpp +++ b/client/tests/testUiLanguageModelAndController.cpp @@ -54,18 +54,18 @@ private slots: void testChangeLanguage() { - QVERIFY(m_coreController->m_languageModel->rowCount() > 0, "Language model should not be empty"); + QVERIFY2(m_coreController->m_languageModel->rowCount() > 0, "Language model should not be empty"); QSignalSpy updateTranslationsSpy(m_coreController->m_languageUiController, &LanguageUiController::updateTranslations); QSignalSpy translationsUpdatedSpy(m_coreController->m_languageUiController, &LanguageUiController::translationsUpdated); m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::China_cn); - QVERIFY(updateTranslationsSpy.count() == 1, "updateTranslations signal should be emitted"); - QVERIFY(translationsUpdatedSpy.count() == 1, "translationsUpdated signal should be emitted"); + QVERIFY2(updateTranslationsSpy.count() == 1, "updateTranslations signal should be emitted"); + QVERIFY2(translationsUpdatedSpy.count() == 1, "translationsUpdated signal should be emitted"); m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::English); - QVERIFY(updateTranslationsSpy.count() == 2, "updateTranslations signal should be emitted"); - QVERIFY(translationsUpdatedSpy.count() == 2, "translationsUpdated signal should be emitted"); + QVERIFY2(updateTranslationsSpy.count() == 2, "updateTranslations signal should be emitted"); + QVERIFY2(translationsUpdatedSpy.count() == 2, "translationsUpdated signal should be emitted"); } void testUrl() @@ -78,17 +78,17 @@ private slots: QString siteEN = m_coreController->m_languageUiController->getCurrentSiteUrl("test_path"); QString docsEN = m_coreController->m_languageUiController->getCurrentDocsUrl("test_path"); - QVERIFY(siteRU != siteEN, "site url's should not be same"); - QVERIFY(docsRU != docsEN, "docs url's should not be same"); + QVERIFY2(siteRU != siteEN, "site url's should not be same"); + QVERIFY2(docsRU != docsEN, "docs url's should not be same"); } void testLineHeight() { m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::Burmese); - QVERIFY(m_coreController->m_languageUiController->getLineHeightAppend() == 10, "line height should be 10"); + QVERIFY2(m_coreController->m_languageUiController->getLineHeightAppend() == 10, "line height should be 10"); m_coreController->m_languageUiController->changeLanguage(LanguageSettings::AvailableLanguageEnum::English); - QVERIFY(m_coreController->m_languageUiController->getLineHeightAppend() == 0, "line height should be 0"); + QVERIFY2(m_coreController->m_languageUiController->getLineHeightAppend() == 0, "line height should be 0"); } }; diff --git a/client/tests/testUiSitesModelAndController.cpp b/client/tests/testUiSitesModelAndController.cpp index 4734e0f52..bc308140a 100644 --- a/client/tests/testUiSitesModelAndController.cpp +++ b/client/tests/testUiSitesModelAndController.cpp @@ -81,20 +81,20 @@ private slots: QSignalSpy isSplitTunnelingChangedSpy(m_coreController->m_sitesUiController, &SitesUiController::isTunnelingEnabledChanged); m_coreController->m_sitesUiController->toggleSplitTunneling(true); - QVERIFY(isSplitTunnelingChangedSpy.count() == 1, "isSplitTunnelingChangedSpy signal should be emitted"); - QVERIFY(m_coreController->m_sitesUiController->isTunnelingEnabled() == true, "SiteSplitTunneling should be enabled"); + QVERIFY2(isSplitTunnelingChangedSpy.count() == 1, "isSplitTunnelingChangedSpy signal should be emitted"); + QVERIFY2(m_coreController->m_sitesUiController->isTunnelingEnabled() == true, "SiteSplitTunneling should be enabled"); m_coreController->m_sitesUiController->toggleSplitTunneling(false); - QVERIFY(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); - QVERIFY(m_coreController->m_sitesUiController->isTunnelingEnabled() == false, "SiteSplitTunneling should be disabled"); + QVERIFY2(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); + QVERIFY2(m_coreController->m_sitesUiController->isTunnelingEnabled() == false, "SiteSplitTunneling should be disabled"); QString site = "2ip.io"; m_coreController->m_sitesUiController->addSite(site); m_coreController->m_sitesUiController->addSite("whatismyipaddress.com"); m_coreController->m_sitesUiController->updateModel(); - QVERIFY(finishedSpy.count() == 2, "finished signal should be emitted 2 times"); - QVERIFY(m_coreController->m_sitesModel->rowCount() == 2, "SitesModel should have 2 rows"); + QVERIFY2(finishedSpy.count() == 2, "finished signal should be emitted 2 times"); + QVERIFY2(m_coreController->m_sitesModel->rowCount() == 2, "SitesModel should have 2 rows"); QModelIndex siteModelIndex = m_coreController->m_sitesModel->index(0, 0); QVERIFY2(siteModelIndex.isValid(), "Site model index should be valid"); @@ -103,26 +103,26 @@ private slots: QCOMPARE(siteUrl, normalizeHostname(site)); auto siteIp = m_coreController->m_sitesModel->data(siteModelIndex, SitesModel::IpRole); - QVERIFY(siteIp.isNull() == false, "site ip should not be empty"); + QVERIFY2(siteIp.isNull() == false, "site ip should not be empty"); m_coreController->m_sitesUiController->removeSite(0); m_coreController->m_sitesUiController->updateModel(); - QVERIFY(finishedSpy.count() == 3, "finished signal should be emitted"); - QVERIFY(m_coreController->m_sitesModel->rowCount() == 1, "SitesModel should have 1 row"); + QVERIFY2(finishedSpy.count() == 3, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_sitesModel->rowCount() == 1, "SitesModel should have 1 row"); m_coreController->m_sitesUiController->importSites(getPath(), true); m_coreController->m_sitesUiController->updateModel(); - QVERIFY(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); - QVERIFY(finishedSpy.count() == 4, "finished signal should be emitted"); - QVERIFY(m_coreController->m_sitesModel->rowCount() > 1, "SitesModel should have more than 1 row"); + QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY2(finishedSpy.count() == 4, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_sitesModel->rowCount() > 1, "SitesModel should have more than 1 row"); m_coreController->m_sitesUiController->exportSites(getExportPath() + "test_sites_export.json"); - QVERIFY(finishedSpy.count() == 5, "finished signal should be emitted"); + QVERIFY2(finishedSpy.count() == 5, "finished signal should be emitted"); m_coreController->m_sitesUiController->removeSites(); m_coreController->m_sitesUiController->updateModel(); - QVERIFY(finishedSpy.count() == 6, "finished signal should be emitted"); - QVERIFY(m_coreController->m_sitesModel->rowCount() == 0, "SitesModel should have 0 rows"); + QVERIFY2(finishedSpy.count() == 6, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_sitesModel->rowCount() == 0, "SitesModel should have 0 rows"); } }; From 473a968d75a93cfcb99a9e6dd6c7364392c48f3a Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 27 Apr 2026 15:13:20 +0300 Subject: [PATCH 43/53] update: some qverify2 messages --- client/tests/testUiAllowedDnsModelAndController.cpp | 3 ++- client/tests/testUiAppSTModelAndController.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/tests/testUiAllowedDnsModelAndController.cpp b/client/tests/testUiAllowedDnsModelAndController.cpp index 46aee886b..18144a96a 100644 --- a/client/tests/testUiAllowedDnsModelAndController.cpp +++ b/client/tests/testUiAllowedDnsModelAndController.cpp @@ -81,7 +81,8 @@ private slots: QVERIFY2(allowedDnsModelIndex.isValid(), "Site model index should be valid"); auto dnsIp = m_coreController->m_allowedDnsModel->data(allowedDnsModelIndex, AllowedDnsModel::IpRole); - QVERIFY2(dnsIp == ip, QString("app path should be %1, got %2").arg(ip, appPath)); + QString msg = QString("dns ip should be %1, got %2").arg(ip, dnsIp.toString()); + QVERIFY2(dnsIp == ip, msg.toLocal8Bit().constData()); m_coreController->m_allowedDnsUiController->importDns(getPath(), true); m_coreController->m_allowedDnsUiController->updateModel(); diff --git a/client/tests/testUiAppSTModelAndController.cpp b/client/tests/testUiAppSTModelAndController.cpp index b36926274..f9966a28d 100644 --- a/client/tests/testUiAppSTModelAndController.cpp +++ b/client/tests/testUiAppSTModelAndController.cpp @@ -83,7 +83,8 @@ private slots: QVERIFY2(appSTModelIndex.isValid(), "Site model index should be valid"); auto appPath = m_coreController->m_appSplitTunnelingModel->data(appSTModelIndex, AppSplitTunnelingModel::AppPathRole); - QVERIFY2(app.contains(appPath.toString()) == true, QString("app path should be %1, got %2").arg(app, appPath)); + QString msg = QString("app path should be %1, got %2").arg(app, appPath.toString()); + QVERIFY2(app.contains(appPath.toString()) == true, msg.toLocal8Bit().constData()); auto pkgAppName = m_coreController->m_appSplitTunnelingModel->data(appSTModelIndex, AppSplitTunnelingModel::PackageAppNameRole); QVERIFY2(pkgAppName == true, "app name should be set"); From 37b8c03e3364f14438cdb65c435dc272b4395bda Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Mon, 27 Apr 2026 16:12:32 +0300 Subject: [PATCH 44/53] update: linux additional dependencies --- .github/workflows/deploy.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9206fe983..24e1067d1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -768,8 +768,21 @@ jobs: sudo apt-get install -y \ cmake \ ninja-build \ + libsecret-1-dev \ + libxcb-cursor0 \ libxkbcommon-x11-0 \ - libsecret-1-dev + libxcb-xinerama0 \ + libxcb-icccm4 \ + libxcb-image0 \ + libxcb-keysyms1 \ + libxcb-randr0 \ + libxcb-render-util0 \ + libxcb-xfixes0 \ + libxcb-shape0 \ + libxcb-sync1 \ + libxcb-xkb1 \ + libgl1 \ + libglib2.0-0 - name: 'Configure' run: | From a1b7a98ae165af2f55c2c89887cdb7e397644b05 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 28 Apr 2026 11:11:38 +0300 Subject: [PATCH 45/53] update: offscreen for linux tests --- .github/workflows/deploy.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 24e1067d1..2fe16fb75 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -795,11 +795,13 @@ jobs: - name: 'Run tests' run: | + QT_ROOT=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64 + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:\ - ${{ env.Qt6_DIR }}/../../../lib:\ + $QT_ROOT/lib:\ $PWD/client/3rd-prebuilt/deploy-prebuilt/linux/x64 - ldd build/client/tests/testSettingsSignals || true + export QT_QPA_PLATFORM=offscreen ctest --test-dir build/client --output-on-failure From b6407e049e672279192c48d53f07e2a5eb551329 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 28 Apr 2026 13:17:01 +0300 Subject: [PATCH 46/53] update: MacOS tests job --- .github/workflows/deploy.yml | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2fe16fb75..7793c90f7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -863,3 +863,60 @@ jobs: set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x64 set PATH=%PATH%;%Qt6_DIR%\..\..\..\bin ctest --test-dir build\client --output-on-failure + +# ------------------------------------------------------ + + Test-MacOS: + runs-on: macos-latest + + env: + QT_VERSION: 6.10.1 + + steps: + - name: 'Setup xcode' + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '16.2.0' + + - name: 'Get sources' + uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 10 + + - name: 'Install Qt' + uses: jurplel/install-qt-action@v4 + with: + version: ${{ env.QT_VERSION }} + host: 'mac' + target: 'desktop' + arch: 'clang_64' + modules: 'qtremoteobjects qt5compat qtshadertools' + dir: ${{ runner.temp }} + set-env: 'true' + + - name: 'Install dependencies' + run: | + brew update + brew install cmake ninja + + - name: 'Configure' + run: | + cmake -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_TESTING=ON + + - name: 'Build' + run: cmake --build build + + - name: 'Run tests' + run: | + QT_ROOT=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos + + export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:\ + $QT_ROOT/lib:\ + $PWD/client/3rd-prebuilt/deploy-prebuilt/macos + + export QT_QPA_PLATFORM=offscreen + + ctest --test-dir build/client --output-on-failure From 8fc9fb87fbe6fbbea4f06bf212984f511b233531 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 28 Apr 2026 13:23:04 +0300 Subject: [PATCH 47/53] update: Android tests job --- .github/workflows/deploy.yml | 84 ++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7793c90f7..fda0cbfb4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -920,3 +920,87 @@ jobs: export QT_QPA_PLATFORM=offscreen ctest --test-dir build/client --output-on-failure + +# ------------------------------------------------------ + + Test-Android: + runs-on: ubuntu-latest + + env: + QT_VERSION: 6.10.1 + QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools' + + steps: + - name: 'Get sources' + uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 10 + + - name: 'Install Qt (host)' + uses: jurplel/install-qt-action@v4 + with: + version: ${{ env.QT_VERSION }} + host: 'linux' + target: 'desktop' + arch: 'linux_gcc_64' + modules: ${{ env.QT_MODULES }} + dir: ${{ runner.temp }} + set-env: 'true' + + - name: 'Install Qt (android arm64)' + uses: jurplel/install-qt-action@v4 + with: + version: ${{ env.QT_VERSION }} + host: 'linux' + target: 'android' + arch: 'android_arm64_v8a' + modules: ${{ env.QT_MODULES }} + dir: ${{ runner.temp }} + set-env: 'true' + + - name: 'Setup Java' + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + + - name: 'Setup Android NDK' + id: setup-ndk + uses: nttld/setup-ndk@v1 + with: + ndk-version: 'r26b' + + - name: 'Configure Android build' + run: | + QT_ANDROID=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/android_arm64_v8a + QT_HOST=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64 + + cmake -B build-android -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE=$QT_ANDROID/lib/cmake/Qt6/qt.toolchain.cmake \ + -DQT_HOST_PATH=$QT_HOST + + - name: 'Build Android' + run: cmake --build build-android + + - name: 'Configure tests (host)' + run: | + cmake -B build-host -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_TESTING=ON + + - name: 'Build tests' + run: cmake --build build-host + + - name: 'Run tests' + run: | + QT_ROOT=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64 + + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:\ + $QT_ROOT/lib:\ + $PWD/client/3rd-prebuilt/deploy-prebuilt/linux/x64 + + export QT_QPA_PLATFORM=offscreen + + ctest --test-dir build-host/client --output-on-failure From 1238920b60e9dc24b82a6105d25e2b2526ec9b07 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 28 Apr 2026 16:46:58 +0300 Subject: [PATCH 48/53] update: rewrited env's, qtest include and clear clients in some tests --- .github/workflows/deploy.yml | 113 +++++------------- client/tests/testAdminSelfHostedExport.cpp | 7 +- client/tests/testComplexOperations.cpp | 7 +- client/tests/testDefaultServerChange.cpp | 7 +- client/tests/testGatewayStacks.cpp | 7 +- client/tests/testMultipleExports.cpp | 14 +-- client/tests/testMultipleImports.cpp | 7 +- client/tests/testSelfHostedServerSetup.cpp | 7 +- client/tests/testSerialization.cpp | 17 ++- client/tests/testServerEdgeCases.cpp | 7 +- client/tests/testServerEdit.cpp | 7 +- client/tests/testServersModelSync.cpp | 7 +- client/tests/testSettingsSignals.cpp | 7 +- client/tests/testSignalOrder.cpp | 7 +- .../testUiAllowedDnsModelAndController.cpp | 13 +- .../tests/testUiAppSTModelAndController.cpp | 10 +- .../testUiLanguageModelAndController.cpp | 7 +- .../tests/testUiServersModelAndController.cpp | 7 +- .../tests/testUiSitesModelAndController.cpp | 13 +- 19 files changed, 64 insertions(+), 207 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index fda0cbfb4..dd58c8e09 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -743,6 +743,16 @@ jobs: env: QT_VERSION: 6.10.1 + TEST_SELF_HOSTED_CONFIG: ${{ secrets.TEST_SELF_HOSTED_CONFIG }} + TEST_APP_PATH: ${{ secrets.TEST_APP_PATH }} + TEST_SITES_LIST_PATH: ${{ secrets.TEST_SITES_LIST_PATH }} + TEST_DNS_LIST_PATH: ${{ secrets.TEST_DNS_LIST_PATH }} + TEST_EXPORT_PATH: ${{ secrets.TEST_EXPORT_PATH }} + TEST_KEY_VMESS_NEW: ${{ secrets.TEST_KEY_VMESS_NEW }} + TEST_KEY_VMESS: ${{ secrets.TEST_KEY_VMESS }} + TEST_KEY_TROJAN: ${{ secrets.TEST_KEY_TROJAN }} + TEST_KEY_SS: ${{ secrets.TEST_KEY_SS }} + TEST_KEY_SSD: ${{ secrets.TEST_KEY_SSD }} steps: - name: 'Get sources' @@ -812,6 +822,16 @@ jobs: env: QT_VERSION: 6.10.1 + TEST_SELF_HOSTED_CONFIG: ${{ secrets.TEST_SELF_HOSTED_CONFIG }} + TEST_APP_PATH: ${{ secrets.TEST_APP_PATH }} + TEST_SITES_LIST_PATH: ${{ secrets.TEST_SITES_LIST_PATH }} + TEST_DNS_LIST_PATH: ${{ secrets.TEST_DNS_LIST_PATH }} + TEST_EXPORT_PATH: ${{ secrets.TEST_EXPORT_PATH }} + TEST_KEY_VMESS_NEW: ${{ secrets.TEST_KEY_VMESS_NEW }} + TEST_KEY_VMESS: ${{ secrets.TEST_KEY_VMESS }} + TEST_KEY_TROJAN: ${{ secrets.TEST_KEY_TROJAN }} + TEST_KEY_SS: ${{ secrets.TEST_KEY_SS }} + TEST_KEY_SSD: ${{ secrets.TEST_KEY_SSD }} steps: - name: 'Get sources' @@ -871,6 +891,16 @@ jobs: env: QT_VERSION: 6.10.1 + TEST_SELF_HOSTED_CONFIG: ${{ secrets.TEST_SELF_HOSTED_CONFIG }} + TEST_APP_PATH: ${{ secrets.TEST_APP_PATH }} + TEST_SITES_LIST_PATH: ${{ secrets.TEST_SITES_LIST_PATH }} + TEST_DNS_LIST_PATH: ${{ secrets.TEST_DNS_LIST_PATH }} + TEST_EXPORT_PATH: ${{ secrets.TEST_EXPORT_PATH }} + TEST_KEY_VMESS_NEW: ${{ secrets.TEST_KEY_VMESS_NEW }} + TEST_KEY_VMESS: ${{ secrets.TEST_KEY_VMESS }} + TEST_KEY_TROJAN: ${{ secrets.TEST_KEY_TROJAN }} + TEST_KEY_SS: ${{ secrets.TEST_KEY_SS }} + TEST_KEY_SSD: ${{ secrets.TEST_KEY_SSD }} steps: - name: 'Setup xcode' @@ -921,86 +951,3 @@ jobs: ctest --test-dir build/client --output-on-failure -# ------------------------------------------------------ - - Test-Android: - runs-on: ubuntu-latest - - env: - QT_VERSION: 6.10.1 - QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools' - - steps: - - name: 'Get sources' - uses: actions/checkout@v4 - with: - submodules: 'true' - fetch-depth: 10 - - - name: 'Install Qt (host)' - uses: jurplel/install-qt-action@v4 - with: - version: ${{ env.QT_VERSION }} - host: 'linux' - target: 'desktop' - arch: 'linux_gcc_64' - modules: ${{ env.QT_MODULES }} - dir: ${{ runner.temp }} - set-env: 'true' - - - name: 'Install Qt (android arm64)' - uses: jurplel/install-qt-action@v4 - with: - version: ${{ env.QT_VERSION }} - host: 'linux' - target: 'android' - arch: 'android_arm64_v8a' - modules: ${{ env.QT_MODULES }} - dir: ${{ runner.temp }} - set-env: 'true' - - - name: 'Setup Java' - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '17' - - - name: 'Setup Android NDK' - id: setup-ndk - uses: nttld/setup-ndk@v1 - with: - ndk-version: 'r26b' - - - name: 'Configure Android build' - run: | - QT_ANDROID=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/android_arm64_v8a - QT_HOST=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64 - - cmake -B build-android -G Ninja \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_TOOLCHAIN_FILE=$QT_ANDROID/lib/cmake/Qt6/qt.toolchain.cmake \ - -DQT_HOST_PATH=$QT_HOST - - - name: 'Build Android' - run: cmake --build build-android - - - name: 'Configure tests (host)' - run: | - cmake -B build-host -G Ninja \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTING=ON - - - name: 'Build tests' - run: cmake --build build-host - - - name: 'Run tests' - run: | - QT_ROOT=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64 - - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:\ - $QT_ROOT/lib:\ - $PWD/client/3rd-prebuilt/deploy-prebuilt/linux/x64 - - export QT_QPA_PLATFORM=offscreen - - ctest --test-dir build-host/client --output-on-failure diff --git a/client/tests/testAdminSelfHostedExport.cpp b/client/tests/testAdminSelfHostedExport.cpp index 439a93b27..4c6d326d0 100644 --- a/client/tests/testAdminSelfHostedExport.cpp +++ b/client/tests/testAdminSelfHostedExport.cpp @@ -5,12 +5,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testComplexOperations.cpp b/client/tests/testComplexOperations.cpp index 931f6a51b..52103262c 100644 --- a/client/tests/testComplexOperations.cpp +++ b/client/tests/testComplexOperations.cpp @@ -2,12 +2,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testDefaultServerChange.cpp b/client/tests/testDefaultServerChange.cpp index 675a8fa1e..e5288da42 100644 --- a/client/tests/testDefaultServerChange.cpp +++ b/client/tests/testDefaultServerChange.cpp @@ -2,12 +2,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testGatewayStacks.cpp b/client/tests/testGatewayStacks.cpp index 2271f07f1..f51d99a07 100644 --- a/client/tests/testGatewayStacks.cpp +++ b/client/tests/testGatewayStacks.cpp @@ -2,12 +2,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testMultipleExports.cpp b/client/tests/testMultipleExports.cpp index c88af391e..2b31d1b7d 100644 --- a/client/tests/testMultipleExports.cpp +++ b/client/tests/testMultipleExports.cpp @@ -4,12 +4,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" @@ -28,8 +23,7 @@ private: QString getSHAdminConfig() { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_SELF_HOSTED_CONFIG"); + return QProcessEnvironment::systemEnvironment().value("TEST_SELF_HOSTED_CONFIG"); } private slots: @@ -53,6 +47,10 @@ private slots: void cleanupTestCase() { int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + + for (int containerIndex = 1; containerIndex < 7; ++containerIndex) + m_coreController->m_installUiController->clearCachedProfile(serverIndex, containerIndex); + m_coreController->m_serversController->removeServer(serverIndex); qDebug() << "SERVER REMOVED\n"; diff --git a/client/tests/testMultipleImports.cpp b/client/tests/testMultipleImports.cpp index e4ad96d3c..a39235b58 100644 --- a/client/tests/testMultipleImports.cpp +++ b/client/tests/testMultipleImports.cpp @@ -3,12 +3,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testSelfHostedServerSetup.cpp b/client/tests/testSelfHostedServerSetup.cpp index 184b40e32..842d76683 100644 --- a/client/tests/testSelfHostedServerSetup.cpp +++ b/client/tests/testSelfHostedServerSetup.cpp @@ -4,12 +4,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testSerialization.cpp b/client/tests/testSerialization.cpp index 86717f3b9..f38d583ce 100644 --- a/client/tests/testSerialization.cpp +++ b/client/tests/testSerialization.cpp @@ -4,12 +4,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" @@ -30,14 +25,12 @@ private: QString getSHAdminConfig() { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_SELF_HOSTED_CONFIG"); + return QProcessEnvironment::systemEnvironment().value("TEST_SELF_HOSTED_CONFIG"); } QString getKey(QString name) { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_KEY_" + name); + return QProcessEnvironment::systemEnvironment().value("TEST_KEY_" + name); } QJsonObject extractXrayConfig(const QString &data, ConfigTypes configType, const QString &description = "") const @@ -106,6 +99,10 @@ private slots: void cleanupTestCase() { int serverIndex = m_coreController->m_serversRepository->defaultServerIndex(); + + for (int containerIndex = 1; containerIndex < 7; ++containerIndex) + m_coreController->m_installUiController->clearCachedProfile(serverIndex, containerIndex); + m_coreController->m_serversController->removeServer(serverIndex); qDebug() << "SERVER REMOVED\n"; diff --git a/client/tests/testServerEdgeCases.cpp b/client/tests/testServerEdgeCases.cpp index 82e0b6ee6..68b2ec9e7 100644 --- a/client/tests/testServerEdgeCases.cpp +++ b/client/tests/testServerEdgeCases.cpp @@ -2,12 +2,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testServerEdit.cpp b/client/tests/testServerEdit.cpp index 45009dc1c..a66f69608 100644 --- a/client/tests/testServerEdit.cpp +++ b/client/tests/testServerEdit.cpp @@ -2,12 +2,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testServersModelSync.cpp b/client/tests/testServersModelSync.cpp index 773d720b9..5c15e4f05 100644 --- a/client/tests/testServersModelSync.cpp +++ b/client/tests/testServersModelSync.cpp @@ -2,12 +2,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testSettingsSignals.cpp b/client/tests/testSettingsSignals.cpp index eef42b54c..540b6ddc8 100644 --- a/client/tests/testSettingsSignals.cpp +++ b/client/tests/testSettingsSignals.cpp @@ -3,12 +3,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testSignalOrder.cpp b/client/tests/testSignalOrder.cpp index 61304dd19..ea8e38559 100644 --- a/client/tests/testSignalOrder.cpp +++ b/client/tests/testSignalOrder.cpp @@ -2,12 +2,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testUiAllowedDnsModelAndController.cpp b/client/tests/testUiAllowedDnsModelAndController.cpp index 18144a96a..73577e795 100644 --- a/client/tests/testUiAllowedDnsModelAndController.cpp +++ b/client/tests/testUiAllowedDnsModelAndController.cpp @@ -4,12 +4,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" @@ -28,14 +23,12 @@ private: QString getPath() { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_PATH"); + return QProcessEnvironment::systemEnvironment().value("TEST_DNS_LIST_PATH"); } QString getExportPath() { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_EXPORT_PATH"); + return QProcessEnvironment::systemEnvironment().value("TEST_EXPORT_PATH"); } private slots: diff --git a/client/tests/testUiAppSTModelAndController.cpp b/client/tests/testUiAppSTModelAndController.cpp index f9966a28d..a597269ca 100644 --- a/client/tests/testUiAppSTModelAndController.cpp +++ b/client/tests/testUiAppSTModelAndController.cpp @@ -4,12 +4,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" @@ -28,8 +23,7 @@ private: QString getPath() { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_PATH"); + return QProcessEnvironment::systemEnvironment().value("TEST_APP_PATH"); } private slots: diff --git a/client/tests/testUiLanguageModelAndController.cpp b/client/tests/testUiLanguageModelAndController.cpp index 539d7a333..fad16b351 100644 --- a/client/tests/testUiLanguageModelAndController.cpp +++ b/client/tests/testUiLanguageModelAndController.cpp @@ -4,12 +4,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testUiServersModelAndController.cpp b/client/tests/testUiServersModelAndController.cpp index 9cb500e93..93acda6a3 100644 --- a/client/tests/testUiServersModelAndController.cpp +++ b/client/tests/testUiServersModelAndController.cpp @@ -5,12 +5,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" diff --git a/client/tests/testUiSitesModelAndController.cpp b/client/tests/testUiSitesModelAndController.cpp index bc308140a..18ba72cba 100644 --- a/client/tests/testUiSitesModelAndController.cpp +++ b/client/tests/testUiSitesModelAndController.cpp @@ -4,12 +4,7 @@ #include #include #include - -#ifdef Q_OS_WIN - #include -#else - #include -#endif +#include #include "core/controllers/coreController.h" #include "core/models/serverConfig.h" @@ -28,14 +23,12 @@ private: QString getPath() { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_PATH"); + return QProcessEnvironment::systemEnvironment().value("TEST_SITES_LIST_PATH"); } QString getExportPath() { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - return env.value("TEST_EXPORT_PATH"); + return QProcessEnvironment::systemEnvironment().value("TEST_EXPORT_PATH"); } QString normalizeHostname(const QString &hostname) const From 132c836777ca33354673e9541c9d328bcd7793d0 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 29 Apr 2026 17:16:32 +0300 Subject: [PATCH 49/53] update: added local vars file for tests --- .github/workflows/deploy.yml | 30 ------------------- client/tests/testAdminSelfHostedExport.cpp | 8 ++++- client/tests/testComplexOperations.cpp | 12 ++++++-- client/tests/testDefaultServerChange.cpp | 18 +++++++---- client/tests/testGatewayStacks.cpp | 8 ++++- client/tests/testMultipleExports.cpp | 7 +++-- client/tests/testMultipleImports.cpp | 16 ++++++---- client/tests/testSelfHostedServerSetup.cpp | 14 ++++++--- client/tests/testSerialization.cpp | 22 ++++++-------- client/tests/testServerEdgeCases.cpp | 8 ++++- client/tests/testServerEdit.cpp | 12 ++++++-- client/tests/testServersModelSync.cpp | 14 ++++++--- .../testUiAllowedDnsModelAndController.cpp | 14 ++++----- .../tests/testUiAppSTModelAndController.cpp | 7 +++-- .../tests/testUiSitesModelAndController.cpp | 14 ++++----- client/tests/test_vars.ini | 23 ++++++++++++++ 16 files changed, 132 insertions(+), 95 deletions(-) create mode 100644 client/tests/test_vars.ini diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index dd58c8e09..8db3169a0 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -743,16 +743,6 @@ jobs: env: QT_VERSION: 6.10.1 - TEST_SELF_HOSTED_CONFIG: ${{ secrets.TEST_SELF_HOSTED_CONFIG }} - TEST_APP_PATH: ${{ secrets.TEST_APP_PATH }} - TEST_SITES_LIST_PATH: ${{ secrets.TEST_SITES_LIST_PATH }} - TEST_DNS_LIST_PATH: ${{ secrets.TEST_DNS_LIST_PATH }} - TEST_EXPORT_PATH: ${{ secrets.TEST_EXPORT_PATH }} - TEST_KEY_VMESS_NEW: ${{ secrets.TEST_KEY_VMESS_NEW }} - TEST_KEY_VMESS: ${{ secrets.TEST_KEY_VMESS }} - TEST_KEY_TROJAN: ${{ secrets.TEST_KEY_TROJAN }} - TEST_KEY_SS: ${{ secrets.TEST_KEY_SS }} - TEST_KEY_SSD: ${{ secrets.TEST_KEY_SSD }} steps: - name: 'Get sources' @@ -822,16 +812,6 @@ jobs: env: QT_VERSION: 6.10.1 - TEST_SELF_HOSTED_CONFIG: ${{ secrets.TEST_SELF_HOSTED_CONFIG }} - TEST_APP_PATH: ${{ secrets.TEST_APP_PATH }} - TEST_SITES_LIST_PATH: ${{ secrets.TEST_SITES_LIST_PATH }} - TEST_DNS_LIST_PATH: ${{ secrets.TEST_DNS_LIST_PATH }} - TEST_EXPORT_PATH: ${{ secrets.TEST_EXPORT_PATH }} - TEST_KEY_VMESS_NEW: ${{ secrets.TEST_KEY_VMESS_NEW }} - TEST_KEY_VMESS: ${{ secrets.TEST_KEY_VMESS }} - TEST_KEY_TROJAN: ${{ secrets.TEST_KEY_TROJAN }} - TEST_KEY_SS: ${{ secrets.TEST_KEY_SS }} - TEST_KEY_SSD: ${{ secrets.TEST_KEY_SSD }} steps: - name: 'Get sources' @@ -891,16 +871,6 @@ jobs: env: QT_VERSION: 6.10.1 - TEST_SELF_HOSTED_CONFIG: ${{ secrets.TEST_SELF_HOSTED_CONFIG }} - TEST_APP_PATH: ${{ secrets.TEST_APP_PATH }} - TEST_SITES_LIST_PATH: ${{ secrets.TEST_SITES_LIST_PATH }} - TEST_DNS_LIST_PATH: ${{ secrets.TEST_DNS_LIST_PATH }} - TEST_EXPORT_PATH: ${{ secrets.TEST_EXPORT_PATH }} - TEST_KEY_VMESS_NEW: ${{ secrets.TEST_KEY_VMESS_NEW }} - TEST_KEY_VMESS: ${{ secrets.TEST_KEY_VMESS }} - TEST_KEY_TROJAN: ${{ secrets.TEST_KEY_TROJAN }} - TEST_KEY_SS: ${{ secrets.TEST_KEY_SS }} - TEST_KEY_SSD: ${{ secrets.TEST_KEY_SSD }} steps: - name: 'Setup xcode' diff --git a/client/tests/testAdminSelfHostedExport.cpp b/client/tests/testAdminSelfHostedExport.cpp index 4c6d326d0..591aef598 100644 --- a/client/tests/testAdminSelfHostedExport.cpp +++ b/client/tests/testAdminSelfHostedExport.cpp @@ -20,6 +20,12 @@ private: CoreController* m_coreController; SecureQSettings* m_settings; + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + QJsonObject decodeVpnKey(const QString &vpnKey) { QString key = vpnKey; key.replace("vpn://", ""); @@ -97,7 +103,7 @@ private slots: } void testAdminSelfHostedExport() { - QString vpnKey = "vpn://AAABTXjarZIxT8MwEIX_Cro5jbDjQunKUhhYyoZQZZKjRGpsy3baQtT_zp2bJh3oACLLPfvz3bOe00FpTdS1QR9g_tKB3q1h3sFCwBzEdf9N5ElBBgtJqBiQOkcFoemAbs6RInQ7oNkZemAvrrKvRV9VX6fH-lhSVSwavU9GSdcmXZX0UqSbseJRMqlioDxuSsJZH1mKWTrhvI22tJvVljKoLU-TtB3aN4NxpavKYwhpSD7LRc4t0WsTeMwqNRNsKweHbAyTtnRj8KvWE0pUEut-hNah2TpDM0-Kwu8vKMSd-ttFLrntao_rVvuKWkc9OnIk4n8t915_Ulcqo5FSxa9tYsk2rxlU-K7bTby_lDWfCKWvXTy-5jOGeLVET-9L7MOG-KQbJEBx57jXjdtgXtqG_wUdws5yJhCpa1iefhopM2gD-n4An-ElHL4BvzD6nw"; + QString vpnKey = getValueFromIni("configs/TEST_CONFIG_ANY"); QSignalSpy importFinishedSpy(m_coreController->m_importCoreController, &ImportController::importFinished); QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged); diff --git a/client/tests/testComplexOperations.cpp b/client/tests/testComplexOperations.cpp index 52103262c..6d12399f7 100644 --- a/client/tests/testComplexOperations.cpp +++ b/client/tests/testComplexOperations.cpp @@ -19,6 +19,12 @@ private: CoreController* m_coreController; SecureQSettings* m_settings; + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + private slots: void initTestCase() { QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); @@ -42,9 +48,9 @@ private slots: } void testComplexOperationSequence() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; - QString xrayKey = "vpn://AAAAtXjadY7NCsJADIRfRXKui1YP0qt3L14EkRK7EQt2d0lS_0rf3awonjyFmW-YyQBNDIptIBao9sNPQgXYBXq2OL0zPqCA96kGSJHV6HK5MFP6YyCt0XsmsQqYz9zKzd3MmDIGyek6cdRoUJsE43gowNMJ-4uu_695kobbpG0MBndmTrbEV4sWcI6iG-zIQE47umOXLuSa2BlNKHKL7PMeiX5lmdH79bIsoBfiT0UOZQnjCw_AXRQ"; - QString wgKey = "vpn://AAAAwXjahY89a8NADIb_StDsHLFDIHjt0C1LhgwlBNWnpgfx3SHp6hDj_15dacnYTS_Po68ZhhQVQyQW6N_mZ4QecIz0CLieAtO1IHto4Fn3M-TEat6u3XetMSnvkfSC3jOJjYN24_audRtjyhil-pfMSZPB4jMsy7kBTx9Ybvryz2ZPMnDIGlI042TktZLVkfjLmhr4TKIHHMnodHV0xzHfyA1pNJZRZEr1alAS_Yvbin6e6LoGihD_DqhSjbB8AyB_ZI8"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); + QString xrayKey = getValueFromIni("configs/TEST_CONFIG_WG"); + QString wgKey = getValueFromIni("configs/TEST_CONFIG_XRAY"); QSignalSpy importFinishedSpy(m_coreController->m_importCoreController, &ImportController::importFinished); QSignalSpy serverAddedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverAdded); diff --git a/client/tests/testDefaultServerChange.cpp b/client/tests/testDefaultServerChange.cpp index e5288da42..fdd912c45 100644 --- a/client/tests/testDefaultServerChange.cpp +++ b/client/tests/testDefaultServerChange.cpp @@ -20,6 +20,12 @@ private: CoreController* m_coreController; SecureQSettings* m_settings; + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + private slots: void initTestCase() { QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); @@ -44,9 +50,9 @@ private slots: } void testSetDefaultServerIndex() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; - QString xrayKey = "vpn://AAAAtXjadY7NCsJADIRfRXKui1YP0qt3L14EkRK7EQt2d0lS_0rf3awonjyFmW-YyQBNDIptIBao9sNPQgXYBXq2OL0zPqCA96kGSJHV6HK5MFP6YyCt0XsmsQqYz9zKzd3MmDIGyek6cdRoUJsE43gowNMJ-4uu_695kobbpG0MBndmTrbEV4sWcI6iG-zIQE47umOXLuSa2BlNKHKL7PMeiX5lmdH79bIsoBfiT0UOZQnjCw_AXRQ"; - QString wgKey = "vpn://AAAAwXjahY89a8NADIb_StDsHLFDIHjt0C1LhgwlBNWnpgfx3SHp6hDj_15dacnYTS_Po68ZhhQVQyQW6N_mZ4QecIz0CLieAtO1IHto4Fn3M-TEat6u3XetMSnvkfSC3jOJjYN24_audRtjyhil-pfMSZPB4jMsy7kBTx9Ybvryz2ZPMnDIGlI042TktZLVkfjLmhr4TKIHHMnodHV0xzHfyA1pNJZRZEr1alAS_Yvbin6e6LoGihD_DqhSjbB8AyB_ZI8"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); + QString xrayKey = getValueFromIni("configs/TEST_CONFIG_WG"); + QString wgKey = getValueFromIni("configs/TEST_CONFIG_XRAY"); auto importResult1 = m_coreController->m_importCoreController->extractConfigFromData(awgKey); m_coreController->m_importCoreController->importConfig(importResult1.config); @@ -77,9 +83,9 @@ private slots: } void testDefaultServerChangeOnRemoveEdgeCases() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; - QString xrayKey = "vpn://AAAAtXjadY7NCsJADIRfRXKui1YP0qt3L14EkRK7EQt2d0lS_0rf3awonjyFmW-YyQBNDIptIBao9sNPQgXYBXq2OL0zPqCA96kGSJHV6HK5MFP6YyCt0XsmsQqYz9zKzd3MmDIGyek6cdRoUJsE43gowNMJ-4uu_695kobbpG0MBndmTrbEV4sWcI6iG-zIQE47umOXLuSa2BlNKHKL7PMeiX5lmdH79bIsoBfiT0UOZQnjCw_AXRQ"; - QString wgKey = "vpn://AAAAwXjahY89a8NADIb_StDsHLFDIHjt0C1LhgwlBNWnpgfx3SHp6hDj_15dacnYTS_Po68ZhhQVQyQW6N_mZ4QecIz0CLieAtO1IHto4Fn3M-TEat6u3XetMSnvkfSC3jOJjYN24_audRtjyhil-pfMSZPB4jMsy7kBTx9Ybvryz2ZPMnDIGlI042TktZLVkfjLmhr4TKIHHMnodHV0xzHfyA1pNJZRZEr1alAS_Yvbin6e6LoGihD_DqhSjbB8AyB_ZI8"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); + QString xrayKey = getValueFromIni("configs/TEST_CONFIG_WG"); + QString wgKey = getValueFromIni("configs/TEST_CONFIG_XRAY"); auto importResult1 = m_coreController->m_importCoreController->extractConfigFromData(awgKey); m_coreController->m_importCoreController->importConfig(importResult1.config); diff --git a/client/tests/testGatewayStacks.cpp b/client/tests/testGatewayStacks.cpp index f51d99a07..abd34a0ba 100644 --- a/client/tests/testGatewayStacks.cpp +++ b/client/tests/testGatewayStacks.cpp @@ -19,6 +19,12 @@ private: CoreController* m_coreController; SecureQSettings* m_settings; + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + private slots: void initTestCase() { QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); @@ -42,7 +48,7 @@ private slots: } void testGatewayStacksRecomputeOnServerOperations() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); QSignalSpy gatewayStacksExpandedSpy(m_coreController->m_serversController, &ServersController::gatewayStacksExpanded); QSignalSpy serverAddedSpy(m_coreController->m_serversRepository, &SecureServersRepository::serverAdded); diff --git a/client/tests/testMultipleExports.cpp b/client/tests/testMultipleExports.cpp index 2b31d1b7d..a32bcee51 100644 --- a/client/tests/testMultipleExports.cpp +++ b/client/tests/testMultipleExports.cpp @@ -21,9 +21,10 @@ private: CoreController *m_coreController; SecureQSettings *m_settings; - QString getSHAdminConfig() + QString getValueFromIni(const QString &key) { - return QProcessEnvironment::systemEnvironment().value("TEST_SELF_HOSTED_CONFIG"); + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); } private slots: @@ -36,7 +37,7 @@ private slots: m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); - QString vpnKey = getSHAdminConfig(); + QString vpnKey = getValueFromIni("configs/TEST_SELF_HOSTED_CONFIG"); QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; m_coreController->m_importCoreController->importConfig(importedConfig); diff --git a/client/tests/testMultipleImports.cpp b/client/tests/testMultipleImports.cpp index a39235b58..bc621cd8f 100644 --- a/client/tests/testMultipleImports.cpp +++ b/client/tests/testMultipleImports.cpp @@ -20,6 +20,12 @@ private: CoreController* m_coreController; SecureQSettings* m_settings; + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + private slots: void initTestCase() { QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); @@ -45,9 +51,9 @@ private slots: } void testMultipleImports() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; - QString xrayKey = "vpn://AAAAtXjadY7NCsJADIRfRXKui1YP0qt3L14EkRK7EQt2d0lS_0rf3awonjyFmW-YyQBNDIptIBao9sNPQgXYBXq2OL0zPqCA96kGSJHV6HK5MFP6YyCt0XsmsQqYz9zKzd3MmDIGyek6cdRoUJsE43gowNMJ-4uu_695kobbpG0MBndmTrbEV4sWcI6iG-zIQE47umOXLuSa2BlNKHKL7PMeiX5lmdH79bIsoBfiT0UOZQnjCw_AXRQ"; - QString wgKey = "vpn://AAAAwXjahY89a8NADIb_StDsHLFDIHjt0C1LhgwlBNWnpgfx3SHp6hDj_15dacnYTS_Po68ZhhQVQyQW6N_mZ4QecIz0CLieAtO1IHto4Fn3M-TEat6u3XetMSnvkfSC3jOJjYN24_audRtjyhil-pfMSZPB4jMsy7kBTx9Ybvryz2ZPMnDIGlI042TktZLVkfjLmhr4TKIHHMnodHV0xzHfyA1pNJZRZEr1alAS_Yvbin6e6LoGihD_DqhSjbB8AyB_ZI8"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); + QString xrayKey = getValueFromIni("configs/TEST_CONFIG_WG"); + QString wgKey = getValueFromIni("configs/TEST_CONFIG_XRAY"); QSignalSpy importFinishedSpy(m_coreController->m_importCoreController, &ImportController::importFinished); QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged); @@ -125,8 +131,8 @@ private slots: } void testMultipleImportsRemoval() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; - QString xrayKey = "vpn://AAAAtXjadY7NCsJADIRfRXKui1YP0qt3L14EkRK7EQt2d0lS_0rf3awonjyFmW-YyQBNDIptIBao9sNPQgXYBXq2OL0zPqCA96kGSJHV6HK5MFP6YyCt0XsmsQqYz9zKzd3MmDIGyek6cdRoUJsE43gowNMJ-4uu_695kobbpG0MBndmTrbEV4sWcI6iG-zIQE47umOXLuSa2BlNKHKL7PMeiX5lmdH79bIsoBfiT0UOZQnjCw_AXRQ"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); + QString xrayKey = getValueFromIni("configs/TEST_CONFIG_XRAY"); QSignalSpy importFinishedSpy(m_coreController->m_importCoreController, &ImportController::importFinished); QSignalSpy defaultServerChangedSpy(m_coreController->m_serversRepository, &SecureServersRepository::defaultServerChanged); diff --git a/client/tests/testSelfHostedServerSetup.cpp b/client/tests/testSelfHostedServerSetup.cpp index 842d76683..60c525deb 100644 --- a/client/tests/testSelfHostedServerSetup.cpp +++ b/client/tests/testSelfHostedServerSetup.cpp @@ -31,13 +31,19 @@ private: CoreController* m_coreController; SecureQSettings* m_settings; + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + ServerCredentials getCredentialsFromEnv() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - QString hostName = env.value("TEST_SERVER_HOST"); - QString userName = env.value("TEST_SERVER_USER"); - QString password = env.value("TEST_SERVER_PASSWORD"); - QString portStr = env.value("TEST_SERVER_PORT", "22"); + QString hostName = getValueFromIni("TEST_SERVER_HOST"); + QString userName = getValueFromIni("TEST_SERVER_USER"); + QString password = getValueFromIni("TEST_SERVER_PASSWORD"); + QString portStr = getValueFromIni("TEST_SERVER_PORT"); int port = portStr.toInt(); ServerCredentials credentials; diff --git a/client/tests/testSerialization.cpp b/client/tests/testSerialization.cpp index f38d583ce..b4e685d40 100644 --- a/client/tests/testSerialization.cpp +++ b/client/tests/testSerialization.cpp @@ -23,14 +23,10 @@ private: CoreController *m_coreController; SecureQSettings *m_settings; - QString getSHAdminConfig() + QString getValueFromIni(const QString &key) { - return QProcessEnvironment::systemEnvironment().value("TEST_SELF_HOSTED_CONFIG"); - } - - QString getKey(QString name) - { - return QProcessEnvironment::systemEnvironment().value("TEST_KEY_" + name); + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); } QJsonObject extractXrayConfig(const QString &data, ConfigTypes configType, const QString &description = "") const @@ -88,7 +84,7 @@ private slots: m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); - QString vpnKey = getSHAdminConfig(); + QString vpnKey = getValueFromIni("configs/TEST_SELF_HOSTED_CONFIG"); QJsonObject importedConfig = m_coreController->m_importCoreController->extractConfigFromData(vpnKey).config; m_coreController->m_importCoreController->importConfig(importedConfig); @@ -154,7 +150,7 @@ private slots: ImportController::ImportResult importResult; - m_coreController->m_importController->extractConfigFromData(getKey("VMESS_NEW")); + m_coreController->m_importController->extractConfigFromData(getValueFromIni("configs/TEST_CONFIG_VMESS_NEW")); QString config = m_coreController->m_importController->getConfig(); QString prefix; @@ -180,7 +176,7 @@ private slots: ImportController::ImportResult importResult; - m_coreController->m_importController->extractConfigFromData(getKey("VMESS")); + m_coreController->m_importController->extractConfigFromData(getValueFromIni("configs/TEST_CONFIG_VMESS")); QString config = m_coreController->m_importController->getConfig(); QString prefix; @@ -206,7 +202,7 @@ private slots: ImportController::ImportResult importResult; - m_coreController->m_importController->extractConfigFromData(getKey("TROJAN")); + m_coreController->m_importController->extractConfigFromData(getValueFromIni("configs/TEST_CONFIG_TROJAN")); QString config = m_coreController->m_importController->getConfig(); QString prefix; @@ -232,7 +228,7 @@ private slots: ImportController::ImportResult importResult; - m_coreController->m_importController->extractConfigFromData(getKey("SS")); + m_coreController->m_importController->extractConfigFromData(getValueFromIni("configs/TEST_CONFIG_SS")); QString config = m_coreController->m_importController->getConfig(); QString prefix; @@ -258,7 +254,7 @@ private slots: ImportController::ImportResult importResult; - m_coreController->m_importController->extractConfigFromData(getKey("SSD")); + m_coreController->m_importController->extractConfigFromData(getValueFromIni("configs/TEST_CONFIG_SSD")); QString config = m_coreController->m_importController->getConfig(); QString prefix; diff --git a/client/tests/testServerEdgeCases.cpp b/client/tests/testServerEdgeCases.cpp index 68b2ec9e7..20bf2ea09 100644 --- a/client/tests/testServerEdgeCases.cpp +++ b/client/tests/testServerEdgeCases.cpp @@ -19,6 +19,12 @@ private: CoreController* m_coreController; SecureQSettings* m_settings; + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + private slots: void initTestCase() { QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); @@ -43,7 +49,7 @@ private slots: } void testInvalidIndexOperations() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); auto importResult = m_coreController->m_importCoreController->extractConfigFromData(awgKey); m_coreController->m_importCoreController->importConfig(importResult.config); diff --git a/client/tests/testServerEdit.cpp b/client/tests/testServerEdit.cpp index a66f69608..d1159b042 100644 --- a/client/tests/testServerEdit.cpp +++ b/client/tests/testServerEdit.cpp @@ -20,6 +20,12 @@ private: CoreController* m_coreController; SecureQSettings* m_settings; + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + private slots: void initTestCase() { QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); @@ -44,7 +50,7 @@ private slots: } void testServerEditTriggersHandlers() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); QSignalSpy importFinishedSpy(m_coreController->m_importCoreController, &ImportController::importFinished); auto importResult = m_coreController->m_importCoreController->extractConfigFromData(awgKey); @@ -75,8 +81,8 @@ private slots: } void testServerEditPreservesDefault() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; - QString xrayKey = "vpn://AAAAtXjadY7NCsJADIRfRXKui1YP0qt3L14EkRK7EQt2d0lS_0rf3awonjyFmW-YyQBNDIptIBao9sNPQgXYBXq2OL0zPqCA96kGSJHV6HK5MFP6YyCt0XsmsQqYz9zKzd3MmDIGyek6cdRoUJsE43gowNMJ-4uu_695kobbpG0MBndmTrbEV4sWcI6iG-zIQE47umOXLuSa2BlNKHKL7PMeiX5lmdH79bIsoBfiT0UOZQnjCw_AXRQ"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); + QString xrayKey = getValueFromIni("configs/TEST_CONFIG_XRAY"); auto importResult1 = m_coreController->m_importCoreController->extractConfigFromData(awgKey); m_coreController->m_importCoreController->importConfig(importResult1.config); diff --git a/client/tests/testServersModelSync.cpp b/client/tests/testServersModelSync.cpp index 5c15e4f05..64b50711a 100644 --- a/client/tests/testServersModelSync.cpp +++ b/client/tests/testServersModelSync.cpp @@ -20,6 +20,12 @@ private: CoreController* m_coreController; SecureQSettings* m_settings; + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + private slots: void initTestCase() { QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); @@ -43,7 +49,7 @@ private slots: } void testServersModelSyncOnOperations() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); if (!m_coreController->m_serversModel) { QSKIP("ServersModel not available"); @@ -72,9 +78,9 @@ private slots: } void testServersModelDefaultIndexSync() { - QString awgKey = "vpn://AAABFHjadZBBT4QwEIX_ipkzS2wBJdyMB1cPXvbgwRgyQnclgZa0RTYS_rszXRa52Mt77TfzOu0EldEeG62sg-J9AhxPUEywF1CAuF3WTl4dRLCXhJIVpVuUEMpWdLdFKaH7FeUb9Mx3scpFk0XTRbOLvlSkKZsOz-Gi4BsdRiV_EGEydhwlg0tWynEZmd5Yz1bkoaK3xpvKtOU3_UFjOE3SsRs-tfIl1rVVzoWQOI9FzC3eonYcU4ZmgkPdwxz9fSYdYafVT4M7-lEJ80cEtTri0PrH_2q4wlW26f1lioe3p5uDsjQWoS_j_Ct2ipvGU6zO2PWtiivT8RPQudHYmqBXzl-3Yn2slBEMTtklgYt4C_Mv3ROMwA"; - QString xrayKey = "vpn://AAAAtXjadY7NCsJADIRfRXKui1YP0qt3L14EkRK7EQt2d0lS_0rf3awonjyFmW-YyQBNDIptIBao9sNPQgXYBXq2OL0zPqCA96kGSJHV6HK5MFP6YyCt0XsmsQqYz9zKzd3MmDIGyek6cdRoUJsE43gowNMJ-4uu_695kobbpG0MBndmTrbEV4sWcI6iG-zIQE47umOXLuSa2BlNKHKL7PMeiX5lmdH79bIsoBfiT0UOZQnjCw_AXRQ"; - QString wgKey = "vpn://AAAAwXjahY89a8NADIb_StDsHLFDIHjt0C1LhgwlBNWnpgfx3SHp6hDj_15dacnYTS_Po68ZhhQVQyQW6N_mZ4QecIz0CLieAtO1IHto4Fn3M-TEat6u3XetMSnvkfSC3jOJjYN24_audRtjyhil-pfMSZPB4jMsy7kBTx9Ybvryz2ZPMnDIGlI042TktZLVkfjLmhr4TKIHHMnodHV0xzHfyA1pNJZRZEr1alAS_Yvbin6e6LoGihD_DqhSjbB8AyB_ZI8"; + QString awgKey = getValueFromIni("configs/TEST_CONFIG_AWG"); + QString xrayKey = getValueFromIni("configs/TEST_CONFIG_WG"); + QString wgKey = getValueFromIni("configs/TEST_CONFIG_XRAY"); if (!m_coreController->m_serversModel) { QSKIP("ServersModel not available"); diff --git a/client/tests/testUiAllowedDnsModelAndController.cpp b/client/tests/testUiAllowedDnsModelAndController.cpp index 73577e795..4bbaecc7c 100644 --- a/client/tests/testUiAllowedDnsModelAndController.cpp +++ b/client/tests/testUiAllowedDnsModelAndController.cpp @@ -21,14 +21,10 @@ private: CoreController *m_coreController; SecureQSettings *m_settings; - QString getPath() + QString getValueFromIni(const QString &key) { - return QProcessEnvironment::systemEnvironment().value("TEST_DNS_LIST_PATH"); - } - - QString getExportPath() - { - return QProcessEnvironment::systemEnvironment().value("TEST_EXPORT_PATH"); + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); } private slots: @@ -77,13 +73,13 @@ private slots: QString msg = QString("dns ip should be %1, got %2").arg(ip, dnsIp.toString()); QVERIFY2(dnsIp == ip, msg.toLocal8Bit().constData()); - m_coreController->m_allowedDnsUiController->importDns(getPath(), true); + m_coreController->m_allowedDnsUiController->importDns(getValueFromIni("paths/TEST_DNS_LIST_PATH"), true); m_coreController->m_allowedDnsUiController->updateModel(); QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); QVERIFY2(finishedSpy.count() == 2, "finished signal should be emitted"); QVERIFY2(m_coreController->m_allowedDnsModel->rowCount() > 1, "AllowedDnsModel should have more than 1 row"); - m_coreController->m_allowedDnsUiController->exportDns(getExportPath() + "test_dns_export.json"); + m_coreController->m_allowedDnsUiController->exportDns(getValueFromIni("paths/TEST_EXPORT_PATH") + "test_dns_export.json"); QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); QVERIFY2(finishedSpy.count() == 3, "finished signal should be emitted"); diff --git a/client/tests/testUiAppSTModelAndController.cpp b/client/tests/testUiAppSTModelAndController.cpp index a597269ca..08d3dc0a7 100644 --- a/client/tests/testUiAppSTModelAndController.cpp +++ b/client/tests/testUiAppSTModelAndController.cpp @@ -21,9 +21,10 @@ private: CoreController *m_coreController; SecureQSettings *m_settings; - QString getPath() + QString getValueFromIni(const QString &key) { - return QProcessEnvironment::systemEnvironment().value("TEST_APP_PATH"); + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); } private slots: @@ -66,7 +67,7 @@ private slots: QVERIFY2(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); QVERIFY2(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == false, "AppSplitTunneling should be disabled"); - QString app = getPath(); + QString app = getValueFromIni("paths/TEST_APP_PATH"); m_coreController->m_appSplitTunnelingUiController->addApp(app); m_coreController->m_appSplitTunnelingUiController->updateModel(); diff --git a/client/tests/testUiSitesModelAndController.cpp b/client/tests/testUiSitesModelAndController.cpp index 18ba72cba..b22f67b2e 100644 --- a/client/tests/testUiSitesModelAndController.cpp +++ b/client/tests/testUiSitesModelAndController.cpp @@ -21,14 +21,10 @@ private: CoreController *m_coreController; SecureQSettings *m_settings; - QString getPath() + QString getValueFromIni(const QString &key) { - return QProcessEnvironment::systemEnvironment().value("TEST_SITES_LIST_PATH"); - } - - QString getExportPath() - { - return QProcessEnvironment::systemEnvironment().value("TEST_EXPORT_PATH"); + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); } QString normalizeHostname(const QString &hostname) const @@ -103,13 +99,13 @@ private slots: QVERIFY2(finishedSpy.count() == 3, "finished signal should be emitted"); QVERIFY2(m_coreController->m_sitesModel->rowCount() == 1, "SitesModel should have 1 row"); - m_coreController->m_sitesUiController->importSites(getPath(), true); + m_coreController->m_sitesUiController->importSites(getValueFromIni("paths/TEST_SITES_LIST_PATH"), true); m_coreController->m_sitesUiController->updateModel(); QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); QVERIFY2(finishedSpy.count() == 4, "finished signal should be emitted"); QVERIFY2(m_coreController->m_sitesModel->rowCount() > 1, "SitesModel should have more than 1 row"); - m_coreController->m_sitesUiController->exportSites(getExportPath() + "test_sites_export.json"); + m_coreController->m_sitesUiController->exportSites(getValueFromIni("paths/TEST_EXPORT_PATH") + "test_sites_export.json"); QVERIFY2(finishedSpy.count() == 5, "finished signal should be emitted"); m_coreController->m_sitesUiController->removeSites(); diff --git a/client/tests/test_vars.ini b/client/tests/test_vars.ini new file mode 100644 index 000000000..2413b41cb --- /dev/null +++ b/client/tests/test_vars.ini @@ -0,0 +1,23 @@ +[configs] +TEST_SELF_HOSTED_CONFIG = self-hosted_config_string +TEST_CONFIG_ANY = any_config_string +TEST_CONFIG_AWG = awg_config_string +TEST_CONFIG_WG = wg_config_string +TEST_CONFIG_XRAY = xray_config_string +TEST_CONFIG_VMESS_NEW = vmess_new_config_string +TEST_CONFIG_VMESS = vmess_config_string +TEST_CONFIG_TROJAN = trojan_config_string +TEST_CONFIG_SS = ss_config_string +TEST_CONFIG_SSD = ssd_config_string + +[paths] +TEST_APP_PATH = path/to/app +TEST_SITES_LIST_PATH = path/to/file/with/sites_list +TEST_DNS_LIST_PATH = path/to/file/with/dns_list +TEST_EXPORT_PATH = path/to/export_directory + +[secrets] +TEST_SERVER_HOST = server_host +TEST_SERVER_USER = server_user +TEST_SERVER_PASSWORD = server_password +TEST_SERVER_PORT = 22 From f7cba6dd2cdf4aff5b570014773f2b3a8ef31fb6 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 29 Apr 2026 18:39:04 +0300 Subject: [PATCH 50/53] proper path for some vars --- client/tests/testSelfHostedServerSetup.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/tests/testSelfHostedServerSetup.cpp b/client/tests/testSelfHostedServerSetup.cpp index 60c525deb..4298a5ce9 100644 --- a/client/tests/testSelfHostedServerSetup.cpp +++ b/client/tests/testSelfHostedServerSetup.cpp @@ -40,10 +40,10 @@ private: ServerCredentials getCredentialsFromEnv() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - QString hostName = getValueFromIni("TEST_SERVER_HOST"); - QString userName = getValueFromIni("TEST_SERVER_USER"); - QString password = getValueFromIni("TEST_SERVER_PASSWORD"); - QString portStr = getValueFromIni("TEST_SERVER_PORT"); + QString hostName = getValueFromIni("secrets/TEST_SERVER_HOST"); + QString userName = getValueFromIni("secrets/TEST_SERVER_USER"); + QString password = getValueFromIni("secrets/TEST_SERVER_PASSWORD"); + QString portStr = getValueFromIni("secrets/TEST_SERVER_PORT"); int port = portStr.toInt(); ServerCredentials credentials; From 651f2b28c4a0c052d5d18851efd9adda3afd820f Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 12 May 2026 16:09:17 +0300 Subject: [PATCH 51/53] some fixes due merge --- client/core/controllers/coreController.h | 4 +- client/tests/CMakeLists.txt | 8 +- client/tests/testMultipleExports.cpp | 2 +- .../tests/testUiAppSTModelAndController.cpp | 6 +- client/tests/testUiIpModelAndController.cpp | 119 ++++++++++++++++++ .../tests/testUiSitesModelAndController.cpp | 119 ------------------ 6 files changed, 129 insertions(+), 129 deletions(-) create mode 100644 client/tests/testUiIpModelAndController.cpp delete mode 100644 client/tests/testUiSitesModelAndController.cpp diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index eb38eb217..e1c39c894 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -90,7 +90,7 @@ class TestSelfHostedServerSetup; class TestMultipleExports; class TestSerialization; class TestUiLanguageModelAndController; -class TestUiSitesModelAndController; +class TestUiIpModelAndController; class TestUiAppSTModelAndController; class TestUiAllowedDnsModelAndController; class TestUiNewsModelAndController; @@ -115,7 +115,7 @@ class CoreController : public QObject friend class TestMultipleExports; friend class TestSerialization; friend class TestUiLanguageModelAndController; - friend class TestUiSitesModelAndController; + friend class TestUiIpModelAndController; friend class TestUiAppSTModelAndController; friend class TestUiAllowedDnsModelAndController; friend class TestUiNewsModelAndController; diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index 9c3ac6f86..961ae1029 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -170,11 +170,11 @@ target_link_libraries(test_ui_language_model_and_controller PRIVATE test_common ) -add_executable(test_ui_sites_model_and_controller - testUiSitesModelAndController.cpp +add_executable(test_ui_ip_model_and_controller + testUiIpModelAndController.cpp ) -target_link_libraries(test_ui_sites_model_and_controller PRIVATE +target_link_libraries(test_ui_ip_model_and_controller PRIVATE Qt6::Test test_common ) @@ -222,6 +222,6 @@ add_test(NAME SelfHostedServerSetupTest COMMAND test_self_hosted_server_setup) add_test(NAME MultipleExportsTest COMMAND test_exports) add_test(NAME SerializationTest COMMAND test_serialization) add_test(NAME UiLanguageModelAndControllerTest COMMAND test_ui_language_model_and_controller) -add_test(NAME UiSitesModelAndControllerTest COMMAND test_ui_sites_model_and_controller) +add_test(NAME UiIpModelAndControllerTest COMMAND test_ui_ip_model_and_controller) add_test(NAME UiAppSTModelAndControllerTest COMMAND test_ui_app_st_model_and_controller) add_test(NAME UiAllowedDnsModelAndControllerTest COMMAND test_ui_allowed_dns_model_and_controller) diff --git a/client/tests/testMultipleExports.cpp b/client/tests/testMultipleExports.cpp index a32bcee51..5ac1640f4 100644 --- a/client/tests/testMultipleExports.cpp +++ b/client/tests/testMultipleExports.cpp @@ -108,7 +108,7 @@ private slots: QString clientName = "MultipleExports Test Client"; - auto exportResultAwg = m_coreController->m_exportController->generateAwgConfig(serverIndex, clientName); + auto exportResultAwg = m_coreController->m_exportController->generateAwgConfig(serverIndex, DockerContainer::Awg2, clientName); auto exportResultWg = m_coreController->m_exportController->generateWireGuardConfig(serverIndex, clientName); auto exportResultOvpn = m_coreController->m_exportController->generateOpenVpnConfig(serverIndex, clientName); auto exportResultXray = m_coreController->m_exportController->generateXrayConfig(serverIndex, clientName); diff --git a/client/tests/testUiAppSTModelAndController.cpp b/client/tests/testUiAppSTModelAndController.cpp index 08d3dc0a7..c47c34783 100644 --- a/client/tests/testUiAppSTModelAndController.cpp +++ b/client/tests/testUiAppSTModelAndController.cpp @@ -57,15 +57,15 @@ private slots: { QSignalSpy finishedSpy(m_coreController->m_appSplitTunnelingUiController, &AppSplitTunnelingUiController::finished); QSignalSpy errorOccurredSpy(m_coreController->m_appSplitTunnelingUiController, &AppSplitTunnelingUiController::errorOccurred); - QSignalSpy isSplitTunnelingChangedSpy(m_coreController->m_appSplitTunnelingUiController, &AppSplitTunnelingUiController::isTunnelingEnabledChanged); + QSignalSpy isSplitTunnelingChangedSpy(m_coreController->m_appSplitTunnelingUiController, &AppSplitTunnelingUiController::isSplitTunnelingEnabledChanged); m_coreController->m_appSplitTunnelingUiController->toggleSplitTunneling(true); QVERIFY2(isSplitTunnelingChangedSpy.count() == 1, "isSplitTunnelingChangedSpy signal should be emitted"); - QVERIFY2(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == true, "AppSplitTunneling should be enabled"); + QVERIFY2(m_coreController->m_appSplitTunnelingUiController->isSplitTunnelingEnabled() == true, "AppSplitTunneling should be enabled"); m_coreController->m_appSplitTunnelingUiController->toggleSplitTunneling(false); QVERIFY2(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); - QVERIFY2(m_coreController->m_appSplitTunnelingUiController->isTunnelingEnabled() == false, "AppSplitTunneling should be disabled"); + QVERIFY2(m_coreController->m_appSplitTunnelingUiController->isSplitTunnelingEnabled() == false, "AppSplitTunneling should be disabled"); QString app = getValueFromIni("paths/TEST_APP_PATH"); diff --git a/client/tests/testUiIpModelAndController.cpp b/client/tests/testUiIpModelAndController.cpp new file mode 100644 index 000000000..1f7da1344 --- /dev/null +++ b/client/tests/testUiIpModelAndController.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "core/controllers/coreController.h" +#include "core/models/serverConfig.h" +#include "secureQSettings.h" +#include "vpnConnection.h" + +using namespace amnezia; + +class TestUiIpModelAndController : public QObject +{ + Q_OBJECT + +private: + CoreController *m_coreController; + SecureQSettings *m_settings; + + QString getValueFromIni(const QString &key) + { + QSettings settings("test_vars.ini", QSettings::IniFormat); + return settings.value(key).toString(); + } + + QString normalizeHostname(const QString &hostname) const + { + QString normalized = hostname; + normalized.replace("https://", ""); + normalized.replace("http://", ""); + normalized.replace("ftp://", ""); + normalized = normalized.split("/", Qt::SkipEmptyParts).first(); + return normalized; + } + +private slots: + void initTestCase() + { + QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); + m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); + + auto vpnConnection = QSharedPointer::create(nullptr, nullptr); + + m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); + } + + void cleanupTestCase() + { + m_settings->clearSettings(); + delete m_coreController; + delete m_settings; + } + + void init() + { + m_settings->clearSettings(); + if (m_coreController->m_serversModel) { + m_coreController->m_serversModel->updateModel(QVector(), -1, false); + } + } + + void testRolesAndSignals() + { + QSignalSpy finishedSpy(m_coreController->m_ipSplitTunnelingUiController, &IpSplitTunnelingUiController::finished); + QSignalSpy errorOccurredSpy(m_coreController->m_ipSplitTunnelingUiController, &IpSplitTunnelingUiController::errorOccurred); + QSignalSpy isSplitTunnelingChangedSpy(m_coreController->m_ipSplitTunnelingUiController, &IpSplitTunnelingUiController::isSplitTunnelingEnabledChanged); + + m_coreController->m_ipSplitTunnelingUiController->toggleSplitTunneling(true); + QVERIFY2(isSplitTunnelingChangedSpy.count() == 1, "isSplitTunnelingChangedSpy signal should be emitted"); + QVERIFY2(m_coreController->m_ipSplitTunnelingUiController->isSplitTunnelingEnabled() == true, "ipSplitTunneling should be enabled"); + + m_coreController->m_ipSplitTunnelingUiController->toggleSplitTunneling(false); + QVERIFY2(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); + QVERIFY2(m_coreController->m_ipSplitTunnelingUiController->isSplitTunnelingEnabled() == false, "ipSplitTunneling should be disabled"); + + QString site = "2ip.io"; + + m_coreController->m_ipSplitTunnelingUiController->addSite(site); + m_coreController->m_ipSplitTunnelingUiController->addSite("whatismyipaddress.com"); + m_coreController->m_ipSplitTunnelingUiController->updateModel(); + QVERIFY2(finishedSpy.count() == 2, "finished signal should be emitted 2 times"); + QVERIFY2(m_coreController->m_ipSplitTunnelingModel->rowCount() == 2, "IpSplitTunnelingModel should have 2 rows"); + + QModelIndex siteModelIndex = m_coreController->m_ipSplitTunnelingModel->index(0, 0); + QVERIFY2(siteModelIndex.isValid(), "Ip model index should be valid"); + + auto siteUrl = m_coreController->m_ipSplitTunnelingModel->data(siteModelIndex, IpSplitTunnelingModel::UrlRole); + QCOMPARE(siteUrl, normalizeHostname(site)); + + auto siteIp = m_coreController->m_ipSplitTunnelingModel->data(siteModelIndex, IpSplitTunnelingModel::IpRole); + QVERIFY2(siteIp.isNull() == false, "Ip should not be empty"); + + m_coreController->m_ipSplitTunnelingUiController->removeSite(0); + m_coreController->m_ipSplitTunnelingUiController->updateModel(); + QVERIFY2(finishedSpy.count() == 3, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_ipSplitTunnelingModel->rowCount() == 1, "IpSplitTunnelingModel should have 1 row"); + + m_coreController->m_ipSplitTunnelingUiController->importSites(getValueFromIni("paths/TEST_SITES_LIST_PATH"), true); + m_coreController->m_ipSplitTunnelingUiController->updateModel(); + QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); + QVERIFY2(finishedSpy.count() == 4, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_ipSplitTunnelingModel->rowCount() > 1, "IpSplitTunnelingModel should have more than 1 row"); + + m_coreController->m_ipSplitTunnelingUiController->exportSites(getValueFromIni("paths/TEST_EXPORT_PATH") + "test_ips_export.json"); + QVERIFY2(finishedSpy.count() == 5, "finished signal should be emitted"); + + m_coreController->m_ipSplitTunnelingUiController->removeSites(); + m_coreController->m_ipSplitTunnelingUiController->updateModel(); + QVERIFY2(finishedSpy.count() == 6, "finished signal should be emitted"); + QVERIFY2(m_coreController->m_ipSplitTunnelingModel->rowCount() == 0, "IpSplitTunnelingModel should have 0 rows"); + } +}; + +QTEST_MAIN(TestUiIpModelAndController) +#include "testUiIpModelAndController.moc" diff --git a/client/tests/testUiSitesModelAndController.cpp b/client/tests/testUiSitesModelAndController.cpp deleted file mode 100644 index b22f67b2e..000000000 --- a/client/tests/testUiSitesModelAndController.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "core/controllers/coreController.h" -#include "core/models/serverConfig.h" -#include "secureQSettings.h" -#include "vpnConnection.h" - -using namespace amnezia; - -class TestUiSitesModelAndController : public QObject -{ - Q_OBJECT - -private: - CoreController *m_coreController; - SecureQSettings *m_settings; - - QString getValueFromIni(const QString &key) - { - QSettings settings("test_vars.ini", QSettings::IniFormat); - return settings.value(key).toString(); - } - - QString normalizeHostname(const QString &hostname) const - { - QString normalized = hostname; - normalized.replace("https://", ""); - normalized.replace("http://", ""); - normalized.replace("ftp://", ""); - normalized = normalized.split("/", Qt::SkipEmptyParts).first(); - return normalized; - } - -private slots: - void initTestCase() - { - QString testOrg = "AmneziaVPN-Test-" + QUuid::createUuid().toString(); - m_settings = new SecureQSettings(testOrg, "amnezia-client", nullptr, false); - - auto vpnConnection = QSharedPointer::create(nullptr, nullptr); - - m_coreController = new CoreController(vpnConnection, m_settings, nullptr, this); - } - - void cleanupTestCase() - { - m_settings->clearSettings(); - delete m_coreController; - delete m_settings; - } - - void init() - { - m_settings->clearSettings(); - if (m_coreController->m_serversModel) { - m_coreController->m_serversModel->updateModel(QVector(), -1, false); - } - } - - void testRolesAndSignals() - { - QSignalSpy finishedSpy(m_coreController->m_sitesUiController, &SitesUiController::finished); - QSignalSpy errorOccurredSpy(m_coreController->m_sitesUiController, &SitesUiController::errorOccurred); - QSignalSpy isSplitTunnelingChangedSpy(m_coreController->m_sitesUiController, &SitesUiController::isTunnelingEnabledChanged); - - m_coreController->m_sitesUiController->toggleSplitTunneling(true); - QVERIFY2(isSplitTunnelingChangedSpy.count() == 1, "isSplitTunnelingChangedSpy signal should be emitted"); - QVERIFY2(m_coreController->m_sitesUiController->isTunnelingEnabled() == true, "SiteSplitTunneling should be enabled"); - - m_coreController->m_sitesUiController->toggleSplitTunneling(false); - QVERIFY2(isSplitTunnelingChangedSpy.count() == 2, "isSplitTunnelingChangedSpy signal should be emitted 2nd time"); - QVERIFY2(m_coreController->m_sitesUiController->isTunnelingEnabled() == false, "SiteSplitTunneling should be disabled"); - - QString site = "2ip.io"; - - m_coreController->m_sitesUiController->addSite(site); - m_coreController->m_sitesUiController->addSite("whatismyipaddress.com"); - m_coreController->m_sitesUiController->updateModel(); - QVERIFY2(finishedSpy.count() == 2, "finished signal should be emitted 2 times"); - QVERIFY2(m_coreController->m_sitesModel->rowCount() == 2, "SitesModel should have 2 rows"); - - QModelIndex siteModelIndex = m_coreController->m_sitesModel->index(0, 0); - QVERIFY2(siteModelIndex.isValid(), "Site model index should be valid"); - - auto siteUrl = m_coreController->m_sitesModel->data(siteModelIndex, SitesModel::UrlRole); - QCOMPARE(siteUrl, normalizeHostname(site)); - - auto siteIp = m_coreController->m_sitesModel->data(siteModelIndex, SitesModel::IpRole); - QVERIFY2(siteIp.isNull() == false, "site ip should not be empty"); - - m_coreController->m_sitesUiController->removeSite(0); - m_coreController->m_sitesUiController->updateModel(); - QVERIFY2(finishedSpy.count() == 3, "finished signal should be emitted"); - QVERIFY2(m_coreController->m_sitesModel->rowCount() == 1, "SitesModel should have 1 row"); - - m_coreController->m_sitesUiController->importSites(getValueFromIni("paths/TEST_SITES_LIST_PATH"), true); - m_coreController->m_sitesUiController->updateModel(); - QVERIFY2(errorOccurredSpy.count() == 0, "errorOccurred signal should not be emitted"); - QVERIFY2(finishedSpy.count() == 4, "finished signal should be emitted"); - QVERIFY2(m_coreController->m_sitesModel->rowCount() > 1, "SitesModel should have more than 1 row"); - - m_coreController->m_sitesUiController->exportSites(getValueFromIni("paths/TEST_EXPORT_PATH") + "test_sites_export.json"); - QVERIFY2(finishedSpy.count() == 5, "finished signal should be emitted"); - - m_coreController->m_sitesUiController->removeSites(); - m_coreController->m_sitesUiController->updateModel(); - QVERIFY2(finishedSpy.count() == 6, "finished signal should be emitted"); - QVERIFY2(m_coreController->m_sitesModel->rowCount() == 0, "SitesModel should have 0 rows"); - } -}; - -QTEST_MAIN(TestUiSitesModelAndController) -#include "testUiSitesModelAndController.moc" From 4fd3a995d07bf458b12865c0aff26613bb87ce36 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Tue, 12 May 2026 16:23:54 +0300 Subject: [PATCH 52/53] update: windows tests deploy --- .github/workflows/deploy.yml | 96 +++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index eb5980737..39a6d6b99 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -967,61 +967,65 @@ jobs: # ------------------------------------------------------ Test-Windows: - runs-on: windows-latest + runs-on: windows-latest - env: - QT_VERSION: 6.10.1 + env: + QT_VERSION: 6.10.1 - steps: - - name: 'Get sources' - uses: actions/checkout@v4 - with: - submodules: 'true' - fetch-depth: 10 + steps: + - name: 'Get sources' + uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 10 - - name: 'Install Qt' - uses: jurplel/install-qt-action@v3 - with: - version: ${{ env.QT_VERSION }} - host: 'windows' - target: 'desktop' - arch: 'win64_msvc2022_64' - modules: 'qtremoteobjects qt5compat qtshadertools' - dir: ${{ runner.temp }} - set-env: 'true' + - name: 'Install Qt' + uses: jurplel/install-qt-action@v3 + with: + version: ${{ env.QT_VERSION }} + host: 'windows' + target: 'desktop' + arch: 'win64_msvc2022_64' + modules: 'qtremoteobjects qt5compat qtshadertools' + dir: ${{ runner.temp }} + setup-python: 'true' + tools: 'tools_ifw' + set-env: 'true' + aqtversion: '==3.3.0' + py7zrversion: '==0.22.*' - - name: 'Setup MSVC' - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: 'x64' + - name: 'Setup MSVC' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: 'x64' - - name: 'Install dependencies' - shell: bash - run: | - choco install ninja -y + - name: 'Install dependencies' + shell: bash + run: | + choco install ninja -y - - name: 'Configure' - shell: cmd - run: | - cmake -B build -G Ninja ^ - -DCMAKE_BUILD_TYPE=Release ^ - -DBUILD_TESTING=ON + - name: 'Configure' + shell: cmd + run: | + cmake -S . -B build -G Ninja ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DBUILD_TESTING=ON - - name: 'Build' - shell: cmd - run: cmake --build build --config Release + - name: 'Build' + shell: cmd + run: cmake --build build --config Release - - name: 'Deploy Qt dependencies' - shell: cmd - run: | - for %%f in (build\client\test_*.exe) do (windeployqt %%f) + - name: 'Deploy Qt dependencies' + shell: cmd + run: | + for %%f in (build\client\test_*.exe) do ("%Qt6_DIR%\bin\windeployqt.exe" %%f) - - name: 'Run tests' - shell: cmd - run: | - set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x64 - set PATH=%PATH%;%Qt6_DIR%\..\..\..\bin - ctest --test-dir build\client --output-on-failure + - name: 'Run tests' + shell: cmd + run: | + set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x64 + set PATH=%PATH%;%Qt6_DIR%\bin + ctest --test-dir build\client --output-on-failure # ------------------------------------------------------ From 0315be088599a1aef9fda51256c3e3b8c173fb97 Mon Sep 17 00:00:00 2001 From: MrMirDan Date: Wed, 13 May 2026 11:57:21 +0300 Subject: [PATCH 53/53] python and conan installation to tests jobs --- .github/workflows/deploy.yml | 120 ++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 50 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 39a6d6b99..1d2ad53df 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -943,6 +943,14 @@ jobs: libgl1 \ libglib2.0-0 + - name: 'Setup python' + uses: actions/setup-python@v6 + with: + python-version: 3.14 + + - name: 'Install conan' + run: pip install "conan==2.26.2" + - name: 'Configure' run: | cmake -B build -G Ninja \ @@ -967,65 +975,69 @@ jobs: # ------------------------------------------------------ Test-Windows: - runs-on: windows-latest + runs-on: windows-latest - env: - QT_VERSION: 6.10.1 + env: + QT_VERSION: 6.10.1 - steps: - - name: 'Get sources' - uses: actions/checkout@v4 - with: - submodules: 'true' - fetch-depth: 10 + steps: + - name: 'Get sources' + uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 10 - - name: 'Install Qt' - uses: jurplel/install-qt-action@v3 - with: - version: ${{ env.QT_VERSION }} - host: 'windows' - target: 'desktop' - arch: 'win64_msvc2022_64' - modules: 'qtremoteobjects qt5compat qtshadertools' - dir: ${{ runner.temp }} - setup-python: 'true' - tools: 'tools_ifw' - set-env: 'true' - aqtversion: '==3.3.0' - py7zrversion: '==0.22.*' + - name: 'Install Qt' + uses: jurplel/install-qt-action@v3 + with: + version: ${{ env.QT_VERSION }} + host: 'windows' + target: 'desktop' + arch: 'win64_msvc2022_64' + modules: 'qtremoteobjects qt5compat qtshadertools' + dir: ${{ runner.temp }} + set-env: 'true' - - name: 'Setup MSVC' - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: 'x64' + - name: 'Setup MSVC' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: 'x64' - - name: 'Install dependencies' - shell: bash - run: | - choco install ninja -y + - name: 'Setup python' + uses: actions/setup-python@v6 + with: + python-version: 3.14 - - name: 'Configure' - shell: cmd - run: | - cmake -S . -B build -G Ninja ^ - -DCMAKE_BUILD_TYPE=Release ^ - -DBUILD_TESTING=ON + - name: 'Install conan' + run: pip install "conan==2.26.2" - - name: 'Build' - shell: cmd - run: cmake --build build --config Release + - name: 'Install dependencies' + shell: bash + run: | + choco install ninja -y - - name: 'Deploy Qt dependencies' - shell: cmd - run: | - for %%f in (build\client\test_*.exe) do ("%Qt6_DIR%\bin\windeployqt.exe" %%f) + - name: 'Configure' + shell: cmd + run: | + cmake -B build -G Ninja ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DBUILD_TESTING=ON - - name: 'Run tests' - shell: cmd - run: | - set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x64 - set PATH=%PATH%;%Qt6_DIR%\bin - ctest --test-dir build\client --output-on-failure + - name: 'Build' + shell: cmd + run: cmake --build build --config Release + + - name: 'Deploy Qt dependencies' + shell: cmd + run: | + for %%f in (build\client\test_*.exe) do (windeployqt %%f) + + - name: 'Run tests' + shell: cmd + run: | + set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x64 + set PATH=%PATH%;%Qt6_DIR%\..\..\..\bin + ctest --test-dir build\client --output-on-failure # ------------------------------------------------------ @@ -1063,6 +1075,14 @@ jobs: brew update brew install cmake ninja + - name: 'Setup python' + uses: actions/setup-python@v6 + with: + python-version: 3.14 + + - name: 'Install conan' + run: pip install "conan==2.26.2" + - name: 'Configure' run: | cmake -B build -G Ninja \