1
0
mirror of https://github.com/qt/qtmqtt.git synced 2026-10-25 16:16:26 +00:00

Add tests for websocket support for mqtt

For at least one platform run the twelve combinations of:
 Transport: [Tcp,Ssl,Ws,Wss]
 Protocol: [3.1, 3.1.1, 5.0]

This happens if the following defines are present:
  MQTT_TEST_BROKER
  MQTT_TEST_TYPE
  MQTT_TEST_PROTOCOL

If these are not defined, the old test behavior is kept

The logic is that we are replacing the type of VersionClient
to homegrown logic that replaces connectToHost with the
correct function:
  connectToHost
  connectToHostEncrypted,
  connectToHostWebSocket
  connectToHostWebSocketEncrypted

For this to work it is important that the VersionClient
macro is used everywhere.

Also, DefaultVersionTestData has been changed to
return version(0) if MQTT_TEST_PROTOCOL is defined,
we will now run one protocol at the time instead.

This is Change Request 2 of 2 wrt testing.

Task-number: QTBUG-129171
Change-Id: I4f68d7c2ea226a1107f009c80f87f8b749d9f120
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
This commit is contained in:
Even Oscar Andersen 2025-01-29 13:38:24 +01:00
parent 967c70f1d5
commit 8316766cec
22 changed files with 553 additions and 34 deletions

View File

@ -1,6 +1,109 @@
# Copyright (C) 2022 The Qt Company Ltd.
# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
# This function adds the test 12 times if run on a computer where the
# mosquitto broker has been provisioned by running the corresponding
# script located qt6/coin/provisioning/*/*mosquitto*
#
# The script adds the file /etc/mosquitto/conf.d/mqtt.conf on unix-like
# systems, and the file C:\\Program Files\\mosquitto\\conf.d\\mqtt.conf
# on windows like systems. So this is what we test for.
#
# If we are on a provisioned system as detected by the two files above
# we define these variables which the test use
# MQTT_TEST_TYPE= selection from; 3, 4, 5
# 3 -> Vers 3.1
# 4 -> Vers 3.1.1
# 5 -> Vers 5.0
# MQTT_TEST_PROTOCOL= selection from; Tcp,Ssl,Ws,Wss
# MQTT_TEST_BROKER="localhost"
#
# If neither of these files are present, we use the existing
# design which is to run for tcp,3.1.1 by default.
# In this case set the environment variable MQTT_TEST_BROKER
# to localhost
#
# Finally, we allow the test to override for individual test
# cases, if wanted. This is mostly used for MQTT_TEST_TYPE
#
function(qtmqtt_add_test)
set(options)
set(oneValueArgs TARGET)
set(multiValueArgs SOURCES DEFINES INCLUDE_DIRECTORIES LIBRARIES)
cmake_parse_arguments(
arg_mqtt
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
set(TYPES)
set(PROTOCOLS)
if((EXISTS "/etc/mosquitto/conf.d/mqtt.conf") OR
(EXISTS "C:\\Program Files\\mosquitto\\conf.d\\mqtt.conf"))
if(WASM)
if(TARGET Qt::WebSockets)
set(TYPES Ws Wss)
set(PROTOCOLS 3 4 5)
endif()
elseif(QT_FEATURE_ssl)
if(TARGET Qt::WebSockets)
set(TYPES Tcp Ssl Ws Wss)
else()
set(TYPES Tcp Ssl)
endif()
set(PROTOCOLS 3 4 5)
else()
if(TARGET Qt::WebSockets)
set(TYPES Tcp Ws)
else()
set(TYPES Tcp)
endif()
set(PROTOCOLS 3 4 5)
endif()
elseif(NOT WASM)
set(TYPES Tcp)
set(PROTOCOLS 4)
endif()
foreach(TYPE ${TYPES})
foreach(PROTOCOL ${PROTOCOLS})
set(EXTRA_DEFINES)
set(EXTRA_LIBS)
if(EXISTS "/etc/mosquitto/conf.d/mqtt.conf" OR
EXISTS "C:\\Program Files\\mosquitto\\conf.d\\mqtt.conf")
set(EXTRA_DEFINES MQTT_TEST_TYPE="${TYPE}" MQTT_TEST_PROTOCOL=${PROTOCOL} MQTT_TEST_BROKER="localhost")
endif()
if(TARGET Qt::WebSockets)
set(EXTRA_DEFINES ${EXTRA_DEFINES} QT_MQTT_WITH_WEBSOCKETS)
set(EXTRA_LIBS Qt::WebSockets)
endif()
qt_internal_add_test(
${arg_mqtt_TARGET}_${TYPE}_${PROTOCOL}
SOURCES
${arg_mqtt_SOURCES}
DEFINES
${arg_mqtt_DEFINES} ${EXTRA_DEFINES}
INCLUDE_DIRECTORIES
${arg_mqtt_INCLUDE_DIRECTORIES}
LIBRARIES
${arg_mqtt_LIBRARIES} ${EXTRA_LIBS}
TESTDATA
"../../certificate/cert.crt"
"../../certificate/cert.key"
BUILTIN_TESTDATA
)
endforeach()
endforeach()
endfunction()
if(QT_BUILD_STANDALONE_TESTS)
# Add qt_find_package calls for extra dependencies that need to be found when building
# the standalone tests here.

View File

@ -5,7 +5,9 @@
## tst_conformance Test:
#####################################################################
qt_internal_add_test(tst_conformance
qtmqtt_add_test(
TARGET
tst_conformance
SOURCES
../../common/broker_connection.h
tst_conformance.cpp

View File

@ -42,7 +42,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
Tst_MqttConformance::Tst_MqttConformance()

View File

@ -5,7 +5,9 @@
## tst_qmqttclient Test:
#####################################################################
qt_internal_add_test(tst_qmqttclient
qtmqtt_add_test(
TARGET
tst_qmqttclient
SOURCES
../../common/broker_connection.h
tst_qmqttclient.cpp

View File

@ -51,10 +51,11 @@ private Q_SLOTS:
void subscriptionIdsOverlap();
void keepAlive_data();
void keepAlive();
void reconnect();
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
Tst_QMqttClient::Tst_QMqttClient()
@ -185,7 +186,7 @@ void Tst_QMqttClient::sendReceive()
QSKIP("The MQTT 5 test broker does not support huge packages.", SkipOnce);
publisher.publish(testTopic, data, 1);
QTRY_VERIFY2(received, "Subscriber did not receive message");
QTRY_VERIFY2_WITH_TIMEOUT(received, "Subscriber did not receive message", std::chrono::seconds(180));
QVERIFY2(verified, "Subscriber received different message");
}
@ -270,6 +271,9 @@ void Tst_QMqttClient::willMessage()
client1.connectToHost();
QTRY_COMPARE(client1.state(), QMqttClient::Connected);
if (!client1.isTcp())
QSKIP("This test is only for tcp");
auto client1Sub = client1.subscribe(willTopic, 1);
connect(client1Sub, &QMqttSubscription::messageReceived, [=](QMqttMessage message) {
Q_UNUSED(message);
@ -282,7 +286,7 @@ void Tst_QMqttClient::willMessage()
// Client B connects (via TcpSocket)
QTcpSocket sock;
sock.connectToHost(m_testBroker, m_port);
sock.connectToHost(client1.hostname(), client1.port());
QVERIFY(sock.waitForConnected());
for (int i = 1; i > 0; --i) {
@ -507,6 +511,9 @@ void Tst_QMqttClient::reconnect_QTBUG65726()
client.setHostname(QLatin1String("localhost"));
client.setPort(5726);
if (!client.isTcp())
QSKIP("This test is only for tcp");
server.version = client.protocolVersion();
client.connectToHost();
@ -569,6 +576,9 @@ void Tst_QMqttClient::staticProperties_QTBUG_67176()
client.setHostname(m_testBroker);
client.setPort(m_port);
auto clientVersion = client.protocolVersion();
const QString hostname = client.hostname();
const int port = client.port();
const QString clientId = client.clientId();
const quint16 keepAlive = client.keepAlive();
const bool clean = client.cleanSession();
@ -580,16 +590,16 @@ void Tst_QMqttClient::staticProperties_QTBUG_67176()
QCOMPARE(client.clientId(), clientId);
client.setHostname(QLatin1String("some.domain.foo"));
QCOMPARE(client.hostname(), m_testBroker);
QCOMPARE(client.hostname(), hostname);
client.setPort(1234);
QCOMPARE(client.port(), m_port);
QCOMPARE(client.port(), port);
client.setKeepAlive(keepAlive + 10);
QCOMPARE(client.keepAlive(), keepAlive);
client.setProtocolVersion(QMqttClient::MQTT_3_1);
QCOMPARE(client.protocolVersion(), mqttVersion);
QCOMPARE(client.protocolVersion(), clientVersion);
client.setUsername(QLatin1String("someUser"));
QCOMPARE(client.username(), QLatin1String());
@ -651,6 +661,7 @@ void Tst_QMqttClient::messageStatus()
client.setPort(m_port);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
const QString topic = QLatin1String("Qt/client/statusCheck");
@ -881,6 +892,76 @@ void Tst_QMqttClient::keepAlive()
QTRY_COMPARE(client.state(), QMqttClient::Disconnected);
}
void Tst_QMqttClient::reconnect()
{
VersionClient(QMqttClient::ProtocolVersion(0), client);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Connected);
client.disconnectFromHost();
QTRY_COMPARE(client.state(), QMqttClient::Disconnected);
/* The rest requires a mosquitto installation that runs
on multiple ports.
*/
#if defined(MQTT_TEST_BROKER)
client.setPort(client.port() + 1000);
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Connected);
client.disconnectFromHost();
QTRY_COMPARE(client.state(), QMqttClient::Disconnected);
QMqttClient client2;
client2.setHostname(client.hostname());
for (int i = 0; i < 2; ++i) {
#if defined(QT_MQTT_WITH_WEBSOCKETS)
client2.setPort(9080);
client2.connectToHostWebSocket();
QTRY_COMPARE(client2.state(), QMqttClient::Connected);
client2.disconnectFromHost();
QTRY_COMPARE(client2.state(), QMqttClient::Disconnected);
#endif
#if defined(QT_MQTT_WITH_WEBSOCKETS) && !defined(QT_NO_SSL)
client2.setPort(9081);
QUrl url(QString(u"wss://") + client2.hostname() + QString(u":") + QString::number(client2.port()));
QWebSocketHandshakeOptions options;
options.setSubprotocols(QStringList{ QString::fromUtf8("mqttv3.1") });
QWebSocket socket;
socket.setSslConfiguration(makeConfig(QString::fromUtf8(getenv("MQTT_TEST_BROKER_CERTIFICATE"))));
socket.open(url, options);
client2.connectToHostWebSocketEncrypted(&socket);
QTRY_COMPARE(client2.state(), QMqttClient::Connected);
client2.disconnectFromHost();
QTRY_COMPARE(client2.state(), QMqttClient::Disconnected);
#endif
#if !defined(QT_NO_SSL)
client2.setPort(9883);
client2.connectToHostEncrypted(makeConfig(QString::fromUtf8(getenv("MQTT_TEST_BROKER_CERTIFICATE"))));
QTRY_COMPARE(client2.state(), QMqttClient::Connected);
client2.disconnectFromHost();
QTRY_COMPARE(client2.state(), QMqttClient::Disconnected);
#endif
client2.setPort(2883);
client2.connectToHost();
QTRY_COMPARE(client2.state(), QMqttClient::Connected);
client2.disconnectFromHost();
QTRY_COMPARE(client2.state(), QMqttClient::Disconnected);
}
#endif
}
QTEST_MAIN(Tst_QMqttClient)
#include "tst_qmqttclient.moc"

View File

@ -5,7 +5,9 @@
## tst_qmqttconnectionproperties Test:
#####################################################################
qt_internal_add_test(tst_qmqttconnectionproperties
qtmqtt_add_test(
TARGET
tst_qmqttconnectionproperties
SOURCES
../../common/broker_connection.h
tst_qmqttconnectionproperties.cpp

View File

@ -31,7 +31,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
tst_QMqttConnectionProperties::tst_QMqttConnectionProperties()
@ -239,7 +239,7 @@ void tst_QMqttConnectionProperties::maximumTopicAlias()
client.publish(topic, msgContent, 1);
QTRY_VERIFY(publishSpy.size() == 1);
QVERIFY(transportSpy.size() == 1);
QTRY_VERIFY(transportSpy.size() == 1);
const int dataSize = transportSpy.at(0).at(0).toInt();
if (publishTransportSize == 0) {
publishTransportSize = dataSize;

View File

@ -5,7 +5,9 @@
## tst_qmqttcontrolpacket Test:
#####################################################################
qt_internal_add_test(tst_qmqttcontrolpacket
qtmqtt_add_test(
TARGET
tst_qmqttcontrolpacket
SOURCES
tst_qmqttcontrolpacket.cpp
DEFINES

View File

@ -5,7 +5,9 @@
## tst_qmqttlastwillproperties Test:
#####################################################################
qt_internal_add_test(tst_qmqttlastwillproperties
qtmqtt_add_test(
TARGET
tst_qmqttlastwillproperties
SOURCES
../../common/broker_connection.h
tst_qmqttlastwillproperties.cpp

View File

@ -27,7 +27,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
tst_QMqttLastWillProperties::tst_QMqttLastWillProperties()

View File

@ -5,7 +5,9 @@
## tst_qmqttpublishproperties Test:
#####################################################################
qt_internal_add_test(tst_qmqttpublishproperties
qtmqtt_add_test(
TARGET
tst_qmqttpublishproperties
SOURCES
../../common/broker_connection.h
tst_qmqttpublishproperties.cpp

View File

@ -26,7 +26,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
tst_QMqttPublishProperties::tst_QMqttPublishProperties()

View File

@ -5,7 +5,9 @@
## tst_qmqttsubscription Test:
#####################################################################
qt_internal_add_test(tst_qmqttsubscription
qtmqtt_add_test(
TARGET
tst_qmqttsubscription
SOURCES
../../common/broker_connection.h
tst_qmqttsubscription.cpp

View File

@ -36,7 +36,7 @@ private:
void createAndSubscribe(Client *c, QMqttSubscription **sub, const QString &topic);
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
Tst_QMqttSubscription::Tst_QMqttSubscription()
@ -149,6 +149,9 @@ void Tst_QMqttSubscription::reconnect()
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
if (!client.isTcp() && !client.isSsl())
QSKIP("This test only runs for tcp and ssl");
// - Subscribe to topic A
const QString subscription("Qt/subscription/topics/resub");
auto sub = client.subscribe(subscription, 1);
@ -384,6 +387,8 @@ void Tst_QMqttSubscription::noLocal()
client.setPort(m_port);
client.connectToHost();
const auto clientVersion = client.protocolVersion();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
QMqttSubscriptionProperties subProps;
@ -400,7 +405,7 @@ void Tst_QMqttSubscription::noLocal()
client.publish(topic, "content", 1);
QTRY_VERIFY(publishSpy.size() == 1);
if (version == QMqttClient::MQTT_3_1_1 || !non) { // 3.1.1 does not know NoLocal and sends to subscription
if (clientVersion == QMqttClient::MQTT_3_1_1 || !non) { // 3.1.1 does not know NoLocal and sends to subscription
QTRY_VERIFY(receivalSpy.size() == 1);
} else {
QTest::qWait(3000);
@ -483,8 +488,8 @@ void Tst_QMqttSubscription::qtbug_104478()
client.publish(topic, "Wildcard checks", 1);
QTRY_VERIFY2(pubSpy.size() == 1, "Could not publish message.");
QTRY_VERIFY2(singleSpy.count() == 1, "Did not receive message");
QTRY_VERIFY2(mixedSpy.count() == 1, "Did not receive message");
QTRY_VERIFY2(singleSpy.count() >= 1, "Did not receive message");
QTRY_VERIFY2(mixedSpy.count() >= 1, "Did not receive message");
client.disconnectFromHost();
QTRY_VERIFY2(client.state() == QMqttClient::Disconnected, "Could not disconnect from broker.");

View File

@ -5,7 +5,9 @@
## tst_qmqttsubscriptionproperties Test:
#####################################################################
qt_internal_add_test(tst_qmqttsubscriptionproperties
qtmqtt_add_test(
TARGET
tst_qmqttsubscriptionproperties
SOURCES
../../common/broker_connection.h
tst_qmqttsubscriptionproperties.cpp

View File

@ -26,7 +26,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
tst_QMqttSubscriptionProperties::tst_QMqttSubscriptionProperties()

View File

@ -5,7 +5,9 @@
## tst_qmqtttopicfilter Test:
#####################################################################
qt_internal_add_test(tst_qmqtttopicfilter
qtmqtt_add_test(
TARGET
tst_qmqtttopicfilter
SOURCES
tst_qmqtttopicfilter.cpp
DEFINES

View File

@ -5,7 +5,9 @@
## tst_qmqtttopicname Test:
#####################################################################
qt_internal_add_test(tst_qmqtttopicname
qtmqtt_add_test(
TARGET
tst_qmqtttopicname
SOURCES
tst_qmqtttopicname.cpp
DEFINES

View File

@ -25,7 +25,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
Tst_QMqttClient::Tst_QMqttClient()
@ -54,8 +54,8 @@ void Tst_QMqttClient::stressTest_data()
void Tst_QMqttClient::stressTest()
{
QFETCH(int, qos);
VersionClient(QMqttClient::MQTT_3_1_1, subscriber);
VersionClient(QMqttClient::MQTT_3_1_1, publisher);
VersionClient(0, subscriber);
VersionClient(0, publisher);
subscriber.setHostname(m_testBroker);
subscriber.setPort(m_port);
@ -109,7 +109,7 @@ void Tst_QMqttClient::stressTest2()
QSet<qint32> msgIds;
msgIds.reserve(msgCount);
VersionClient(QMqttClient::MQTT_3_1_1, publisher);
VersionClient(0, publisher);
publisher.setHostname(m_testBroker);
publisher.setPort(m_port);

View File

@ -0,0 +1,27 @@
# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-----BEGIN CERTIFICATE-----
MIID6zCCAtOgAwIBAgIUbbY+pKEPOOytRZ3RujmmdriEAKcwDQYJKoZIhvcNAQEL
BQAwgYMxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARPc2xvMQ0wCwYDVQQHDARPc2xv
MQswCQYDVQQKDAJRdDELMAkGA1UECwwCUXQxEjAQBgNVBAMMCWxvY2FsaG9zdDEo
MCYGCSqGSIb3DQEJARYZZXZlbi5vc2Nhci5hbmRlcnNlbkBxdC5pbzAgFw0yNDEw
MzExMTMyNDdaGA8yMTI0MTAwNzExMzI0N1owgYMxCzAJBgNVBAYTAk5PMQ0wCwYD
VQQIDARPc2xvMQ0wCwYDVQQHDARPc2xvMQswCQYDVQQKDAJRdDELMAkGA1UECwwC
UXQxEjAQBgNVBAMMCWxvY2FsaG9zdDEoMCYGCSqGSIb3DQEJARYZZXZlbi5vc2Nh
ci5hbmRlcnNlbkBxdC5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AJzWmpWU9f/baRi/Fhn362W488HzC2/MUdbTZGIQUqt1TwTLyYMEqkr6WMy/NdYL
8X5oXW0uz8LttbFp98wJTkNirYBMxowxwWWePnqbK0iKaZTBvBzUh0vWvmtFzHUW
E93K1NtKyL76Zj/EZv0I0CpkWMobpzEW/zquPj83Wxki0xp2rr/HHynqFv8KFMoJ
pR1A6uWtly12V1aQyXZIyMoIUPgDPmsHtNZKBCcz7IsAYHjjfvEIJ+r4lOOsgTXj
cdMU+0hHfyNCy1/6xmBwnchSqDZf3bTyFRu6GK+zzFKBSyt4MB7zQ2P29qYwoNJO
buJkPRfqiQJJRLkwyu59TB0CAwEAAaNTMFEwHQYDVR0OBBYEFGGxHowwihBbJlM5
2wzicQa2sCfwMB8GA1UdIwQYMBaAFGGxHowwihBbJlM52wzicQa2sCfwMA8GA1Ud
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACf4lUaBpw65tOZk32EpMD0D
M0ilx1AwfUqliKdhVvkFJ6jN5h17YhVjFoGtSzE7ry5Rg5J07tUK5Xkjcfk39UWV
RofVnRhrtiticXs0eXQkDXqao0aMjUjsWiokr4/cTNT5R3h9jmjzyjA6pWf2oSjT
GTzZAHdcuBTUfvPy/Ff4M5AVNsI6geUqrUd6XzFwQsDWTT86sdWQIC8j+FMghhss
9XRNOmhWtWGSRbP0HqlWOz5hFRPP/faI/FGTknzkkVYoWaB1CR+ThFK9jYi0FnFL
2fIcJPt+6g6d01Ws5cb9HpL9joUloCjsZ+w6PXYNVyHTaG3Lg5o4nT1Oizvrq1k=
-----END CERTIFICATE-----

View File

@ -0,0 +1,32 @@
# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCc1pqVlPX/22kY
vxYZ9+tluPPB8wtvzFHW02RiEFKrdU8Ey8mDBKpK+ljMvzXWC/F+aF1tLs/C7bWx
affMCU5DYq2ATMaMMcFlnj56mytIimmUwbwc1IdL1r5rRcx1FhPdytTbSsi++mY/
xGb9CNAqZFjKG6cxFv86rj4/N1sZItMadq6/xx8p6hb/ChTKCaUdQOrlrZctdldW
kMl2SMjKCFD4Az5rB7TWSgQnM+yLAGB4437xCCfq+JTjrIE143HTFPtIR38jQstf
+sZgcJ3IUqg2X9208hUbuhivs8xSgUsreDAe80Nj9vamMKDSTm7iZD0X6okCSUS5
MMrufUwdAgMBAAECggEAKs2u9q/my2M4NZbBE2lEB0kIzZ/lOSfMFhMvTEwkI8Mq
Q6bSYj19tGTKo2Zz7OzphZQ6GzgxX4O8mKTRChBoGZ/uths9/Lj/jRo49wEuOOf9
lKmjC0M9gYckBObRvArAdUGMAiVQ0D5KdZDGgrxLA6bLTK1rXcxm777qIhqbdCpN
i9RwW9wp9rMV53J8mmWWUDVpfbIKHAmp50JknXj07onPEqN6IKdZY7sYACfYiz/8
l31rKfR/P5j/aRBOFwBnq7Z3JGfOEQPmE8bxQ2Vt3ZXPK2ekreDx4j2Tz+gSZmF3
Ee8DonQtA1DTOlhMyb6FhJrEFmDr38jGQqDK4qV8iQKBgQDLoOSYzX0xcyK2dPMD
woPGcKymI+XYx0Q6cVZo1GttNarhBN0w0ms9a4SYoTMhAI9tzjJw/sU5t9kLan6n
m11PqQVK+Vbh1v2YICJW89LcOFYwyO6IAiMN1LUdy8las4GwcXRwBWWnXAnE+YJK
AiXcmB1ZX3j8pgStCF9VApC50wKBgQDFLP87pGtWW3nvkxoDpgVb1CwpO1T1EsFF
Yzv7eIkFQGUkqF7OlslhMCOERE8pj4dr4CoTIvVsYW+lYfBnFPpQ0pQ+BZ2meZ0u
GfWBDYpNGTGrxEDBc923glb2oegQQirHpiWtlinp5nciOn/rqpUwJR3b46drFlNy
26CTKA+8TwKBgQDKv8qdMo2i/QblMRD+/2CB55KgYkHrVI1ku5DUFB1awgMAxf0P
LZRFtZZy+p6UD6DALn0e8S2jSKE9sq2laRbByINSoW2WtKAQJn7KoT+kshtvu8F1
fts0XERyBITaYL2S14SePWF4ADZiACVwVy8ns/YVFPC8bvlc6Gczl7hOrQKBgQCP
BUmJSIT3GdlDlq7q8JS4fBkgO0IvldAM9aL/j/nLjl8PDPXf4e3mihVpDmdhXRO8
gtfiE5xzZeWmz3iiPMworeYLauVkaJhDZV73ogusStcFoY/bAqFTR76unNgIWwZO
1MxFskNqvtmxQT+igJRAXNvgsKuyeHpFONurggaP7wKBgCj25sAxVcOuOcANQGcO
wCNvt1pHDJengrzaKooCJqm5YxNhrcKlJsdQcQ1Mu+KyhcMY/WF/0UaJZytlHMWf
aDlF7zKqhQFqFY7nk/C7+fED7Kg3XJR54qtweVNzD6k4yTeSsvBeTd2aaepzZvJI
IOQ3RPVQNsdgjn3VTGs/rmrR
-----END PRIVATE KEY-----

View File

@ -8,8 +8,16 @@
#include <QtNetwork/QTcpSocket>
#include <QtTest/QTest>
#ifdef QT_MQTT_WITH_WEBSOCKETS
#include <QWebSocket>
#include <QWebSocketHandshakeOptions>
#endif
QString invokeOrInitializeBroker(QProcess *gBrokerProcess)
{
#if defined(MQTT_TEST_BROKER)
return QString::fromLatin1(MQTT_TEST_BROKER);
#endif
const QString broker = qgetenv("MQTT_TEST_BROKER");
if (broker.size()) {
qDebug("Overwriting default test broker");
@ -65,13 +73,256 @@ QString invokeOrInitializeBroker(QProcess *gBrokerProcess)
return QString();
}
#if !defined(QT_NO_SSL)
QSslConfiguration makeConfig(QString certificateFile)
{
if (certificateFile.isEmpty())
certificateFile=QString(u":/certificate/cert.crt");
QSslConfiguration config;
QFile file(certificateFile);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << " Could not open certificate file " << certificateFile;
} else {
const auto bytes = file.readAll();
const QSslCertificate certificate(bytes);
config.addCaCertificate(certificate);
}
return config;
}
#endif /* !QT_NO_SSL */
int getBrokerPort(int defaultPort)
{
if (getenv("MQTT_TEST_BROKER_PORT"))
return atoi(getenv("MQTT_TEST_BROKER_PORT"));
#if defined (MQTT_TEST_PROTOCOL)
return defaultPort;
#else
return defaultPort - 1000; /* evaluates to 1883 for the old system */
#endif
}
QMqttClient::ProtocolVersion getProtocolVersion(int version)
{
#if defined (MQTT_TEST_PROTOCOL)
if (version == 0)
version=MQTT_TEST_PROTOCOL;
#else
if ((version == 0) && getenv("MQTT_TEST_PROTOCOL_VERSION")) {
switch (atoi(getenv("MQTT_TEST_PROTOCOL_VERSION"))) {
case 3: version = QMqttClient::MQTT_3_1; break;
case 4: version = QMqttClient::MQTT_3_1_1; break;
case 5: version = QMqttClient::MQTT_5_0; break;
}
}
if (version == 0)
version = QMqttClient::MQTT_5_0;
#endif
return (QMqttClient::ProtocolVersion)version;
}
class MqTTTestClientBase : public QMqttClient
{
public:
virtual bool isTcp() const { return false; }
virtual bool isSsl() const { return false; }
virtual bool isWs() const { return false; }
virtual bool isWss() const { return false; }
public:
virtual void setPort(quint16 port) = 0;
virtual void connectToHost() = 0;
void setTransport(QIODevice *device, TransportType transport)
{
m_transportSet = true;
QMqttClient::setTransport(device, transport);
}
void disconnectFromHost()
{
m_transportSet = false;
QMqttClient::disconnectFromHost();
}
protected:
bool m_transportSet = false;
};
class MqTTClientTcp : public MqTTTestClientBase
{
public:
MqTTClientTcp() = default;
virtual bool isTcp() const override { return true; }
void setPort(quint16 port) override
{
if (port == 0)
port = getBrokerPort(2883);
QMqttClient::setPort(port);
}
void connectToHost() override
{
QMqttClient::connectToHost();
}
};
#ifdef QT_MQTT_WITH_WEBSOCKETS
class MqTTClientWs : public MqTTTestClientBase
{
public:
MqTTClientWs() = default;
virtual bool isWs() const override { return true; }
void setPort(quint16 port) override
{
if (port == 0)
port = getBrokerPort(9080);
QMqttClient::setPort(port);
}
void connectToHost() override
{
if (m_transportSet)
QMqttClient::connectToHost();
else
QMqttClient::connectToHostWebSocket();
}
};
#endif
#ifdef QT_MQTT_WITH_WEBSOCKETS
class MqTTClientWss : public MqTTTestClientBase
{
public:
MqTTClientWss()
{
#ifndef QT_NO_SSL
const QString origin;
const QWebSocketProtocol::Version version = QWebSocketProtocol::VersionLatest;
socket = new QWebSocket(origin, version, this);
#endif
}
virtual bool isWss() const override { return true; }
void setPort(quint16 port) override
{
if (port == 0)
port = getBrokerPort(9081);
QMqttClient::setPort(port);
}
void connectToHost() override
{
if (m_transportSet)
QMqttClient::connectToHost();
else {
#ifndef QT_NO_SSL
QUrl url(QString(u"wss://") + QMqttClient::hostname() + QString(u":") + QString::number(QMqttClient::port()));
QWebSocketHandshakeOptions options;
options.setSubprotocols(QStringList{ QString::fromUtf8("mqttv3.1") });
socket->setSslConfiguration(makeConfig(QString::fromUtf8(getenv("MQTT_TEST_BROKER_CERTIFICATE"))));
socket->open(url, options);
#endif
QMqttClient::connectToHostWebSocketEncrypted(socket);
}
}
private:
QWebSocket *socket = nullptr;
};
#endif
#ifndef QT_NO_SSL
class MqTTClientSsl : public MqTTTestClientBase
{
public:
MqTTClientSsl() = default;
virtual bool isSsl() const override { return true; }
void setPort(quint16 port) override
{
if (port == 0)
port = getBrokerPort(9883);
QMqttClient::setPort(port);
}
void connectToHost() override
{
if (m_transportSet)
QMqttClient::connectToHost();
else {
QMqttClient::connectToHostEncrypted(makeConfig(QString::fromUtf8(getenv("MQTT_TEST_BROKER_CERTIFICATE"))));
}
}
};
#endif /* !QT_NO_SSL */
Q_DECLARE_METATYPE(QMqttClient::ProtocolVersion)
#define VersionClient(MQTTVERSION, CLIENTNAME) QMqttClient CLIENTNAME; CLIENTNAME.setProtocolVersion(MQTTVERSION)
#if !defined(QT_NO_SSL) && defined(QT_MQTT_WITH_WEBSOCKETS)
#define VersionClientBase(MQTTVERSION, CLIENTNAME, TestType) \
std::shared_ptr<MqTTTestClientBase> p##CLIENTNAME; \
if (TestType == QString(u"Tcp")) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
if (TestType == QString(u"Ws")) p##CLIENTNAME = std::make_shared<MqTTClientWs>(); \
if (TestType == QString(u"Wss")) p##CLIENTNAME = std::make_shared<MqTTClientWss>(); \
if (TestType == QString(u"Ssl")) p##CLIENTNAME = std::make_shared<MqTTClientSsl>(); \
if (!p##CLIENTNAME) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
MqTTTestClientBase &CLIENTNAME = *p##CLIENTNAME; \
CLIENTNAME.setProtocolVersion(getProtocolVersion(MQTTVERSION))
#endif
#if defined(QT_NO_SSL) && defined(QT_MQTT_WITH_WEBSOCKETS)
#define VersionClientBase(MQTTVERSION, CLIENTNAME, TestType) \
std::shared_ptr<MqTTTestClientBase> p##CLIENTNAME; \
if (TestType == QString(u"Tcp")) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
if (TestType == QString(u"Ws")) p##CLIENTNAME = std::make_shared<MqTTClientWs>(); \
if (TestType == QString(u"Wss")) p##CLIENTNAME = std::make_shared<MqTTClientWss>(); \
if (!p##CLIENTNAME) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
MqTTTestClientBase &CLIENTNAME = *p##CLIENTNAME; \
CLIENTNAME.setProtocolVersion(getProtocolVersion(MQTTVERSION))
#endif
#if !defined(QT_NO_SSL) && !defined(QT_MQTT_WITH_WEBSOCKETS)
#define VersionClientBase(MQTTVERSION, CLIENTNAME, TestType) \
std::shared_ptr<MqTTTestClientBase> p##CLIENTNAME; \
if (TestType == QString(u"Tcp")) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
if (TestType == QString(u"Ssl")) p##CLIENTNAME = std::make_shared<MqTTClientSsl>(); \
if (!p##CLIENTNAME) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
MqTTTestClientBase &CLIENTNAME = *p##CLIENTNAME; \
CLIENTNAME.setProtocolVersion(getProtocolVersion(MQTTVERSION))
#endif
#if defined(QT_NO_SSL) && !defined(QT_MQTT_WITH_WEBSOCKETS)
#define VersionClientBase(MQTTVERSION, CLIENTNAME, TestType) \
std::shared_ptr<MqTTTestClientBase> p##CLIENTNAME; \
if (TestType == QString(u"Tcp")) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
if (!p##CLIENTNAME) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
MqTTTestClientBase &CLIENTNAME = *p##CLIENTNAME; \
CLIENTNAME.setProtocolVersion(getProtocolVersion(MQTTVERSION))
#endif
#if defined(MQTT_TEST_TYPE)
#define VersionClient(MQTTVERSION, CLIENTNAME) \
VersionClientBase(MQTTVERSION, CLIENTNAME, MQTT_TEST_TYPE)
#else
#define VersionClient(MQTTVERSION, CLIENTNAME) \
VersionClientBase(MQTTVERSION, CLIENTNAME, qgetenv("MQTT_TEST_BROKER_TYPE"))
#endif
#define DefaultVersionTestData(FUNCTION) \
void FUNCTION() \
{ \
QTest::addColumn<QMqttClient::ProtocolVersion>("mqttVersion"); \
QTest::newRow("V3.1.1") << QMqttClient::MQTT_3_1_1; \
QTest::newRow("V5.0.0") << QMqttClient::MQTT_5_0; \
if (getenv("MQTT_TEST_PROTOCOL_VERSION"))\
QTest::newRow("V0") << QMqttClient::ProtocolVersion(0); \
else { \
QTest::newRow("V3.1.1") << QMqttClient::MQTT_3_1_1; \
QTest::newRow("V5.0.0") << QMqttClient::MQTT_5_0; \
} \
}