diff --git a/src/amqp_client.cpp b/src/amqp_client.cpp index 2017146..8af1d25 100644 --- a/src/amqp_client.cpp +++ b/src/amqp_client.cpp @@ -28,8 +28,11 @@ void ClientPrivate::init(QObject *parent) { Q_Q(Client); q->setParent(parent); - if (!network_) + if (!network_) { network_ = new Network(q); + QObject::connect(network_.data(), SIGNAL(connected()), q, SIGNAL(connected())); + QObject::connect(network_.data(), SIGNAL(disconnected()), q, SIGNAL(disconnected())); + } if (!connection_) connection_ = new Connection(q); @@ -135,12 +138,14 @@ Queue *ClientPrivate::createQueue(int channelNumber, const QString &name ) void ClientPrivate::disconnect() { - Q_Q(Client); - if (network_->state() != QAbstractSocket::UnconnectedState) { - network_->disconnect(); - connection_->d_func()->connected = false; - Q_EMIT q->disconnected(); +// Q_Q(Client); + if (network_->state() == QAbstractSocket::UnconnectedState) { + qDebug() << Q_FUNC_INFO << "already disconnected"; + return; } + + network_->disconnect(); + connection_->d_func()->connected = false; } ////////////////////////////////////////////////////////////////////////// @@ -278,32 +283,6 @@ Queue *Client::createQueue( const QString &name, int channelNumber ) return d->createQueue(channelNumber, name); } -void Client::open() -{ - Q_D(Client); - return d->connect(); -} - -void Client::open(const QUrl &connectionString) -{ - Q_D(Client); - d->parseConnectionString(connectionString); - open(); -} - -void Client::close() -{ - Q_D(Client); - return d->disconnect(); -} - -void Client::reopen() -{ - Q_D(Client); - d->disconnect(); - d->connect(); -} - void Client::setAuth(Authenticator *auth) { Q_D(Client); @@ -358,3 +337,28 @@ QString Client::customProperty(const QString &name) const return d->connection_->customProperty(name); } +void Client::connectToHost(const QString &connectionString) +{ + Q_D(Client); + if (connectionString.isEmpty()) { + d->connect(); + return; + } + + d->parseConnectionString(QUrl::fromUserInput(connectionString)); + d->connect(); +} + +void Client::connectToHost(const QHostAddress &address, quint16 port) +{ + Q_D(Client); + d->host = address.toString(); + d->port = port; + d->connect(); +} + +void Client::disconnectFromHost() +{ + Q_D(Client); + d->disconnect(); +} diff --git a/src/amqp_client.h b/src/amqp_client.h index 8094a9c..0e5f151 100644 --- a/src/amqp_client.h +++ b/src/amqp_client.h @@ -62,11 +62,6 @@ public: void setAuth(Authenticator *auth); Authenticator *auth() const; - void open(); - void open(const QUrl &connectionString); - void close(); - void reopen(); - bool isSsl() const; void setSsl(bool value); @@ -75,6 +70,10 @@ public: bool isConnected() const; + void connectToHost(const QString &connectionString = QString()); + void connectToHost(const QHostAddress &address, quint16 port); + void disconnectFromHost(); + Q_SIGNALS: void connected(); void disconnected(); @@ -86,6 +85,7 @@ private: friend class ConnectionPrivate; friend class ChannelPrivate; + }; } // namespace QAMQP diff --git a/tests/auto/basic/tst_basic.cpp b/tests/auto/basic/tst_basic.cpp index 84d5a51..b8cb6b6 100644 --- a/tests/auto/basic/tst_basic.cpp +++ b/tests/auto/basic/tst_basic.cpp @@ -1,5 +1,8 @@ #include +#include "amqp_client.h" +#include "signalspy.h" + class tst_Basic : public QObject { Q_OBJECT @@ -12,12 +15,22 @@ private Q_SLOTS: void tst_Basic::connect() { - QVERIFY(true); + QAMQP::Client client; + SignalSpy spy(&client, SIGNAL(connected())); + client.connectToHost(); + QVERIFY(spy.wait()); } void tst_Basic::connectDisconnect() { - QVERIFY(true); + QAMQP::Client client; + SignalSpy connectSpy(&client, SIGNAL(connected())); + client.connectToHost(); + QVERIFY(connectSpy.wait()); + + SignalSpy disconnectSpy(&client, SIGNAL(disconnected())); + client.disconnectFromHost(); + QVERIFY(disconnectSpy.wait()); } void tst_Basic::reconnect() diff --git a/tests/common/signalspy.h b/tests/common/signalspy.h new file mode 100644 index 0000000..2a46612 --- /dev/null +++ b/tests/common/signalspy.h @@ -0,0 +1,124 @@ +#ifndef SIGNALSPY_H +#define SIGNALSPY_H + +#if QT_VERSION >= 0x050000 +typedef QSignalSpy SignalSpy; +#else +#include +#include +#include +#include +#include +#include +#include + +class QVariant; +class SignalSpy: public QObject, public QList > +{ +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 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 list; + for (int i = 0; i < args.count(); ++i) { + QMetaType::Type type = static_cast(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 args; + + QTestEventLoop m_loop; + bool m_waiting; +}; +#endif +#endif diff --git a/tests/manual/qamqp/pubsub/EmitLog.h b/tests/manual/qamqp/pubsub/EmitLog.h index 3bf6435..e3d90df 100644 --- a/tests/manual/qamqp/pubsub/EmitLog.h +++ b/tests/manual/qamqp/pubsub/EmitLog.h @@ -28,7 +28,7 @@ public: { // Create AMQP client QAMQP::Client* client = new QAMQP::Client(this); - client->open(QUrl(address)); + client->connectToHost(address); // Create the "logs" fanout exchange exchange_ = client->createExchange("logs"); diff --git a/tests/manual/qamqp/pubsub/ReceiveLog.h b/tests/manual/qamqp/pubsub/ReceiveLog.h index d8ae25b..d4a9cb8 100644 --- a/tests/manual/qamqp/pubsub/ReceiveLog.h +++ b/tests/manual/qamqp/pubsub/ReceiveLog.h @@ -28,7 +28,7 @@ public: { // Create AMQP client QAMQP::Client* client = new QAMQP::Client(this); - client->open(QUrl(address)); + client->connectToHost(address); // Create an exclusive queue queue_ = client->createQueue(); diff --git a/tests/manual/qamqp/routing/EmitLogDirect.h b/tests/manual/qamqp/routing/EmitLogDirect.h index ec05a26..7ddc2fd 100644 --- a/tests/manual/qamqp/routing/EmitLogDirect.h +++ b/tests/manual/qamqp/routing/EmitLogDirect.h @@ -30,7 +30,7 @@ public: { // Create AMQP client QAMQP::Client* client = new QAMQP::Client(this); - client->open(QUrl(address)); + client->connectToHost(address); // Create the "direct_logs" fanout exchange exchange_ = client->createExchange("direct_logs"); diff --git a/tests/manual/qamqp/routing/ReceiveLogDirect.h b/tests/manual/qamqp/routing/ReceiveLogDirect.h index 9d02155..d516ecd 100644 --- a/tests/manual/qamqp/routing/ReceiveLogDirect.h +++ b/tests/manual/qamqp/routing/ReceiveLogDirect.h @@ -31,7 +31,7 @@ public: { // Create AMQP client QAMQP::Client* client = new QAMQP::Client(this); - client->open(QUrl(address)); + client->connectToHost(address); // Create an exclusive queue queue_ = client->createQueue(); diff --git a/tests/manual/qamqp/sendreceive/Receive.h b/tests/manual/qamqp/sendreceive/Receive.h index fdc586f..cd7a0b9 100644 --- a/tests/manual/qamqp/sendreceive/Receive.h +++ b/tests/manual/qamqp/sendreceive/Receive.h @@ -30,7 +30,7 @@ public: : super(parent) { QAMQP::Client* client = new QAMQP::Client(this); - client->open(QUrl(address)); + client->connectToHost(address); queue_ = client->createQueue("hello"); queue_->declare(); diff --git a/tests/manual/qamqp/sendreceive/Send.h b/tests/manual/qamqp/sendreceive/Send.h index 8efd4d9..f7e589f 100644 --- a/tests/manual/qamqp/sendreceive/Send.h +++ b/tests/manual/qamqp/sendreceive/Send.h @@ -31,7 +31,7 @@ public: { // Create AMQP client QAMQP::Client* client = new QAMQP::Client(this); - client->open(QUrl(address)); + client->connectToHost(address); // Retrieve the "Default" exchange // No need to declare (i.e. to create), nor to bind to a queue diff --git a/tests/manual/qamqp/workqueues/NewTask.h b/tests/manual/qamqp/workqueues/NewTask.h index d889805..18fa1d8 100644 --- a/tests/manual/qamqp/workqueues/NewTask.h +++ b/tests/manual/qamqp/workqueues/NewTask.h @@ -29,7 +29,7 @@ public: { // Create AMQP client QAMQP::Client* client = new QAMQP::Client(this); - client->open(QUrl(address)); + client->connectToHost(address); // Retrieve the "Default" exchange exchange_ = client->createExchange(); diff --git a/tests/manual/qamqp/workqueues/Worker.h b/tests/manual/qamqp/workqueues/Worker.h index fa37d2d..1132f0f 100644 --- a/tests/manual/qamqp/workqueues/Worker.h +++ b/tests/manual/qamqp/workqueues/Worker.h @@ -27,7 +27,7 @@ public: : super(parent) { QAMQP::Client* client = new QAMQP::Client(this); - client->open(QUrl(address)); + client->connectToHost(address); queue_ = client->createQueue(); queue_->declare("task_queue", Queue::Durable); diff --git a/tests/tests.pri b/tests/tests.pri index 80d7f7a..11e6c7f 100644 --- a/tests/tests.pri +++ b/tests/tests.pri @@ -1,6 +1,8 @@ -INCLUDEPATH += $${QAMQP_INCLUDEPATH} +INCLUDEPATH += $${QAMQP_INCLUDEPATH} $${PWD}/common LIBS += -L$${DEPTH}/src $${QAMQP_LIBS} QT = core network testlib QT -= gui CONFIG -= app_bundle CONFIG += testcase + +HEADERS += $${PWD}/common/signalspy.h