mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
300 lines
18 KiB
C++
300 lines
18 KiB
C++
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QJsonArray>
|
|
#include <QDebug>
|
|
#include <QUuid>
|
|
#include <QSignalSpy>
|
|
#include <QModelIndex>
|
|
|
|
#ifdef Q_OS_WIN
|
|
#include <QTest>
|
|
#else
|
|
#include <QtTest/qtest.h>
|
|
#endif
|
|
|
|
#include "core/controllers/coreController.h"
|
|
#include "core/models/serverConfig.h"
|
|
#include "core/controllers/selfhosted/importController.h"
|
|
#include "ui/models/serversModel.h"
|
|
#include "ui/models/containersModel.h"
|
|
#include "core/utils/constants/configKeys.h"
|
|
|
|
using namespace amnezia;
|
|
#include "core/utils/constants/protocolConstants.h"
|
|
#include "core/utils/containerEnum.h"
|
|
#include "core/utils/protocolEnum.h"
|
|
#include "vpnConnection.h"
|
|
#include "secureQSettings.h"
|
|
|
|
using namespace amnezia;
|
|
|
|
class TestUiServersModelAndController : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private:
|
|
CoreController* m_coreController;
|
|
SecureQSettings* m_settings;
|
|
|
|
QJsonObject createAwg2Config()
|
|
{
|
|
QJsonObject clientConfig;
|
|
clientConfig[configKey::mtu] = protocols::awg::defaultMtu;
|
|
clientConfig[configKey::junkPacketCount] = protocols::awg::defaultJunkPacketCount;
|
|
clientConfig[configKey::junkPacketMinSize] = protocols::awg::defaultJunkPacketMinSize;
|
|
clientConfig[configKey::junkPacketMaxSize] = protocols::awg::defaultJunkPacketMaxSize;
|
|
clientConfig[configKey::specialJunk1] = protocols::awg::defaultSpecialJunk1;
|
|
clientConfig[configKey::specialJunk2] = protocols::awg::defaultSpecialJunk2;
|
|
clientConfig[configKey::specialJunk3] = protocols::awg::defaultSpecialJunk3;
|
|
clientConfig[configKey::specialJunk4] = protocols::awg::defaultSpecialJunk4;
|
|
clientConfig[configKey::specialJunk5] = protocols::awg::defaultSpecialJunk5;
|
|
clientConfig[configKey::clientPrivKey] = "test_client_private_key";
|
|
clientConfig[configKey::clientPubKey] = "test_client_public_key";
|
|
clientConfig[configKey::serverPubKey] = "test_server_public_key";
|
|
clientConfig[configKey::pskKey] = "test_psk_key";
|
|
clientConfig[configKey::clientIp] = "10.8.1.2";
|
|
clientConfig[configKey::allowedIps] = QJsonArray::fromStringList({"0.0.0.0/0"});
|
|
|
|
QJsonObject awgConfig;
|
|
awgConfig[configKey::lastConfig] = QString(QJsonDocument(clientConfig).toJson());
|
|
awgConfig[configKey::port] = protocols::awg::defaultPort;
|
|
awgConfig[configKey::transportProto] = "udp";
|
|
awgConfig[configKey::protocolVersion] = protocols::awg::awgV2;
|
|
awgConfig[configKey::subnetAddress] = protocols::wireguard::defaultSubnetAddress;
|
|
awgConfig[configKey::junkPacketCount] = protocols::awg::defaultJunkPacketCount;
|
|
awgConfig[configKey::junkPacketMinSize] = protocols::awg::defaultJunkPacketMinSize;
|
|
awgConfig[configKey::junkPacketMaxSize] = protocols::awg::defaultJunkPacketMaxSize;
|
|
awgConfig[configKey::initPacketJunkSize] = protocols::awg::defaultInitPacketJunkSize;
|
|
awgConfig[configKey::responsePacketJunkSize] = protocols::awg::defaultResponsePacketJunkSize;
|
|
awgConfig[configKey::cookieReplyPacketJunkSize] = protocols::awg::defaultCookieReplyPacketJunkSize;
|
|
awgConfig[configKey::transportPacketJunkSize] = protocols::awg::defaultTransportPacketJunkSize;
|
|
awgConfig[configKey::initPacketMagicHeader] = protocols::awg::defaultInitPacketMagicHeader;
|
|
awgConfig[configKey::responsePacketMagicHeader] = protocols::awg::defaultResponsePacketMagicHeader;
|
|
awgConfig[configKey::underloadPacketMagicHeader] = protocols::awg::defaultUnderloadPacketMagicHeader;
|
|
awgConfig[configKey::transportPacketMagicHeader] = protocols::awg::defaultTransportPacketMagicHeader;
|
|
awgConfig[configKey::specialJunk1] = protocols::awg::defaultSpecialJunk1;
|
|
awgConfig[configKey::specialJunk2] = protocols::awg::defaultSpecialJunk2;
|
|
awgConfig[configKey::specialJunk3] = protocols::awg::defaultSpecialJunk3;
|
|
awgConfig[configKey::specialJunk4] = protocols::awg::defaultSpecialJunk4;
|
|
awgConfig[configKey::specialJunk5] = protocols::awg::defaultSpecialJunk5;
|
|
awgConfig[configKey::isThirdPartyConfig] = true;
|
|
|
|
QJsonObject container;
|
|
container[configKey::container] = "amnezia-awg";
|
|
container[configKey::awg] = awgConfig;
|
|
|
|
QJsonArray containers;
|
|
containers.append(container);
|
|
|
|
QJsonObject config;
|
|
config[configKey::containers] = containers;
|
|
config[configKey::defaultContainer] = "amnezia-awg";
|
|
config[configKey::description] = "AWG2 Test Server";
|
|
config[configKey::hostName] = "test.example.com";
|
|
|
|
return config;
|
|
}
|
|
|
|
QJsonObject createServerDescriptionTestConfig(bool withAmneziaDns)
|
|
{
|
|
QJsonObject config = createAwg2Config();
|
|
config[configKey::description] = "Server 1";
|
|
if (withAmneziaDns) {
|
|
config[configKey::dns1] = protocols::dns::amneziaDnsIp;
|
|
}
|
|
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<VpnConnection>::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<ServerConfig>(), -1, false);
|
|
}
|
|
}
|
|
|
|
void testUiServersModelAndControllerRoles() {
|
|
QJsonObject testConfig = createAwg2Config();
|
|
|
|
QSignalSpy importFinishedSpy(m_coreController->m_importCoreController, &ImportController::importFinished);
|
|
|
|
m_coreController->m_importCoreController->importConfig(testConfig);
|
|
|
|
QVERIFY2(importFinishedSpy.count() == 1, "importFinished signal should be emitted");
|
|
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "Server should be imported");
|
|
|
|
int serverIndex = m_coreController->m_serversRepository->defaultServerIndex();
|
|
QVERIFY2(serverIndex == 0, "Default server index should be 0");
|
|
|
|
if (m_coreController->m_serversModel) {
|
|
QVERIFY2(m_coreController->m_serversModel->rowCount() == 1, "ServersModel should have 1 row");
|
|
|
|
QModelIndex serverModelIndex = m_coreController->m_serversModel->index(0, 0);
|
|
QVERIFY2(serverModelIndex.isValid(), "Server model index should be valid");
|
|
|
|
QString serverName = m_coreController->m_serversModel->data(serverModelIndex, ServersModel::NameRole).toString();
|
|
QVERIFY2(serverName == "AWG2 Test Server", QString("Server name should be 'AWG2 Test Server', got '%1'").arg(serverName).toUtf8().constData());
|
|
|
|
QString serverDescription = m_coreController->m_serversModel->data(serverModelIndex, ServersModel::ServerDescriptionRole).toString();
|
|
QVERIFY2(serverDescription.contains("test.example.com"), QString("Server description should contain hostname, got '%1'").arg(serverDescription).toUtf8().constData());
|
|
|
|
QString hostName = m_coreController->m_serversModel->data(serverModelIndex, ServersModel::HostNameRole).toString();
|
|
QVERIFY2(hostName == "test.example.com", "Host name should match");
|
|
|
|
bool isDefault = m_coreController->m_serversModel->data(serverModelIndex, ServersModel::IsDefaultRole).toBool();
|
|
QVERIFY2(isDefault == true, "Server should be default");
|
|
|
|
bool hasInstalledContainers = m_coreController->m_serversModel->data(serverModelIndex, ServersModel::HasInstalledContainers).toBool();
|
|
QVERIFY2(hasInstalledContainers == true, "Server should have installed containers");
|
|
|
|
bool hasWriteAccess = m_coreController->m_serversModel->data(serverModelIndex, ServersModel::HasWriteAccessRole).toBool();
|
|
QVERIFY2(hasWriteAccess == false, "Server should not have write access for imported config");
|
|
|
|
int defaultContainerRole = m_coreController->m_serversModel->data(serverModelIndex, ServersModel::DefaultContainerRole).toInt();
|
|
DockerContainer expectedContainer = DockerContainer::Awg;
|
|
QVERIFY2(defaultContainerRole == static_cast<int>(expectedContainer), "Default container should be Awg");
|
|
}
|
|
|
|
if (m_coreController->m_serversUiController) {
|
|
m_coreController->m_serversUiController->setProcessedServerIndex(serverIndex);
|
|
|
|
ServerConfig serverConfig = m_coreController->m_serversRepository->server(serverIndex);
|
|
QString actualServerName = serverConfig.description();
|
|
QString containerName = ContainerUtils::containerHumanNames().value(DockerContainer::Awg);
|
|
QString hostName = "test.example.com";
|
|
|
|
QString collapsedDescription = m_coreController->m_serversUiController->getDefaultServerDescriptionCollapsed();
|
|
QString expectedCollapsed = "AmneziaWG (version 2) | " + hostName;
|
|
QVERIFY2(collapsedDescription == expectedCollapsed,
|
|
QString("Collapsed description should be '%1', got '%2'").arg(expectedCollapsed, collapsedDescription).toUtf8().constData());
|
|
|
|
QString expandedDescription = m_coreController->m_serversUiController->getDefaultServerDescriptionExpanded();
|
|
QString expectedExpanded = hostName;
|
|
QVERIFY2(expandedDescription == expectedExpanded,
|
|
QString("Expanded description should be '%1', got '%2'").arg(expectedExpanded, expandedDescription).toUtf8().constData());
|
|
}
|
|
|
|
if (m_coreController->m_containersModel) {
|
|
|
|
int awgContainerIndex = -1;
|
|
for (int i = 0; i < ContainerUtils::allContainers().size(); ++i) {
|
|
DockerContainer container = ContainerUtils::allContainers().at(i);
|
|
if (container == DockerContainer::Awg) {
|
|
awgContainerIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
QVERIFY2(awgContainerIndex >= 0, "Awg container index should be found");
|
|
|
|
QModelIndex containerModelIndex = m_coreController->m_containersModel->index(awgContainerIndex, 0);
|
|
QVERIFY2(containerModelIndex.isValid(), "Container model index should be valid");
|
|
|
|
bool isInstalled = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::IsInstalledRole).toBool();
|
|
QVERIFY2(isInstalled == true, "Awg container should be installed");
|
|
|
|
bool isVpnContainer = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::IsVpnContainerRole).toBool();
|
|
QVERIFY2(isVpnContainer == true, "Awg container should be VPN container");
|
|
|
|
QString containerName = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::NameRole).toString();
|
|
QString expectedContainerName = ContainerUtils::containerHumanNames().value(DockerContainer::Awg);
|
|
QVERIFY2(containerName == expectedContainerName, QString("Container name should be '%1', got '%2'").arg(expectedContainerName, containerName).toUtf8().constData());
|
|
|
|
QString containerDescription = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::DescriptionRole).toString();
|
|
QString expectedDescription = ContainerUtils::containerDescriptions().value(DockerContainer::Awg);
|
|
QVERIFY2(containerDescription == expectedDescription, QString("Container description should match, got '%1'").arg(containerDescription).toUtf8().constData());
|
|
|
|
QString detailedDescription = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::DetailedDescriptionRole).toString();
|
|
QString expectedDetailedDescription = ContainerUtils::containerDetailedDescriptions().value(DockerContainer::Awg);
|
|
QVERIFY2(detailedDescription == expectedDetailedDescription, QString("Container detailed description should match, got '%1'").arg(detailedDescription).toUtf8().constData());
|
|
|
|
int serviceType = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::ServiceTypeRole).toInt();
|
|
QVERIFY2(serviceType == static_cast<int>(ProtocolEnumNS::ServiceType::Vpn), "Service type should be Vpn");
|
|
|
|
bool isSupported = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::IsSupportedRole).toBool();
|
|
QVERIFY2(isSupported == true, "Container should be supported");
|
|
|
|
bool isShareable = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::IsShareableRole).toBool();
|
|
QVERIFY2(isShareable == true, "Container should be shareable");
|
|
|
|
QJsonObject containerConfig = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::ConfigRole).toJsonObject();
|
|
QVERIFY2(!containerConfig.isEmpty(), "Container config should not be empty");
|
|
QVERIFY2(containerConfig.value(configKey::container).toString() == "amnezia-awg", "Container config should have correct container type");
|
|
|
|
QJsonObject awgProtocolConfig = containerConfig.value(configKey::awg).toObject();
|
|
QVERIFY2(!awgProtocolConfig.isEmpty(), "AWG protocol config should not be empty");
|
|
|
|
QString protocolVersion = awgProtocolConfig.value(configKey::protocolVersion).toString();
|
|
QVERIFY2(protocolVersion == protocols::awg::awgV2, QString("Protocol version should be '%1', got '%2'").arg(protocols::awg::awgV2, protocolVersion).toUtf8().constData());
|
|
|
|
QString port = awgProtocolConfig.value(configKey::port).toString();
|
|
QVERIFY2(port == protocols::awg::defaultPort, QString("Port should be '%1', got '%2'").arg(protocols::awg::defaultPort, port).toUtf8().constData());
|
|
|
|
QString subnetAddress = awgProtocolConfig.value(configKey::subnetAddress).toString();
|
|
QVERIFY2(subnetAddress == protocols::wireguard::defaultSubnetAddress, QString("Subnet address should be '%1', got '%2'").arg(protocols::wireguard::defaultSubnetAddress, subnetAddress).toUtf8().constData());
|
|
|
|
bool isThirdParty = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::IsThirdPartyConfigRole).toBool();
|
|
QVERIFY2(isThirdParty == true, "Imported config should be third party config");
|
|
|
|
DockerContainer dockerContainer = static_cast<DockerContainer>(m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::DockerContainerRole).toInt());
|
|
QVERIFY2(dockerContainer == DockerContainer::Awg, "Docker container should be Awg");
|
|
|
|
QString containerString = m_coreController->m_containersModel->data(containerModelIndex, ContainersModel::ContainerStringRole).toString();
|
|
QVERIFY2(containerString == "amnezia-awg", "Container string should be amnezia-awg");
|
|
}
|
|
}
|
|
|
|
void testServerDescriptionFormat() {
|
|
QSignalSpy importFinishedSpy(m_coreController->m_importCoreController, &ImportController::importFinished);
|
|
|
|
QJsonObject configNoDns = createServerDescriptionTestConfig(false);
|
|
m_coreController->m_importCoreController->importConfig(configNoDns);
|
|
QVERIFY2(importFinishedSpy.count() == 1, "importFinished should be emitted");
|
|
m_coreController->m_appSettingsRepository->setUseAmneziaDns(false);
|
|
m_coreController->m_serversModel->updateModel(
|
|
m_coreController->m_serversRepository->servers(),
|
|
m_coreController->m_serversRepository->defaultServerIndex(),
|
|
m_coreController->m_appSettingsRepository->useAmneziaDns());
|
|
|
|
QString descNoDns = m_coreController->m_serversModel->data(
|
|
m_coreController->m_serversModel->index(0, 0), ServersModel::ServerDescriptionRole).toString();
|
|
QVERIFY2(descNoDns == "test.example.com",
|
|
QString("Without Amnezia DNS expected 'test.example.com', got '%1'").arg(descNoDns).toUtf8().constData());
|
|
|
|
m_coreController->m_serversRepository->setServersArray(QJsonArray());
|
|
m_coreController->m_serversRepository->setDefaultServer(0);
|
|
|
|
QJsonObject configWithDns = createServerDescriptionTestConfig(true);
|
|
m_coreController->m_importCoreController->importConfig(configWithDns);
|
|
QVERIFY2(m_coreController->m_serversRepository->serversCount() == 1, "Server should be imported");
|
|
m_coreController->m_appSettingsRepository->setUseAmneziaDns(true);
|
|
m_coreController->m_serversModel->updateModel(
|
|
m_coreController->m_serversRepository->servers(),
|
|
m_coreController->m_serversRepository->defaultServerIndex(),
|
|
m_coreController->m_appSettingsRepository->useAmneziaDns());
|
|
|
|
QString descWithDns = m_coreController->m_serversModel->data(
|
|
m_coreController->m_serversModel->index(0, 0), ServersModel::ServerDescriptionRole).toString();
|
|
QVERIFY2(descWithDns == "Amnezia DNS | test.example.com",
|
|
QString("With Amnezia DNS expected 'Amnezia DNS | test.example.com', got '%1'").arg(descWithDns).toUtf8().constData());
|
|
}
|
|
};
|
|
|
|
QTEST_MAIN(TestUiServersModelAndController)
|
|
#include "testUiServersModelAndController.moc"
|