chore: update class interfaces to support Qt5 and Qt6 while dropping support for Qt4

all tests checked against RabbitMQ 3.11.13 with Erlang 25.3 with following kits:
Qt 5.6.3 32Bit MSVC2017
Qt 5.15.2 32Bit Clang 15.0.1
Qt 5.15.2 32,64Bit MSVC2019
Qt 5.15.2 32Bit MSVC2022
Qt 6.5.0 64Bit MinGW 11.2.0
Qt 6.5.0 64Bit MSVC2019
Qt 6.5.0 64Bit MSVC2022
This commit is contained in:
hensels 2023-05-08 12:07:45 +02:00
parent b5c660a1ac
commit 6cc6bbcdfa
16 changed files with 202 additions and 316 deletions

View File

@ -1,8 +1,8 @@
language: cpp language: cpp
cache: apt cache: apt
env: env:
- QT_SELECT=qt4
- QT_SELECT=qt5 - QT_SELECT=qt5
- QT_SELECT=qt6
services: services:
- rabbitmq - rabbitmq
before_install: before_install:

View File

@ -3,7 +3,7 @@
QAMQP QAMQP
============= =============
A Qt4/Qt5 implementation of AMQP 0.9.1, focusing primarily on RabbitMQ support. A Qt5/Qt6 implementation of AMQP 0.9.1, focusing primarily on RabbitMQ support.
Usage Usage
------------ ------------
@ -16,8 +16,16 @@ Usage
Documentation Documentation
------------ ------------
Coming soon! Tests checked and integrated against rabbitmq 3.11 (August 1, 2022)
Qt5.6.3 (MSVC2017) 32Bit
Qt5.15.2 (MSVC2019, MSVC2022, MinGW, Clang) 32 and 64Bit
Qt6.5 (MSVC2019, MSVC2022) 64Bit
A good starting point is:
* running a local RabbitMQ,
* browse to http://localhost:15672/#/queues (guest/guest)
* Start the "receive" sample and see in your browser the "hello" queue appear
* publish a message there
AMQP Support AMQP Support
------------ ------------

View File

@ -1,4 +1,4 @@
QAMQP_VERSION = 0.5.0 QAMQP_VERSION = 0.6.0
isEmpty(QAMQP_LIBRARY_TYPE) { isEmpty(QAMQP_LIBRARY_TYPE) {
QAMQP_LIBRARY_TYPE = shared QAMQP_LIBRARY_TYPE = shared
@ -7,6 +7,7 @@ isEmpty(QAMQP_LIBRARY_TYPE) {
QT += network QT += network
QAMQP_INCLUDEPATH = $${PWD}/src QAMQP_INCLUDEPATH = $${PWD}/src
QAMQP_LIBS = -lqamqp QAMQP_LIBS = -lqamqp
CONFIG(debug, debug|release){ CONFIG(debug, debug|release){
QAMQP_LIBS = -lqamqpd QAMQP_LIBS = -lqamqpd
} }
@ -14,7 +15,6 @@ contains(QAMQP_LIBRARY_TYPE, staticlib) {
DEFINES += QAMQP_STATIC DEFINES += QAMQP_STATIC
} else { } else {
DEFINES += QAMQP_SHARED DEFINES += QAMQP_SHARED
win32:QAMQP_LIBS = -lqamqp0
} }
isEmpty(PREFIX) { isEmpty(PREFIX) {

View File

@ -62,10 +62,25 @@ void QAmqpClientPrivate::initSocket()
QObject::connect(socket, SIGNAL(connected()), q, SLOT(_q_socketConnected())); QObject::connect(socket, SIGNAL(connected()), q, SLOT(_q_socketConnected()));
QObject::connect(socket, SIGNAL(disconnected()), q, SLOT(_q_socketDisconnected())); QObject::connect(socket, SIGNAL(disconnected()), q, SLOT(_q_socketDisconnected()));
QObject::connect(socket, SIGNAL(readyRead()), q, SLOT(_q_readyRead())); QObject::connect(socket, SIGNAL(readyRead()), q, SLOT(_q_readyRead()));
QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), #if QT_VERSION >= 0x060000
q, SLOT(_q_socketError(QAbstractSocket::SocketError))); QObject::connect(socket,
QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SIGNAL(errorOccurred(QAbstractSocket::SocketError)),
q, SIGNAL(socketError(QAbstractSocket::SocketError))); q,
SLOT(_q_socketError(QAbstractSocket::SocketError)));
QObject::connect(socket,
SIGNAL(errorOccurred(QAbstractSocket::SocketError)),
q,
SIGNAL(socketErrorOccurred(QAbstractSocket::SocketError)));
#else
QObject::connect(socket,
SIGNAL(error(QAbstractSocket::SocketError)),
q,
SLOT(_q_socketError(QAbstractSocket::SocketError)));
QObject::connect(socket,
SIGNAL(error(QAbstractSocket::SocketError)),
q,
SIGNAL(socketErrorOccurred(QAbstractSocket::SocketError)));
#endif
QObject::connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), QObject::connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
q, SIGNAL(socketStateChanged(QAbstractSocket::SocketState))); q, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
QObject::connect(socket, SIGNAL(sslErrors(QList<QSslError>)), QObject::connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
@ -107,11 +122,7 @@ void QAmqpClientPrivate::setPassword(const QString &password)
void QAmqpClientPrivate::parseConnectionString(const QString &uri) void QAmqpClientPrivate::parseConnectionString(const QString &uri)
{ {
#if QT_VERSION > 0x040801
QUrl connectionString = QUrl::fromUserInput(uri); QUrl connectionString = QUrl::fromUserInput(uri);
#else
QUrl connectionString(uri, QUrl::TolerantMode);
#endif
if (connectionString.scheme() != AMQP_SCHEME && if (connectionString.scheme() != AMQP_SCHEME &&
connectionString.scheme() != AMQP_SSL_SCHEME) { connectionString.scheme() != AMQP_SSL_SCHEME) {
@ -126,15 +137,9 @@ void QAmqpClientPrivate::parseConnectionString(const QString &uri)
QString vhost = connectionString.path(); QString vhost = connectionString.path();
if (vhost.startsWith("/") && vhost.size() > 1) if (vhost.startsWith("/") && vhost.size() > 1)
vhost = vhost.mid(1); vhost = vhost.mid(1);
#if QT_VERSION <= 0x050200
virtualHost = QUrl::fromPercentEncoding(vhost.toUtf8());
setPassword(QUrl::fromPercentEncoding(connectionString.password().toUtf8()));
setUsername(QUrl::fromPercentEncoding(connectionString.userName().toUtf8()));
#else
virtualHost = vhost; virtualHost = vhost;
setPassword(connectionString.password()); setPassword(connectionString.password());
setUsername(connectionString.userName()); setUsername(connectionString.userName());
#endif
} }
void QAmqpClientPrivate::_q_connect() void QAmqpClientPrivate::_q_connect()
@ -531,7 +536,11 @@ void QAmqpClientPrivate::startOk()
clientProperties["version"] = QString(QAMQP_VERSION); clientProperties["version"] = QString(QAMQP_VERSION);
clientProperties["platform"] = QString("Qt %1").arg(qVersion()); clientProperties["platform"] = QString("Qt %1").arg(qVersion());
clientProperties["product"] = QString("QAMQP"); clientProperties["product"] = QString("QAMQP");
#if QT_VERSION >= 0x060000
clientProperties.insert(customProperties);
#else
clientProperties.unite(customProperties); clientProperties.unite(customProperties);
#endif
stream << clientProperties; stream << clientProperties;
authenticator->write(stream); authenticator->write(stream);

View File

@ -115,7 +115,7 @@ Q_SIGNALS:
void disconnected(); void disconnected();
void heartbeat(); void heartbeat();
void error(QAMQP::Error error); void error(QAMQP::Error error);
void socketError(QAbstractSocket::SocketError error); void socketErrorOccurred(QAbstractSocket::SocketError error);
void socketStateChanged(QAbstractSocket::SocketState state); void socketStateChanged(QAbstractSocket::SocketState state);
void sslErrors(const QList<QSslError> &errors); void sslErrors(const QList<QSslError> &errors);

View File

@ -31,7 +31,6 @@ class QAMQP_EXPORT QAmqpExchange : public QAmqpChannel
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString type READ type CONSTANT) Q_PROPERTY(QString type READ type CONSTANT)
Q_PROPERTY(ExchangeOptions options READ options CONSTANT) Q_PROPERTY(ExchangeOptions options READ options CONSTANT)
Q_ENUMS(ExchangeOptions)
public: public:
virtual ~QAmqpExchange(); virtual ~QAmqpExchange();
@ -68,6 +67,7 @@ public:
}; };
Q_DECLARE_FLAGS(ExchangeOptions, ExchangeOption) Q_DECLARE_FLAGS(ExchangeOptions, ExchangeOption)
ExchangeOptions options() const; ExchangeOptions options() const;
Q_ENUM(ExchangeOptions)
bool isDeclared() const; bool isDeclared() const;
@ -83,11 +83,11 @@ Q_SIGNALS:
public Q_SLOTS: public Q_SLOTS:
// AMQP Exchange // AMQP Exchange
void declare(ExchangeType type = Direct, void declare(QAmqpExchange::ExchangeType type = Direct,
ExchangeOptions options = NoOptions, QAmqpExchange::ExchangeOptions options = NoOptions,
const QAmqpTable &args = QAmqpTable()); const QAmqpTable &args = QAmqpTable());
void declare(const QString &type, void declare(const QString &type,
ExchangeOptions options = NoOptions, QAmqpExchange::ExchangeOptions options = NoOptions,
const QAmqpTable &args = QAmqpTable()); const QAmqpTable &args = QAmqpTable());
void remove(int options = roIfUnused|roNoWait); void remove(int options = roIfUnused|roNoWait);

View File

@ -1,6 +1,7 @@
#include <QDateTime> #include <QDateTime>
#include <QList>
#include <QDebug> #include <QDebug>
#include <QIODevice>
#include <QList>
#include "qamqptable.h" #include "qamqptable.h"
#include "qamqpglobal.h" #include "qamqpglobal.h"
@ -208,7 +209,11 @@ QVariant QAmqpFrame::readAmqpField(QDataStream &s, QAmqpMetaType::ValueType type
{ {
qulonglong tmp_value; qulonglong tmp_value;
s >> tmp_value; s >> tmp_value;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
return QDateTime::fromSecsSinceEpoch(tmp_value);
#else
return QDateTime::fromTime_t(tmp_value); return QDateTime::fromTime_t(tmp_value);
#endif
} }
case QAmqpMetaType::Hash: case QAmqpMetaType::Hash:
{ {
@ -262,7 +267,11 @@ void QAmqpFrame::writeAmqpField(QDataStream &s, QAmqpMetaType::ValueType type, c
} }
break; break;
case QAmqpMetaType::Timestamp: case QAmqpMetaType::Timestamp:
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
s << qulonglong(value.toDateTime().toSecsSinceEpoch());
#else
s << qulonglong(value.toDateTime().toTime_t()); s << qulonglong(value.toDateTime().toTime_t());
#endif
break; break;
case QAmqpMetaType::Hash: case QAmqpMetaType::Hash:
{ {

View File

@ -47,7 +47,7 @@
#define AMQP_BASIC_APP_ID_FLAG (1 << 3) #define AMQP_BASIC_APP_ID_FLAG (1 << 3)
#define AMQP_BASIC_CLUSTER_ID_FLAG (1 << 2) #define AMQP_BASIC_CLUSTER_ID_FLAG (1 << 2)
#define QAMQP_VERSION "0.5.0" #define QAMQP_VERSION "0.6.0"
#define AMQP_CONNECTION_FORCED 320 #define AMQP_CONNECTION_FORCED 320
@ -61,7 +61,7 @@
# define QAMQP_EXPORT # define QAMQP_EXPORT
#endif #endif
#define qAmqpDebug if (qgetenv("QAMQP_DEBUG").isEmpty()); else qDebug #define qAmqpDebug if (qEnvironmentVariableIsEmpty("QAMQP_DEBUG")); else qDebug
namespace QAmqpMetaType { namespace QAmqpMetaType {

View File

@ -113,13 +113,6 @@ QHash<QString, QVariant> QAmqpMessage::headers() const
return d->headers; return d->headers;
} }
#if QT_VERSION < 0x050000
bool QAmqpMessage::isDetached() const
{
return d && d->ref == 1;
}
#endif
uint qHash(const QAmqpMessage &message, uint seed) uint qHash(const QAmqpMessage &message, uint seed)
{ {
Q_UNUSED(seed); Q_UNUSED(seed);

View File

@ -34,9 +34,7 @@ public:
QAmqpMessage &operator=(const QAmqpMessage &other); QAmqpMessage &operator=(const QAmqpMessage &other);
~QAmqpMessage(); ~QAmqpMessage();
#if QT_VERSION >= 0x050000
inline void swap(QAmqpMessage &other) { qSwap(d, other.d); } inline void swap(QAmqpMessage &other) { qSwap(d, other.d); }
#endif
bool operator==(const QAmqpMessage &message) const; bool operator==(const QAmqpMessage &message) const;
inline bool operator!=(const QAmqpMessage &message) const { return !(operator==(message)); } inline bool operator!=(const QAmqpMessage &message) const { return !(operator==(message)); }
@ -80,22 +78,9 @@ private:
QSharedDataPointer<QAmqpMessagePrivate> d; QSharedDataPointer<QAmqpMessagePrivate> d;
friend class QAmqpQueuePrivate; friend class QAmqpQueuePrivate;
friend class QAmqpQueue; friend class QAmqpQueue;
#if QT_VERSION < 0x050000
public:
typedef QSharedDataPointer<QAmqpMessagePrivate> DataPtr;
inline DataPtr &data_ptr() { return d; }
// internal
bool isDetached() const;
#endif
}; };
Q_DECLARE_METATYPE(QAmqpMessage::PropertyHash) Q_DECLARE_METATYPE(QAmqpMessage::PropertyHash)
#if QT_VERSION < 0x050000
Q_DECLARE_TYPEINFO(QAmqpMessage, Q_MOVABLE_TYPE);
#endif
Q_DECLARE_SHARED(QAmqpMessage) Q_DECLARE_SHARED(QAmqpMessage)
// NOTE: needed only for MSVC support, don't depend on this hash // NOTE: needed only for MSVC support, don't depend on this hash

View File

@ -1,127 +1,126 @@
/* /*
* Copyright (C) 2012-2014 Alexey Shcherbakov * Copyright (C) 2012-2014 Alexey Shcherbakov
* Copyright (C) 2014-2015 Matt Broadstone * Copyright (C) 2014-2015 Matt Broadstone
* Contact: https://github.com/mbroadst/qamqp * Contact: https://github.com/mbroadst/qamqp
* *
* This file is part of the QAMQP Library. * This file is part of the QAMQP Library.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
*/ */
#ifndef QAMQPQUEUE_H #ifndef QAMQPQUEUE_H
#define QAMQPQUEUE_H #define QAMQPQUEUE_H
#include <QQueue> #include <QQueue>
#include "qamqpchannel.h" #include "qamqpchannel.h"
#include "qamqpmessage.h" #include "qamqpmessage.h"
#include "qamqpglobal.h" #include "qamqpglobal.h"
#include "qamqptable.h" #include "qamqptable.h"
class QAmqpClient; class QAmqpClient;
class QAmqpClientPrivate; class QAmqpClientPrivate;
class QAmqpExchange; class QAmqpExchange;
class QAmqpQueuePrivate; class QAmqpQueuePrivate;
class QAMQP_EXPORT QAmqpQueue : public QAmqpChannel, public QQueue<QAmqpMessage> class QAMQP_EXPORT QAmqpQueue : public QAmqpChannel, public QQueue<QAmqpMessage>
{ {
Q_OBJECT Q_OBJECT
Q_ENUMS(QueueOptions) Q_PROPERTY(int options READ options CONSTANT)
Q_PROPERTY(int options READ options CONSTANT) Q_PROPERTY(QString consumerTag READ consumerTag WRITE setConsumerTag)
Q_PROPERTY(QString consumerTag READ consumerTag WRITE setConsumerTag)
Q_ENUMS(QueueOption) public:
Q_ENUMS(ConsumeOption) enum QueueOption {
Q_ENUMS(RemoveOption) NoOptions = 0x0,
Passive = 0x01,
public: Durable = 0x02,
enum QueueOption { Exclusive = 0x04,
NoOptions = 0x0, AutoDelete = 0x08,
Passive = 0x01, NoWait = 0x10
Durable = 0x02, };
Exclusive = 0x04, Q_DECLARE_FLAGS(QueueOptions, QueueOption)
AutoDelete = 0x08, Q_ENUM(QueueOption)
NoWait = 0x10 Q_ENUM(QueueOptions) int options() const;
};
Q_DECLARE_FLAGS(QueueOptions, QueueOption) enum ConsumeOption {
int options() const; coNoLocal = 0x01,
coNoAck = 0x02,
enum ConsumeOption { coExclusive = 0x04,
coNoLocal = 0x01, coNoWait = 0x08
coNoAck = 0x02, };
coExclusive = 0x04, Q_DECLARE_FLAGS(ConsumeOptions, ConsumeOption)
coNoWait = 0x08 Q_ENUM(ConsumeOption)
};
Q_DECLARE_FLAGS(ConsumeOptions, ConsumeOption) enum RemoveOption {
roForce = 0x0,
enum RemoveOption { roIfUnused = 0x01,
roForce = 0x0, roIfEmpty = 0x02,
roIfUnused = 0x01, roNoWait = 0x04
roIfEmpty = 0x02, };
roNoWait = 0x04 Q_DECLARE_FLAGS(RemoveOptions, RemoveOption)
}; Q_ENUM(RemoveOption)
Q_DECLARE_FLAGS(RemoveOptions, RemoveOption)
~QAmqpQueue();
~QAmqpQueue();
bool isConsuming() const;
bool isConsuming() const; bool isDeclared() const;
bool isDeclared() const;
void setConsumerTag(const QString &consumerTag);
void setConsumerTag(const QString &consumerTag); QString consumerTag() const;
QString consumerTag() const;
qint32 messageCount() const;
qint32 messageCount() const; qint32 consumerCount() const;
qint32 consumerCount() const;
Q_SIGNALS:
Q_SIGNALS: void declared();
void declared(); void bound();
void bound(); void unbound();
void unbound(); void removed();
void removed(); void purged(int messageCount);
void purged(int messageCount);
void messageReceived();
void messageReceived(); void empty();
void empty(); void consuming(const QString &consumerTag);
void consuming(const QString &consumerTag); void cancelled(const QString &consumerTag);
void cancelled(const QString &consumerTag);
public Q_SLOTS:
public Q_SLOTS: // AMQP Queue
// AMQP Queue void declare(int options = Durable|AutoDelete, const QAmqpTable &arguments = QAmqpTable());
void declare(int options = Durable|AutoDelete, const QAmqpTable &arguments = QAmqpTable()); void bind(const QString &exchangeName, const QString &key);
void bind(const QString &exchangeName, const QString &key); void bind(QAmqpExchange *exchange, const QString &key);
void bind(QAmqpExchange *exchange, const QString &key); void unbind(const QString &exchangeName, const QString &key);
void unbind(const QString &exchangeName, const QString &key); void unbind(QAmqpExchange *exchange, const QString &key);
void unbind(QAmqpExchange *exchange, const QString &key); void purge();
void purge(); void remove(int options = roIfUnused|roIfEmpty|roNoWait);
void remove(int options = roIfUnused|roIfEmpty|roNoWait);
// AMQP Basic
// AMQP Basic bool consume(int options = NoOptions);
bool consume(int options = NoOptions); void get(bool noAck = true);
void get(bool noAck = true); bool cancel(bool noWait = false);
bool cancel(bool noWait = false); void ack(const QAmqpMessage &message);
void ack(const QAmqpMessage &message); void ack(qlonglong deliveryTag, bool multiple);
void ack(qlonglong deliveryTag, bool multiple); void reject(const QAmqpMessage &message, bool requeue);
void reject(const QAmqpMessage &message, bool requeue); void reject(qlonglong deliveryTag, bool requeue);
void reject(qlonglong deliveryTag, bool requeue);
protected:
protected: // reimp Channel
// reimp Channel virtual void channelOpened();
virtual void channelOpened(); virtual void channelClosed();
virtual void channelClosed();
private:
private: explicit QAmqpQueue(int channelNumber = -1, QAmqpClient *parent = 0);
explicit QAmqpQueue(int channelNumber = -1, QAmqpClient *parent = 0);
Q_DISABLE_COPY(QAmqpQueue)
Q_DISABLE_COPY(QAmqpQueue) Q_DECLARE_PRIVATE(QAmqpQueue)
Q_DECLARE_PRIVATE(QAmqpQueue) friend class QAmqpClient;
friend class QAmqpClient; friend class QAmqpClientPrivate;
friend class QAmqpClientPrivate;
};
};
#endif // QAMQPQUEUE_H
#endif // QAMQPQUEUE_H

View File

@ -2,6 +2,7 @@
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
#include <QIODevice>
#include "qamqpframe_p.h" #include "qamqpframe_p.h"
#include "qamqptable.h" #include "qamqptable.h"

View File

@ -64,16 +64,12 @@ HEADERS += \
$${INSTALL_HEADERS} \ $${INSTALL_HEADERS} \
$${PRIVATE_HEADERS} $${PRIVATE_HEADERS}
SOURCES += \ SOURCES += $$files($$PWD/*.cpp)
qamqpauthenticator.cpp \
qamqpchannel.cpp \ DISTFILES += \
qamqpchannelhash.cpp \ ../.travis.yml \
qamqpclient.cpp \ ../LICENSE \
qamqpexchange.cpp \ ../README.md
qamqpframe.cpp \
qamqpmessage.cpp \
qamqpqueue.cpp \
qamqptable.cpp
# install # install
headers.files = $${INSTALL_HEADERS} headers.files = $${INSTALL_HEADERS}

View File

@ -179,7 +179,7 @@ void tst_QAMQPClient::tune()
client.connectToHost(); client.connectToHost();
QVERIFY(waitForSignal(&client, SIGNAL(connected()))); QVERIFY(waitForSignal(&client, SIGNAL(connected())));
QCOMPARE((int)client.channelMax(), 15); QCOMPARE((int) client.channelMax(), 2047);
QCOMPARE((int)client.heartbeatDelay(), 600); QCOMPARE((int)client.heartbeatDelay(), 600);
QCOMPARE((int)client.frameMax(), 5000); QCOMPARE((int)client.frameMax(), 5000);
@ -191,7 +191,7 @@ void tst_QAMQPClient::socketError()
{ {
QAmqpClient client; QAmqpClient client;
client.connectToHost("amqp://127.0.0.1:56725/"); client.connectToHost("amqp://127.0.0.1:56725/");
QVERIFY(waitForSignal(&client, SIGNAL(socketError(QAbstractSocket::SocketError)))); QVERIFY(waitForSignal(&client, SIGNAL(socketErrorOccurred(QAbstractSocket::SocketError))));
QCOMPARE(client.socketError(), QAbstractSocket::ConnectionRefusedError); QCOMPARE(client.socketError(), QAbstractSocket::ConnectionRefusedError);
} }
@ -208,10 +208,8 @@ void tst_QAMQPClient::validateUri_data()
<< "guest" << "guest" << "192.168.1.10" << quint16(5672) << "/"; << "guest" << "guest" << "192.168.1.10" << quint16(5672) << "/";
QTest::newRow("standard") << "amqp://user:pass@host:10000/vhost" QTest::newRow("standard") << "amqp://user:pass@host:10000/vhost"
<< "user" << "pass" << "host" << quint16(10000) << "vhost"; << "user" << "pass" << "host" << quint16(10000) << "vhost";
#if QT_VERSION >= 0x040806
QTest::newRow("urlencoded") << "amqp://user%61:%61pass@ho%61st:10000/v%2fhost" QTest::newRow("urlencoded") << "amqp://user%61:%61pass@ho%61st:10000/v%2fhost"
<< "usera" << "apass" << "hoast" << quint16(10000) << "v/host"; << "usera" << "apass" << "hoast" << quint16(10000) << "v/host";
#endif
QTest::newRow("empty") << "amqp://" << "" << "" << "" << quint16(AMQP_PORT) << ""; QTest::newRow("empty") << "amqp://" << "" << "" << "" << quint16(AMQP_PORT) << "";
QTest::newRow("empty2") << "amqp://:@/" << "" << "" << "" << quint16(AMQP_PORT) << "/"; QTest::newRow("empty2") << "amqp://:@/" << "" << "" << "" << quint16(AMQP_PORT) << "/";
QTest::newRow("onlyuser") << "amqp://user@" << "user" << "" << "" << quint16(AMQP_PORT) << ""; QTest::newRow("onlyuser") << "amqp://user@" << "user" << "" << "" << quint16(AMQP_PORT) << "";

View File

@ -356,7 +356,7 @@ void tst_QAMQPQueue::canOnlyStartConsumingOnce()
void tst_QAMQPQueue::ensureConsumeOnlySentOnce() void tst_QAMQPQueue::ensureConsumeOnlySentOnce()
{ {
QAmqpQueue *queue = client->createQueue("test-single-consumer"); QAmqpQueue *queue = client->createQueue("test-single-consumer");
SignalSpy spy(queue, SIGNAL(consuming(QString))); QSignalSpy spy(queue, SIGNAL(consuming(QString)));
queue->declare(); queue->declare();
QVERIFY(waitForSignal(queue, SIGNAL(declared()))); QVERIFY(waitForSignal(queue, SIGNAL(declared())));
@ -601,8 +601,13 @@ void tst_QAMQPQueue::tableFieldDataTypes()
QCOMPARE(message.header("double").toDouble(), double(FLT_MAX)); QCOMPARE(message.header("double").toDouble(), double(FLT_MAX));
QCOMPARE(message.header("short-string").toString(), QLatin1String("test")); QCOMPARE(message.header("short-string").toString(), QLatin1String("test"));
QCOMPARE(message.header("long-string").toString(), QLatin1String("test")); QCOMPARE(message.header("long-string").toString(), QLatin1String("test"));
QCOMPARE(message.header("timestamp").toDateTime().toTime_t(), timestamp.toTime_t());
QCOMPARE(message.header("bytes").toByteArray(), QByteArray("abcdefg1234567")); QCOMPARE(message.header("bytes").toByteArray(), QByteArray("abcdefg1234567"));
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
QCOMPARE(message.header("timestamp").toDateTime().toSecsSinceEpoch(),
timestamp.toSecsSinceEpoch());
#else
QCOMPARE(message.header("timestamp").toDateTime().toTime_t(), timestamp.toTime_t());
#endif
QVERIFY(message.hasHeader("nested-table")); QVERIFY(message.hasHeader("nested-table"));
QAmqpTable compareTable(message.header("nested-table").toHash()); QAmqpTable compareTable(message.header("nested-table").toHash());
@ -654,11 +659,17 @@ void tst_QAMQPQueue::messageProperties()
QCOMPARE(message.property(QAmqpMessage::ReplyTo).toString(), QLatin1String("another-queue")); QCOMPARE(message.property(QAmqpMessage::ReplyTo).toString(), QLatin1String("another-queue"));
QCOMPARE(message.property(QAmqpMessage::MessageId).toString(), QLatin1String("some-message-id")); QCOMPARE(message.property(QAmqpMessage::MessageId).toString(), QLatin1String("some-message-id"));
QCOMPARE(message.property(QAmqpMessage::Expiration).toString(), QLatin1String("60000")); QCOMPARE(message.property(QAmqpMessage::Expiration).toString(), QLatin1String("60000"));
QCOMPARE(message.property(QAmqpMessage::Timestamp).toDateTime().toTime_t(), timestamp.toTime_t());
QCOMPARE(message.property(QAmqpMessage::Type).toString(), QLatin1String("some-message-type")); QCOMPARE(message.property(QAmqpMessage::Type).toString(), QLatin1String("some-message-type"));
QCOMPARE(message.property(QAmqpMessage::UserId).toString(), QLatin1String("guest")); QCOMPARE(message.property(QAmqpMessage::UserId).toString(), QLatin1String("guest"));
QCOMPARE(message.property(QAmqpMessage::AppId).toString(), QLatin1String("some-app-id")); QCOMPARE(message.property(QAmqpMessage::AppId).toString(), QLatin1String("some-app-id"));
QCOMPARE(message.property(QAmqpMessage::ClusterID).toString(), QLatin1String("some-cluster-id")); QCOMPARE(message.property(QAmqpMessage::ClusterID).toString(), QLatin1String("some-cluster-id"));
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
QCOMPARE(message.property(QAmqpMessage::Timestamp).toDateTime().toSecsSinceEpoch(),
timestamp.toSecsSinceEpoch());
#else
QCOMPARE(message.property(QAmqpMessage::Timestamp).toDateTime().toTime_t(),
timestamp.toTime_t());
#endif
} }
void tst_QAMQPQueue::emptyMessage() void tst_QAMQPQueue::emptyMessage()

View File

@ -17,127 +17,4 @@ bool waitForSignal(QObject *obj, const char *signal, int delay)
} // namespace Test } // namespace Test
} // namespace QAMQP } // namespace QAMQP
#if QT_VERSION >= 0x050000
typedef QSignalSpy SignalSpy;
#else
#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
#include <QtCore/qobject.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qvariant.h>
#include <QtCore/qvector.h>
#include <QtTest/qtesteventloop.h>
class QVariant;
class SignalSpy: public QObject, public QList<QList<QVariant> >
{
public:
explicit SignalSpy(const QObject *obj, const char *aSignal)
: m_waiting(false)
{
static const int memberOffset = QObject::staticMetaObject.methodCount();
if (!obj) {
qWarning("SignalSpy: Cannot spy on a null object");
return;
}
if (!aSignal) {
qWarning("SignalSpy: Null signal name is not valid");
return;
}
if (((aSignal[0] - '0') & 0x03) != QSIGNAL_CODE) {
qWarning("SignalSpy: Not a valid signal, use the SIGNAL macro");
return;
}
const QByteArray ba = QMetaObject::normalizedSignature(aSignal + 1);
const QMetaObject * const mo = obj->metaObject();
const int sigIndex = mo->indexOfMethod(ba.constData());
if (sigIndex < 0) {
qWarning("SignalSpy: No such signal: '%s'", ba.constData());
return;
}
if (!QMetaObject::connect(obj, sigIndex, this, memberOffset,
Qt::DirectConnection, 0)) {
qWarning("SignalSpy: QMetaObject::connect returned false. Unable to connect.");
return;
}
sig = ba;
initArgs(mo->method(sigIndex), obj);
}
inline bool isValid() const { return !sig.isEmpty(); }
inline QByteArray signal() const { return sig; }
bool wait(int timeout = 5)
{
Q_ASSERT(!m_waiting);
const int origCount = count();
m_waiting = true;
m_loop.enterLoop(timeout);
m_waiting = false;
return count() > origCount;
}
int qt_metacall(QMetaObject::Call call, int methodId, void **a)
{
methodId = QObject::qt_metacall(call, methodId, a);
if (methodId < 0)
return methodId;
if (call == QMetaObject::InvokeMetaMethod) {
if (methodId == 0) {
appendArgs(a);
}
--methodId;
}
return methodId;
}
private:
void initArgs(const QMetaMethod &member)
{
initArgs(member, 0);
}
void initArgs(const QMetaMethod &member, const QObject *obj)
{
Q_UNUSED(obj)
QList<QByteArray> params = member.parameterTypes();
for (int i = 0; i < params.count(); ++i) {
int tp = QMetaType::type(params.at(i).constData());
if (tp == QMetaType::Void)
qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
params.at(i).constData());
args << tp;
}
}
void appendArgs(void **a)
{
QList<QVariant> list;
for (int i = 0; i < args.count(); ++i) {
QMetaType::Type type = static_cast<QMetaType::Type>(args.at(i));
list << QVariant(type, a[i + 1]);
}
append(list);
if (m_waiting)
m_loop.exitLoop();
}
// the full, normalized signal name
QByteArray sig;
// holds the QMetaType types for the argument list of the signal
QVector<int> args;
QTestEventLoop m_loop;
bool m_waiting;
};
#endif
#endif #endif