Add more factory methods for commands

This commit is contained in:
fbraem 2015-11-10 22:48:54 +01:00
parent 98918b39c4
commit b66751a919
4 changed files with 318 additions and 43 deletions

View File

@ -22,6 +22,7 @@
#include "Poco/Redis/Array.h" #include "Poco/Redis/Array.h"
#include <vector> #include <vector>
#include <map>
namespace Poco { namespace Poco {
namespace Redis { namespace Redis {
@ -43,6 +44,9 @@ public:
static Command append(const std::string& key, const std::string& value); static Command append(const std::string& key, const std::string& value);
/// Returns an APPEND command /// Returns an APPEND command
static Command decr(const std::string& key, Int64 by = 0);
/// Returns an DECR or DECRBY command. Calls DECR when by is omitted or zero.
static Command del(const std::string& key); static Command del(const std::string& key);
/// Returns an DEL command /// Returns an DEL command
@ -62,7 +66,10 @@ public:
/// Returns a LINSERT command /// Returns a LINSERT command
static Command llen(const std::string& list); static Command llen(const std::string& list);
/// Returns a LINDEX command /// Returns a LLEN command
static Command lpop(const std::string& list);
/// Returns a LPOP command
static Command lpush(const std::string& list, const std::string& value, bool create = true); static Command lpush(const std::string& list, const std::string& value, bool create = true);
/// Returns a LPUSH or LPUSHX (when create is false) command /// Returns a LPUSH or LPUSHX (when create is false) command
@ -70,8 +77,18 @@ public:
static Command lpush(const std::string& list, const std::vector<std::string>& value, bool create = true); static Command lpush(const std::string& list, const std::vector<std::string>& value, bool create = true);
/// Returns a LPUSH or LPUSHX (when create is false) command /// Returns a LPUSH or LPUSHX (when create is false) command
static Command lrange(const std::string& list, Int64 start = 0, Int64 stop = 0); static Command lrange(const std::string& list, Int64 start = 0, Int64 stop = -1);
/// Returns a LRANGE command /// Returns a LRANGE command. When start and stop is omitted an LRANGE
/// command will returned that returns all items of the list.
static Command lrem(const std::string& list, Int64 count, const std::string& value);
/// Returns a LREM command
static Command mget(const std::vector<std::string>& keys);
/// Returns a MGET command
static Command mset(const std::map<std::string, std::string>& keyvalues, bool create = true);
/// Returns a MSET or MSETNX (when create is false) command
static Command set(const std::string& key, const std::string& value, bool overwrite = true, const Poco::Timespan& expireTime = 0, bool create = true); static Command set(const std::string& key, const std::string& value, bool overwrite = true, const Poco::Timespan& expireTime = 0, bool create = true);
/// Returns a SET command to set the key with a value /// Returns a SET command to set the key with a value

View File

@ -41,6 +41,14 @@ Command Command::append(const std::string& key, const std::string& value)
return cmd; return cmd;
} }
Command Command::decr(const std::string& key, Int64 by)
{
Command cmd(by == 0 ? "DECR" : "DECRBY");
cmd.add(key);
if ( by > 0 ) cmd.add(NumberFormatter::format(by));
return cmd;
}
Command Command::del(const std::string& key) Command Command::del(const std::string& key)
{ {
Command cmd("DEL"); Command cmd("DEL");
@ -94,6 +102,13 @@ Command Command::llen(const std::string& list)
return cmd; return cmd;
} }
Command Command::lpop(const std::string& list)
{
Command cmd("LPOP");
cmd.add(list);
return cmd;
}
Command Command::lpush(const std::string& list, const std::string& value, bool create) Command Command::lpush(const std::string& list, const std::string& value, bool create)
{ {
Command cmd(create ? "LPUSH" : "LPUSHX"); Command cmd(create ? "LPUSH" : "LPUSHX");
@ -122,6 +137,39 @@ Command Command::lrange(const std::string& list, Int64 start, Int64 stop)
return cmd; return cmd;
} }
Command Command::lrem(const std::string& list, Int64 count, const std::string& value)
{
Command cmd("LREM");
cmd.add(list).add(NumberFormatter::format(count)).add(value);
return cmd;
}
Command Command::mget(const std::vector<std::string>& keys)
{
Command cmd("MGET");
for(std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it)
{
cmd.add(*it);
}
return cmd;
}
Command Command::mset(const std::map<std::string, std::string>& keyvalues, bool create)
{
Command cmd(create ? "MSET" : "MSETNX");
for(std::map<std::string, std::string>::const_iterator it = keyvalues.begin(); it != keyvalues.end(); ++it)
{
cmd.add(it->first);
cmd.add(it->second);
}
return cmd;
}
Command Command::set(const std::string& key, const std::string& value, bool overwrite, const Poco::Timespan& expireTime, bool create) Command Command::set(const std::string& key, const std::string& value, bool overwrite, const Poco::Timespan& expireTime, bool create)
{ {

View File

@ -140,6 +140,59 @@ void RedisTest::testAppend()
} }
} }
void RedisTest::testDecr()
{
if (!_connected)
{
std::cout << "Not connected, test skipped." << std::endl;
return;
}
Command set = Command::set("mykey", 10);
try
{
std::string result = _redis.execute<std::string>(set);
assert(result.compare("OK") == 0);
}
catch(RedisException& e)
{
fail(e.message());
}
Command decr = Command::decr("mykey");
try
{
Poco::Int64 result = _redis.execute<Poco::Int64>(decr);
assert(result == 9);
}
catch(RedisException& e)
{
fail(e.message());
}
set = Command::set("mykey", "234293482390480948029348230948");
try
{
std::string result = _redis.execute<std::string>(set);
assert(result.compare("OK") == 0);
}
catch(RedisException& e)
{
fail(e.message());
}
try
{
Poco::Int64 result = _redis.execute<Poco::Int64>(decr);
fail("This must fail");
}
catch(RedisException& e)
{
// ERR value is not an integer or out of range
}
}
void RedisTest::testEcho() void RedisTest::testEcho()
{ {
if (!_connected) if (!_connected)
@ -164,6 +217,66 @@ void RedisTest::testEcho()
} }
} }
void RedisTest::testError()
{
if (!_connected)
{
std::cout << "Not connected, test skipped." << std::endl;
return;
}
Array command;
command.add("Wrong Command");
try
{
BulkString result = _redis.execute<BulkString>(command);
fail("Invalid command must throw RedisException");
}
catch(RedisException &e)
{
// Must fail
}
}
void RedisTest::testSet()
{
if (!_connected)
{
std::cout << "Not connected, test skipped." << std::endl;
return;
}
Array command;
command.add("SET")
.add("mykey")
.add("Hello");
// A set responds with a simple OK string
try
{
std::string result = _redis.execute<std::string>(command);
assert(result.compare("OK") == 0);
}
catch(RedisException &e)
{
fail(e.message());
}
command.add("NX");
// A set NX responds with a Null bulk string
// when the key is already set
try
{
BulkString result = _redis.execute<BulkString>(command);
assert(result.isNull());
}
catch(RedisException &e)
{
fail(e.message());
}
}
void RedisTest::testIncr() void RedisTest::testIncr()
{ {
if (!_connected) if (!_connected)
@ -265,44 +378,6 @@ void RedisTest::testPing()
} }
void RedisTest::testSet()
{
if (!_connected)
{
std::cout << "Not connected, test skipped." << std::endl;
return;
}
Array command;
command.add("SET")
.add("mykey")
.add("Hello");
// A set responds with a simple OK string
try
{
std::string result = _redis.execute<std::string>(command);
assert(result.compare("OK") == 0);
}
catch(RedisException &e)
{
fail(e.message());
}
command.add("NX");
// A set NX responds with a Null bulk string
// when the key is already set
try
{
BulkString result = _redis.execute<BulkString>(command);
assert(result.isNull());
}
catch(RedisException &e)
{
fail(e.message());
}
}
void RedisTest::testMSet() void RedisTest::testMSet()
{ {
if (!_connected) if (!_connected)
@ -358,6 +433,62 @@ void RedisTest::testMSet()
} }
} }
void RedisTest::testMSetWithMap()
{
if (!_connected)
{
std::cout << "Not connected, test skipped." << std::endl;
return;
}
std::map<std::string, std::string> keyValuePairs;
keyValuePairs.insert(std::make_pair<std::string, std::string>("key1", "Hello"));
keyValuePairs.insert(std::make_pair<std::string, std::string>("key2", "World"));
Command mset = Command::mset(keyValuePairs);
// A MSET responds with a simple OK string
try
{
std::string result = _redis.execute<std::string>(mset);
assert(result.compare("OK") == 0);
}
catch(RedisException &e)
{
fail(e.message());
}
std::vector<std::string> keys;
keys.push_back("key1");
keys.push_back("key2");
keys.push_back("nonexisting");
Command mget = Command::mget(keys);
try
{
Array result = _redis.execute<Array>(mget);
assert(result.size() == 3);
BulkString value = result.get<BulkString>(0);
assert(value.value().compare("Hello") == 0);
value = result.get<BulkString>(1);
assert(value.value().compare("World") == 0);
value = result.get<BulkString>(2);
assert(value.isNull());
}
catch(RedisException& e)
{
fail(e.message());
}
catch(Poco::BadCastException& e)
{
fail(e.message());
}
}
void RedisTest::testStrlen() void RedisTest::testStrlen()
{ {
if (!_connected) if (!_connected)
@ -561,8 +692,6 @@ void RedisTest::testLInsert()
Array range = _redis.execute<Array>(lrange); Array range = _redis.execute<Array>(lrange);
assert(range.size() == 3); assert(range.size() == 3);
std::cout << range.toString() << std::endl;
assert(range.get<BulkString>(0).value().compare("Hello") == 0); assert(range.get<BulkString>(0).value().compare("Hello") == 0);
assert(range.get<BulkString>(1).value().compare("There") == 0); assert(range.get<BulkString>(1).value().compare("There") == 0);
assert(range.get<BulkString>(2).value().compare("World") == 0); assert(range.get<BulkString>(2).value().compare("World") == 0);
@ -581,6 +710,79 @@ void RedisTest::testLInsert()
} }
} }
void RedisTest::testLRem()
{
if (!_connected)
{
std::cout << "Not connected, test skipped." << std::endl;
return;
}
// Make sure the list is not there yet ...
Command delCommand = Command::del("mylist");
try
{
_redis.execute<Poco::Int64>(delCommand);
}
catch(RedisException& e)
{
fail(e.message());
}
catch(Poco::BadCastException& e)
{
fail(e.message());
}
try
{
std::vector<std::string> list;
list.push_back("hello");
list.push_back("hello");
list.push_back("foo");
list.push_back("hello");
Command rpush = Command::rpush("mylist", list);
Poco::Int64 result = _redis.execute<Poco::Int64>(rpush);
assert(result == 4);
}
catch(RedisException &e)
{
fail(e.message());
}
Command lrem = Command::lrem("mylist", -2, "hello");
try
{
Poco::Int64 n = _redis.execute<Poco::Int64>(lrem);
assert(n == 2);
}
catch(RedisException &e)
{
fail(e.message());
}
catch(Poco::BadCastException& e)
{
fail(e.message());
}
Command lrange = Command::lrange("mylist");
try
{
Array result = _redis.execute<Array>(lrange);
assert(result.size() == 2);
assert(result.get<BulkString>(0).value().compare("hello") == 0);
assert(result.get<BulkString>(1).value().compare("foo") == 0);
}
catch(RedisException &e)
{
fail(e.message());
}
catch(Poco::NullValueException &e)
{
fail(e.message());
}
}
void RedisTest::testMulti() void RedisTest::testMulti()
{ {
if (!_connected) if (!_connected)
@ -827,16 +1029,20 @@ CppUnit::Test* RedisTest::suite()
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RedisTest"); CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RedisTest");
CppUnit_addTest(pSuite, RedisTest, testAppend); CppUnit_addTest(pSuite, RedisTest, testAppend);
CppUnit_addTest(pSuite, RedisTest, testDecr);
CppUnit_addTest(pSuite, RedisTest, testIncr); CppUnit_addTest(pSuite, RedisTest, testIncr);
CppUnit_addTest(pSuite, RedisTest, testIncrBy); CppUnit_addTest(pSuite, RedisTest, testIncrBy);
CppUnit_addTest(pSuite, RedisTest, testEcho); CppUnit_addTest(pSuite, RedisTest, testEcho);
CppUnit_addTest(pSuite, RedisTest, testError);
CppUnit_addTest(pSuite, RedisTest, testPing); CppUnit_addTest(pSuite, RedisTest, testPing);
CppUnit_addTest(pSuite, RedisTest, testSet); CppUnit_addTest(pSuite, RedisTest, testSet);
CppUnit_addTest(pSuite, RedisTest, testMSet); CppUnit_addTest(pSuite, RedisTest, testMSet);
CppUnit_addTest(pSuite, RedisTest, testMSetWithMap);
CppUnit_addTest(pSuite, RedisTest, testStrlen); CppUnit_addTest(pSuite, RedisTest, testStrlen);
CppUnit_addTest(pSuite, RedisTest, testRPush); CppUnit_addTest(pSuite, RedisTest, testRPush);
CppUnit_addTest(pSuite, RedisTest, testLIndex); CppUnit_addTest(pSuite, RedisTest, testLIndex);
CppUnit_addTest(pSuite, RedisTest, testLInsert); CppUnit_addTest(pSuite, RedisTest, testLInsert);
CppUnit_addTest(pSuite, RedisTest, testLRem);
CppUnit_addTest(pSuite, RedisTest, testMulti); CppUnit_addTest(pSuite, RedisTest, testMulti);
CppUnit_addTest(pSuite, RedisTest, testPubSub); CppUnit_addTest(pSuite, RedisTest, testPubSub);

View File

@ -31,16 +31,20 @@ public:
virtual ~RedisTest(); virtual ~RedisTest();
void testAppend(); void testAppend();
void testDecr();
void testEcho(); void testEcho();
void testError();
void testIncr(); void testIncr();
void testIncrBy(); void testIncrBy();
void testPing(); void testPing();
void testSet(); void testSet();
void testMSet(); void testMSet();
void testMSetWithMap();
void testStrlen(); void testStrlen();
void testRPush(); void testRPush();
void testLIndex(); void testLIndex();
void testLInsert(); void testLInsert();
void testLRem();
void testMulti(); void testMulti();
void testPubSub(); void testPubSub();