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_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.
find_package(Qt5Core REQUIRED)
find_package(Qt5Network REQUIRED)
@ -38,7 +28,8 @@ set(QREDIS_SRC
qt5_wrap_cpp(QREDIS_MOC
include/qredis/client.h
include/qredis/request.h
src/client_p.h)
src/client_p.h
src/request_p.h)
# Create the client library.
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:
* GCC 4.6+ or Microsoft Visual C++ 2010+
* GCC or Microsoft Visual C++
* 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.*
@ -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>
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:
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
* @param parent the parent QObject
*/
explicit Client(QObject * parent = nullptr);
explicit Client(QObject * parent = 0);
/**
* @brief Destroys the 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
* @param hostName the hostname of the Redis server

View File

@ -4,7 +4,6 @@
#include <QObject>
#include <QScopedPointer>
#include <QVariant>
#include <QVariantList>
#include "qredis_export.h"
@ -13,7 +12,7 @@ namespace QRedis
class QREDIS_EXPORT RequestPrivate;
/**
* @brief Represents a request and its response
* @brief Represents a request and its reply
*/
class QREDIS_EXPORT Request : public QObject
{
@ -21,48 +20,43 @@ namespace QRedis
public:
/**
* @brief Types of replies received from the Redis server
*/
enum ReplyType {
Status,
Error,
Integer,
Bulk,
MultiBulk
};
/**
* @brief Creates a request
* @param parent
*/
explicit Request(QObject * parent = nullptr);
explicit Request(QObject * parent = 0);
/**
* @brief Destroys the 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:
/**
* @brief Emitted when a bulk reply is received
* @param value the bulk value
* @brief Emitted when a reply is received
* @param type the type of value received
* @param value the value received
*/
void bulk(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);
void reply(ReplyType type, const QVariant & value);
private:

View File

@ -14,6 +14,14 @@ ClientPrivate::ClientPrivate(Client * client)
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;
}

View File

@ -1,8 +1,15 @@
#include <QTimer>
#include <qredis/request.h>
#include "request_p.h"
using namespace QRedis;
void RequestPrivate::quitEventLoop()
{
loop.exit(1);
}
Request::Request(QObject * parent)
: QObject(parent), d(new RequestPrivate)
{
@ -11,3 +18,19 @@ Request::Request(QObject * parent)
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
#define QREDIS_REQUEST_P_H
#include <QEventLoop>
#include <QObject>
namespace QRedis
{
class RequestPrivate
class RequestPrivate : public QObject
{
Q_OBJECT
public:
//...
QEventLoop loop;
public Q_SLOTS:
void quitEventLoop();
};
}

View File

@ -1,5 +1,7 @@
#include <QSignalSpy>
#include <QTest>
#include <qredis/request.h>
#include "testclient.h"
void TestClient::initTestCase()
@ -15,3 +17,9 @@ void TestClient::cleanupTestCase()
if(client.isConnected())
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
public Q_SLOTS:
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
void testPing();
private:
QRedis::Client client;