Delete flakey tests
This commit is contained in:
parent
2e15294caf
commit
b7643ecbad
7 changed files with 1 additions and 1632 deletions
|
@ -28,12 +28,7 @@ set(kdeconnect_sms_libraries
|
|||
|
||||
ecm_add_test(pluginloadtest.cpp LINK_LIBRARIES ${kdeconnect_libraries})
|
||||
ecm_add_test(sendfiletest.cpp LINK_LIBRARIES ${kdeconnect_libraries})
|
||||
ecm_add_test(networkpackettests.cpp LINK_LIBRARIES ${kdeconnect_libraries})
|
||||
ecm_add_test(testsocketlinereader.cpp TEST_NAME testsocketlinereader LINK_LIBRARIES ${kdeconnect_libraries})
|
||||
ecm_add_test(testsslsocketlinereader.cpp TEST_NAME testsslsocketlinereader LINK_LIBRARIES ${kdeconnect_libraries})
|
||||
ecm_add_test(kdeconnectconfigtest.cpp TEST_NAME kdeconnectconfigtest LINK_LIBRARIES ${kdeconnect_libraries})
|
||||
ecm_add_test(lanlinkprovidertest.cpp TEST_NAME lanlinkprovidertest LINK_LIBRARIES ${kdeconnect_libraries})
|
||||
ecm_add_test(devicetest.cpp TEST_NAME devicetest LINK_LIBRARIES ${kdeconnect_libraries})
|
||||
ecm_add_test(testsocketlinereader.cpp TEST_NAME testsocketlinereader LINK_LIBRARIES ${kdeconnect_libraries})\
|
||||
|
||||
if (NOT SAILFISHOS)
|
||||
ecm_add_test(testnotificationlistener.cpp
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
/**
|
||||
* Copyright 2015 Vineet Garg <grgvineet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../core/device.h"
|
||||
#include "../core/backends/lan/lanlinkprovider.h"
|
||||
#include "../core/kdeconnectconfig.h"
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
/**
|
||||
* This class tests the working of device class
|
||||
*/
|
||||
class DeviceTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void initTestCase();
|
||||
void testUnpairedDevice();
|
||||
void testPairedDevice();
|
||||
void cleanupTestCase();
|
||||
|
||||
private:
|
||||
QString deviceId;
|
||||
QString deviceName;
|
||||
QString deviceType;
|
||||
NetworkPacket* identityPacket;
|
||||
|
||||
};
|
||||
|
||||
void DeviceTest::initTestCase()
|
||||
{
|
||||
deviceId = QStringLiteral("testdevice");
|
||||
deviceName = QStringLiteral("Test Device");
|
||||
deviceType = QStringLiteral("smartphone");
|
||||
QString stringPacket = QStringLiteral("{\"id\":1439365924847,\"type\":\"kdeconnect.identity\",\"body\":{\"deviceId\":\"testdevice\",\"deviceName\":\"Test Device\",\"protocolVersion\":6,\"deviceType\":\"phone\"}}");
|
||||
identityPacket = new NetworkPacket(QStringLiteral("kdeconnect.identity"));
|
||||
NetworkPacket::unserialize(stringPacket.toLatin1(), identityPacket);
|
||||
}
|
||||
|
||||
void DeviceTest::testPairedDevice()
|
||||
{
|
||||
KdeConnectConfig::instance().addTrustedDevice(deviceId, deviceName, deviceType);
|
||||
KdeConnectConfig::instance().setDeviceProperty(deviceId, QStringLiteral("certificate"), QString::fromLatin1(KdeConnectConfig::instance().certificate().toPem())); // Using same certificate from kcc, instead of generating one
|
||||
|
||||
Device device(this, deviceId);
|
||||
|
||||
QCOMPARE(device.id(), deviceId);
|
||||
QCOMPARE(device.name(), deviceName);
|
||||
QCOMPARE(device.type(), deviceType);
|
||||
|
||||
QCOMPARE(device.isTrusted(), true);
|
||||
|
||||
QCOMPARE(device.isReachable(), false);
|
||||
|
||||
// Add link
|
||||
LanLinkProvider linkProvider;
|
||||
QSslSocket socket;
|
||||
LanDeviceLink* link = new LanDeviceLink(deviceId, &linkProvider, &socket, LanDeviceLink::Locally);
|
||||
device.addLink(*identityPacket, link);
|
||||
|
||||
QCOMPARE(device.isReachable(), true);
|
||||
QCOMPARE(device.availableLinks().contains(linkProvider.name()), true);
|
||||
|
||||
// Remove link
|
||||
device.removeLink(link);
|
||||
|
||||
QCOMPARE(device.isReachable(), false);
|
||||
QCOMPARE(device.availableLinks().contains(linkProvider.name()), false);
|
||||
|
||||
device.unpair();
|
||||
QCOMPARE(device.isTrusted(), false);
|
||||
|
||||
}
|
||||
|
||||
void DeviceTest::testUnpairedDevice()
|
||||
{
|
||||
KdeConnectConfig::instance().removeTrustedDevice(deviceId);
|
||||
|
||||
LanLinkProvider linkProvider;
|
||||
QSslSocket socket;
|
||||
LanDeviceLink* link = new LanDeviceLink(deviceId, &linkProvider, &socket, LanDeviceLink::Locally);
|
||||
|
||||
Device device(this, *identityPacket, link);
|
||||
|
||||
QCOMPARE(device.id(), deviceId);
|
||||
QCOMPARE(device.name(), deviceName);
|
||||
QCOMPARE(device.type(), deviceType);
|
||||
|
||||
QCOMPARE(device.isTrusted(), false);
|
||||
|
||||
QCOMPARE(device.isReachable(), true);
|
||||
QCOMPARE(device.availableLinks().contains(linkProvider.name()), true);
|
||||
|
||||
// Remove link
|
||||
device.removeLink(link);
|
||||
|
||||
QCOMPARE(device.isReachable(), false);
|
||||
QCOMPARE(device.availableLinks().contains(linkProvider.name()), false);
|
||||
}
|
||||
|
||||
void DeviceTest::cleanupTestCase()
|
||||
{
|
||||
delete identityPacket;
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(DeviceTest)
|
||||
|
||||
#include "devicetest.moc"
|
|
@ -1,85 +0,0 @@
|
|||
/**
|
||||
* Copyright 2015 Vineet Garg <grgvineet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "../core/kdeconnectconfig.h"
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
/*
|
||||
* This class tests the working of kdeconnect config that certificate and key is generated and saved properly
|
||||
*/
|
||||
class KdeConnectConfigTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void addTrustedDevice();
|
||||
/*
|
||||
void remoteCertificateTest();
|
||||
*/
|
||||
void removeTrustedDevice();
|
||||
};
|
||||
|
||||
void KdeConnectConfigTest::addTrustedDevice()
|
||||
{
|
||||
KdeConnectConfig::instance().addTrustedDevice(QStringLiteral("testdevice"), QStringLiteral("Test Device"), QStringLiteral("phone"));
|
||||
KdeConnectConfig::DeviceInfo devInfo = KdeConnectConfig::instance().getTrustedDevice(QStringLiteral("testdevice"));
|
||||
QCOMPARE(devInfo.deviceName, QStringLiteral("Test Device"));
|
||||
QCOMPARE(devInfo.deviceType, QStringLiteral("phone"));
|
||||
}
|
||||
|
||||
/*
|
||||
// This checks whether certificate is generated correctly and stored correctly or not
|
||||
void KdeConnectConfigTest::remoteCertificateTest()
|
||||
{
|
||||
QSslCertificate certificate = kcc->certificate(); // Using same certificate as of device
|
||||
|
||||
QCOMPARE(certificate.serialNumber().toInt(0,16), 10);
|
||||
QCOMPARE(certificate.subjectInfo(QSslCertificate::SubjectInfo::CommonName).first(), kcc->deviceId());
|
||||
QCOMPARE(certificate.subjectInfo(QSslCertificate::SubjectInfo::Organization).first(), QString("KDE"));
|
||||
QCOMPARE(certificate.subjectInfo(QSslCertificate::OrganizationalUnitName).first(), QString("Kde connect"));
|
||||
|
||||
kcc->setDeviceProperty("testdevice","certificate", QString::fromLatin1(certificate.toPem()));
|
||||
|
||||
KdeConnectConfig::DeviceInfo devInfo = kcc->getTrustedDevice("testdevice");
|
||||
QSslCertificate devCertificate = QSslCertificate::fromData(devInfo.certificate.toLatin1()).first();
|
||||
|
||||
QCOMPARE(devCertificate.serialNumber().toInt(0,16), 10);
|
||||
QCOMPARE(devCertificate.subjectInfo(QSslCertificate::SubjectInfo::CommonName).first(), kcc->deviceId());
|
||||
QCOMPARE(devCertificate.subjectInfo(QSslCertificate::SubjectInfo::Organization).first(), QString("KDE"));
|
||||
QCOMPARE(devCertificate.subjectInfo(QSslCertificate::OrganizationalUnitName).first(), QString("Kde connect"));
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void KdeConnectConfigTest::removeTrustedDevice()
|
||||
{
|
||||
KdeConnectConfig::instance().removeTrustedDevice(QStringLiteral("testdevice"));
|
||||
KdeConnectConfig::DeviceInfo devInfo = KdeConnectConfig::instance().getTrustedDevice(QStringLiteral("testdevice"));
|
||||
QCOMPARE(devInfo.deviceName, QStringLiteral("unnamed"));
|
||||
QCOMPARE(devInfo.deviceType, QStringLiteral("unknown"));
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(KdeConnectConfigTest)
|
||||
|
||||
#include "kdeconnectconfigtest.moc"
|
|
@ -1,454 +0,0 @@
|
|||
/**
|
||||
* Copyright 2015 Vineet Garg <grgvineet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// This class tests the behaviour of the class LanLinkProvider, be sure to kill process kdeconnectd to avoid any port binding issues
|
||||
|
||||
|
||||
#include "../core/backends/lan/lanlinkprovider.h"
|
||||
#include "../core/backends/lan/server.h"
|
||||
#include "../core/backends/lan/socketlinereader.h"
|
||||
#include "../core/kdeconnectconfig.h"
|
||||
|
||||
#include <QAbstractSocket>
|
||||
#include <QSslSocket>
|
||||
#include <QtTest>
|
||||
#include <QSslKey>
|
||||
#include <QUdpSocket>
|
||||
#include <QtCrypto>
|
||||
#include <QMetaEnum>
|
||||
|
||||
/*
|
||||
* This class tests the working of LanLinkProvider under different conditions that when identity packet is received over TCP, over UDP and same when the device is paired.
|
||||
* It depends on KdeConnectConfig since LanLinkProvider internally uses it.
|
||||
*/
|
||||
class LanLinkProviderTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LanLinkProviderTest()
|
||||
: m_lanLinkProvider(true)
|
||||
, m_server(nullptr)
|
||||
, m_reader(nullptr)
|
||||
, m_udpSocket(nullptr)
|
||||
{
|
||||
QStandardPaths::setTestModeEnabled(true);
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* Test that the LanLinkProvider will send an identity packet to a non-default port
|
||||
*/
|
||||
void testChangedUDPBroadcastPort();
|
||||
/**
|
||||
* Test that the LanLinkProvider will receive an identity packet on a non-default port
|
||||
*/
|
||||
void testChangedUDPListenPort();
|
||||
|
||||
void pairedDeviceTcpPacketReceived();
|
||||
void pairedDeviceUdpPacketReceived();
|
||||
|
||||
void unpairedDeviceTcpPacketReceived();
|
||||
void unpairedDeviceUdpPacketReceived();
|
||||
|
||||
|
||||
private:
|
||||
const int TEST_PORT = 8520;
|
||||
// Add some private fields here
|
||||
LanLinkProvider m_lanLinkProvider;
|
||||
Server* m_server;
|
||||
SocketLineReader* m_reader;
|
||||
QUdpSocket* m_udpSocket;
|
||||
QString m_identityPacket;
|
||||
|
||||
// Attributes for test device
|
||||
QString m_deviceId;
|
||||
QString m_name;
|
||||
QCA::PrivateKey m_privateKey;
|
||||
QSslCertificate m_certificate;
|
||||
|
||||
QSslCertificate generateCertificate(QString&, QCA::PrivateKey&);
|
||||
void addTrustedDevice();
|
||||
void removeTrustedDevice();
|
||||
void setSocketAttributes(QSslSocket* socket);
|
||||
void testIdentityPacket(QByteArray& identityPacket);
|
||||
void socketBindErrorFail(const QUdpSocket& socket);
|
||||
};
|
||||
|
||||
void LanLinkProviderTest::initTestCase()
|
||||
{
|
||||
removeTrustedDevice(); // Remove trusted device if left by chance by any test
|
||||
|
||||
m_deviceId = QStringLiteral("testdevice");
|
||||
m_name = QStringLiteral("Test Device");
|
||||
m_privateKey = QCA::KeyGenerator().createRSA(2048);
|
||||
m_certificate = generateCertificate(m_deviceId, m_privateKey);
|
||||
|
||||
m_identityPacket = QStringLiteral("{\"id\":1439365924847,\"type\":\"kdeconnect.identity\",\"body\":{\"deviceId\":\"testdevice\",\"deviceName\":\"Test Device\",\"protocolVersion\":6,\"deviceType\":\"phone\",\"tcpPort\":") + QString::number(TEST_PORT) + QStringLiteral("}}");
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::init()
|
||||
{
|
||||
m_lanLinkProvider.onStart();
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::cleanup()
|
||||
{
|
||||
m_lanLinkProvider.onStop();
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::testChangedUDPBroadcastPort()
|
||||
{
|
||||
quint16 udpListenPort = LanLinkProvider::UDP_PORT;
|
||||
quint16 udpBroadcastPort = LanLinkProvider::UDP_PORT + 1;
|
||||
|
||||
m_lanLinkProvider.onStop();
|
||||
LanLinkProvider testlanLinkProvider(true, udpBroadcastPort, udpListenPort);
|
||||
testlanLinkProvider.onStart();
|
||||
|
||||
QUdpSocket mUdpServer;
|
||||
bool bindSuccessful = mUdpServer.bind(QHostAddress::LocalHost, udpBroadcastPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
|
||||
if (!bindSuccessful) {
|
||||
socketBindErrorFail(mUdpServer);
|
||||
}
|
||||
|
||||
QSignalSpy spy(&mUdpServer, SIGNAL(readyRead()));
|
||||
testlanLinkProvider.onNetworkChange();
|
||||
QVERIFY2(!spy.isEmpty() || spy.wait(), "Did not receive UDP packet");
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::testChangedUDPListenPort()
|
||||
{
|
||||
quint16 udpListenPort = LanLinkProvider::UDP_PORT + 1;
|
||||
quint16 udpBroadcastPort = LanLinkProvider::UDP_PORT;
|
||||
|
||||
m_lanLinkProvider.onStop();
|
||||
LanLinkProvider testlanLinkProvider(true, udpBroadcastPort, udpListenPort);
|
||||
testlanLinkProvider.onStart();
|
||||
|
||||
m_server = new Server(this);
|
||||
QUdpSocket testUdpSocket;
|
||||
|
||||
m_server->listen(QHostAddress::LocalHost, TEST_PORT);
|
||||
|
||||
QSignalSpy spy(m_server, SIGNAL(newConnection()));
|
||||
|
||||
// Write an identity packet to udp socket here. We do not broadcast it here.
|
||||
qint64 bytesWritten = testUdpSocket.writeDatagram(m_identityPacket.toLatin1(), QHostAddress::LocalHost, udpListenPort);
|
||||
QCOMPARE(bytesWritten, m_identityPacket.size());
|
||||
|
||||
// In response to receiving an identity packet, the LanLinkProvider should try to open a TCP connection to us
|
||||
QVERIFY(!spy.isEmpty() || spy.wait());
|
||||
|
||||
QSslSocket* serverSocket = m_server->nextPendingConnection();
|
||||
|
||||
QVERIFY2(serverSocket != 0, "Server socket is null");
|
||||
QVERIFY2(serverSocket->isOpen(), "Server socket already closed");
|
||||
|
||||
delete m_server;
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::pairedDeviceTcpPacketReceived()
|
||||
{
|
||||
quint16 udpListenPort = LanLinkProvider::UDP_PORT;
|
||||
quint16 udpBroadcastPort = LanLinkProvider::UDP_PORT + 1;
|
||||
|
||||
m_lanLinkProvider.onStop();
|
||||
LanLinkProvider testlanLinkProvider(true, udpBroadcastPort, udpListenPort);
|
||||
testlanLinkProvider.onStart();
|
||||
|
||||
addTrustedDevice();
|
||||
|
||||
QUdpSocket* mUdpServer = new QUdpSocket;
|
||||
bool bindSuccessful = mUdpServer->bind(QHostAddress::LocalHost, udpBroadcastPort, QUdpSocket::ShareAddress);
|
||||
if (!bindSuccessful) {
|
||||
socketBindErrorFail(*mUdpServer);
|
||||
}
|
||||
|
||||
QSignalSpy spy(mUdpServer, SIGNAL(readyRead()));
|
||||
testlanLinkProvider.onNetworkChange();
|
||||
QVERIFY(!spy.isEmpty() || spy.wait());
|
||||
|
||||
QByteArray datagram;
|
||||
datagram.resize(mUdpServer->pendingDatagramSize());
|
||||
QHostAddress sender;
|
||||
|
||||
mUdpServer->readDatagram(datagram.data(), datagram.size(), &sender);
|
||||
|
||||
testIdentityPacket(datagram);
|
||||
|
||||
QJsonDocument jsonDocument = QJsonDocument::fromJson(datagram);
|
||||
QJsonObject body = jsonDocument.object().value(QStringLiteral("body")).toObject();
|
||||
int tcpPort = body.value(QStringLiteral("tcpPort")).toInt();
|
||||
|
||||
QSslSocket socket;
|
||||
QSignalSpy spy2(&socket, SIGNAL(connected()));
|
||||
|
||||
socket.connectToHost(sender, tcpPort);
|
||||
QVERIFY(spy2.wait());
|
||||
|
||||
QVERIFY2(socket.isOpen(), "Socket disconnected immediately");
|
||||
|
||||
socket.write(m_identityPacket.toLatin1());
|
||||
socket.waitForBytesWritten(2000);
|
||||
|
||||
QSignalSpy spy3(&socket, SIGNAL(encrypted()));
|
||||
|
||||
setSocketAttributes(&socket);
|
||||
socket.addCaCertificate(KdeConnectConfig::instance().certificate());
|
||||
socket.setPeerVerifyMode(QSslSocket::VerifyPeer);
|
||||
socket.setPeerVerifyName(KdeConnectConfig::instance().name());
|
||||
|
||||
socket.startServerEncryption();
|
||||
QVERIFY(spy3.wait());
|
||||
|
||||
QCOMPARE(socket.sslErrors().size(), 0);
|
||||
QVERIFY2(socket.isValid(), "Server socket disconnected");
|
||||
QVERIFY2(socket.isEncrypted(), "Server socket not yet encrypted");
|
||||
QVERIFY2(!socket.peerCertificate().isNull(), "Peer certificate is null");
|
||||
|
||||
removeTrustedDevice();
|
||||
delete mUdpServer;
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::pairedDeviceUdpPacketReceived()
|
||||
{
|
||||
addTrustedDevice();
|
||||
|
||||
m_server = new Server(this);
|
||||
m_udpSocket = new QUdpSocket(this);
|
||||
|
||||
m_server->listen(QHostAddress::LocalHost, TEST_PORT);
|
||||
|
||||
QSignalSpy spy(m_server, SIGNAL(newConnection()));
|
||||
|
||||
qint64 bytesWritten = m_udpSocket->writeDatagram(m_identityPacket.toLatin1(), QHostAddress::LocalHost, LanLinkProvider::UDP_PORT); // write an identity packet to udp socket here, we do not broadcast it here
|
||||
QCOMPARE(bytesWritten, m_identityPacket.size());
|
||||
|
||||
// We should have an incoming connection now, wait for incoming connection
|
||||
QVERIFY(!spy.isEmpty() || spy.wait());
|
||||
|
||||
QSslSocket* serverSocket = m_server->nextPendingConnection();
|
||||
|
||||
QVERIFY2(serverSocket != 0, "Server socket is null");
|
||||
QVERIFY2(serverSocket->isOpen(), "Server socket already closed");
|
||||
|
||||
m_reader = new SocketLineReader(serverSocket, this);
|
||||
QSignalSpy spy2(m_reader, SIGNAL(readyRead()));
|
||||
QVERIFY(spy2.wait());
|
||||
|
||||
QByteArray receivedPacket = m_reader->readLine();
|
||||
testIdentityPacket(receivedPacket);
|
||||
// Received identity packet from LanLinkProvider now start ssl
|
||||
|
||||
QSignalSpy spy3(serverSocket, SIGNAL(encrypted()));
|
||||
QVERIFY(connect(serverSocket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QSslSocket::error),
|
||||
this, [](QAbstractSocket::SocketError error){ qDebug() << "error:" << error; }));
|
||||
|
||||
setSocketAttributes(serverSocket);
|
||||
serverSocket->addCaCertificate(KdeConnectConfig::instance().certificate());
|
||||
serverSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
|
||||
serverSocket->setPeerVerifyName(KdeConnectConfig::instance().deviceId());
|
||||
|
||||
serverSocket->startClientEncryption(); // Its TCP server. but SSL client
|
||||
QVERIFY(!serverSocket->isEncrypted());
|
||||
spy3.wait(2000);
|
||||
qDebug() << "xxxxxxxxx" << serverSocket->sslErrors();
|
||||
|
||||
QCOMPARE(serverSocket->sslErrors().size(), 0);
|
||||
QVERIFY2(serverSocket->isValid(), "Server socket disconnected");
|
||||
QVERIFY2(serverSocket->isEncrypted(), "Server socket not yet encrypted");
|
||||
QVERIFY2(!serverSocket->peerCertificate().isNull(), "Peer certificate is null");
|
||||
|
||||
removeTrustedDevice();
|
||||
|
||||
delete m_server;
|
||||
delete m_udpSocket;
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::unpairedDeviceTcpPacketReceived()
|
||||
{
|
||||
quint16 udpListenPort = LanLinkProvider::UDP_PORT;
|
||||
quint16 udpBroadcastPort = LanLinkProvider::UDP_PORT + 1;
|
||||
|
||||
m_lanLinkProvider.onStop();
|
||||
LanLinkProvider testlanLinkProvider(true, udpBroadcastPort, udpListenPort);
|
||||
testlanLinkProvider.onStart();
|
||||
|
||||
QUdpSocket* mUdpServer = new QUdpSocket;
|
||||
bool bindSuccessful = mUdpServer->bind(QHostAddress::LocalHost, udpBroadcastPort, QUdpSocket::ShareAddress);
|
||||
if (!bindSuccessful) {
|
||||
socketBindErrorFail(*mUdpServer);
|
||||
}
|
||||
|
||||
QSignalSpy spy(mUdpServer, SIGNAL(readyRead()));
|
||||
testlanLinkProvider.onNetworkChange();
|
||||
QVERIFY(!spy.isEmpty() || spy.wait());
|
||||
|
||||
QByteArray datagram;
|
||||
datagram.resize(mUdpServer->pendingDatagramSize());
|
||||
QHostAddress sender;
|
||||
|
||||
mUdpServer->readDatagram(datagram.data(), datagram.size(), &sender);
|
||||
|
||||
testIdentityPacket(datagram);
|
||||
|
||||
QJsonDocument jsonDocument = QJsonDocument::fromJson(datagram);
|
||||
QJsonObject body = jsonDocument.object().value(QStringLiteral("body")).toObject();
|
||||
int tcpPort = body.value(QStringLiteral("tcpPort")).toInt();
|
||||
|
||||
QSslSocket socket;
|
||||
QSignalSpy spy2(&socket, SIGNAL(connected()));
|
||||
|
||||
socket.connectToHost(sender, tcpPort);
|
||||
QVERIFY(spy2.wait());
|
||||
|
||||
QVERIFY2(socket.isOpen(), "Socket disconnected immediately");
|
||||
|
||||
socket.write(m_identityPacket.toLatin1());
|
||||
socket.waitForBytesWritten(2000);
|
||||
|
||||
QSignalSpy spy3(&socket, SIGNAL(encrypted()));
|
||||
// We don't take care for sslErrors signal here, but signal will emit still we will get successful connection
|
||||
|
||||
setSocketAttributes(&socket);
|
||||
socket.setPeerVerifyMode(QSslSocket::QueryPeer);
|
||||
|
||||
socket.startServerEncryption();
|
||||
|
||||
QVERIFY(spy3.wait());
|
||||
|
||||
QVERIFY2(socket.isValid(), "Server socket disconnected");
|
||||
QVERIFY2(socket.isEncrypted(), "Server socket not yet encrypted");
|
||||
QVERIFY2(!socket.peerCertificate().isNull(), "Peer certificate is null");
|
||||
|
||||
delete mUdpServer;
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::unpairedDeviceUdpPacketReceived()
|
||||
{
|
||||
m_server = new Server(this);
|
||||
m_udpSocket = new QUdpSocket(this);
|
||||
|
||||
m_server->listen(QHostAddress::LocalHost, TEST_PORT);
|
||||
|
||||
QSignalSpy spy(m_server, &Server::newConnection);
|
||||
qint64 bytesWritten = m_udpSocket->writeDatagram(m_identityPacket.toLatin1(), QHostAddress::LocalHost, LanLinkProvider::UDP_PORT); // write an identity packet to udp socket here, we do not broadcast it here
|
||||
QCOMPARE(bytesWritten, m_identityPacket.size());
|
||||
|
||||
QVERIFY(!spy.isEmpty() || spy.wait());
|
||||
|
||||
QSslSocket* serverSocket = m_server->nextPendingConnection();
|
||||
|
||||
QVERIFY2(serverSocket != 0, "Server socket is null");
|
||||
QVERIFY2(serverSocket->isOpen(), "Server socket already closed");
|
||||
|
||||
m_reader = new SocketLineReader(serverSocket, this);
|
||||
QSignalSpy spy2(m_reader, &SocketLineReader::readyRead);
|
||||
QVERIFY(spy2.wait());
|
||||
|
||||
QByteArray receivedPacket = m_reader->readLine();
|
||||
QVERIFY2(!receivedPacket.isEmpty(), "Empty packet received");
|
||||
|
||||
testIdentityPacket(receivedPacket);
|
||||
|
||||
// Received identity packet from LanLinkProvider now start ssl
|
||||
|
||||
QSignalSpy spy3(serverSocket, SIGNAL(encrypted()));
|
||||
|
||||
setSocketAttributes(serverSocket);
|
||||
serverSocket->setPeerVerifyMode(QSslSocket::QueryPeer);
|
||||
serverSocket->startClientEncryption(); // Its TCP server. but SSL client
|
||||
QVERIFY(spy3.wait());
|
||||
|
||||
QVERIFY2(serverSocket->isValid(), "Server socket disconnected");
|
||||
QVERIFY2(serverSocket->isEncrypted(), "Server socket not yet encrypted");
|
||||
QVERIFY2(!serverSocket->peerCertificate().isNull(), "Peer certificate is null");
|
||||
|
||||
delete m_server;
|
||||
delete m_udpSocket;
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::testIdentityPacket(QByteArray& identityPacket)
|
||||
{
|
||||
QJsonDocument jsonDocument = QJsonDocument::fromJson(identityPacket);
|
||||
QJsonObject jsonObject = jsonDocument.object();
|
||||
QJsonObject body = jsonObject.value(QStringLiteral("body")).toObject();
|
||||
|
||||
QCOMPARE(jsonObject.value(QStringLiteral("type")).toString(), QStringLiteral("kdeconnect.identity"));
|
||||
QVERIFY2(body.contains(QStringLiteral("deviceName")), "Device name not found in identity packet");
|
||||
QVERIFY2(body.contains(QStringLiteral("deviceId")), "Device id not found in identity packet");
|
||||
QVERIFY2(body.contains(QStringLiteral("protocolVersion")), "Protocol version not found in identity packet");
|
||||
QVERIFY2(body.contains(QStringLiteral("deviceType")), "Device type not found in identity packet");
|
||||
}
|
||||
|
||||
QSslCertificate LanLinkProviderTest::generateCertificate(QString& commonName, QCA::PrivateKey& privateKey)
|
||||
{
|
||||
QDateTime startTime = QDateTime::currentDateTime();
|
||||
QDateTime endTime = startTime.addYears(10);
|
||||
QCA::CertificateInfo certificateInfo;
|
||||
certificateInfo.insert(QCA::CommonName,commonName);
|
||||
certificateInfo.insert(QCA::Organization,QStringLiteral("KDE"));
|
||||
certificateInfo.insert(QCA::OrganizationalUnit,QStringLiteral("Kde connect"));
|
||||
|
||||
QCA::CertificateOptions certificateOptions(QCA::PKCS10);
|
||||
certificateOptions.setSerialNumber(10);
|
||||
certificateOptions.setInfo(certificateInfo);
|
||||
certificateOptions.setValidityPeriod(startTime, endTime);
|
||||
certificateOptions.setFormat(QCA::PKCS10);
|
||||
|
||||
QSslCertificate certificate = QSslCertificate(QCA::Certificate(certificateOptions, privateKey).toPEM().toLatin1());
|
||||
return certificate;
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::setSocketAttributes(QSslSocket* socket)
|
||||
{
|
||||
socket->setPrivateKey(QSslKey(m_privateKey.toPEM().toLatin1(), QSsl::Rsa));
|
||||
socket->setLocalCertificate(m_certificate);
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::addTrustedDevice()
|
||||
{
|
||||
KdeConnectConfig::instance().addTrustedDevice(m_deviceId, m_name, QStringLiteral("phone"));
|
||||
KdeConnectConfig::instance().setDeviceProperty(m_deviceId, QStringLiteral("certificate"), QString::fromLatin1(m_certificate.toPem()));
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::removeTrustedDevice()
|
||||
{
|
||||
KdeConnectConfig::instance().removeTrustedDevice(m_deviceId);
|
||||
}
|
||||
|
||||
void LanLinkProviderTest::socketBindErrorFail(const QUdpSocket& socket)
|
||||
{
|
||||
QAbstractSocket::SocketError sockErr = socket.error();
|
||||
// Refer to https://doc.qt.io/qt-5/qabstractsocket.html#SocketError-enum to decode socket error number
|
||||
QString errorMessage = QLatin1String("Failed to bind UDP socket with error ");
|
||||
errorMessage = errorMessage + QString::fromLatin1(QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey(sockErr));
|
||||
QFAIL(errorMessage.toLocal8Bit().data());
|
||||
}
|
||||
|
||||
|
||||
QTEST_GUILESS_MAIN(LanLinkProviderTest)
|
||||
|
||||
#include "lanlinkprovidertest.moc"
|
|
@ -1,143 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "networkpackettests.h"
|
||||
|
||||
#include "core/networkpacket.h"
|
||||
|
||||
#include <QtTest>
|
||||
#include <QBuffer>
|
||||
|
||||
QTEST_GUILESS_MAIN(NetworkPacketTests);
|
||||
|
||||
void NetworkPacketTests::initTestCase()
|
||||
{
|
||||
// Called before the first testfunction is executed
|
||||
}
|
||||
|
||||
void NetworkPacketTests::networkPacketTest()
|
||||
{
|
||||
NetworkPacket np(QStringLiteral("com.test"));
|
||||
|
||||
np.set(QStringLiteral("hello"), QStringLiteral("hola"));
|
||||
QCOMPARE( (np.get<QString>(QStringLiteral("hello"), QStringLiteral("bye"))) , QStringLiteral("hola") );
|
||||
|
||||
np.set(QStringLiteral("hello"), QString());
|
||||
QCOMPARE((np.get<QString>(QStringLiteral("hello"), QStringLiteral("bye"))) , QString());
|
||||
|
||||
np.body().remove(QStringLiteral("hello"));
|
||||
QCOMPARE((np.get<QString>(QStringLiteral("hello"), QStringLiteral("bye"))) , QStringLiteral("bye"));
|
||||
|
||||
np.set(QStringLiteral("foo"), QStringLiteral("bar"));
|
||||
QByteArray ba = np.serialize();
|
||||
//qDebug() << "Serialized packet:" << ba;
|
||||
NetworkPacket np2(QLatin1String(""));
|
||||
NetworkPacket::unserialize(ba,&np2);
|
||||
|
||||
QCOMPARE( np.id(), np2.id() );
|
||||
QCOMPARE( np.type(), np2.type() );
|
||||
QCOMPARE( np.body(), np2.body() );
|
||||
|
||||
QByteArray json("{\"id\":\"123\",\"type\":\"test\",\"body\":{\"testing\":true}}");
|
||||
//qDebug() << json;
|
||||
NetworkPacket::unserialize(json,&np2);
|
||||
QCOMPARE( np2.id(), QStringLiteral("123") );
|
||||
QCOMPARE( (np2.get<bool>(QStringLiteral("testing"))), true );
|
||||
QCOMPARE( (np2.get<bool>(QStringLiteral("not_testing"))), false );
|
||||
QCOMPARE( (np2.get<bool>(QStringLiteral("not_testing"),true)), true );
|
||||
|
||||
//NetworkPacket::unserialize("this is not json",&np2);
|
||||
//QtTest::ignoreMessage(QtSystemMsg, "json_parser - syntax error found, forcing abort, Line 1 Column 0");
|
||||
//QtTest::ignoreMessage(QtDebugMsg, "Unserialization error: 1 \"syntax error, unexpected string\"");
|
||||
|
||||
}
|
||||
|
||||
void NetworkPacketTests::networkPacketIdentityTest()
|
||||
{
|
||||
NetworkPacket np(QLatin1String(""));
|
||||
NetworkPacket::createIdentityPacket(&np);
|
||||
|
||||
QCOMPARE( np.get<int>(QStringLiteral("protocolVersion"), -1) , NetworkPacket::s_protocolVersion );
|
||||
QCOMPARE( np.type() , PACKET_TYPE_IDENTITY );
|
||||
|
||||
}
|
||||
|
||||
void NetworkPacketTests::networkPacketPayloadTest()
|
||||
{
|
||||
QByteArray json;
|
||||
NetworkPacket np;
|
||||
|
||||
// empty package
|
||||
np = NetworkPacket(QStringLiteral("com.test"));
|
||||
json = np.serialize();
|
||||
qDebug() << json;
|
||||
QVERIFY(!json.contains("\"payloadSize\""));
|
||||
QVERIFY(!json.contains("\"payloadTransferInfo\""));
|
||||
|
||||
// package with payload
|
||||
QByteArray buffer("test data");
|
||||
auto payload = QSharedPointer<QIODevice>(new QBuffer(&buffer, this));
|
||||
np = NetworkPacket(QStringLiteral("com.test"));
|
||||
np.setPayload(payload, buffer.size());
|
||||
|
||||
json = np.serialize();
|
||||
qDebug() << json;
|
||||
QVERIFY(json.contains("\"payloadSize\":9"));
|
||||
QVERIFY(json.contains("\"payloadTransferInfo\""));
|
||||
|
||||
// package with empty payload
|
||||
QByteArray emptyBuffer("test data");
|
||||
auto emptyPayload = QSharedPointer<QIODevice>(new QBuffer(&emptyBuffer, this));
|
||||
np = NetworkPacket(QStringLiteral("com.test"));
|
||||
np.setPayload(emptyPayload, 0);
|
||||
|
||||
json = np.serialize();
|
||||
qDebug() << json;
|
||||
QVERIFY(!json.contains("\"payloadSize\""));
|
||||
QVERIFY(!json.contains("\"payloadTransferInfo\""));
|
||||
|
||||
// incoming package without payload
|
||||
np = NetworkPacket();
|
||||
QVERIFY(NetworkPacket::unserialize(
|
||||
"{\"body\":{},\"id\":\"1578136807254\",\"type\":\"com.test\"}\n", &np));
|
||||
QVERIFY(!np.hasPayload());
|
||||
|
||||
// incoming package without payload (but with payload keys)
|
||||
np = NetworkPacket();
|
||||
QVERIFY(NetworkPacket::unserialize(
|
||||
"{\"body\":{},\"id\":\"1578136807254\",\"payloadSize\":0,\"payloadTransferInfo\":{},\"type\":\"com.test\"}\n", &np));
|
||||
QVERIFY(!np.hasPayload());
|
||||
}
|
||||
|
||||
void NetworkPacketTests::cleanupTestCase()
|
||||
{
|
||||
// Called after the last testfunction was executed
|
||||
}
|
||||
|
||||
void NetworkPacketTests::init()
|
||||
{
|
||||
// Called before each testfunction is executed
|
||||
}
|
||||
|
||||
void NetworkPacketTests::cleanup()
|
||||
{
|
||||
// Called after every testfunction
|
||||
}
|
||||
|
|
@ -1,456 +0,0 @@
|
|||
/**
|
||||
* Copyright 2015 Holger Kaelberer <holger.k@elberer.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QSocketNotifier>
|
||||
#include <QApplication>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QTest>
|
||||
#include <QBuffer>
|
||||
#include <QStandardPaths>
|
||||
#include <QImage>
|
||||
#include <QColor>
|
||||
|
||||
#include <kiconloader.h>
|
||||
|
||||
#include "core/daemon.h"
|
||||
#include "core/device.h"
|
||||
#include "testdevice.h"
|
||||
#include "core/kdeconnectplugin.h"
|
||||
#include "kdeconnect-version.h"
|
||||
#include "plugins/sendnotifications/sendnotificationsplugin.h"
|
||||
#include "plugins/sendnotifications/notificationslistener.h"
|
||||
#include "plugins/sendnotifications/notifyingapplication.h"
|
||||
|
||||
// Tweaked NotificationsPlugin for testing
|
||||
class TestNotificationsPlugin : public SendNotificationsPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TestNotificationsPlugin(QObject* parent, const QVariantList& args)
|
||||
: SendNotificationsPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
~TestNotificationsPlugin() override = default;
|
||||
|
||||
// allow to access notificationsListener for testing:
|
||||
NotificationsListener* getNotificationsListener() const
|
||||
{
|
||||
return notificationsListener;
|
||||
}
|
||||
|
||||
void setNotificationsListener(NotificationsListener* value)
|
||||
{
|
||||
notificationsListener = value;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Tweaked NotificationsListener for testing:
|
||||
class TestedNotificationsListener: public NotificationsListener
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TestedNotificationsListener(KdeConnectPlugin* aPlugin)
|
||||
: NotificationsListener(aPlugin)
|
||||
{}
|
||||
|
||||
~TestedNotificationsListener() override
|
||||
{}
|
||||
|
||||
QHash<QString, NotifyingApplication>& getApplications()
|
||||
{
|
||||
return m_applications;
|
||||
}
|
||||
|
||||
void setApplications(const QHash<QString, NotifyingApplication>& value)
|
||||
{
|
||||
m_applications = value;
|
||||
}
|
||||
|
||||
QSharedPointer<QIODevice> iconForIconName(const QString& iconName) const {
|
||||
return NotificationsListener::iconForIconName(iconName);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool parseImageDataArgument(const QVariant& argument, int& width,
|
||||
int& height, int& rowStride, int& bitsPerSample,
|
||||
int& channels, bool& hasAlpha,
|
||||
QByteArray& imageData) const override
|
||||
{
|
||||
width = argument.toMap().value(QStringLiteral("width")).toInt();
|
||||
height = argument.toMap().value(QStringLiteral("height")).toInt();
|
||||
rowStride = argument.toMap().value(QStringLiteral("rowStride")).toInt();
|
||||
bitsPerSample = argument.toMap().value(QStringLiteral("bitsPerSample")).toInt();
|
||||
channels = argument.toMap().value(QStringLiteral("channels")).toInt();
|
||||
hasAlpha = argument.toMap().value(QStringLiteral("hasAlpha")).toBool();
|
||||
imageData = argument.toMap().value(QStringLiteral("imageData")).toByteArray();
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class TestNotificationListener : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestNotificationListener()
|
||||
: plugin(nullptr)
|
||||
{
|
||||
QStandardPaths::setTestModeEnabled(true);
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
void testNotify();
|
||||
|
||||
private:
|
||||
TestNotificationsPlugin* plugin;
|
||||
};
|
||||
|
||||
void TestNotificationListener::testNotify()
|
||||
{
|
||||
//
|
||||
// set things up:
|
||||
//
|
||||
|
||||
QString dId(QStringLiteral("testid"));
|
||||
TestDevice* d = new TestDevice(nullptr, dId);
|
||||
|
||||
int proxiedNotifications = 0;
|
||||
QCOMPARE(proxiedNotifications, d->getSentPackets());
|
||||
plugin = new TestNotificationsPlugin(this,
|
||||
QVariantList({ QVariant::fromValue<Device*>(d),
|
||||
QStringLiteral("notifications_plugin"),
|
||||
{QStringLiteral("kdeconnect.notification")},
|
||||
QStringLiteral("preferences-desktop-notification")}));
|
||||
QVERIFY(plugin->getNotificationsListener());
|
||||
delete plugin->getNotificationsListener();
|
||||
|
||||
// inject our tweaked NotificationsListener:
|
||||
TestedNotificationsListener* listener = new TestedNotificationsListener(plugin);
|
||||
QVERIFY(listener);
|
||||
plugin->setNotificationsListener(listener);
|
||||
QCOMPARE(listener, plugin->getNotificationsListener());
|
||||
|
||||
// make sure config is default:
|
||||
plugin->config()->set(QStringLiteral("generalPersistent"), false);
|
||||
plugin->config()->set(QStringLiteral("generalIncludeBody"), true);
|
||||
plugin->config()->set(QStringLiteral("generalUrgency"), 0);
|
||||
QCOMPARE(plugin->config()->get<bool>(QStringLiteral("generalPersistent")), false);
|
||||
QCOMPARE(plugin->config()->get<bool>(QStringLiteral("generalIncludeBody")), true);
|
||||
QCOMPARE(plugin->config()->get<bool>(QStringLiteral("generalUrgency")), false);
|
||||
|
||||
// applications are modified directly:
|
||||
listener->getApplications().clear();
|
||||
QCOMPARE(listener->getApplications().count(), 0);
|
||||
|
||||
//
|
||||
// Go !!!
|
||||
//
|
||||
|
||||
uint replacesId = 99;
|
||||
uint retId;
|
||||
QString appName(QStringLiteral("some-appName"));
|
||||
QString body(QStringLiteral("some-body"));
|
||||
QString icon(QStringLiteral("some-icon"));
|
||||
QString summary(QStringLiteral("some-summary"));
|
||||
|
||||
// regular Notify call that is synchronized ...
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 0);
|
||||
// ... should return replacesId,
|
||||
QCOMPARE(retId, replacesId);
|
||||
// ... have triggered sending a packet
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
// ... with our properties,
|
||||
QCOMPARE(d->getLastPacket()->get<uint>(QStringLiteral("id")), replacesId);
|
||||
QCOMPARE(d->getLastPacket()->get<QString>(QStringLiteral("appName")), appName);
|
||||
QCOMPARE(d->getLastPacket()->get<QString>(QStringLiteral("ticker")), summary + QStringLiteral(": ") + body);
|
||||
QCOMPARE(d->getLastPacket()->get<bool>(QStringLiteral("isClearable")), true);
|
||||
QCOMPARE(d->getLastPacket()->hasPayload(), false);
|
||||
|
||||
// ... and create a new application internally that is initialized correctly:
|
||||
QCOMPARE(listener->getApplications().count(), 1);
|
||||
QVERIFY(listener->getApplications().contains(appName));
|
||||
QVERIFY(listener->getApplications()[appName].active);
|
||||
QCOMPARE(listener->getApplications()[appName].name, appName);
|
||||
QVERIFY(listener->getApplications()[appName].blacklistExpression.pattern().isEmpty());
|
||||
QCOMPARE(listener->getApplications()[appName].name, appName);
|
||||
QCOMPARE(listener->getApplications()[appName].icon, icon);
|
||||
|
||||
// another one, with other timeout and urgency values:
|
||||
QString appName2(QStringLiteral("some-appName2"));
|
||||
QString body2(QStringLiteral("some-body2"));
|
||||
QString icon2(QStringLiteral("some-icon2"));
|
||||
QString summary2(QStringLiteral("some-summary2"));
|
||||
|
||||
retId = listener->Notify(appName2, replacesId+1, icon2, summary2, body2, {}, {{QStringLiteral("urgency"), 2}}, 10);
|
||||
QCOMPARE(retId, replacesId+1);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QCOMPARE(d->getLastPacket()->get<uint>(QStringLiteral("id")), replacesId+1);
|
||||
QCOMPARE(d->getLastPacket()->get<QString>(QStringLiteral("appName")), appName2);
|
||||
QCOMPARE(d->getLastPacket()->get<QString>(QStringLiteral("ticker")), summary2 + QStringLiteral(": ") + body2);
|
||||
QCOMPARE(d->getLastPacket()->get<bool>(QStringLiteral("isClearable")), false); // timeout != 0
|
||||
QCOMPARE(d->getLastPacket()->hasPayload(), false);
|
||||
QCOMPARE(listener->getApplications().count(), 2);
|
||||
QVERIFY(listener->getApplications().contains(appName2));
|
||||
QVERIFY(listener->getApplications().contains(appName));
|
||||
|
||||
// if persistent-only is set, timeouts > 0 are not synced:
|
||||
plugin->config()->set(QStringLiteral("generalPersistent"), true);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 1);
|
||||
QCOMPARE(retId, 0U);
|
||||
QCOMPARE(proxiedNotifications, d->getSentPackets());
|
||||
retId = listener->Notify(appName2, replacesId, icon2, summary2, body2, {}, {{}}, 3);
|
||||
QCOMPARE(retId, 0U);
|
||||
QCOMPARE(proxiedNotifications, d->getSentPackets());
|
||||
// but timeout == 0 is
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
plugin->config()->set(QStringLiteral("generalPersistent"), false);
|
||||
|
||||
// if min-urgency is set, lower urgency levels are not synced:
|
||||
plugin->config()->set(QStringLiteral("generalUrgency"), 1);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{QStringLiteral("urgency"), 0}}, 0);
|
||||
QCOMPARE(retId, 0U);
|
||||
QCOMPARE(proxiedNotifications, d->getSentPackets());
|
||||
// equal urgency is
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{QStringLiteral("urgency"), 1}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
// higher urgency as well
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{QStringLiteral("urgency"), 2}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
plugin->config()->set(QStringLiteral("generalUrgency"), 0);
|
||||
|
||||
// notifications for a deactivated application are not synced:
|
||||
QVERIFY(listener->getApplications().contains(appName));
|
||||
listener->getApplications()[appName].active = false;
|
||||
QVERIFY(!listener->getApplications()[appName].active);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{QStringLiteral("urgency"), 0}}, 0);
|
||||
QCOMPARE(retId, 0U);
|
||||
QCOMPARE(proxiedNotifications, d->getSentPackets());
|
||||
// others are still:
|
||||
retId = listener->Notify(appName2, replacesId+1, icon2, summary2, body2, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId+1);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
// back to normal:
|
||||
listener->getApplications()[appName].active = true;
|
||||
QVERIFY(listener->getApplications()[appName].active);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
|
||||
// notifications with blacklisted subjects are not synced:
|
||||
QVERIFY(listener->getApplications().contains(appName));
|
||||
listener->getApplications()[appName].blacklistExpression.setPattern(QStringLiteral("black[12]|foo(bar|baz)"));
|
||||
retId = listener->Notify(appName, replacesId, icon, QStringLiteral("summary black1"), body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, 0U);
|
||||
QCOMPARE(proxiedNotifications, d->getSentPackets());
|
||||
retId = listener->Notify(appName, replacesId, icon, QStringLiteral("summary foobar"), body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, 0U);
|
||||
QCOMPARE(proxiedNotifications, d->getSentPackets());
|
||||
// other subjects are synced:
|
||||
retId = listener->Notify(appName, replacesId, icon, QStringLiteral("summary foo"), body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
retId = listener->Notify(appName, replacesId, icon, QStringLiteral("summary black3"), body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
// also body is checked by blacklist if requested:
|
||||
plugin->config()->set(QStringLiteral("generalIncludeBody"), true);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, QStringLiteral("body black1"), {}, {{}}, 0);
|
||||
QCOMPARE(retId, 0U);
|
||||
QCOMPARE(proxiedNotifications, d->getSentPackets());
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, QStringLiteral("body foobaz"), {}, {{}}, 0);
|
||||
QCOMPARE(retId, 0U);
|
||||
QCOMPARE(proxiedNotifications, d->getSentPackets());
|
||||
// body does not matter if inclusion was not requested:
|
||||
plugin->config()->set(QStringLiteral("generalIncludeBody"), false);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, QStringLiteral("body black1"), {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
// without body, also ticker value is different:
|
||||
QCOMPARE(d->getLastPacket()->get<QString>(QStringLiteral("ticker")), summary);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, QStringLiteral("body foobaz"), {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
|
||||
// back to normal:
|
||||
listener->getApplications()[appName].blacklistExpression.setPattern(QLatin1String(""));
|
||||
plugin->config()->set(QStringLiteral("generalIncludeBody"), true);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
retId = listener->Notify(appName2, replacesId, icon2, summary2, body2, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
|
||||
// icon synchronization:
|
||||
QStringList iconPaths;
|
||||
// appIcon
|
||||
int count = 0;
|
||||
const QStringList icons = KIconLoader::global()->queryIcons(-KIconLoader::SizeEnormous, KIconLoader::Application);
|
||||
for (const auto& iconName : icons) {
|
||||
if (!iconName.endsWith(QLatin1String(".png")))
|
||||
continue;
|
||||
if (count++ > 3) // max 3 iterations
|
||||
break;
|
||||
iconPaths.append(iconName); // memorize some paths for later
|
||||
|
||||
// existing icons are sync-ed if requested
|
||||
plugin->config()->set(QStringLiteral("generalSynchronizeIcons"), true);
|
||||
QFileInfo fi(iconName);
|
||||
retId = listener->Notify(appName, replacesId, fi.baseName(), summary, body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QVERIFY(d->getLastPacket()->hasPayload());
|
||||
QCOMPARE(d->getLastPacket()->payloadSize(), listener->iconForIconName(fi.baseName())->size());
|
||||
// works also with absolute paths
|
||||
retId = listener->Notify(appName, replacesId, iconName, summary, body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QVERIFY(d->getLastPacket()->hasPayload());
|
||||
QCOMPARE(d->getLastPacket()->payloadSize(), fi.size());
|
||||
// extensions other than png are not accepted:
|
||||
retId = listener->Notify(appName, replacesId, iconName + QStringLiteral(".svg"), summary, body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QVERIFY(!d->getLastPacket()->hasPayload());
|
||||
|
||||
// if sync not requested no payload:
|
||||
plugin->config()->set(QStringLiteral("generalSynchronizeIcons"), false);
|
||||
retId = listener->Notify(appName, replacesId, fi.baseName(), summary, body, {}, {{}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QVERIFY(!d->getLastPacket()->hasPayload());
|
||||
QCOMPARE(d->getLastPacket()->payloadSize(), 0);
|
||||
}
|
||||
plugin->config()->set(QStringLiteral("generalSynchronizeIcons"), true);
|
||||
|
||||
// image-path in hints
|
||||
if (iconPaths.size() > 0) {
|
||||
retId = listener->Notify(appName, replacesId, iconPaths.size() > 1 ? iconPaths[1] : icon, summary, body, {}, {{QStringLiteral("image-path"), iconPaths[0]}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QVERIFY(d->getLastPacket()->hasPayload());
|
||||
QFileInfo hintsFi(iconPaths[0]);
|
||||
// image-path has priority over appIcon parameter:
|
||||
QCOMPARE(d->getLastPacket()->payloadSize(), hintsFi.size());
|
||||
}
|
||||
|
||||
// image_path in hints
|
||||
if (iconPaths.size() > 0) {
|
||||
retId = listener->Notify(appName, replacesId, iconPaths.size() > 1 ? iconPaths[1] : icon, summary, body, {}, {{QStringLiteral("image_path"), iconPaths[0]}}, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QVERIFY(d->getLastPacket()->hasPayload());
|
||||
QFileInfo hintsFi(iconPaths[0]);
|
||||
// image_path has priority over appIcon parameter:
|
||||
QCOMPARE(d->getLastPacket()->payloadSize(), hintsFi.size());
|
||||
}
|
||||
|
||||
// image-data in hints
|
||||
// set up:
|
||||
QBuffer* buffer;
|
||||
QImage image;
|
||||
int width = 2, height = 2, rowStride = 4*width, bitsPerSample = 8,
|
||||
channels = 4;
|
||||
bool hasAlpha = 1;
|
||||
char rawData[] = { 0x01, 0x02, 0x03, 0x04, // raw rgba data
|
||||
0x11, 0x12, 0x13, 0x14,
|
||||
0x21, 0x22, 0x23, 0x24,
|
||||
0x31, 0x32, 0x33, 0x34 };
|
||||
QVariantMap imageData = {{QStringLiteral("width"), width}, {QStringLiteral("height"), height}, {QStringLiteral("rowStride"), rowStride},
|
||||
{QStringLiteral("bitsPerSample"), bitsPerSample}, {QStringLiteral("channels"), channels},
|
||||
{QStringLiteral("hasAlpha"), hasAlpha}, {QStringLiteral("imageData"), QByteArray(rawData, sizeof(rawData))}};
|
||||
QVariantMap hints;
|
||||
#define COMPARE_PIXEL(x, y) \
|
||||
QCOMPARE(qRed(image.pixel(x,y)), (int)rawData[x*4 + y*rowStride + 0]); \
|
||||
QCOMPARE(qGreen(image.pixel(x,y)), (int)rawData[x*4 + y*rowStride + 1]); \
|
||||
QCOMPARE(qBlue(image.pixel(x,y)), (int)rawData[x*4 + y*rowStride + 2]); \
|
||||
QCOMPARE(qAlpha(image.pixel(x,y)), (int)rawData[x*4 + y*rowStride + 3]);
|
||||
|
||||
hints.insert(QStringLiteral("image-data"), imageData);
|
||||
if (iconPaths.size() > 0)
|
||||
hints.insert(QStringLiteral("image-path"), iconPaths[0]);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, hints, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QVERIFY(d->getLastPacket()->hasPayload());
|
||||
buffer = dynamic_cast<QBuffer*>(d->getLastPacket()->payload().data());
|
||||
QCOMPARE(d->getLastPacket()->payloadSize(), buffer->size());
|
||||
// image-data is attached as png data
|
||||
QVERIFY(image.loadFromData(reinterpret_cast<const uchar*>(buffer->data().constData()), buffer->size(), "PNG"));
|
||||
// image-data has priority over image-path:
|
||||
QCOMPARE(image.sizeInBytes(), rowStride*height);
|
||||
// rgba -> argb conversion was done correctly:
|
||||
COMPARE_PIXEL(0,0);
|
||||
COMPARE_PIXEL(1,0);
|
||||
COMPARE_PIXEL(0,1);
|
||||
COMPARE_PIXEL(1,1);
|
||||
|
||||
// same for image_data in hints
|
||||
hints.clear();
|
||||
hints.insert(QStringLiteral("image-data"), imageData);
|
||||
if (iconPaths.size() > 0)
|
||||
hints.insert(QStringLiteral("image_path"), iconPaths[0]);
|
||||
retId = listener->Notify(appName, replacesId, icon, summary, body, {}, hints, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QVERIFY(d->getLastPacket()->hasPayload());
|
||||
buffer = dynamic_cast<QBuffer*>(d->getLastPacket()->payload().data());
|
||||
QCOMPARE(d->getLastPacket()->payloadSize(), buffer->size());
|
||||
// image-data is attached as png data
|
||||
QVERIFY(image.loadFromData(reinterpret_cast<const uchar*>(buffer->data().constData()), buffer->size(), "PNG"));
|
||||
// image_data has priority over image_path/image-path:
|
||||
QCOMPARE(image.sizeInBytes(), rowStride*height);
|
||||
// rgba -> argb conversion was done correctly:
|
||||
COMPARE_PIXEL(0,0);
|
||||
COMPARE_PIXEL(1,0);
|
||||
COMPARE_PIXEL(0,1);
|
||||
COMPARE_PIXEL(1,1);
|
||||
|
||||
// same for icon_data, which has lowest priority
|
||||
hints.clear();
|
||||
hints.insert(QStringLiteral("icon_data"), imageData);
|
||||
retId = listener->Notify(appName, replacesId, QLatin1String(""), summary, body, {}, hints, 0);
|
||||
QCOMPARE(retId, replacesId);
|
||||
QCOMPARE(++proxiedNotifications, d->getSentPackets());
|
||||
QVERIFY(d->getLastPacket());
|
||||
QVERIFY(d->getLastPacket()->hasPayload());
|
||||
buffer = dynamic_cast<QBuffer*>(d->getLastPacket()->payload().data());
|
||||
// image-data is attached as png data
|
||||
QVERIFY(image.loadFromData(reinterpret_cast<const uchar*>(buffer->data().constData()), buffer->size(), "PNG"));
|
||||
QCOMPARE(image.sizeInBytes(), rowStride*height);
|
||||
// rgba -> argb conversion was done correctly:
|
||||
COMPARE_PIXEL(0,0);
|
||||
COMPARE_PIXEL(1,0);
|
||||
COMPARE_PIXEL(0,1);
|
||||
COMPARE_PIXEL(1,1);
|
||||
|
||||
#undef COMPARE_PIXEL
|
||||
}
|
||||
|
||||
|
||||
QTEST_GUILESS_MAIN(TestNotificationListener);
|
||||
|
||||
#include "testnotificationlistener.moc"
|
|
@ -1,361 +0,0 @@
|
|||
/**
|
||||
* Copyright 2015 Vineet Garg <albertvaka@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../core/backends/lan/server.h"
|
||||
#include "../core/backends/lan/socketlinereader.h"
|
||||
#include "../core/qtcompat_p.h"
|
||||
|
||||
#include <QSslKey>
|
||||
#include <QtCrypto>
|
||||
#include <QTest>
|
||||
#include <QTimer>
|
||||
#include <QSignalSpy>
|
||||
|
||||
/*
|
||||
* This class tests the behaviour of socket line reader when the connection if over ssl. Since SSL takes part below application layer,
|
||||
* working of SocketLineReader should be same.
|
||||
*/
|
||||
class TestSslSocketLineReader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public Q_SLOTS:
|
||||
void newPacket();
|
||||
void testTimeout();
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
void cleanupTestCase();
|
||||
|
||||
void testTrustedDevice();
|
||||
void testUntrustedDevice();
|
||||
void testTrustedDeviceWithWrongCertificate();
|
||||
|
||||
|
||||
private:
|
||||
const int PORT = 7894;
|
||||
const int TIMEOUT = 4 * 1000;
|
||||
QTimer m_timer;
|
||||
QCA::Initializer m_qcaInitializer;
|
||||
QEventLoop m_loop;
|
||||
QList<QByteArray> m_packets;
|
||||
Server* m_server;
|
||||
QSslSocket* m_clientSocket;
|
||||
SocketLineReader* m_reader;
|
||||
|
||||
private:
|
||||
void setSocketAttributes(QSslSocket* socket, QString deviceName);
|
||||
};
|
||||
|
||||
void TestSslSocketLineReader::initTestCase()
|
||||
{
|
||||
m_server = new Server(this);
|
||||
|
||||
QVERIFY2(m_server->listen(QHostAddress::LocalHost, PORT), "Failed to create local tcp server");
|
||||
|
||||
m_timer.setSingleShot(true);
|
||||
connect(&m_timer, &QTimer::timeout, this, &TestSslSocketLineReader::testTimeout);
|
||||
}
|
||||
|
||||
void TestSslSocketLineReader::init()
|
||||
{
|
||||
m_timer.setInterval(TIMEOUT);
|
||||
m_timer.start();
|
||||
|
||||
m_clientSocket = new QSslSocket(this);
|
||||
m_clientSocket->connectToHost(QHostAddress::LocalHost, PORT);
|
||||
connect(m_clientSocket, &QAbstractSocket::connected, &m_loop, &QEventLoop::quit);
|
||||
|
||||
m_loop.processEvents(QEventLoop::AllEvents, TIMEOUT);
|
||||
|
||||
QVERIFY2(m_clientSocket->isOpen(), "Could not connect to local tcp server");
|
||||
}
|
||||
|
||||
void TestSslSocketLineReader::cleanup()
|
||||
{
|
||||
m_clientSocket->disconnectFromHost();
|
||||
m_timer.stop();
|
||||
delete m_clientSocket;
|
||||
}
|
||||
|
||||
void TestSslSocketLineReader::cleanupTestCase()
|
||||
{
|
||||
delete m_server;
|
||||
}
|
||||
|
||||
void TestSslSocketLineReader::testTrustedDevice()
|
||||
{
|
||||
|
||||
int maxAttemps = 5;
|
||||
while(!m_server->hasPendingConnections() && maxAttemps > 0) {
|
||||
--maxAttemps;
|
||||
QTest::qSleep(1000);
|
||||
}
|
||||
QCOMPARE(true, m_server->hasPendingConnections());
|
||||
|
||||
QSslSocket* serverSocket = m_server->nextPendingConnection();
|
||||
|
||||
QSignalSpy serverEncryptedSpy(serverSocket, SIGNAL(encrypted()));
|
||||
|
||||
QVERIFY2(serverSocket != 0, "Null socket returned by server");
|
||||
QVERIFY2(serverSocket->isOpen(), "Server socket already closed");
|
||||
|
||||
setSocketAttributes(serverSocket, QStringLiteral("Test Server"));
|
||||
setSocketAttributes(m_clientSocket, QStringLiteral("Test Client"));
|
||||
|
||||
serverSocket->setPeerVerifyName(QStringLiteral("Test Client"));
|
||||
serverSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
|
||||
serverSocket->addCaCertificate(m_clientSocket->localCertificate());
|
||||
|
||||
m_clientSocket->setPeerVerifyName(QStringLiteral("Test Server"));
|
||||
m_clientSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
|
||||
m_clientSocket->addCaCertificate(serverSocket->localCertificate());
|
||||
|
||||
int connected_sockets = 0;
|
||||
auto connected_lambda = [&](){
|
||||
connected_sockets++;
|
||||
if (connected_sockets >= 2) {
|
||||
m_loop.quit();
|
||||
}
|
||||
};
|
||||
connect(serverSocket, &QSslSocket::encrypted, connected_lambda);
|
||||
connect(m_clientSocket, &QSslSocket::encrypted, connected_lambda);
|
||||
|
||||
serverSocket->startServerEncryption();
|
||||
m_clientSocket->startClientEncryption();
|
||||
m_loop.exec(); //Block until QEventLoop::quit gets called by the lambda
|
||||
|
||||
if (serverEncryptedSpy.count() < 1) {
|
||||
for(int x = 0;x < 50; ++x) {
|
||||
QVERIFY(serverEncryptedSpy.wait(100));
|
||||
if (serverEncryptedSpy.count() > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Both client and server socket should be encrypted here and should have remote certificate because VerifyPeer is used
|
||||
QVERIFY2(m_clientSocket->isOpen(), "Client socket already closed");
|
||||
QVERIFY2(serverSocket->isOpen(), "Server socket already closed");
|
||||
QVERIFY2(m_clientSocket->isEncrypted(), "Client is not encrypted");
|
||||
QVERIFY2(serverSocket->isEncrypted(), "Server is not encrypted");
|
||||
QVERIFY2(!m_clientSocket->peerCertificate().isNull(), "Server certificate not received");
|
||||
QVERIFY2(!serverSocket->peerCertificate().isNull(), "Client certificate not received");
|
||||
|
||||
QList<QByteArray> dataToSend;
|
||||
dataToSend << "foobar\n" << "barfoo\n" << "foobar?\n" << "\n" << "barfoo!\n" << "panda\n";
|
||||
for (const QByteArray& line : qAsConst(dataToSend)) {
|
||||
m_clientSocket->write(line);
|
||||
}
|
||||
m_clientSocket->flush();
|
||||
|
||||
m_packets.clear();
|
||||
|
||||
m_reader = new SocketLineReader(serverSocket, this);
|
||||
connect(m_reader, &SocketLineReader::readyRead, this,&TestSslSocketLineReader::newPacket);
|
||||
m_loop.exec();
|
||||
|
||||
/* remove the empty line before compare */
|
||||
dataToSend.removeOne("\n");
|
||||
|
||||
QCOMPARE(m_packets.count(), 5);//We expect 5 Packets
|
||||
for(int x = 0;x < 5; ++x) {
|
||||
QCOMPARE(m_packets[x], dataToSend[x]);
|
||||
}
|
||||
|
||||
delete m_reader;
|
||||
}
|
||||
|
||||
void TestSslSocketLineReader::testUntrustedDevice()
|
||||
{
|
||||
int maxAttemps = 5;
|
||||
while(!m_server->hasPendingConnections() && maxAttemps > 0) {
|
||||
--maxAttemps;
|
||||
QTest::qSleep(1000);
|
||||
}
|
||||
QCOMPARE(true, m_server->hasPendingConnections());
|
||||
|
||||
QSslSocket* serverSocket = m_server->nextPendingConnection();
|
||||
|
||||
QSignalSpy serverEncryptedSpy(serverSocket, SIGNAL(encrypted()));
|
||||
|
||||
QVERIFY2(serverSocket != 0, "Null socket returned by server");
|
||||
QVERIFY2(serverSocket->isOpen(), "Server socket already closed");
|
||||
|
||||
setSocketAttributes(serverSocket, QStringLiteral("Test Server"));
|
||||
setSocketAttributes(m_clientSocket, QStringLiteral("Test Client"));
|
||||
|
||||
serverSocket->setPeerVerifyName(QStringLiteral("Test Client"));
|
||||
serverSocket->setPeerVerifyMode(QSslSocket::QueryPeer);
|
||||
|
||||
m_clientSocket->setPeerVerifyName(QStringLiteral("Test Server"));
|
||||
m_clientSocket->setPeerVerifyMode(QSslSocket::QueryPeer);
|
||||
|
||||
int connected_sockets = 0;
|
||||
auto connected_lambda = [&](){
|
||||
connected_sockets++;
|
||||
if (connected_sockets >= 2) {
|
||||
m_loop.quit();
|
||||
}
|
||||
};
|
||||
connect(serverSocket, &QSslSocket::encrypted, connected_lambda);
|
||||
connect(m_clientSocket, &QSslSocket::encrypted, connected_lambda);
|
||||
serverSocket->startServerEncryption();
|
||||
m_clientSocket->startClientEncryption();
|
||||
m_loop.exec(); //Block until QEventLoop::quit gets called by the lambda
|
||||
|
||||
if (serverEncryptedSpy.count() < 1) {
|
||||
for(int x = 0;x < 50; ++x) {
|
||||
QVERIFY(serverEncryptedSpy.wait(100));
|
||||
if (serverEncryptedSpy.count() > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVERIFY2(m_clientSocket->isOpen(), "Client socket already closed");
|
||||
QVERIFY2(serverSocket->isOpen(), "Server socket already closed");
|
||||
QVERIFY2(m_clientSocket->isEncrypted(), "Client is not encrypted");
|
||||
QVERIFY2(serverSocket->isEncrypted(), "Server is not encrypted");
|
||||
QVERIFY2(!m_clientSocket->peerCertificate().isNull(), "Server certificate not received");
|
||||
QVERIFY2(!serverSocket->peerCertificate().isNull(), "Client certificate not received");
|
||||
|
||||
QList<QByteArray> dataToSend;
|
||||
dataToSend << "foobar\n" << "barfoo\n" << "foobar?\n" << "\n" << "barfoo!\n" << "panda\n";
|
||||
for (const QByteArray& line : qAsConst(dataToSend)) {
|
||||
m_clientSocket->write(line);
|
||||
}
|
||||
m_clientSocket->flush();
|
||||
|
||||
m_packets.clear();
|
||||
|
||||
m_reader = new SocketLineReader(serverSocket, this);
|
||||
connect(m_reader, &SocketLineReader::readyRead, this, &TestSslSocketLineReader::newPacket);
|
||||
m_loop.exec();
|
||||
|
||||
/* remove the empty line before compare */
|
||||
dataToSend.removeOne("\n");
|
||||
|
||||
QCOMPARE(m_packets.count(), 5);//We expect 5 Packets
|
||||
for(int x = 0;x < 5; ++x) {
|
||||
QCOMPARE(m_packets[x], dataToSend[x]);
|
||||
}
|
||||
|
||||
delete m_reader;
|
||||
}
|
||||
|
||||
void TestSslSocketLineReader::testTrustedDeviceWithWrongCertificate()
|
||||
{
|
||||
int maxAttemps = 5;
|
||||
while(!m_server->hasPendingConnections() && maxAttemps > 0) {
|
||||
--maxAttemps;
|
||||
QTest::qSleep(1000);
|
||||
}
|
||||
QCOMPARE(true, m_server->hasPendingConnections());
|
||||
|
||||
QSslSocket* serverSocket = m_server->nextPendingConnection();
|
||||
|
||||
QVERIFY2(serverSocket != 0, "Could not open a connection to the client");
|
||||
|
||||
setSocketAttributes(serverSocket, QStringLiteral("Test Server"));
|
||||
setSocketAttributes(m_clientSocket, QStringLiteral("Test Client"));
|
||||
|
||||
// Not adding other device certificate to list of CA certificate, and using VerifyPeer. This should lead to handshake failure
|
||||
serverSocket->setPeerVerifyName(QStringLiteral("Test Client"));
|
||||
serverSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
|
||||
|
||||
m_clientSocket->setPeerVerifyName(QStringLiteral("Test Server"));
|
||||
m_clientSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
|
||||
|
||||
connect(serverSocket, &QSslSocket::encrypted, &m_loop, &QEventLoop::quit); // Encrypted signal should never be emitted
|
||||
connect(m_clientSocket, &QSslSocket::encrypted, &m_loop, &QEventLoop::quit); // Encrypted signal should never be emitted
|
||||
connect(serverSocket, &QAbstractSocket::disconnected, &m_loop, &QEventLoop::quit);
|
||||
connect(m_clientSocket, &QAbstractSocket::disconnected, &m_loop, &QEventLoop::quit);
|
||||
|
||||
serverSocket->startServerEncryption();
|
||||
m_clientSocket->startClientEncryption();
|
||||
m_loop.exec();
|
||||
|
||||
QVERIFY2(!serverSocket->isEncrypted(), "Server is encrypted, it should not");
|
||||
QVERIFY2(!m_clientSocket->isEncrypted(), "lient is encrypted, it should now");
|
||||
|
||||
if (serverSocket->state() != QAbstractSocket::UnconnectedState) m_loop.exec(); // Wait until serverSocket is disconnected, It should be in disconnected state
|
||||
if (m_clientSocket->state() != QAbstractSocket::UnconnectedState) m_loop.exec(); // Wait until mClientSocket is disconnected, It should be in disconnected state
|
||||
|
||||
QCOMPARE((int)m_clientSocket->state(), 0);
|
||||
QCOMPARE((int)serverSocket->state(), 0);
|
||||
|
||||
}
|
||||
|
||||
void TestSslSocketLineReader::newPacket()
|
||||
{
|
||||
if (!m_reader->bytesAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int maxLoops = 5;
|
||||
while(m_reader->bytesAvailable() > 0 && maxLoops > 0) {
|
||||
--maxLoops;
|
||||
const QByteArray packet = m_reader->readLine();
|
||||
if (!packet.isEmpty()) {
|
||||
m_packets.append(packet);
|
||||
}
|
||||
|
||||
if (m_packets.count() == 5) {
|
||||
m_loop.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestSslSocketLineReader::testTimeout()
|
||||
{
|
||||
m_loop.exit(-1);
|
||||
QFAIL("Test Timed Out");
|
||||
}
|
||||
|
||||
void TestSslSocketLineReader::setSocketAttributes(QSslSocket* socket, QString deviceName) {
|
||||
|
||||
QDateTime startTime = QDateTime::currentDateTime();
|
||||
QDateTime endTime = startTime.addYears(10);
|
||||
QCA::CertificateInfo certificateInfo;
|
||||
certificateInfo.insert(QCA::CommonName,deviceName);
|
||||
certificateInfo.insert(QCA::Organization,QStringLiteral("KDE"));
|
||||
certificateInfo.insert(QCA::OrganizationalUnit,QStringLiteral("Kde connect"));
|
||||
|
||||
QCA::CertificateOptions certificateOptions(QCA::PKCS10);
|
||||
certificateOptions.setSerialNumber(10);
|
||||
certificateOptions.setInfo(certificateInfo);
|
||||
certificateOptions.setValidityPeriod(startTime, endTime);
|
||||
certificateOptions.setFormat(QCA::PKCS10);
|
||||
|
||||
QCA::PrivateKey privKey = QCA::KeyGenerator().createRSA(2048);
|
||||
QSslCertificate certificate = QSslCertificate(QCA::Certificate(certificateOptions, privKey).toPEM().toLatin1());
|
||||
|
||||
socket->setPrivateKey(QSslKey(privKey.toPEM().toLatin1(), QSsl::Rsa));
|
||||
socket->setLocalCertificate(certificate);
|
||||
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(TestSslSocketLineReader)
|
||||
|
||||
#include "testsslsocketlinereader.moc"
|
||||
|
Loading…
Reference in a new issue