1
0
mirror of https://github.com/qt/qtmqtt.git synced 2026-10-25 16:16:26 +00:00
qtmqtt/tests/auto/qmqttconnectionproperties/tst_qmqttconnectionproperties.cpp
Lucie Gérard edd6855344 Use SPDX license identifiers
Replace the current license disclaimer in files by
a SPDX-License-Identifier.
License files are organized under LICENSES directory.

Pick-to: 6.4
Task-number: QTBUG-67283
Change-Id: Ie4309963c8e17d4e7dad602f61a660246d5e23cb
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
2022-06-16 10:22:20 +02:00

390 lines
15 KiB
C++

// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "broker_connection.h"
#include <QtCore/QLoggingCategory>
#include <QtCore/QString>
#include <QtTest/QtTest>
#include <QtMqtt/QMqttClient>
#include <QtMqtt/QMqttConnectionProperties>
#include <QtMqtt/QMqttSubscription>
#include <QtMqtt/private/qmqttconnectionproperties_p.h>
class tst_QMqttConnectionProperties : public QObject
{
Q_OBJECT
public:
tst_QMqttConnectionProperties();
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
void getSet();
void receiveServerProperties();
void maximumPacketSize();
void maximumTopicAlias();
void maximumTopicAliasReceive();
void assignedClientId();
void userProperties();
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
};
tst_QMqttConnectionProperties::tst_QMqttConnectionProperties()
{
}
void tst_QMqttConnectionProperties::initTestCase()
{
m_testBroker = invokeOrInitializeBroker(&m_brokerProcess);
if (m_testBroker.isEmpty())
qFatal("No MQTT broker present to test against.");
}
void tst_QMqttConnectionProperties::cleanupTestCase()
{
}
void tst_QMqttConnectionProperties::getSet()
{
QMqttConnectionProperties p;
QVERIFY(p.userProperties().isEmpty());
QMqttUserProperties properties;
properties.append(QMqttStringPair(QLatin1String("someKey"), QLatin1String("someValue")));
p.setUserProperties(properties);
QCOMPARE(p.userProperties(), properties);
QVERIFY(p.authenticationMethod().isEmpty());
const QLatin1String authMethod("SomeAuthentication");
p.setAuthenticationMethod(authMethod);
QCOMPARE(p.authenticationMethod(), authMethod);
QVERIFY(p.authenticationData().isEmpty());
const QByteArray authData("AuthData123");
p.setAuthenticationData(authData);
QCOMPARE(p.authenticationData(), authData);
QCOMPARE(p.sessionExpiryInterval(), 0u);
p.setSessionExpiryInterval(1000);
QCOMPARE(p.sessionExpiryInterval(), 1000u);
QCOMPARE(p.maximumPacketSize(), std::numeric_limits<quint32>::max());
p.setMaximumPacketSize(0);
QVERIFY(p.maximumPacketSize() != 0u);
p.setMaximumPacketSize(500);
QCOMPARE(p.maximumPacketSize(), 500u);
QCOMPARE(p.maximumReceive(), 65535);
p.setMaximumReceive(0);
QVERIFY(p.maximumReceive() != 0u);
p.setMaximumReceive(30);
QCOMPARE(p.maximumReceive(), 30u);
QCOMPARE(p.maximumTopicAlias(), 0u);
p.setMaximumTopicAlias(5);
QCOMPARE(p.maximumTopicAlias(), 5u);
QCOMPARE(p.requestResponseInformation(), false);
p.setRequestResponseInformation(true);
QCOMPARE(p.requestResponseInformation(), true);
QCOMPARE(p.requestProblemInformation(), true);
p.setRequestProblemInformation(false);
QCOMPARE(p.requestProblemInformation(), false);
}
void tst_QMqttConnectionProperties::receiveServerProperties()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
QMqttServerConnectionProperties server = client.serverConnectionProperties();
QCOMPARE(server.isValid(), false);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
server = client.serverConnectionProperties();
QCOMPARE(server.isValid(), true);
QMqttServerConnectionProperties::ServerPropertyDetails properties = server.availableProperties();
qDebug() << "Specified properties:" << properties;
if (properties & QMqttServerConnectionProperties::SessionExpiryInterval)
qDebug() << " SessionExpiryInterval:" << server.sessionExpiryInterval();
if (properties & QMqttServerConnectionProperties::MaximumReceive)
qDebug() << " MaximumReceive:" << server.maximumReceive();
if (properties & QMqttServerConnectionProperties::MaximumQoS)
qDebug() << " MaximumQoS:" << server.maximumQoS();
if (properties & QMqttServerConnectionProperties::RetainAvailable)
qDebug() << " RetainAvailable:" << server.retainAvailable();
if (properties & QMqttServerConnectionProperties::MaximumPacketSize)
qDebug() << " MaximumPacketSize:" << server.maximumPacketSize();
if (properties & QMqttServerConnectionProperties::AssignedClientId)
qDebug() << " AssignedClientId:" << server.clientIdAssigned();
if (properties & QMqttServerConnectionProperties::MaximumTopicAlias)
qDebug() << " MaximumTopicAlias:" << server.maximumTopicAlias();
if (properties & QMqttServerConnectionProperties::ReasonString)
qDebug() << " ReasonString:" << server.reason();
if (properties & QMqttServerConnectionProperties::UserProperty)
qDebug() << " UserProperty:" << server.userProperties();
if (properties & QMqttServerConnectionProperties::WildCardSupported)
qDebug() << " WildCard Support:" << server.wildcardSupported();
if (properties & QMqttServerConnectionProperties::SubscriptionIdentifierSupport)
qDebug() << " Subscription Identifier Support:" << server.subscriptionIdentifierSupported();
if (properties & QMqttServerConnectionProperties::SharedSubscriptionSupport)
qDebug() << " Shared Subscription Support:" << server.sharedSubscriptionSupported();
if (properties & QMqttServerConnectionProperties::ServerKeepAlive)
qDebug() << " Server KeepAlive:" << server.serverKeepAlive();
if (properties & QMqttServerConnectionProperties::ResponseInformation)
qDebug() << " ResponseInformation:" << server.responseInformation();
if (properties & QMqttServerConnectionProperties::ServerReference)
qDebug() << " Server Reference:" << server.serverReference();
if (properties & QMqttServerConnectionProperties::AuthenticationMethod)
qDebug() << " AuthenticationMethod:" << server.authenticationMethod();
if (properties & QMqttServerConnectionProperties::AuthenticationData)
qDebug() << " AuthenticationData:" << server.authenticationData();
}
void tst_QMqttConnectionProperties::maximumPacketSize()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
client.setHostname(m_testBroker);
client.setPort(m_port);
QMqttConnectionProperties props;
props.setMaximumPacketSize(500);
client.setConnectionProperties(props);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
QMqttServerConnectionProperties serverProperties = client.serverConnectionProperties();
if (serverProperties.availableProperties() & QMqttServerConnectionProperties::MaximumPacketSize) {
if (serverProperties.maximumPacketSize() < props.maximumPacketSize()) {
qDebug() << "Server accepts less data than required for this test.";
}
} else {
QSKIP("Server has no max packet size defined. Default is unlimited.");
}
const QString topic = QLatin1String("Qt/ConnectionProperties/some/Topic/maxSize");
auto sub = client.subscribe(topic, 1);
QTRY_COMPARE(sub->state(), QMqttSubscription::Subscribed);
QSignalSpy subscribeSpy(sub, SIGNAL(messageReceived(QMqttMessage)));
QByteArray shortData(100, 'd');
QByteArray overFlowData(1000, 'o');
QSignalSpy publishSpy(&client, SIGNAL(messageSent(qint32)));
client.publish(topic, shortData, 1);
QTRY_COMPARE(publishSpy.count(), 1);
QTRY_COMPARE(subscribeSpy.count(), 1);
client.publish(topic, overFlowData, 1);
QTRY_COMPARE(publishSpy.count(), 1);
// We defined maximum size to receive is 500, hence the message should not be sent back
// to us. Wait for some time and verify no message got sent to subscriber
QTest::qWait(3000);
QTRY_COMPARE(subscribeSpy.count(), 1);
}
void tst_QMqttConnectionProperties::maximumTopicAlias()
{
const QByteArray msgContent("SomeContent");
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
client.setHostname(m_testBroker);
client.setPort(m_port);
const int userMaxTopicAlias = 20;
QMqttConnectionProperties userProperties;
userProperties.setMaximumTopicAlias(userMaxTopicAlias);
client.setConnectionProperties(userProperties);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
int publishTransportSize = 0;
auto transport = client.transport();
QSignalSpy transportSpy(transport, SIGNAL(bytesWritten(qint64))); //&QIODevice::bytesWritten);
const auto serverProperties = client.serverConnectionProperties();
const quint16 serverMaxAlias = serverProperties.maximumTopicAlias();
if (serverMaxAlias == 0)
QSKIP("Need to skip this test due to topic aliases not supported on server");
if (serverMaxAlias > userMaxTopicAlias)
QSKIP("This test requires that the client contains more topic aliases than the server");
//qDebug() << "Server Max Alias:" << serverMaxAlias;
//QLoggingCategory::setFilterRules("qt.mqtt.connection*=true");
// Fill up the internal publish vector
const QLatin1String topicBase("Qt/connprop/alias/top");
for (quint16 i = 0; i < serverMaxAlias; ++i) {
QSignalSpy publishSpy(&client, SIGNAL(messageSent(qint32)));
QMqttTopicName topic(topicBase + QString::number(i));
client.publish(topic, msgContent, 1);
QTRY_VERIFY(publishSpy.count() == 1);
QVERIFY(transportSpy.count() == 1);
const int dataSize = transportSpy.at(0).at(0).toInt();
if (publishTransportSize == 0) {
publishTransportSize = dataSize;
} else {
QCOMPARE(dataSize, publishTransportSize);
}
transportSpy.clear();
}
// Verify non auto assignable defaults to old behavior
QSignalSpy fullSpy(&client, SIGNAL(messageSent(qint32)));
transportSpy.clear();
client.publish(QLatin1String("Qt/connprop/alias/full/with/long/topic/to/verify/bigger/size"), msgContent, 1);
QTRY_VERIFY(fullSpy.count() == 1);
QVERIFY(transportSpy.count() == 1);
QVERIFY(transportSpy.at(0).at(0).toInt() > publishTransportSize);
// Verify alias is used at sending second time
transportSpy.clear();
fullSpy.clear();
client.publish(topicBase + QLatin1String("0"), msgContent, 1);
QTRY_VERIFY(fullSpy.count() == 1);
QVERIFY(transportSpy.count() == 1);
int usageSize = transportSpy.at(0).at(0).toInt();
QVERIFY(usageSize < publishTransportSize);
// Manually overwrite topic alias 1
const QMqttTopicName overwrite(QLatin1String("Qt/connprop/alias/overwrite/with/long/topic/to/verify/reset"));
QMqttPublishProperties overProp;
overProp.setTopicAlias(2);
fullSpy.clear();
transportSpy.clear();
client.publish(overwrite, overProp, msgContent, 1);
QTRY_VERIFY(fullSpy.count() == 1);
QVERIFY(transportSpy.count() == 1);
const int overwriteSize = transportSpy.at(0).at(0).toInt();
QVERIFY(overwriteSize > publishTransportSize);
// After resend new alias should be used and msg size reduced
fullSpy.clear();
transportSpy.clear();
client.publish(overwrite, msgContent, 1);
QTRY_VERIFY(fullSpy.count() == 1);
QVERIFY(transportSpy.count() == 1);
usageSize = transportSpy.at(0).at(0).toInt();
QVERIFY(usageSize < overwriteSize);
}
void createTopicAliasClient(QMqttClient &client, const QString &hostname, quint16 port)
{
client.setProtocolVersion(QMqttClient::MQTT_5_0);
client.setHostname(hostname);
client.setPort(port);
const int userMaxTopicAlias = 9;
QMqttConnectionProperties userProperties;
userProperties.setMaximumTopicAlias(userMaxTopicAlias);
client.setConnectionProperties(userProperties);
}
void tst_QMqttConnectionProperties::maximumTopicAliasReceive()
{
const QByteArray msgContent("SomeContent");
const QString topic("Qt/connprop/receive/alias");
QMqttClient client;
createTopicAliasClient(client, m_testBroker, m_port);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
QMqttClient subscriber;
createTopicAliasClient(subscriber, m_testBroker, m_port);
subscriber.connectToHost();
QTRY_VERIFY2(subscriber.state() == QMqttClient::Connected, "Could not connect to broker.");
auto sub = subscriber.subscribe(topic + "/#", 1);
int receiveCounter = 0;
connect(sub, &QMqttSubscription::messageReceived, [&receiveCounter](QMqttMessage msg) {
qDebug() << "Received message with alias:" << msg.publishProperties().topicAlias();
receiveCounter++;
});
QTRY_VERIFY2(sub->state() == QMqttSubscription::Subscribed, "Could not subscribe");
QSignalSpy publishSpy(&client, &QMqttClient::messageSent);
//QLoggingCategory::setFilterRules("qt.mqtt.connection*=true");
client.publish(topic, msgContent, 1);
QTRY_VERIFY2(publishSpy.count() == 1, "Could not publish");
QTRY_VERIFY2(receiveCounter == 1, "Did not receive initial message");
publishSpy.clear();
client.publish(topic, msgContent, 1);
QTRY_VERIFY2(publishSpy.count() == 1, "Could not publish");
QTRY_VERIFY2(receiveCounter == 2, "Did not receive second aliases message");
}
void tst_QMqttConnectionProperties::assignedClientId()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.setClientId(QLatin1String(""));
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
QMqttServerConnectionProperties serverProperties = client.serverConnectionProperties();
QVERIFY2(serverProperties.availableProperties() & QMqttServerConnectionProperties::AssignedClientId, "Must contain client ID");
QVERIFY2(!client.clientId().isEmpty(), "Client ID must not be empty");
}
void tst_QMqttConnectionProperties::userProperties()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
client.setHostname(m_testBroker);
client.setPort(m_port);
QMqttConnectionProperties p;
QMqttUserProperties userProperties;
userProperties.append(QMqttStringPair(QLatin1String("TestKey"), QLatin1String("TestValue")));
p.setUserProperties(userProperties);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
// ### TODO: We should a method to verify transmission of the user data
// Probably in conjunction with authentication
//QMqttServerConnectionProperties serverProperties = client.serverConnectionProperties();
//if (serverProperties.availableProperties() & QMqttServerConnectionProperties::UserProperty) {
// auto serverUserProps = serverProperties.userProperties();
// qDebug() << serverUserProps;
//} else
// qDebug() << "No user props available";
}
QTEST_MAIN(tst_QMqttConnectionProperties)
#include "tst_qmqttconnectionproperties.moc"