mirror of https://github.com/qt/qtcoap.git
Add security tests
Change-Id: I2e227977f1b8d407b4c9b069d2a18043cef844c2 Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
This commit is contained in:
parent
3e83021fbc
commit
13d450eff7
|
@ -32,6 +32,7 @@
|
|||
#include <QtCore/qstring.h>
|
||||
#include <QtNetwork/qhostinfo.h>
|
||||
#include <QtCoap/qcoapclient.h>
|
||||
#include <QtCoap/qcoapsecurityconfiguration.h>
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
@ -97,6 +98,12 @@ QString testServerHost()
|
|||
return testServerHostAddress;
|
||||
}
|
||||
|
||||
QString timeServerUrl()
|
||||
{
|
||||
static QString timeServerHostAddress = getHostAddress("freecoap");
|
||||
return QStringLiteral("coaps://") + timeServerHostAddress + QStringLiteral(":5685/time");
|
||||
}
|
||||
|
||||
QString testServerUrl()
|
||||
{
|
||||
return QStringLiteral("coap://") + testServerHost() + QStringLiteral(":")
|
||||
|
@ -105,13 +112,64 @@ QString testServerUrl()
|
|||
|
||||
QString testServerResource()
|
||||
{
|
||||
return testServerUrl() + QStringLiteral("/test");
|
||||
return testServerHost() + QStringLiteral("/test");
|
||||
}
|
||||
|
||||
bool waitForHost(const QUrl &url, quint8 retries = 10)
|
||||
QCoapSecurityConfiguration createConfiguration(QtCoap::SecurityMode securityMode)
|
||||
{
|
||||
QCoapSecurityConfiguration configuration;
|
||||
|
||||
if (securityMode == QtCoap::SecurityMode::PreSharedKey) {
|
||||
configuration.setPreSharedKeyIdentity("Client_identity");
|
||||
configuration.setPreSharedKey("secretPSK");
|
||||
} else if (securityMode == QtCoap::SecurityMode::Certificate) {
|
||||
const QString directory = QFINDTESTDATA("testdata");
|
||||
if (directory.isEmpty()) {
|
||||
qWarning() << "Found no testdata/, cannot load certificates.";
|
||||
return configuration;
|
||||
}
|
||||
|
||||
const auto localCertPath = directory + QDir::separator() +"local_cert.pem";
|
||||
const auto localCerts = QSslCertificate::fromPath(localCertPath);
|
||||
if (localCerts.isEmpty()) {
|
||||
qWarning() << "Failed to load local certificates, the"
|
||||
<< localCertPath
|
||||
<< "file was not found or it is not valid.";
|
||||
} else {
|
||||
configuration.setLocalCertificateChain(localCerts.toVector());
|
||||
}
|
||||
|
||||
const auto caCertPath = directory + QDir::separator() + "ca_cert.pem";
|
||||
const auto caCerts = QSslCertificate::fromPath(caCertPath);
|
||||
if (caCerts.isEmpty()) {
|
||||
qWarning() << "Failed to load CA certificates, the"
|
||||
<< caCertPath
|
||||
<< "file was not found or it is not valid.";
|
||||
} else {
|
||||
configuration.setCaCertificates(caCerts.toVector());
|
||||
}
|
||||
|
||||
const auto privateKeyPath = directory + QDir::separator() + "privkey.pem";
|
||||
QFile privateKey(privateKeyPath);
|
||||
if (privateKey.open(QIODevice::ReadOnly)) {
|
||||
QCoapPrivateKey key(privateKey.readAll(), QSsl::Ec);
|
||||
configuration.setPrivateKey(key);
|
||||
} else {
|
||||
qWarning() << "Failed to read the private key" << privateKeyPath;
|
||||
}
|
||||
}
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
bool waitForHost(const QUrl &url, QtCoap::SecurityMode security = QtCoap::SecurityMode::NoSecurity,
|
||||
quint8 retries = 10)
|
||||
{
|
||||
while (retries-- > 0) {
|
||||
QCoapClient client;
|
||||
QCoapClient client(security);
|
||||
if (security != QtCoap::SecurityMode::NoSecurity)
|
||||
client.setSecurityConfiguration(createConfiguration(security));
|
||||
|
||||
QSignalSpy spyClientFinished(&client, SIGNAL(finished(QCoapReply *)));
|
||||
client.get(url);
|
||||
|
||||
|
|
|
@ -8,4 +8,4 @@ HEADERS += ../coapnetworksettings.h
|
|||
SOURCES += tst_qcoapclient.cpp
|
||||
|
||||
CONFIG += unsupported/testserver
|
||||
QT_TEST_SERVER_LIST = californium
|
||||
QT_TEST_SERVER_LIST = californium freecoap
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIBrTCCAVOgAwIBAgIMWBtPBCPy5ZOTqJ69MAoGCCqGSM49BAMCMDgxEzARBgNV
|
||||
BAMTCmR1bW15L3Jvb3QxETAPBgNVBAsTCFNvZnR3YXJlMQ4wDAYDVQQKEwVEdW1t
|
||||
eTAeFw0xNjExMDMxNDUxNDhaFw0yNjExMDExNDUxNDhaMDgxEzARBgNVBAMTCmR1
|
||||
bW15L3Jvb3QxETAPBgNVBAsTCFNvZnR3YXJlMQ4wDAYDVQQKEwVEdW1teTBZMBMG
|
||||
ByqGSM49AgEGCCqGSM49AwEHA0IABMJ6XvBwMC3sZRyBatX95w+/AieUhN1cNfWI
|
||||
Uc4HA0IXp+WwDN7QXd7mm1FDV/wQmNx/y2MJ7OQMJUvSozRPpfKjQzBBMA8GA1Ud
|
||||
EwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcEADAdBgNVHQ4EFgQUsib+R29JtRKp
|
||||
G6duvLrDjM8PySUwCgYIKoZIzj0EAwIDSAAwRQIgQC6ZVZi6sXnYypt1CKlDSS2Q
|
||||
W+CV62TyOdE9j9phNfECIQDno7uEc8sXHnwkCcfuZhFVAkEfE8KBPhEF7ZmqJz5c
|
||||
BQ==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,13 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIB4jCCAYigAwIBAgIMWBtPBCa+RXwaSLCOMAoGCCqGSM49BAMCMDgxEzARBgNV
|
||||
BAMTCmR1bW15L3Jvb3QxETAPBgNVBAsTCFNvZnR3YXJlMQ4wDAYDVQQKEwVEdW1t
|
||||
eTAeFw0xNjExMDMxNDUxNDhaFw0yNjExMDExNDUxNDhaMDoxFTATBgNVBAMTDGR1
|
||||
bW15L2NsaWVudDERMA8GA1UECxMIU29mdHdhcmUxDjAMBgNVBAoTBUR1bW15MFkw
|
||||
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcrIeFXrfmAu/fiT49ToNubG6u/w5GAQb
|
||||
xI0V7vmFCxFSn4ttoPfEUMlUKCTFYc6HbzmFgUjct1KFGBuAfZ13M6N2MHQwDAYD
|
||||
VR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAjAPBgNVHQ8BAf8EBQMDB4AA
|
||||
MB0GA1UdDgQWBBSc2q9vjtlLW1IUSzDa9X2qnJYU1DAfBgNVHSMEGDAWgBQEbS8W
|
||||
F1883YRUvUnCBnkSs/NhmjAKBggqhkjOPQQDAgNIADBFAiEA9fZYVTMn9My9erGO
|
||||
j5tFYsGj4A7CkWHFRj50KirZN4ECIFLEmt5SbmipqFdkiRBxkjkJEMYC+iLBeMqI
|
||||
Cgi5tYDF
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,40 @@
|
|||
Public Key Info:
|
||||
Public Key Algorithm: EC/ECDSA
|
||||
Key Security Level: High (256 bits)
|
||||
|
||||
curve: SECP256R1
|
||||
private key:
|
||||
00:f7:ea:23:23:78:12:38:e3:8f:e0:2b:05:72:2f:6a
|
||||
24:91:a0:54:c6:3d:ed:68:ce:6e:60:8d:0f:fd:9f:39
|
||||
c6:
|
||||
|
||||
x:
|
||||
72:b2:1e:15:7a:df:98:0b:bf:7e:24:f8:f5:3a:0d:b9
|
||||
b1:ba:bb:fc:39:18:04:1b:c4:8d:15:ee:f9:85:0b:11
|
||||
|
||||
|
||||
y:
|
||||
52:9f:8b:6d:a0:f7:c4:50:c9:54:28:24:c5:61:ce:87
|
||||
6f:39:85:81:48:dc:b7:52:85:18:1b:80:7d:9d:77:33
|
||||
|
||||
|
||||
|
||||
Public Key ID: 9C:DA:AF:6F:8E:D9:4B:5B:52:14:4B:30:DA:F5:7D:AA:9C:96:14:D4
|
||||
Public key's random art:
|
||||
+--[SECP256R1]----+
|
||||
| o.=. |
|
||||
| o = +E. |
|
||||
| . . + . o|
|
||||
| . . . . ..|
|
||||
| S o . |
|
||||
| o + + |
|
||||
| . . o B |
|
||||
| *.= |
|
||||
| +=B. |
|
||||
+-----------------+
|
||||
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHgCAQEEIQD36iMjeBI444/gKwVyL2okkaBUxj3taM5uYI0P/Z85xqAKBggqhkjO
|
||||
PQMBB6FEA0IABHKyHhV635gLv34k+PU6Dbmxurv8ORgEG8SNFe75hQsRUp+LbaD3
|
||||
xFDJVCgkxWHOh285hYFI3LdShRgbgH2ddzM=
|
||||
-----END EC PRIVATE KEY-----
|
|
@ -37,6 +37,7 @@
|
|||
#include <QtCoap/qcoapresourcediscoveryreply.h>
|
||||
#include <QtCore/qbuffer.h>
|
||||
#include <QtNetwork/qnetworkdatagram.h>
|
||||
#include <QtNetwork/qsslcipher.h>
|
||||
#include <private/qcoapclient_p.h>
|
||||
#include <private/qcoapqudpconnection_p.h>
|
||||
#include <private/qcoapprotocol_p.h>
|
||||
|
@ -66,6 +67,7 @@ private Q_SLOTS:
|
|||
void setBlockSize();
|
||||
void requestWithQIODevice_data();
|
||||
void requestWithQIODevice();
|
||||
void multipleRequests_data();
|
||||
void multipleRequests();
|
||||
void blockwiseReply_data();
|
||||
void blockwiseReply();
|
||||
|
@ -82,8 +84,40 @@ private Q_SLOTS:
|
|||
void setMinimumTokenSize();
|
||||
};
|
||||
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
class QCoapClientForSecurityTests : public QCoapClient
|
||||
{
|
||||
public:
|
||||
QCoapClientForSecurityTests(QtCoap::SecurityMode security)
|
||||
: QCoapClient(security)
|
||||
, securityMode(security)
|
||||
{
|
||||
if (security != QtCoap::SecurityMode::NoSecurity)
|
||||
setSecurityConfiguration(createConfiguration(security));
|
||||
}
|
||||
|
||||
bool securityMissing() const
|
||||
{
|
||||
#if QT_CONFIG(dtls)
|
||||
if (securityMode == QtCoap::SecurityMode::PreSharedKey) {
|
||||
const auto ciphers = QSslConfiguration::defaultDtlsConfiguration().ciphers();
|
||||
const auto it = std::find_if(ciphers.cbegin(), ciphers.cend(),
|
||||
[](const QSslCipher &cipher) {
|
||||
return cipher.name() == "PSK-AES128-CCM8"
|
||||
|| cipher.name() == "PSK-AES128-CBC-SHA256";
|
||||
});
|
||||
return it == ciphers.cend();
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
QtCoap::SecurityMode securityMode;
|
||||
};
|
||||
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
class QCoapQUdpConnectionSocketTestsPrivate : public QCoapQUdpConnectionPrivate
|
||||
{
|
||||
bool bind() override
|
||||
|
@ -199,6 +233,10 @@ void tst_QCoapClient::initTestCase()
|
|||
{
|
||||
#if defined(COAP_TEST_SERVER_IP) || defined(QT_TEST_SERVER)
|
||||
QVERIFY2(waitForHost(testServerHost()), "Failed to connect to Californium plugtest server.");
|
||||
#if QT_CONFIG(dtls)
|
||||
QVERIFY2(waitForHost(timeServerUrl(), QtCoap::SecurityMode::Certificate),
|
||||
"Failed to connect to FreeCoAP sample time server.");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -243,24 +281,59 @@ void tst_QCoapClient::methods_data()
|
|||
{
|
||||
QTest::addColumn<QUrl>("url");
|
||||
QTest::addColumn<QtCoap::Method>("method");
|
||||
QTest::addColumn<QtCoap::SecurityMode>("security");
|
||||
|
||||
QTest::newRow("get") << QUrl(testServerResource()) << QtCoap::Method::Get;
|
||||
QTest::newRow("get_no_port") << QUrl("coap://" + testServerHost() + "/test")
|
||||
<< QtCoap::Method::Get;
|
||||
QTest::newRow("get_no_scheme_no_port") << QUrl(testServerHost() + "/test")
|
||||
<< QtCoap::Method::Get;
|
||||
QTest::newRow("post") << QUrl(testServerResource())
|
||||
<< QtCoap::Method::Post;
|
||||
QTest::newRow("post_no_scheme_no_port") << QUrl(testServerHost() + "/test")
|
||||
<< QtCoap::Method::Post;
|
||||
QTest::newRow("put") << QUrl(testServerResource())
|
||||
<< QtCoap::Method::Put;
|
||||
QTest::newRow("put_no_scheme_no_port") << QUrl(testServerHost() + "/test")
|
||||
<< QtCoap::Method::Put;
|
||||
QTest::newRow("delete") << QUrl(testServerResource())
|
||||
<< QtCoap::Method::Delete;
|
||||
QTest::newRow("delete_no_scheme_no_port") << QUrl(testServerHost() + "/test")
|
||||
<< QtCoap::Method::Delete;
|
||||
QTest::newRow("get")
|
||||
<< QUrl(testServerResource())
|
||||
<< QtCoap::Method::Get
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("get_no_port")
|
||||
<< QUrl("coap://" + testServerHost() + "/test")
|
||||
<< QtCoap::Method::Get
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("get_no_scheme_no_port")
|
||||
<< QUrl(testServerHost() + "/test")
|
||||
<< QtCoap::Method::Get
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("get_psk")
|
||||
<< QUrl(testServerResource()) << QtCoap::Method::Get
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
QTest::newRow("get_cert")
|
||||
<< QUrl(timeServerUrl()) << QtCoap::Method::Get
|
||||
<< QtCoap::SecurityMode::Certificate;
|
||||
QTest::newRow("post")
|
||||
<< QUrl(testServerResource())
|
||||
<< QtCoap::Method::Post
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("post_no_scheme_no_port")
|
||||
<< QUrl(testServerHost() + "/test")
|
||||
<< QtCoap::Method::Post
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("post_psk")
|
||||
<< QUrl(testServerResource()) << QtCoap::Method::Post
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
QTest::newRow("put")
|
||||
<< QUrl(testServerResource())
|
||||
<< QtCoap::Method::Put
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("put_no_scheme_no_port")
|
||||
<< QUrl(testServerHost() + "/test")
|
||||
<< QtCoap::Method::Put
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("put_psk")
|
||||
<< QUrl(testServerResource()) << QtCoap::Method::Put
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
QTest::newRow("delete")
|
||||
<< QUrl(testServerResource())
|
||||
<< QtCoap::Method::Delete
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("delete_no_scheme_no_port")
|
||||
<< QUrl(testServerHost() + "/test")
|
||||
<< QtCoap::Method::Delete
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("delete_psk")
|
||||
<< QUrl(testServerResource()) << QtCoap::Method::Delete
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
}
|
||||
|
||||
void tst_QCoapClient::methods()
|
||||
|
@ -269,8 +342,12 @@ void tst_QCoapClient::methods()
|
|||
|
||||
QFETCH(QUrl, url);
|
||||
QFETCH(QtCoap::Method, method);
|
||||
QFETCH(QtCoap::SecurityMode, security);
|
||||
|
||||
QCoapClientForSecurityTests client(security);
|
||||
if (client.securityMissing())
|
||||
QSKIP("Skipping this test, security is not configured properly");
|
||||
|
||||
QCoapClient client;
|
||||
QCoapRequest request(url);
|
||||
|
||||
QSignalSpy spyClientFinished(&client, SIGNAL(finished(QCoapReply *)));
|
||||
|
@ -291,7 +368,8 @@ void tst_QCoapClient::methods()
|
|||
|
||||
QVERIFY2(!reply.isNull(), "Request failed unexpectedly");
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
QCOMPARE(reply->url(), QCoapRequestPrivate::adjustedUrl(url, false));
|
||||
QCOMPARE(reply->url(),
|
||||
QCoapRequestPrivate::adjustedUrl(url, security != QtCoap::SecurityMode::NoSecurity));
|
||||
#endif
|
||||
QSignalSpy spyReplyFinished(reply.data(), SIGNAL(finished(QCoapReply *)));
|
||||
QTRY_COMPARE(spyReplyFinished.count(), 1);
|
||||
|
@ -430,51 +508,56 @@ void tst_QCoapClient::requestWithQIODevice()
|
|||
}
|
||||
}
|
||||
|
||||
void tst_QCoapClient::multipleRequests_data()
|
||||
{
|
||||
QTest::addColumn<QtCoap::SecurityMode>("security");
|
||||
|
||||
QTest::newRow("multiple_requests") << QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("multiple_requests_secure") << QtCoap::SecurityMode::PreSharedKey;
|
||||
}
|
||||
|
||||
void tst_QCoapClient::multipleRequests()
|
||||
{
|
||||
CHECK_FOR_COAP_SERVER;
|
||||
|
||||
QCoapClient client;
|
||||
QFETCH(QtCoap::SecurityMode, security);
|
||||
|
||||
QCoapClientForSecurityTests client(security);
|
||||
if (client.securityMissing())
|
||||
QSKIP("Skipping this test, security is not configured properly");
|
||||
|
||||
QUrl url = QUrl(testServerResource());
|
||||
QSignalSpy spyClientFinished(&client, SIGNAL(finished(QCoapReply *)));
|
||||
|
||||
QScopedPointer<QCoapReply> replyGet1(client.get(url));
|
||||
QScopedPointer<QCoapReply> replyGet2(client.get(url));
|
||||
QScopedPointer<QCoapReply> replyGet3(client.get(url));
|
||||
QScopedPointer<QCoapReply> replyGet4(client.get(url));
|
||||
const uint8_t requestCount = 4;
|
||||
QVector<QSharedPointer<QCoapReply>> replies;
|
||||
QVector<QSharedPointer<QSignalSpy>> signalSpies;
|
||||
for (uint8_t i = 0; i < requestCount; ++i) {
|
||||
QCoapRequest request;
|
||||
const auto token = "token" + QByteArray::number(i);
|
||||
request.setToken(token);
|
||||
request.setUrl(url);
|
||||
|
||||
QVERIFY2(!replyGet1.isNull(), "Request failed unexpectedly");
|
||||
QVERIFY2(!replyGet2.isNull(), "Request failed unexpectedly");
|
||||
QVERIFY2(!replyGet3.isNull(), "Request failed unexpectedly");
|
||||
QVERIFY2(!replyGet4.isNull(), "Request failed unexpectedly");
|
||||
QSharedPointer<QCoapReply> reply(client.get(request));
|
||||
const auto errorMsg = QStringLiteral("Request number %1 failed unexpectedly").arg(i);
|
||||
QVERIFY2(!reply.isNull(), qPrintable(errorMsg));
|
||||
replies.push_back(reply);
|
||||
|
||||
QSignalSpy spyReplyGet1Finished(replyGet1.data(), SIGNAL(finished(QCoapReply *)));
|
||||
QSignalSpy spyReplyGet2Finished(replyGet2.data(), SIGNAL(finished(QCoapReply *)));
|
||||
QSignalSpy spyReplyGet3Finished(replyGet3.data(), SIGNAL(finished(QCoapReply *)));
|
||||
QSignalSpy spyReplyGet4Finished(replyGet4.data(), SIGNAL(finished(QCoapReply *)));
|
||||
QSharedPointer<QSignalSpy> signalSpy(
|
||||
new QSignalSpy(reply.data(), SIGNAL(finished(QCoapReply *))));
|
||||
signalSpies.push_back(signalSpy);
|
||||
}
|
||||
|
||||
QTRY_COMPARE(spyReplyGet1Finished.count(), 1);
|
||||
QTRY_COMPARE(spyReplyGet2Finished.count(), 1);
|
||||
QTRY_COMPARE(spyReplyGet3Finished.count(), 1);
|
||||
QTRY_COMPARE(spyReplyGet4Finished.count(), 1);
|
||||
for (const auto &signalSpy : signalSpies)
|
||||
QTRY_COMPARE(signalSpy->count(), 1);
|
||||
QTRY_COMPARE(spyClientFinished.count(), 4);
|
||||
|
||||
QByteArray replyData1 = replyGet1->readAll();
|
||||
QByteArray replyData2 = replyGet2->readAll();
|
||||
QByteArray replyData3 = replyGet3->readAll();
|
||||
QByteArray replyData4 = replyGet4->readAll();
|
||||
|
||||
QCOMPARE(replyGet1->responseCode(), QtCoap::ResponseCode::Content);
|
||||
QCOMPARE(replyGet2->responseCode(), QtCoap::ResponseCode::Content);
|
||||
QCOMPARE(replyGet3->responseCode(), QtCoap::ResponseCode::Content);
|
||||
QCOMPARE(replyGet4->responseCode(), QtCoap::ResponseCode::Content);
|
||||
|
||||
QVERIFY(replyData1 != replyData2);
|
||||
QVERIFY(replyData1 != replyData3);
|
||||
QVERIFY(replyData1 != replyData4);
|
||||
QVERIFY(replyData2 != replyData3);
|
||||
QVERIFY(replyData2 != replyData4);
|
||||
QVERIFY(replyData3 != replyData4);
|
||||
for (uint8_t i = 0; i < requestCount; ++i) {
|
||||
QCOMPARE(replies[i]->responseCode(), QtCoap::ResponseCode::Content);
|
||||
QByteArray replyData = replies[i]->readAll();
|
||||
const auto token = "token" + QByteArray::number(i);
|
||||
QVERIFY(replyData.contains(token.toHex()));
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QCoapClient::socketError()
|
||||
|
@ -591,6 +674,7 @@ void tst_QCoapClient::blockwiseReply_data()
|
|||
QTest::addColumn<QUrl>("url");
|
||||
QTest::addColumn<QCoapMessage::Type>("type");
|
||||
QTest::addColumn<QByteArray>("replyData");
|
||||
QTest::addColumn<QtCoap::SecurityMode>("security");
|
||||
|
||||
QByteArray data;
|
||||
data.append("/-------------------------------------------------------------\\\n");
|
||||
|
@ -617,27 +701,43 @@ void tst_QCoapClient::blockwiseReply_data()
|
|||
QTest::newRow("get_large")
|
||||
<< QUrl(testServerUrl() + "/large")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< data;
|
||||
QTest::newRow("get_large_separate")
|
||||
<< QUrl(testServerUrl() + "/large-separate")
|
||||
<< data
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("get_large_secure")
|
||||
<< QUrl(testServerHost() + "/large")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< data;
|
||||
<< data
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
QTest::newRow("get_large_separate")
|
||||
<< QUrl(testServerHost() + "/large-separate")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< data
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("get_large_confirmable")
|
||||
<< QUrl(testServerUrl() + "/large")
|
||||
<< QCoapMessage::Type::Confirmable
|
||||
<< data;
|
||||
<< data
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("get_large_confirmable_secure")
|
||||
<< QUrl(testServerHost() + "/large")
|
||||
<< QCoapMessage::Type::Confirmable
|
||||
<< data
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
QTest::newRow("get_large_separate_confirmable")
|
||||
<< QUrl(testServerUrl() + "/large-separate")
|
||||
<< QCoapMessage::Type::Confirmable
|
||||
<< data;
|
||||
<< data
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("get_large_16bits")
|
||||
<< QUrl(testServerUrl() + "/large")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< data;
|
||||
<< data
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("get_large_16bits_confirmable")
|
||||
<< QUrl(testServerUrl() + "/large")
|
||||
<< QCoapMessage::Type::Confirmable
|
||||
<< data;
|
||||
<< data
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
}
|
||||
|
||||
void tst_QCoapClient::blockwiseReply()
|
||||
|
@ -647,8 +747,12 @@ void tst_QCoapClient::blockwiseReply()
|
|||
QFETCH(QUrl, url);
|
||||
QFETCH(QCoapMessage::Type, type);
|
||||
QFETCH(QByteArray, replyData);
|
||||
QFETCH(QtCoap::SecurityMode, security);
|
||||
|
||||
QCoapClientForSecurityTests client(security);
|
||||
if (client.securityMissing())
|
||||
QSKIP("Skipping this test, security is not configured properly");
|
||||
|
||||
QCoapClient client;
|
||||
QCoapRequest request(url);
|
||||
|
||||
if (qstrncmp(QTest::currentDataTag(), "get_large_16bits", 16) == 0)
|
||||
|
@ -674,22 +778,34 @@ void tst_QCoapClient::blockwiseRequest_data()
|
|||
QTest::addColumn<QByteArray>("requestData");
|
||||
QTest::addColumn<QtCoap::ResponseCode>("responseCode");
|
||||
QTest::addColumn<QByteArray>("replyData");
|
||||
QTest::addColumn<QtCoap::SecurityMode>("security");
|
||||
|
||||
QByteArray data;
|
||||
const char alphabet[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
|
||||
for (int i = 3; i-- > 0; )
|
||||
data.append(alphabet);
|
||||
|
||||
QTest::newRow("large_post_empty_reply") << QUrl(testServerUrl() + "/query")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< data
|
||||
<< QtCoap::ResponseCode::MethodNotAllowed
|
||||
<< QByteArray();
|
||||
QTest::newRow("large_post_large_reply") << QUrl(testServerUrl() + "/large-post")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< data
|
||||
<< QtCoap::ResponseCode::Changed
|
||||
<< data.toUpper();
|
||||
QTest::newRow("large_post_empty_reply")
|
||||
<< QUrl(testServerUrl() + "/query")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< data
|
||||
<< QtCoap::ResponseCode::MethodNotAllowed
|
||||
<< QByteArray()
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("large_post_large_reply")
|
||||
<< QUrl(testServerUrl() + "/large-post")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< data
|
||||
<< QtCoap::ResponseCode::Changed
|
||||
<< data.toUpper()
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("large_post_large_reply_secure")
|
||||
<< QUrl(testServerHost() + "/large-post")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< data
|
||||
<< QtCoap::ResponseCode::Changed
|
||||
<< data.toUpper()
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
}
|
||||
|
||||
void tst_QCoapClient::blockwiseRequest()
|
||||
|
@ -701,8 +817,12 @@ void tst_QCoapClient::blockwiseRequest()
|
|||
QFETCH(QByteArray, requestData);
|
||||
QFETCH(QtCoap::ResponseCode, responseCode);
|
||||
QFETCH(QByteArray, replyData);
|
||||
QFETCH(QtCoap::SecurityMode, security);
|
||||
|
||||
QCoapClientForSecurityTests client(security);
|
||||
if (client.securityMissing())
|
||||
QSKIP("Skipping this test, security is not configured properly");
|
||||
|
||||
QCoapClient client;
|
||||
client.setBlockSize(16);
|
||||
|
||||
QCoapRequest request(url);
|
||||
|
@ -724,12 +844,17 @@ void tst_QCoapClient::discover_data()
|
|||
{
|
||||
QTest::addColumn<QUrl>("url");
|
||||
QTest::addColumn<int>("resourceNumber");
|
||||
QTest::addColumn<QtCoap::SecurityMode>("security");
|
||||
|
||||
// Californium test server exposes 29 resources
|
||||
QTest::newRow("discover") << QUrl(testServerUrl())
|
||||
<< 29;
|
||||
QTest::newRow("discover_no_scheme_no_port") << QUrl(testServerHost())
|
||||
<< 29;
|
||||
QTest::newRow("discover")
|
||||
<< QUrl(testServerHost())
|
||||
<< 29
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
QTest::newRow("discover_secure")
|
||||
<< QUrl(testServerHost())
|
||||
<< 29
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
}
|
||||
|
||||
void tst_QCoapClient::discover()
|
||||
|
@ -738,8 +863,11 @@ void tst_QCoapClient::discover()
|
|||
|
||||
QFETCH(QUrl, url);
|
||||
QFETCH(int, resourceNumber);
|
||||
QFETCH(QtCoap::SecurityMode, security);
|
||||
|
||||
QCoapClient client;
|
||||
QCoapClientForSecurityTests client(security);
|
||||
if (client.securityMissing())
|
||||
QSKIP("Skipping this test, security is not configured properly");
|
||||
|
||||
QScopedPointer<QCoapResourceDiscoveryReply> resourcesReply(client.discover(url)); // /.well-known/core
|
||||
QVERIFY(!resourcesReply.isNull());
|
||||
|
@ -749,7 +877,8 @@ void tst_QCoapClient::discover()
|
|||
|
||||
const auto discoverUrl = QUrl(url.toString() + "/.well-known/core");
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
QCOMPARE(resourcesReply->url(), QCoapRequestPrivate::adjustedUrl(discoverUrl, false));
|
||||
QCOMPARE(resourcesReply->url(),
|
||||
QCoapRequestPrivate::adjustedUrl(discoverUrl, security != QtCoap::SecurityMode::NoSecurity));
|
||||
#endif
|
||||
QCOMPARE(resourcesReply->resources().length(), resourceNumber);
|
||||
QCOMPARE(resourcesReply->request().method(), QtCoap::Method::Get);
|
||||
|
@ -762,42 +891,62 @@ void tst_QCoapClient::observe_data()
|
|||
QWARN("Observe tests may take some time, don't forget to raise Tests timeout in settings.");
|
||||
QTest::addColumn<QUrl>("url");
|
||||
QTest::addColumn<QCoapMessage::Type>("type");
|
||||
QTest::addColumn<QtCoap::SecurityMode>("security");
|
||||
|
||||
QTest::newRow("observe")
|
||||
<< QUrl(testServerUrl() + "/obs")
|
||||
<< QCoapMessage::Type::NonConfirmable;
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
|
||||
QTest::newRow("observe_secure")
|
||||
<< QUrl(testServerHost() + "/obs")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
|
||||
QTest::newRow("observe_no_scheme_no_port")
|
||||
<< QUrl(testServerHost() + "/obs")
|
||||
<< QCoapMessage::Type::NonConfirmable;
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
|
||||
QTest::newRow("observe_confirmable")
|
||||
<< QUrl(testServerUrl() + "/obs")
|
||||
<< QCoapMessage::Type::Confirmable;
|
||||
<< QCoapMessage::Type::Confirmable
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
|
||||
QTest::newRow("observe_receive")
|
||||
<< QUrl(testServerUrl() + "/obs-non")
|
||||
<< QCoapMessage::Type::NonConfirmable;
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
|
||||
QTest::newRow("observe_receive_confirmable")
|
||||
<< QUrl(testServerUrl() + "/obs-non")
|
||||
<< QCoapMessage::Type::Confirmable;
|
||||
<< QCoapMessage::Type::Confirmable
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
|
||||
QTest::newRow("observe_large")
|
||||
<< QUrl(testServerUrl() + "/obs-large")
|
||||
<< QCoapMessage::Type::NonConfirmable;
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
|
||||
QTest::newRow("observe_large_secure")
|
||||
<< QUrl(testServerHost() + "/obs-large")
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< QtCoap::SecurityMode::PreSharedKey;
|
||||
|
||||
QTest::newRow("observe_large_confirmable")
|
||||
<< QUrl(testServerUrl() + "/obs-large")
|
||||
<< QCoapMessage::Type::Confirmable;
|
||||
<< QCoapMessage::Type::Confirmable
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
|
||||
QTest::newRow("observe_pumping")
|
||||
<< QUrl(testServerUrl() + "/obs-pumping")
|
||||
<< QCoapMessage::Type::NonConfirmable;
|
||||
<< QCoapMessage::Type::NonConfirmable
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
|
||||
QTest::newRow("observe_pumping_confirmable")
|
||||
<< QUrl(testServerUrl() + "/obs-pumping")
|
||||
<< QCoapMessage::Type::Confirmable;
|
||||
<< QCoapMessage::Type::Confirmable
|
||||
<< QtCoap::SecurityMode::NoSecurity;
|
||||
}
|
||||
|
||||
void tst_QCoapClient::observe()
|
||||
|
@ -806,8 +955,12 @@ void tst_QCoapClient::observe()
|
|||
|
||||
QFETCH(QUrl, url);
|
||||
QFETCH(QCoapMessage::Type, type);
|
||||
QFETCH(QtCoap::SecurityMode, security);
|
||||
|
||||
QCoapClientForSecurityTests client(security);
|
||||
if (client.securityMissing())
|
||||
QSKIP("Skipping this test, security is not configured properly");
|
||||
|
||||
QCoapClient client;
|
||||
QCoapRequest request(url);
|
||||
|
||||
request.setType(type);
|
||||
|
@ -820,7 +973,8 @@ void tst_QCoapClient::observe()
|
|||
QTRY_COMPARE_WITH_TIMEOUT(spyReplyNotified.count(), 3, 30000);
|
||||
client.cancelObserve(reply.data());
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
QCOMPARE(reply->url(), QCoapRequestPrivate::adjustedUrl(url, false));
|
||||
QCOMPARE(reply->url(),
|
||||
QCoapRequestPrivate::adjustedUrl(url, security != QtCoap::SecurityMode::NoSecurity));
|
||||
#endif
|
||||
QCOMPARE(reply->request().method(), QtCoap::Method::Get);
|
||||
|
||||
|
|
Loading…
Reference in New Issue