Implemented sending of requests in tests and removed dependencies on C++11 features to allow older compilers to compile the client library and test suite.

This commit is contained in:
Nathan Osman 2013-07-02 15:26:19 -07:00
parent 2c4b533124
commit 0979104127
9 changed files with 89 additions and 48 deletions

View File

@ -12,16 +12,6 @@ set(QREDIS_MINOR 1)
set(QREDIS_PATCH 0) set(QREDIS_PATCH 0)
set(QREDIS_VERSION "${QREDIS_MAJOR}.${QREDIS_MINOR}.${QREDIS_PATCH}") set(QREDIS_VERSION "${QREDIS_MAJOR}.${QREDIS_MINOR}.${QREDIS_PATCH}")
# C++11 support must be enabled in GCC.
if(CMAKE_COMPILER_IS_GNUCXX)
# Ensure that we are using at least GCC 4.6+.
if(${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 4.6)
message(FATAL_ERROR "GCC 4.6+ is required (" ${CMAKE_CXX_COMPILER_VERSION} " detected).")
endif()
# Enable C++11 features.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
endif()
# The QtCore and QtNetwork libraries are both required. # The QtCore and QtNetwork libraries are both required.
find_package(Qt5Core REQUIRED) find_package(Qt5Core REQUIRED)
find_package(Qt5Network REQUIRED) find_package(Qt5Network REQUIRED)
@ -38,7 +28,8 @@ set(QREDIS_SRC
qt5_wrap_cpp(QREDIS_MOC qt5_wrap_cpp(QREDIS_MOC
include/qredis/client.h include/qredis/client.h
include/qredis/request.h include/qredis/request.h
src/client_p.h) src/client_p.h
src/request_p.h)
# Create the client library. # Create the client library.
add_library(qredis SHARED add_library(qredis SHARED

View File

@ -6,7 +6,7 @@ QRedis provides a modern Qt client library for communicating with a [Redis serve
To compile QRedis, the following requirements must be met: To compile QRedis, the following requirements must be met:
* GCC 4.6+ or Microsoft Visual C++ 2010+ * GCC or Microsoft Visual C++
* Qt 5+ * Qt 5+
*It is not necessary to have Redis installed in order to build the client library. However, you will be unable to run the test suite.* *It is not necessary to have Redis installed in order to build the client library. However, you will be unable to run the test suite.*
@ -41,10 +41,10 @@ In order to send commands to a Redis server, you need to create an instance of t
#include <qredis/client.h> #include <qredis/client.h>
QRedis::Client client; QRedis::Client client;
client.connectToHost(QHostAddress::LocalHost); client.connectToHost("localhost");
Once the connection is complete, the client will emit the `connected()` signal. You can then begin executing commands. For example, to send the `PING` command: Once the connection is complete, the client will emit the `connected()` signal. You can then begin executing commands. For example, to send the `PING` command:
QRedis::Command * command = client.sendCommand("PING"); QRedis::Command * command = client.sendCommand("PING");
The `sendCommand()` method returns a `Command *`, which provides signals to indicate when the command has completed or when an error occurs. The `sendCommand()` method returns a `Command *`, which provides signals to indicate when the command has completed or when an error occurs.

View File

@ -24,13 +24,19 @@ namespace QRedis
* @brief Creates a Redis client * @brief Creates a Redis client
* @param parent the parent QObject * @param parent the parent QObject
*/ */
explicit Client(QObject * parent = nullptr); explicit Client(QObject * parent = 0);
/** /**
* @brief Destroys the client * @brief Destroys the client
*/ */
virtual ~Client(); virtual ~Client();
/*
* Note: we specifically avoid an overload of connectToHost that
* uses QHostAddress since that would force anyone using the client
* library to use the QtNetwork module, which we wish to avoid.
*/
/** /**
* @brief Attempts to connect to the specified Redis server * @brief Attempts to connect to the specified Redis server
* @param hostName the hostname of the Redis server * @param hostName the hostname of the Redis server

View File

@ -4,7 +4,6 @@
#include <QObject> #include <QObject>
#include <QScopedPointer> #include <QScopedPointer>
#include <QVariant> #include <QVariant>
#include <QVariantList>
#include "qredis_export.h" #include "qredis_export.h"
@ -13,7 +12,7 @@ namespace QRedis
class QREDIS_EXPORT RequestPrivate; class QREDIS_EXPORT RequestPrivate;
/** /**
* @brief Represents a request and its response * @brief Represents a request and its reply
*/ */
class QREDIS_EXPORT Request : public QObject class QREDIS_EXPORT Request : public QObject
{ {
@ -21,48 +20,43 @@ namespace QRedis
public: public:
/**
* @brief Types of replies received from the Redis server
*/
enum ReplyType {
Status,
Error,
Integer,
Bulk,
MultiBulk
};
/** /**
* @brief Creates a request * @brief Creates a request
* @param parent * @param parent
*/ */
explicit Request(QObject * parent = nullptr); explicit Request(QObject * parent = 0);
/** /**
* @brief Destroys the request * @brief Destroys the request
*/ */
virtual ~Request(); virtual ~Request();
/**
* @brief Waits for the reply to be received
* @param msecs the amount of time in milliseconds to wait
* @return true if the reply was received
*/
bool waitForReply(int msecs = 30000);
Q_SIGNALS: Q_SIGNALS:
/** /**
* @brief Emitted when a bulk reply is received * @brief Emitted when a reply is received
* @param value the bulk value * @param type the type of value received
* @param value the value received
*/ */
void bulk(const QVariant & value); void reply(ReplyType type, const QVariant & value);
/**
* @brief Emitted when an error reply is received
* @param message a descriptive error message
*/
void error(const QString & message);
/**
* @brief Emitted when an integer reply is received
* @param value the integer value
*/
void integer(qint64 value);
/**
* @brief Emitted when a multi-bulk reply is received
* @param value the multi-bulk value
*/
void multiBulk(const QVariantList & value);
/**
* @brief Emitted when a status reply is received
* @param message a descriptive status message
*/
void status(const QString & message);
private: private:

View File

@ -14,6 +14,14 @@ ClientPrivate::ClientPrivate(Client * client)
bool ClientPrivate::readStatusOrError() bool ClientPrivate::readStatusOrError()
{ {
/* Check if the reply contains \r\n. */
int pos = buffer.indexOf("\r\n");
if(pos != -1)
{
emit queue.dequeue()->reply(Request::Status, buffer.mid(1, pos - 1));
buffer.remove(0, pos + 2);
}
return false; return false;
} }

View File

@ -1,8 +1,15 @@
#include <QTimer>
#include <qredis/request.h> #include <qredis/request.h>
#include "request_p.h" #include "request_p.h"
using namespace QRedis; using namespace QRedis;
void RequestPrivate::quitEventLoop()
{
loop.exit(1);
}
Request::Request(QObject * parent) Request::Request(QObject * parent)
: QObject(parent), d(new RequestPrivate) : QObject(parent), d(new RequestPrivate)
{ {
@ -11,3 +18,19 @@ Request::Request(QObject * parent)
Request::~Request() Request::~Request()
{ {
} }
bool Request::waitForReply(int msecs)
{
QTimer timer;
timer.setInterval(msecs);
timer.setSingleShot(true);
connect(&timer, SIGNAL(timeout()), &d->loop, SLOT(quit()));
connect(this, SIGNAL(reply(ReplyType,QVariant)), d.data(), SLOT(quitEventLoop()));
/*
* If the timer fires, the return value will be 0.
* Otherwise, quitEventLoop() will terminate the loop with 1.
*/
return d->loop.exec();
}

View File

@ -1,13 +1,22 @@
#ifndef QREDIS_REQUEST_P_H #ifndef QREDIS_REQUEST_P_H
#define QREDIS_REQUEST_P_H #define QREDIS_REQUEST_P_H
#include <QEventLoop>
#include <QObject>
namespace QRedis namespace QRedis
{ {
class RequestPrivate class RequestPrivate : public QObject
{ {
Q_OBJECT
public: public:
//... QEventLoop loop;
public Q_SLOTS:
void quitEventLoop();
}; };
} }

View File

@ -1,5 +1,7 @@
#include <QSignalSpy>
#include <QTest> #include <QTest>
#include <qredis/request.h>
#include "testclient.h" #include "testclient.h"
void TestClient::initTestCase() void TestClient::initTestCase()
@ -15,3 +17,9 @@ void TestClient::cleanupTestCase()
if(client.isConnected()) if(client.isConnected())
QVERIFY(client.waitForDisconnected()); QVERIFY(client.waitForDisconnected());
} }
void TestClient::testPing()
{
QRedis::Request * request = client.sendCommand("PING");
QVERIFY(request->waitForReply());
}

View File

@ -9,11 +9,13 @@ class TestClient : public QObject
{ {
Q_OBJECT Q_OBJECT
public Q_SLOTS: private Q_SLOTS:
void initTestCase(); void initTestCase();
void cleanupTestCase(); void cleanupTestCase();
void testPing();
private: private:
QRedis::Client client; QRedis::Client client;