mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-08-14 02:27:38 -07:00
redis++ binaries for mac
This commit is contained in:
parent
b5c661c5d5
commit
8f3a0b17ad
96 changed files with 35078 additions and 0 deletions
|
@ -0,0 +1,83 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_BENCHMARK_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_BENCHMARK_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
struct BenchmarkOptions {
|
||||
std::size_t pool_size = 5;
|
||||
std::size_t thread_num = 10;
|
||||
std::size_t total_request_num = 100000;
|
||||
std::size_t key_len = 10;
|
||||
std::size_t val_len = 10;
|
||||
};
|
||||
|
||||
template <typename RedisInstance>
|
||||
class BenchmarkTest {
|
||||
public:
|
||||
BenchmarkTest(const BenchmarkOptions &opts, RedisInstance &instance);
|
||||
|
||||
~BenchmarkTest() {
|
||||
_cleanup();
|
||||
}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
template <typename Func>
|
||||
void _run(const std::string &title, Func &&func);
|
||||
|
||||
template <typename Func>
|
||||
std::size_t _run(Func &&func, std::size_t request_num);
|
||||
|
||||
void _test_get();
|
||||
|
||||
std::vector<std::string> _gen_keys() const;
|
||||
|
||||
std::string _gen_value() const;
|
||||
|
||||
void _cleanup();
|
||||
|
||||
const std::string& _key(std::size_t idx) const {
|
||||
return _keys[idx % _keys.size()];
|
||||
}
|
||||
|
||||
BenchmarkOptions _opts;
|
||||
|
||||
RedisInstance &_redis;
|
||||
|
||||
std::vector<std::string> _keys;
|
||||
|
||||
std::string _value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "benchmark_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_BENCHMARK_TEST_H
|
178
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/benchmark_test.hpp
Normal file
178
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/benchmark_test.hpp
Normal file
|
@ -0,0 +1,178 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_BENCHMARK_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_BENCHMARK_TEST_HPP
|
||||
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
#include <future>
|
||||
#include <algorithm>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
BenchmarkTest<RedisInstance>::BenchmarkTest(const BenchmarkOptions &opts,
|
||||
RedisInstance &instance) : _opts(opts), _redis(instance) {
|
||||
REDIS_ASSERT(_opts.pool_size > 0
|
||||
&& _opts.thread_num > 0
|
||||
&& _opts.total_request_num > 0
|
||||
&& _opts.key_len > 0
|
||||
&& _opts.val_len > 0,
|
||||
"Invalid benchmark test options.");
|
||||
|
||||
_keys = _gen_keys();
|
||||
_value = _gen_value();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void BenchmarkTest<RedisInstance>::run() {
|
||||
_cleanup();
|
||||
|
||||
_run("SET key value", [this](std::size_t idx) { this->_redis.set(this->_key(idx), _value); });
|
||||
|
||||
_run("GET key", [this](std::size_t idx) {
|
||||
auto res = this->_redis.get(this->_key(idx));
|
||||
(void)res;
|
||||
});
|
||||
|
||||
_cleanup();
|
||||
|
||||
_run("LPUSH key value", [this](std::size_t idx) {
|
||||
this->_redis.lpush(this->_key(idx), _value);
|
||||
});
|
||||
|
||||
_run("LRANGE key 0 10", [this](std::size_t idx) {
|
||||
std::vector<std::string> res;
|
||||
res.reserve(10);
|
||||
this->_redis.lrange(this->_key(idx), 0, 10, std::back_inserter(res));
|
||||
});
|
||||
|
||||
_run("LPOP key", [this](std::size_t idx) {
|
||||
auto res = this->_redis.lpop(this->_key(idx));
|
||||
(void)res;
|
||||
});
|
||||
|
||||
_cleanup();
|
||||
|
||||
_run("INCR key", [this](std::size_t idx) {
|
||||
auto num = this->_redis.incr(this->_key(idx));
|
||||
(void)num;
|
||||
});
|
||||
|
||||
_cleanup();
|
||||
|
||||
_run("SADD key member", [this](std::size_t idx) {
|
||||
auto num = this->_redis.sadd(this->_key(idx), _value);
|
||||
(void)num;
|
||||
});
|
||||
|
||||
_run("SPOP key", [this](std::size_t idx) {
|
||||
auto res = this->_redis.spop(this->_key(idx));
|
||||
(void)res;
|
||||
});
|
||||
|
||||
_cleanup();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
template <typename Func>
|
||||
void BenchmarkTest<RedisInstance>::_run(const std::string &title, Func &&func) {
|
||||
auto thread_num = _opts.thread_num;
|
||||
auto requests_per_thread = _opts.total_request_num / thread_num;
|
||||
auto total_request_num = requests_per_thread * thread_num;
|
||||
std::vector<std::future<std::size_t>> res;
|
||||
res.reserve(thread_num);
|
||||
res.push_back(std::async(std::launch::async,
|
||||
[this](Func &&func, std::size_t request_num) {
|
||||
return this->_run(std::forward<Func>(func), request_num);
|
||||
},
|
||||
std::forward<Func>(func),
|
||||
requests_per_thread));
|
||||
|
||||
auto total_in_msec = 0;
|
||||
for (auto &fut : res) {
|
||||
total_in_msec += fut.get();
|
||||
}
|
||||
|
||||
auto total_in_sec = total_in_msec * 1.0 / 1000;
|
||||
|
||||
auto avg = total_in_msec * 1.0 / total_request_num;
|
||||
|
||||
auto ops = static_cast<std::size_t>(1000 / avg);
|
||||
|
||||
std::cout << "-----" << title << "-----" << std::endl;
|
||||
std::cout << total_request_num << " requests cost " << total_in_sec << " seconds" << std::endl;
|
||||
std::cout << ops << " requests per second" << std::endl;
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
template <typename Func>
|
||||
std::size_t BenchmarkTest<RedisInstance>::_run(Func &&func, std::size_t request_num) {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
for (auto idx = 0U; idx != request_num; ++idx) {
|
||||
func(idx);
|
||||
}
|
||||
|
||||
auto stop = std::chrono::steady_clock::now();
|
||||
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
std::vector<std::string> BenchmarkTest<RedisInstance>::_gen_keys() const {
|
||||
const auto KEY_NUM = 100;
|
||||
std::vector<std::string> res;
|
||||
res.reserve(KEY_NUM);
|
||||
std::default_random_engine engine(std::random_device{}());
|
||||
std::uniform_int_distribution<int> uniform_dist(0, 255);
|
||||
for (auto i = 0; i != KEY_NUM; ++i) {
|
||||
std::string str;
|
||||
str.reserve(_opts.key_len);
|
||||
for (std::size_t j = 0; j != _opts.key_len; ++j) {
|
||||
str.push_back(static_cast<char>(uniform_dist(engine)));
|
||||
}
|
||||
res.push_back(str);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
std::string BenchmarkTest<RedisInstance>::_gen_value() const {
|
||||
return std::string(_opts.val_len, 'x');
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void BenchmarkTest<RedisInstance>::_cleanup() {
|
||||
for (const auto &key : _keys) {
|
||||
_redis.del(key);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_BENCHMARK_TEST_HPP
|
|
@ -0,0 +1,49 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_CONNECTION_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_CONNECTION_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class ConnectionCmdTest {
|
||||
public:
|
||||
explicit ConnectionCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _run(Redis &redis);
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "connection_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_CONNECTION_CMDS_TEST_H
|
|
@ -0,0 +1,50 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_CONNECTION_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_CONNECTION_CMDS_TEST_HPP
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ConnectionCmdTest<RedisInstance>::run() {
|
||||
cluster_specializing_test(*this, &ConnectionCmdTest<RedisInstance>::_run, _redis);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ConnectionCmdTest<RedisInstance>::_run(Redis &instance) {
|
||||
auto message = std::string("hello");
|
||||
|
||||
REDIS_ASSERT(instance.echo(message) == message, "failed to test echo");
|
||||
|
||||
REDIS_ASSERT(instance.ping() == "PONG", "failed to test ping");
|
||||
|
||||
REDIS_ASSERT(instance.ping(message) == message, "failed to test ping");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_CONNECTION_CMDS_TEST_HPP
|
|
@ -0,0 +1,47 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_GEO_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_GEO_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class GeoCmdTest {
|
||||
public:
|
||||
explicit GeoCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "geo_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_GEO_CMDS_TEST_H
|
149
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/geo_cmds_test.hpp
Normal file
149
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/geo_cmds_test.hpp
Normal file
|
@ -0,0 +1,149 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_GEO_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_GEO_CMDS_TEST_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void GeoCmdTest<RedisInstance>::run() {
|
||||
auto key = test_key("geo");
|
||||
auto dest = test_key("dest");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, {key, dest});
|
||||
|
||||
auto members = {
|
||||
std::make_tuple("m1", 10.0, 11.0),
|
||||
std::make_tuple("m2", 10.1, 11.1),
|
||||
std::make_tuple("m3", 10.2, 11.2)
|
||||
};
|
||||
|
||||
REDIS_ASSERT(_redis.geoadd(key, std::make_tuple("m1", 10.0, 11.0)) == 1,
|
||||
"failed to test geoadd");
|
||||
REDIS_ASSERT(_redis.geoadd(key, members) == 2, "failed to test geoadd");
|
||||
|
||||
auto dist = _redis.geodist(key, "m1", "m4", GeoUnit::KM);
|
||||
REDIS_ASSERT(!dist, "failed to test geodist with nonexistent member");
|
||||
|
||||
std::vector<OptionalString> hashes;
|
||||
_redis.geohash(key, {"m1", "m4"}, std::back_inserter(hashes));
|
||||
REDIS_ASSERT(hashes.size() == 2, "failed to test geohash");
|
||||
REDIS_ASSERT(bool(hashes[0]) && *(hashes[0]) == "s1zned3z8u0" && !(hashes[1]),
|
||||
"failed to test geohash");
|
||||
hashes.clear();
|
||||
_redis.geohash(key, {"m4"}, std::back_inserter(hashes));
|
||||
REDIS_ASSERT(hashes.size() == 1 && !(hashes[0]), "failed to test geohash");
|
||||
|
||||
std::vector<Optional<std::pair<double, double>>> pos;
|
||||
_redis.geopos(key, {"m4"}, std::back_inserter(pos));
|
||||
REDIS_ASSERT(pos.size() == 1 && !(pos[0]), "failed to test geopos");
|
||||
|
||||
auto num = _redis.georadius(key,
|
||||
std::make_pair(10.1, 11.1),
|
||||
100,
|
||||
GeoUnit::KM,
|
||||
dest,
|
||||
false,
|
||||
10);
|
||||
REDIS_ASSERT(bool(num) && *num == 3, "failed to test georadius with store option");
|
||||
|
||||
std::vector<std::string> mems;
|
||||
_redis.georadius(key,
|
||||
std::make_pair(10.1, 11.1),
|
||||
100,
|
||||
GeoUnit::KM,
|
||||
10,
|
||||
true,
|
||||
std::back_inserter(mems));
|
||||
REDIS_ASSERT(mems.size() == 3, "failed to test georadius with no option");
|
||||
|
||||
std::vector<std::tuple<std::string, double>> with_dist;
|
||||
_redis.georadius(key,
|
||||
std::make_pair(10.1, 11.1),
|
||||
100,
|
||||
GeoUnit::KM,
|
||||
10,
|
||||
true,
|
||||
std::back_inserter(with_dist));
|
||||
REDIS_ASSERT(with_dist.size() == 3, "failed to test georadius with dist");
|
||||
|
||||
std::vector<std::tuple<std::string, double, std::pair<double, double>>> with_dist_coord;
|
||||
_redis.georadius(key,
|
||||
std::make_pair(10.1, 11.1),
|
||||
100,
|
||||
GeoUnit::KM,
|
||||
10,
|
||||
true,
|
||||
std::back_inserter(with_dist_coord));
|
||||
REDIS_ASSERT(with_dist_coord.size() == 3, "failed to test georadius with dist and coord");
|
||||
|
||||
num = _redis.georadiusbymember(key,
|
||||
"m1",
|
||||
100,
|
||||
GeoUnit::KM,
|
||||
dest,
|
||||
false,
|
||||
10);
|
||||
REDIS_ASSERT(bool(num) && *num == 3, "failed to test georadiusbymember with store option");
|
||||
|
||||
mems.clear();
|
||||
_redis.georadiusbymember(key,
|
||||
"m1",
|
||||
100,
|
||||
GeoUnit::KM,
|
||||
10,
|
||||
true,
|
||||
std::back_inserter(mems));
|
||||
REDIS_ASSERT(mems.size() == 3, "failed to test georadiusbymember with no option");
|
||||
|
||||
with_dist.clear();
|
||||
_redis.georadiusbymember(key,
|
||||
"m1",
|
||||
100,
|
||||
GeoUnit::KM,
|
||||
10,
|
||||
true,
|
||||
std::back_inserter(with_dist));
|
||||
REDIS_ASSERT(with_dist.size() == 3, "failed to test georadiusbymember with dist");
|
||||
|
||||
with_dist_coord.clear();
|
||||
_redis.georadiusbymember(key,
|
||||
"m1",
|
||||
100,
|
||||
GeoUnit::KM,
|
||||
10,
|
||||
true,
|
||||
std::back_inserter(with_dist_coord));
|
||||
REDIS_ASSERT(with_dist_coord.size() == 3,
|
||||
"failed to test georadiusbymember with dist and coord");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_GEO_CMDS_TEST_HPP
|
|
@ -0,0 +1,55 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_HASH_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_HASH_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class HashCmdTest {
|
||||
public:
|
||||
explicit HashCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _test_hash();
|
||||
|
||||
void _test_hash_batch();
|
||||
|
||||
void _test_numeric();
|
||||
|
||||
void _test_hscan();
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "hash_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_HASH_CMDS_TEST_H
|
177
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/hash_cmds_test.hpp
Normal file
177
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/hash_cmds_test.hpp
Normal file
|
@ -0,0 +1,177 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_HASH_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_HASH_CMDS_TEST_HPP
|
||||
|
||||
#include <unordered_map>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void HashCmdTest<RedisInstance>::run() {
|
||||
_test_hash();
|
||||
|
||||
_test_hash_batch();
|
||||
|
||||
_test_numeric();
|
||||
|
||||
_test_hscan();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void HashCmdTest<RedisInstance>::_test_hash() {
|
||||
auto key = test_key("hash");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto f1 = std::string("f1");
|
||||
auto v1 = std::string("v1");
|
||||
auto f2 = std::string("f2");
|
||||
auto v2 = std::string("v2");
|
||||
auto f3 = std::string("f3");
|
||||
auto v3 = std::string("v3");
|
||||
|
||||
REDIS_ASSERT(_redis.hset(key, f1, v1), "failed to test hset");
|
||||
REDIS_ASSERT(!_redis.hset(key, f1, v2), "failed to test hset with exist field");
|
||||
|
||||
auto res = _redis.hget(key, f1);
|
||||
REDIS_ASSERT(res && *res == v2, "failed to test hget");
|
||||
|
||||
REDIS_ASSERT(_redis.hsetnx(key, f2, v1), "failed to test hsetnx");
|
||||
REDIS_ASSERT(!_redis.hsetnx(key, f2, v2), "failed to test hsetnx with exist field");
|
||||
|
||||
res = _redis.hget(key, f2);
|
||||
REDIS_ASSERT(res && *res == v1, "failed to test hget");
|
||||
|
||||
REDIS_ASSERT(!_redis.hexists(key, f3), "failed to test hexists");
|
||||
REDIS_ASSERT(_redis.hset(key, std::make_pair(f3, v3)), "failed to test hset");
|
||||
REDIS_ASSERT(_redis.hexists(key, f3), "failed to test hexists");
|
||||
|
||||
REDIS_ASSERT(_redis.hlen(key) == 3, "failed to test hlen");
|
||||
REDIS_ASSERT(_redis.hstrlen(key, f1) == static_cast<long long>(v1.size()),
|
||||
"failed to test hstrlen");
|
||||
|
||||
REDIS_ASSERT(_redis.hdel(key, f1) == 1, "failed to test hdel");
|
||||
REDIS_ASSERT(_redis.hdel(key, {f1, f2, f3}) == 2, "failed to test hdel range");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void HashCmdTest<RedisInstance>::_test_hash_batch() {
|
||||
auto key = test_key("hash");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto f1 = std::string("f1");
|
||||
auto v1 = std::string("v1");
|
||||
auto f2 = std::string("f2");
|
||||
auto v2 = std::string("v2");
|
||||
auto f3 = std::string("f3");
|
||||
|
||||
_redis.hmset(key, {std::make_pair(f1, v1),
|
||||
std::make_pair(f2, v2)});
|
||||
|
||||
std::vector<std::string> fields;
|
||||
_redis.hkeys(key, std::back_inserter(fields));
|
||||
REDIS_ASSERT(fields.size() == 2, "failed to test hkeys");
|
||||
|
||||
std::vector<std::string> vals;
|
||||
_redis.hvals(key, std::back_inserter(vals));
|
||||
REDIS_ASSERT(vals.size() == 2, "failed to test hvals");
|
||||
|
||||
std::unordered_map<std::string, std::string> items;
|
||||
_redis.hgetall(key, std::inserter(items, items.end()));
|
||||
REDIS_ASSERT(items.size() == 2 && items[f1] == v1 && items[f2] == v2,
|
||||
"failed to test hgetall");
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> item_vec;
|
||||
_redis.hgetall(key, std::back_inserter(item_vec));
|
||||
REDIS_ASSERT(item_vec.size() == 2, "failed to test hgetall");
|
||||
|
||||
std::vector<OptionalString> res;
|
||||
_redis.hmget(key, {f1, f2, f3}, std::back_inserter(res));
|
||||
REDIS_ASSERT(res.size() == 3
|
||||
&& bool(res[0]) && *(res[0]) == v1
|
||||
&& bool(res[1]) && *(res[1]) == v2
|
||||
&& !res[2],
|
||||
"failed to test hmget");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void HashCmdTest<RedisInstance>::_test_numeric() {
|
||||
auto key = test_key("numeric");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto field = "field";
|
||||
|
||||
REDIS_ASSERT(_redis.hincrby(key, field, 1) == 1, "failed to test hincrby");
|
||||
REDIS_ASSERT(_redis.hincrby(key, field, -1) == 0, "failed to test hincrby");
|
||||
REDIS_ASSERT(_redis.hincrbyfloat(key, field, 1.5) == 1.5, "failed to test hincrbyfloat");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void HashCmdTest<RedisInstance>::_test_hscan() {
|
||||
auto key = test_key("hscan");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto items = std::unordered_map<std::string, std::string>{
|
||||
std::make_pair("f1", "v1"),
|
||||
std::make_pair("f2", "v2"),
|
||||
std::make_pair("f3", "v3"),
|
||||
};
|
||||
|
||||
_redis.hmset(key, items.begin(), items.end());
|
||||
|
||||
std::unordered_map<std::string, std::string> item_map;
|
||||
auto cursor = 0;
|
||||
while (true) {
|
||||
cursor = _redis.hscan(key, cursor, "f*", 2, std::inserter(item_map, item_map.end()));
|
||||
if (cursor == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
REDIS_ASSERT(item_map == items, "failed to test hscan with pattern and count");
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> item_vec;
|
||||
cursor = 0;
|
||||
while (true) {
|
||||
cursor = _redis.hscan(key, cursor, std::back_inserter(item_vec));
|
||||
if (cursor == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
REDIS_ASSERT(item_vec.size() == items.size(), "failed to test hscan");
|
||||
for (const auto &ele : item_vec) {
|
||||
REDIS_ASSERT(items.find(ele.first) != items.end(), "failed to test hscan");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_HASH_CMDS_TEST_HPP
|
|
@ -0,0 +1,47 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_HYPERLOGLOG_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_HYPERLOGLOG_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class HyperloglogCmdTest {
|
||||
public:
|
||||
explicit HyperloglogCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "hyperloglog_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_HYPERLOGLOG_CMDS_TEST_H
|
|
@ -0,0 +1,67 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_HYPERLOGLOG_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_HYPERLOGLOG_CMDS_TEST_HPP
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void HyperloglogCmdTest<RedisInstance>::run() {
|
||||
auto k1 = test_key("k1");
|
||||
auto k2 = test_key("k2");
|
||||
auto k3 = test_key("k3");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, {k1, k2, k3});
|
||||
|
||||
_redis.pfadd(k1, "a");
|
||||
auto members1 = {"b", "c", "d", "e", "f", "g"};
|
||||
_redis.pfadd(k1, members1);
|
||||
|
||||
auto cnt = _redis.pfcount(k1);
|
||||
auto err = cnt * 1.0 / (1 + members1.size());
|
||||
REDIS_ASSERT(err < 1.02 && err > 0.98, "failed to test pfadd and pfcount");
|
||||
|
||||
auto members2 = {"a", "b", "c", "h", "i", "j", "k"};
|
||||
_redis.pfadd(k2, members2);
|
||||
auto total = 1 + members1.size() + members2.size() - 3;
|
||||
|
||||
cnt = _redis.pfcount({k1, k2});
|
||||
err = cnt * 1.0 / total;
|
||||
REDIS_ASSERT(err < 1.02 && err > 0.98, "failed to test pfcount");
|
||||
|
||||
_redis.pfmerge(k3, {k1, k2});
|
||||
cnt = _redis.pfcount(k3);
|
||||
err = cnt * 1.0 / total;
|
||||
REDIS_ASSERT(err < 1.02 && err > 0.98, "failed to test pfcount");
|
||||
|
||||
_redis.pfmerge(k3, k1);
|
||||
REDIS_ASSERT(cnt == _redis.pfcount(k3), "failed to test pfmerge");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_HYPERLOGLOG_CMDS_TEST_HPP
|
|
@ -0,0 +1,55 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_KEYS_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_KEYS_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class KeysCmdTest {
|
||||
public:
|
||||
explicit KeysCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _test_key();
|
||||
|
||||
void _test_randomkey(Redis &instance);
|
||||
|
||||
void _test_ttl();
|
||||
|
||||
void _test_scan(Redis &instance);
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "keys_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_KEYS_CMDS_TEST_H
|
166
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/keys_cmds_test.hpp
Normal file
166
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/keys_cmds_test.hpp
Normal file
|
@ -0,0 +1,166 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_KEYS_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_KEYS_CMDS_TEST_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void KeysCmdTest<RedisInstance>::run() {
|
||||
_test_key();
|
||||
|
||||
cluster_specializing_test(*this, &KeysCmdTest<RedisInstance>::_test_randomkey, _redis);
|
||||
|
||||
_test_ttl();
|
||||
|
||||
cluster_specializing_test(*this, &KeysCmdTest<RedisInstance>::_test_scan, _redis);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void KeysCmdTest<RedisInstance>::_test_key() {
|
||||
auto key = test_key("key");
|
||||
auto dest = test_key("dest");
|
||||
auto new_key_name = test_key("new-key");
|
||||
auto not_exist_key = test_key("not-exist");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, {key, dest, new_key_name});
|
||||
|
||||
REDIS_ASSERT(_redis.exists(key) == 0, "failed to test exists");
|
||||
|
||||
auto val = std::string("val");
|
||||
_redis.set(key, val);
|
||||
|
||||
REDIS_ASSERT(_redis.exists({key, not_exist_key}) == 1, "failed to test exists");
|
||||
|
||||
auto new_val = _redis.dump(key);
|
||||
REDIS_ASSERT(bool(new_val), "failed to test dump");
|
||||
|
||||
_redis.restore(dest, *new_val, std::chrono::seconds(1000));
|
||||
|
||||
new_val = _redis.get(dest);
|
||||
REDIS_ASSERT(bool(new_val) && *new_val == val, "failed to test dump and restore");
|
||||
|
||||
_redis.rename(dest, new_key_name);
|
||||
|
||||
bool not_exist = false;
|
||||
try {
|
||||
_redis.rename(not_exist_key, new_key_name);
|
||||
} catch (const Error &e) {
|
||||
not_exist = true;
|
||||
}
|
||||
REDIS_ASSERT(not_exist, "failed to test rename with nonexistent key");
|
||||
|
||||
REDIS_ASSERT(_redis.renamenx(new_key_name, dest), "failed to test renamenx");
|
||||
|
||||
REDIS_ASSERT(_redis.touch(not_exist_key) == 0, "failed to test touch");
|
||||
REDIS_ASSERT(_redis.touch({key, dest, new_key_name}) == 2, "failed to test touch");
|
||||
|
||||
REDIS_ASSERT(_redis.type(key) == "string", "failed to test type");
|
||||
|
||||
REDIS_ASSERT(_redis.del({new_key_name, dest}) == 1, "failed to test del");
|
||||
REDIS_ASSERT(_redis.unlink({new_key_name, key}) == 1, "failed to test unlink");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void KeysCmdTest<RedisInstance>::_test_randomkey(Redis &instance) {
|
||||
auto key = test_key("randomkey");
|
||||
|
||||
KeyDeleter<Redis> deleter(instance, key);
|
||||
|
||||
instance.set(key, "value");
|
||||
|
||||
auto rand_key = instance.randomkey();
|
||||
REDIS_ASSERT(bool(rand_key), "failed to test randomkey");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void KeysCmdTest<RedisInstance>::_test_ttl() {
|
||||
using namespace std::chrono;
|
||||
|
||||
auto key = test_key("ttl");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
_redis.set(key, "val", seconds(100));
|
||||
auto ttl = _redis.ttl(key);
|
||||
REDIS_ASSERT(ttl > 0 && ttl <= 100, "failed to test ttl");
|
||||
|
||||
REDIS_ASSERT(_redis.persist(key), "failed to test persist");
|
||||
ttl = _redis.ttl(key);
|
||||
REDIS_ASSERT(ttl == -1, "failed to test ttl");
|
||||
|
||||
REDIS_ASSERT(_redis.expire(key, seconds(100)),
|
||||
"failed to test expire");
|
||||
|
||||
auto tp = time_point_cast<seconds>(system_clock::now() + seconds(100));
|
||||
REDIS_ASSERT(_redis.expireat(key, tp), "failed to test expireat");
|
||||
ttl = _redis.ttl(key);
|
||||
REDIS_ASSERT(ttl > 0, "failed to test expireat");
|
||||
|
||||
REDIS_ASSERT(_redis.pexpire(key, milliseconds(100000)), "failed to test expire");
|
||||
|
||||
auto pttl = _redis.pttl(key);
|
||||
REDIS_ASSERT(pttl > 0 && pttl <= 100000, "failed to test pttl");
|
||||
|
||||
auto tp_milli = time_point_cast<milliseconds>(system_clock::now() + milliseconds(100000));
|
||||
REDIS_ASSERT(_redis.pexpireat(key, tp_milli), "failed to test pexpireat");
|
||||
pttl = _redis.pttl(key);
|
||||
REDIS_ASSERT(pttl > 0, "failed to test pexpireat");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void KeysCmdTest<RedisInstance>::_test_scan(Redis &instance) {
|
||||
std::string key_pattern = "!@#$%^&()_+alseufoawhnlkszd";
|
||||
auto k1 = test_key(key_pattern + "k1");
|
||||
auto k2 = test_key(key_pattern + "k2");
|
||||
auto k3 = test_key(key_pattern + "k3");
|
||||
|
||||
auto keys = {k1, k2, k3};
|
||||
|
||||
KeyDeleter<Redis> deleter(instance, keys);
|
||||
|
||||
instance.set(k1, "v");
|
||||
instance.set(k2, "v");
|
||||
instance.set(k3, "v");
|
||||
|
||||
auto cursor = 0;
|
||||
std::unordered_set<std::string> res;
|
||||
while (true) {
|
||||
cursor = instance.scan(cursor, "*" + key_pattern + "*", 2, std::inserter(res, res.end()));
|
||||
if (cursor == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
REDIS_ASSERT(res == std::unordered_set<std::string>(keys),
|
||||
"failed to test scan");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_KEYS_CMDS_TEST_HPP
|
|
@ -0,0 +1,55 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_LIST_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_LIST_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class ListCmdTest {
|
||||
public:
|
||||
explicit ListCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _test_lpoppush();
|
||||
|
||||
void _test_rpoppush();
|
||||
|
||||
void _test_list();
|
||||
|
||||
void _test_blocking();
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "list_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_LIST_CMDS_TEST_H
|
154
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/list_cmds_test.hpp
Normal file
154
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/list_cmds_test.hpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_LIST_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_LIST_CMDS_TEST_HPP
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ListCmdTest<RedisInstance>::run() {
|
||||
_test_lpoppush();
|
||||
|
||||
_test_rpoppush();
|
||||
|
||||
_test_list();
|
||||
|
||||
_test_blocking();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ListCmdTest<RedisInstance>::_test_lpoppush() {
|
||||
auto key = test_key("lpoppush");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto item = _redis.lpop(key);
|
||||
REDIS_ASSERT(!item, "failed to test lpop");
|
||||
|
||||
REDIS_ASSERT(_redis.lpushx(key, "1") == 0, "failed to test lpushx");
|
||||
REDIS_ASSERT(_redis.lpush(key, "1") == 1, "failed to test lpush");
|
||||
REDIS_ASSERT(_redis.lpushx(key, "2") == 2, "failed to test lpushx");
|
||||
REDIS_ASSERT(_redis.lpush(key, {"3", "4", "5"}) == 5, "failed to test lpush");
|
||||
|
||||
item = _redis.lpop(key);
|
||||
REDIS_ASSERT(item && *item == "5", "failed to test lpop");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ListCmdTest<RedisInstance>::_test_rpoppush() {
|
||||
auto key = test_key("rpoppush");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto item = _redis.rpop(key);
|
||||
REDIS_ASSERT(!item, "failed to test rpop");
|
||||
|
||||
REDIS_ASSERT(_redis.rpushx(key, "1") == 0, "failed to test rpushx");
|
||||
REDIS_ASSERT(_redis.rpush(key, "1") == 1, "failed to test rpush");
|
||||
REDIS_ASSERT(_redis.rpushx(key, "2") == 2, "failed to test rpushx");
|
||||
REDIS_ASSERT(_redis.rpush(key, {"3", "4", "5"}) == 5, "failed to test rpush");
|
||||
|
||||
item = _redis.rpop(key);
|
||||
REDIS_ASSERT(item && *item == "5", "failed to test rpop");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ListCmdTest<RedisInstance>::_test_list() {
|
||||
auto key = test_key("list");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto item = _redis.lindex(key, 0);
|
||||
REDIS_ASSERT(!item, "failed to test lindex");
|
||||
|
||||
_redis.lpush(key, {"1", "2", "3", "4", "5"});
|
||||
|
||||
REDIS_ASSERT(_redis.lrem(key, 0, "3") == 1, "failed to test lrem");
|
||||
|
||||
REDIS_ASSERT(_redis.linsert(key, InsertPosition::BEFORE, "2", "3") == 5,
|
||||
"failed to test lindex");
|
||||
|
||||
REDIS_ASSERT(_redis.llen(key) == 5, "failed to test llen");
|
||||
|
||||
_redis.lset(key, 0, "6");
|
||||
item = _redis.lindex(key, 0);
|
||||
REDIS_ASSERT(item && *item == "6", "failed to test lindex");
|
||||
|
||||
_redis.ltrim(key, 0, 2);
|
||||
|
||||
std::vector<std::string> res;
|
||||
_redis.lrange(key, 0, -1, std::back_inserter(res));
|
||||
REDIS_ASSERT(res == std::vector<std::string>({"6", "4", "3"}), "failed to test ltrim");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ListCmdTest<RedisInstance>::_test_blocking() {
|
||||
auto k1 = test_key("k1");
|
||||
auto k2 = test_key("k2");
|
||||
auto k3 = test_key("k3");
|
||||
|
||||
auto keys = {k1, k2, k3};
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, keys);
|
||||
|
||||
std::string val("value");
|
||||
_redis.lpush(k1, val);
|
||||
|
||||
auto res = _redis.blpop(keys.begin(), keys.end());
|
||||
REDIS_ASSERT(res && *res == std::make_pair(k1, val), "failed to test blpop");
|
||||
|
||||
res = _redis.brpop(keys, std::chrono::seconds(1));
|
||||
REDIS_ASSERT(!res, "failed to test brpop with timeout");
|
||||
|
||||
_redis.lpush(k1, val);
|
||||
res = _redis.blpop(k1);
|
||||
REDIS_ASSERT(res && *res == std::make_pair(k1, val), "failed to test blpop");
|
||||
|
||||
res = _redis.blpop(k1, std::chrono::seconds(1));
|
||||
REDIS_ASSERT(!res, "failed to test blpop with timeout");
|
||||
|
||||
_redis.lpush(k1, val);
|
||||
res = _redis.brpop(k1);
|
||||
REDIS_ASSERT(res && *res == std::make_pair(k1, val), "failed to test brpop");
|
||||
|
||||
res = _redis.brpop(k1, std::chrono::seconds(1));
|
||||
REDIS_ASSERT(!res, "failed to test brpop with timeout");
|
||||
|
||||
auto str = _redis.brpoplpush(k2, k3, std::chrono::seconds(1));
|
||||
REDIS_ASSERT(!str, "failed to test brpoplpush with timeout");
|
||||
|
||||
_redis.lpush(k2, val);
|
||||
str = _redis.brpoplpush(k2, k3);
|
||||
REDIS_ASSERT(str && *str == val, "failed to test brpoplpush");
|
||||
|
||||
str = _redis.rpoplpush(k3, k2);
|
||||
REDIS_ASSERT(str && *str == val, "failed to test rpoplpush");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_LIST_CMDS_TEST_HPP
|
|
@ -0,0 +1,57 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_PIPELINE_TRANSACTION_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_PIPELINE_TRANSACTION_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class PipelineTransactionTest {
|
||||
public:
|
||||
explicit PipelineTransactionTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
Pipeline _pipeline(const StringView &key);
|
||||
|
||||
Transaction _transaction(const StringView &key, bool piped);
|
||||
|
||||
void _test_pipeline(const StringView &key, Pipeline &pipe);
|
||||
|
||||
void _test_transaction(const StringView &key, Transaction &tx);
|
||||
|
||||
void _test_watch();
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "pipeline_transaction_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_PIPELINE_TRANSACTION_TEST_H
|
|
@ -0,0 +1,184 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_PIPELINE_TRANSACTION_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_PIPELINE_TRANSACTION_TEST_HPP
|
||||
|
||||
#include <string>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void PipelineTransactionTest<RedisInstance>::run() {
|
||||
{
|
||||
auto key = test_key("pipeline");
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
auto pipe = _pipeline(key);
|
||||
_test_pipeline(key, pipe);
|
||||
}
|
||||
|
||||
{
|
||||
auto key = test_key("transaction");
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
auto tx = _transaction(key, true);
|
||||
_test_transaction(key, tx);
|
||||
}
|
||||
|
||||
{
|
||||
auto key = test_key("transaction");
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
auto tx = _transaction(key, false);
|
||||
_test_transaction(key, tx);
|
||||
}
|
||||
|
||||
_test_watch();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
Pipeline PipelineTransactionTest<RedisInstance>::_pipeline(const StringView &) {
|
||||
return _redis.pipeline();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Pipeline PipelineTransactionTest<RedisCluster>::_pipeline(const StringView &key) {
|
||||
return _redis.pipeline(key);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
Transaction PipelineTransactionTest<RedisInstance>::_transaction(const StringView &, bool piped) {
|
||||
return _redis.transaction(piped);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Transaction PipelineTransactionTest<RedisCluster>::_transaction(const StringView &key,
|
||||
bool piped) {
|
||||
return _redis.transaction(key, piped);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void PipelineTransactionTest<RedisInstance>::_test_pipeline(const StringView &key,
|
||||
Pipeline &pipe) {
|
||||
std::string val("value");
|
||||
auto replies = pipe.set(key, val)
|
||||
.get(key)
|
||||
.strlen(key)
|
||||
.exec();
|
||||
|
||||
REDIS_ASSERT(replies.get<bool>(0), "failed to test pipeline with set operation");
|
||||
|
||||
auto new_val = replies.get<OptionalString>(1);
|
||||
std::size_t len = replies.get<long long>(2);
|
||||
REDIS_ASSERT(bool(new_val) && *new_val == val && len == val.size(),
|
||||
"failed to test pipeline with string operations");
|
||||
|
||||
REDIS_ASSERT(reply::parse<bool>(replies.get(0)), "failed to test pipeline with set operation");
|
||||
|
||||
new_val = reply::parse<OptionalString>(replies.get(1));
|
||||
len = reply::parse<long long>(replies.get(2));
|
||||
REDIS_ASSERT(bool(new_val) && *new_val == val && len == val.size(),
|
||||
"failed to test pipeline with string operations");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void PipelineTransactionTest<RedisInstance>::_test_transaction(const StringView &key,
|
||||
Transaction &tx) {
|
||||
std::unordered_map<std::string, std::string> m = {
|
||||
std::make_pair("f1", "v1"),
|
||||
std::make_pair("f2", "v2"),
|
||||
std::make_pair("f3", "v3")
|
||||
};
|
||||
auto replies = tx.hmset(key, m.begin(), m.end())
|
||||
.hgetall(key)
|
||||
.hdel(key, "f1")
|
||||
.exec();
|
||||
|
||||
replies.get<void>(0);
|
||||
|
||||
decltype(m) mm;
|
||||
replies.get(1, std::inserter(mm, mm.end()));
|
||||
REDIS_ASSERT(mm == m, "failed to test transaction");
|
||||
|
||||
REDIS_ASSERT(replies.get<long long>(2) == 1, "failed to test transaction");
|
||||
|
||||
tx.set(key, "value")
|
||||
.get(key)
|
||||
.incr(key);
|
||||
|
||||
tx.discard();
|
||||
|
||||
replies = tx.del(key)
|
||||
.set(key, "value")
|
||||
.exec();
|
||||
|
||||
REDIS_ASSERT(replies.get<long long>(0) == 1, "failed to test transaction");
|
||||
|
||||
REDIS_ASSERT(replies.get<bool>(1), "failed to test transaction");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void PipelineTransactionTest<RedisInstance>::_test_watch() {
|
||||
auto key = test_key("watch");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
{
|
||||
auto tx = _transaction(key, false);
|
||||
|
||||
auto redis = tx.redis();
|
||||
|
||||
redis.watch(key);
|
||||
|
||||
auto replies = tx.set(key, "1").get(key).exec();
|
||||
|
||||
REDIS_ASSERT(replies.size() == 2
|
||||
&& replies.template get<bool>(0) == true, "failed to test watch");
|
||||
|
||||
auto val = replies.template get<sw::redis::OptionalString>(1);
|
||||
|
||||
REDIS_ASSERT(val && *val == "1", "failed to test watch");
|
||||
}
|
||||
|
||||
try {
|
||||
auto tx = _transaction(key, false);
|
||||
|
||||
auto redis = tx.redis();
|
||||
|
||||
redis.watch(key);
|
||||
|
||||
// Key has been modified by other client.
|
||||
_redis.set(key, "val");
|
||||
|
||||
// Transaction should fail, and throw WatchError
|
||||
tx.set(key, "1").exec();
|
||||
|
||||
REDIS_ASSERT(false, "failed to test watch");
|
||||
} catch (const sw::redis::WatchError &err) {
|
||||
// Catch the error.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_PIPELINE_TRANSACTION_TEST_HPP
|
53
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/pubsub_test.h
Normal file
53
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/pubsub_test.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_SUBPUB_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_SUBPUB_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class PubSubTest {
|
||||
public:
|
||||
explicit PubSubTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _test_sub_channel();
|
||||
|
||||
void _test_sub_pattern();
|
||||
|
||||
void _test_unsubscribe();
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "pubsub_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_SUBPUB_TEST_H
|
244
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/pubsub_test.hpp
Normal file
244
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/pubsub_test.hpp
Normal file
|
@ -0,0 +1,244 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_SUBPUB_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_SUBPUB_TEST_HPP
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void PubSubTest<RedisInstance>::run() {
|
||||
_test_sub_channel();
|
||||
|
||||
_test_sub_pattern();
|
||||
|
||||
_test_unsubscribe();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void PubSubTest<RedisInstance>::_test_sub_channel() {
|
||||
auto sub = _redis.subscriber();
|
||||
|
||||
auto msgs = {"msg1", "msg2"};
|
||||
auto channel1 = test_key("c1");
|
||||
sub.on_message([&msgs, &channel1](std::string channel, std::string msg) {
|
||||
static std::size_t idx = 0;
|
||||
REDIS_ASSERT(channel == channel1 && msg == *(msgs.begin() + idx),
|
||||
"failed to test subscribe");
|
||||
++idx;
|
||||
});
|
||||
|
||||
sub.subscribe(channel1);
|
||||
|
||||
// Consume the SUBSCRIBE message.
|
||||
sub.consume();
|
||||
|
||||
for (const auto &msg : msgs) {
|
||||
_redis.publish(channel1, msg);
|
||||
sub.consume();
|
||||
}
|
||||
|
||||
sub.unsubscribe(channel1);
|
||||
|
||||
// Consume the UNSUBSCRIBE message.
|
||||
sub.consume();
|
||||
|
||||
auto channel2 = test_key("c2");
|
||||
auto channel3 = test_key("c3");
|
||||
auto channel4 = test_key("c4");
|
||||
std::unordered_set<std::string> channels;
|
||||
sub.on_meta([&channels](Subscriber::MsgType type,
|
||||
OptionalString channel,
|
||||
long long num) {
|
||||
REDIS_ASSERT(bool(channel), "failed to test subscribe");
|
||||
|
||||
if (type == Subscriber::MsgType::SUBSCRIBE) {
|
||||
auto iter = channels.find(*channel);
|
||||
REDIS_ASSERT(iter == channels.end(), "failed to test subscribe");
|
||||
channels.insert(*channel);
|
||||
REDIS_ASSERT(static_cast<std::size_t>(num) == channels.size(),
|
||||
"failed to test subscribe");
|
||||
} else if (type == Subscriber::MsgType::UNSUBSCRIBE) {
|
||||
auto iter = channels.find(*channel);
|
||||
REDIS_ASSERT(iter != channels.end(), "failed to test subscribe");
|
||||
channels.erase(*channel);
|
||||
REDIS_ASSERT(static_cast<std::size_t>(num) == channels.size(),
|
||||
"failed to test subscribe");
|
||||
} else {
|
||||
REDIS_ASSERT(false, "Unknown message type");
|
||||
}
|
||||
});
|
||||
|
||||
std::unordered_map<std::string, std::string> messages = {
|
||||
{channel2, "msg2"},
|
||||
{channel3, "msg3"},
|
||||
{channel4, "msg4"},
|
||||
};
|
||||
sub.on_message([&messages](std::string channel, std::string msg) {
|
||||
REDIS_ASSERT(messages.find(channel) != messages.end(),
|
||||
"failed to test subscribe");
|
||||
REDIS_ASSERT(messages[channel] == msg, "failed to test subscribe");
|
||||
});
|
||||
|
||||
sub.subscribe({channel2, channel3, channel4});
|
||||
|
||||
for (std::size_t idx = 0; idx != channels.size(); ++idx) {
|
||||
sub.consume();
|
||||
}
|
||||
|
||||
for (const auto &ele : messages) {
|
||||
_redis.publish(ele.first, ele.second);
|
||||
sub.consume();
|
||||
}
|
||||
|
||||
auto tmp = {channel2, channel3, channel4};
|
||||
sub.unsubscribe(tmp);
|
||||
|
||||
for (std::size_t idx = 0; idx != tmp.size(); ++idx) {
|
||||
sub.consume();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void PubSubTest<RedisInstance>::_test_sub_pattern() {
|
||||
auto sub = _redis.subscriber();
|
||||
|
||||
auto msgs = {"msg1", "msg2"};
|
||||
auto pattern1 = test_key("pattern*");
|
||||
std::string channel1 = test_key("pattern1");
|
||||
sub.on_pmessage([&msgs, &pattern1, &channel1](std::string pattern,
|
||||
std::string channel,
|
||||
std::string msg) {
|
||||
static std::size_t idx = 0;
|
||||
REDIS_ASSERT(pattern == pattern1
|
||||
&& channel == channel1
|
||||
&& msg == *(msgs.begin() + idx),
|
||||
"failed to test psubscribe");
|
||||
++idx;
|
||||
});
|
||||
|
||||
sub.psubscribe(pattern1);
|
||||
|
||||
// Consume the PSUBSCRIBE message.
|
||||
sub.consume();
|
||||
|
||||
for (const auto &msg : msgs) {
|
||||
_redis.publish(channel1, msg);
|
||||
sub.consume();
|
||||
}
|
||||
|
||||
sub.punsubscribe(pattern1);
|
||||
|
||||
// Consume the PUNSUBSCRIBE message.
|
||||
sub.consume();
|
||||
|
||||
auto channel2 = test_key("pattern22");
|
||||
auto channel3 = test_key("pattern33");
|
||||
auto channel4 = test_key("pattern44");
|
||||
std::unordered_set<std::string> channels;
|
||||
sub.on_meta([&channels](Subscriber::MsgType type,
|
||||
OptionalString channel,
|
||||
long long num) {
|
||||
REDIS_ASSERT(bool(channel), "failed to test psubscribe");
|
||||
|
||||
if (type == Subscriber::MsgType::PSUBSCRIBE) {
|
||||
auto iter = channels.find(*channel);
|
||||
REDIS_ASSERT(iter == channels.end(), "failed to test psubscribe");
|
||||
channels.insert(*channel);
|
||||
REDIS_ASSERT(static_cast<std::size_t>(num) == channels.size(),
|
||||
"failed to test psubscribe");
|
||||
} else if (type == Subscriber::MsgType::PUNSUBSCRIBE) {
|
||||
auto iter = channels.find(*channel);
|
||||
REDIS_ASSERT(iter != channels.end(), "failed to test psubscribe");
|
||||
channels.erase(*channel);
|
||||
REDIS_ASSERT(static_cast<std::size_t>(num) == channels.size(),
|
||||
"failed to test psubscribe");
|
||||
} else {
|
||||
REDIS_ASSERT(false, "Unknown message type");
|
||||
}
|
||||
});
|
||||
|
||||
auto pattern2 = test_key("pattern2*");
|
||||
auto pattern3 = test_key("pattern3*");
|
||||
auto pattern4 = test_key("pattern4*");
|
||||
std::unordered_set<std::string> patterns = {pattern2, pattern3, pattern4};
|
||||
|
||||
std::unordered_map<std::string, std::string> messages = {
|
||||
{channel2, "msg2"},
|
||||
{channel3, "msg3"},
|
||||
{channel4, "msg4"},
|
||||
};
|
||||
sub.on_pmessage([&patterns, &messages](std::string pattern,
|
||||
std::string channel,
|
||||
std::string msg) {
|
||||
REDIS_ASSERT(patterns.find(pattern) != patterns.end(),
|
||||
"failed to test psubscribe");
|
||||
REDIS_ASSERT(messages[channel] == msg, "failed to test psubscribe");
|
||||
});
|
||||
|
||||
sub.psubscribe({pattern2, pattern3, pattern4});
|
||||
|
||||
for (std::size_t idx = 0; idx != channels.size(); ++idx) {
|
||||
sub.consume();
|
||||
}
|
||||
|
||||
for (const auto &ele : messages) {
|
||||
_redis.publish(ele.first, ele.second);
|
||||
sub.consume();
|
||||
}
|
||||
|
||||
auto tmp = {pattern2, pattern3, pattern4};
|
||||
sub.punsubscribe(tmp);
|
||||
|
||||
for (std::size_t idx = 0; idx != tmp.size(); ++idx) {
|
||||
sub.consume();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void PubSubTest<RedisInstance>::_test_unsubscribe() {
|
||||
auto sub = _redis.subscriber();
|
||||
|
||||
sub.on_meta([](Subscriber::MsgType type,
|
||||
OptionalString channel,
|
||||
long long num) {
|
||||
REDIS_ASSERT(type == Subscriber::MsgType::UNSUBSCRIBE,
|
||||
"failed to test unsub");
|
||||
|
||||
REDIS_ASSERT(!channel, "failed to test unsub");
|
||||
|
||||
REDIS_ASSERT(num == 0, "failed to test unsub");
|
||||
});
|
||||
|
||||
sub.unsubscribe();
|
||||
sub.consume();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_SUBPUB_TEST_HPP
|
76
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/sanity_test.h
Normal file
76
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/sanity_test.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_SANITY_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_SANITY_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class SanityTest {
|
||||
public:
|
||||
SanityTest(const ConnectionOptions &opts, RedisInstance &instance)
|
||||
: _opts(opts), _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _test_uri_ctor();
|
||||
|
||||
void _ping(Redis &instance);
|
||||
|
||||
void _test_move_ctor();
|
||||
|
||||
void _test_cmdargs();
|
||||
|
||||
void _test_generic_command();
|
||||
|
||||
void _test_hash_tag();
|
||||
|
||||
void _test_hash_tag(std::initializer_list<std::string> keys);
|
||||
|
||||
std::string _test_key(const std::string &key);
|
||||
|
||||
void _test_ping(Redis &instance);
|
||||
|
||||
void _test_pipeline(const StringView &key, Pipeline &pipeline);
|
||||
|
||||
void _test_transaction(const StringView &key, Transaction &transaction);
|
||||
|
||||
Pipeline _pipeline(const StringView &key);
|
||||
|
||||
Transaction _transaction(const StringView &key);
|
||||
|
||||
ConnectionOptions _opts;
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "sanity_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_SANITY_TEST_H
|
299
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/sanity_test.hpp
Normal file
299
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/sanity_test.hpp
Normal file
|
@ -0,0 +1,299 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_SANITY_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_SANITY_TEST_HPP
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::run() {
|
||||
_test_uri_ctor();
|
||||
|
||||
_test_move_ctor();
|
||||
|
||||
cluster_specializing_test(*this, &SanityTest<RedisInstance>::_test_ping, _redis);
|
||||
|
||||
auto pipe_key = test_key("pipeline");
|
||||
auto tx_key = test_key("transaction");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, {pipe_key, tx_key});
|
||||
|
||||
auto pipeline = _pipeline(pipe_key);
|
||||
_test_pipeline(pipe_key, pipeline);
|
||||
|
||||
auto transaction = _transaction(tx_key);
|
||||
_test_transaction(tx_key, transaction);
|
||||
|
||||
_test_cmdargs();
|
||||
|
||||
_test_generic_command();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_test_uri_ctor() {
|
||||
std::string uri;
|
||||
switch (_opts.type) {
|
||||
case sw::redis::ConnectionType::TCP:
|
||||
uri = "tcp://" + _opts.host + ":" + std::to_string(_opts.port);
|
||||
break;
|
||||
|
||||
case sw::redis::ConnectionType::UNIX:
|
||||
REDIS_ASSERT(false, "NO test for UNIX Domain Socket");
|
||||
break;
|
||||
|
||||
default:
|
||||
REDIS_ASSERT(false, "Unknown connection type");
|
||||
}
|
||||
|
||||
auto instance = RedisInstance(uri);
|
||||
|
||||
cluster_specializing_test(*this, &SanityTest<RedisInstance>::_ping, instance);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_ping(Redis &instance) {
|
||||
try {
|
||||
auto pong = instance.ping();
|
||||
REDIS_ASSERT(pong == "PONG", "Failed to test constructing Redis with uri");
|
||||
} catch (const sw::redis::ReplyError &e) {
|
||||
REDIS_ASSERT(e.what() == std::string("NOAUTH Authentication required."),
|
||||
"Failed to test constructing Redis with uri");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_test_move_ctor() {
|
||||
auto test_move_ctor = std::move(_redis);
|
||||
|
||||
_redis = std::move(test_move_ctor);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_test_cmdargs() {
|
||||
auto lpush_num = [](Connection &connection, const StringView &key, long long num) {
|
||||
connection.send("LPUSH %b %lld",
|
||||
key.data(), key.size(),
|
||||
num);
|
||||
};
|
||||
|
||||
auto lpush_nums = [](Connection &connection,
|
||||
const StringView &key,
|
||||
const std::vector<long long> &nums) {
|
||||
CmdArgs args;
|
||||
args.append("LPUSH").append(key);
|
||||
for (auto num : nums) {
|
||||
args.append(std::to_string(num));
|
||||
}
|
||||
|
||||
connection.send(args);
|
||||
};
|
||||
|
||||
auto key = test_key("lpush_num");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto reply = _redis.command(lpush_num, key, 1);
|
||||
REDIS_ASSERT(reply::parse<long long>(*reply) == 1, "failed to test cmdargs");
|
||||
|
||||
std::vector<long long> nums = {2, 3, 4, 5};
|
||||
reply = _redis.command(lpush_nums, key, nums);
|
||||
REDIS_ASSERT(reply::parse<long long>(*reply) == 5, "failed to test cmdargs");
|
||||
|
||||
std::vector<std::string> res;
|
||||
_redis.lrange(key, 0, -1, std::back_inserter(res));
|
||||
REDIS_ASSERT((res == std::vector<std::string>{"5", "4", "3", "2", "1"}),
|
||||
"failed to test cmdargs");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_test_generic_command() {
|
||||
auto key = test_key("key");
|
||||
auto not_exist_key = test_key("not_exist_key");
|
||||
auto k1 = test_key("k1");
|
||||
auto k2 = test_key("k2");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, {key, not_exist_key, k1, k2});
|
||||
|
||||
std::string cmd("set");
|
||||
_redis.command(cmd, key, 123);
|
||||
auto reply = _redis.command("get", key);
|
||||
auto val = reply::parse<OptionalString>(*reply);
|
||||
REDIS_ASSERT(val && *val == "123", "failed to test generic command");
|
||||
|
||||
val = _redis.template command<OptionalString>("get", key);
|
||||
REDIS_ASSERT(val && *val == "123", "failed to test generic command");
|
||||
|
||||
std::vector<OptionalString> res;
|
||||
_redis.command("mget", key, not_exist_key, std::back_inserter(res));
|
||||
REDIS_ASSERT(res.size() == 2 && res[0] && *res[0] == "123" && !res[1],
|
||||
"failed to test generic command");
|
||||
|
||||
reply = _redis.command("incr", key);
|
||||
REDIS_ASSERT(reply::parse<long long>(*reply) == 124, "failed to test generic command");
|
||||
|
||||
_redis.command("mset", k1.c_str(), "v", k2.c_str(), "v");
|
||||
reply = _redis.command("mget", k1, k2);
|
||||
res.clear();
|
||||
reply::to_array(*reply, std::back_inserter(res));
|
||||
REDIS_ASSERT(res.size() == 2 && res[0] && *(res[0]) == "v" && res[1] && *(res[1]) == "v",
|
||||
"failed to test generic command");
|
||||
|
||||
res = _redis.template command<std::vector<OptionalString>>("mget", k1, k2);
|
||||
REDIS_ASSERT(res.size() == 2 && res[0] && *(res[0]) == "v" && res[1] && *(res[1]) == "v",
|
||||
"failed to test generic command");
|
||||
|
||||
res.clear();
|
||||
_redis.command("mget", k1, k2, std::back_inserter(res));
|
||||
REDIS_ASSERT(res.size() == 2 && res[0] && *(res[0]) == "v" && res[1] && *(res[1]) == "v",
|
||||
"failed to test generic command");
|
||||
|
||||
auto set_cmd_str = {"set", key.c_str(), "new_value"};
|
||||
_redis.command(set_cmd_str.begin(), set_cmd_str.end());
|
||||
|
||||
auto get_cmd_str = {"get", key.c_str()};
|
||||
reply = _redis.command(get_cmd_str.begin(), get_cmd_str.end());
|
||||
val = reply::parse<OptionalString>(*reply);
|
||||
REDIS_ASSERT(val && *val == "new_value", "failed to test generic command");
|
||||
|
||||
val = _redis.template command<OptionalString>(get_cmd_str.begin(), get_cmd_str.end());
|
||||
REDIS_ASSERT(val && *val == "new_value", "failed to test generic command");
|
||||
|
||||
auto mget_cmd_str = {"mget", key.c_str(), not_exist_key.c_str()};
|
||||
res.clear();
|
||||
_redis.command(mget_cmd_str.begin(), mget_cmd_str.end(), std::back_inserter(res));
|
||||
REDIS_ASSERT(res.size() == 2 && res[0] && *res[0] == "new_value" && !res[1],
|
||||
"failed to test generic command");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_test_hash_tag() {
|
||||
_test_hash_tag({_test_key("{tag}postfix1"),
|
||||
_test_key("{tag}postfix2"),
|
||||
_test_key("{tag}postfix3")});
|
||||
|
||||
_test_hash_tag({_test_key("prefix1{tag}postfix1"),
|
||||
_test_key("prefix2{tag}postfix2"),
|
||||
_test_key("prefix3{tag}postfix3")});
|
||||
|
||||
_test_hash_tag({_test_key("prefix1{tag}"),
|
||||
_test_key("prefix2{tag}"),
|
||||
_test_key("prefix3{tag}")});
|
||||
|
||||
_test_hash_tag({_test_key("prefix{}postfix"),
|
||||
_test_key("prefix{}postfix"),
|
||||
_test_key("prefix{}postfix")});
|
||||
|
||||
_test_hash_tag({_test_key("prefix1{tag}post}fix1"),
|
||||
_test_key("prefix2{tag}pos}tfix2"),
|
||||
_test_key("prefix3{tag}postfi}x3")});
|
||||
|
||||
_test_hash_tag({_test_key("prefix1{t{ag}postfix1"),
|
||||
_test_key("prefix2{t{ag}postfix2"),
|
||||
_test_key("prefix3{t{ag}postfix3")});
|
||||
|
||||
_test_hash_tag({_test_key("prefix1{t{ag}postfi}x1"),
|
||||
_test_key("prefix2{t{ag}post}fix2"),
|
||||
_test_key("prefix3{t{ag}po}stfix3")});
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_test_hash_tag(std::initializer_list<std::string> keys) {
|
||||
KeyDeleter<RedisInstance> deleter(_redis, keys.begin(), keys.end());
|
||||
|
||||
std::string value = "value";
|
||||
std::vector<std::pair<std::string, std::string>> kvs;
|
||||
for (const auto &key : keys) {
|
||||
kvs.emplace_back(key, value);
|
||||
}
|
||||
|
||||
_redis.mset(kvs.begin(), kvs.end());
|
||||
|
||||
std::vector<OptionalString> res;
|
||||
res.reserve(keys.size());
|
||||
_redis.mget(keys.begin(), keys.end(), std::back_inserter(res));
|
||||
|
||||
REDIS_ASSERT(res.size() == keys.size(), "failed to test hash tag");
|
||||
|
||||
for (const auto &ele : res) {
|
||||
REDIS_ASSERT(ele && *ele == value, "failed to test hash tag");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
std::string SanityTest<RedisInstance>::_test_key(const std::string &key) {
|
||||
REDIS_ASSERT(key.size() > 1, "failed to generate key");
|
||||
|
||||
// Ensure that key prefix has NO hash tag. Also see the implementation of test_key.
|
||||
return key.substr(1);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_test_ping(Redis &instance) {
|
||||
auto reply = instance.command("ping");
|
||||
REDIS_ASSERT(reply && reply::parse<std::string>(*reply) == "PONG",
|
||||
"failed to test generic command");
|
||||
|
||||
auto pong = instance.command<std::string>("ping");
|
||||
REDIS_ASSERT(pong == "PONG", "failed to test generic command");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_test_pipeline(const StringView &key, Pipeline &pipeline) {
|
||||
auto pipe_replies = pipeline.command("set", key, "value").command("get", key).exec();
|
||||
auto val = pipe_replies.get<OptionalString>(1);
|
||||
REDIS_ASSERT(val && *val == "value", "failed to test generic command");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SanityTest<RedisInstance>::_test_transaction(const StringView &key, Transaction &transaction) {
|
||||
auto tx_replies = transaction.command("set", key, 456).command("incr", key).exec();
|
||||
REDIS_ASSERT(tx_replies.get<long long>(1) == 457, "failed to test generic command");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
Pipeline SanityTest<RedisInstance>::_pipeline(const StringView &) {
|
||||
return _redis.pipeline();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Pipeline SanityTest<RedisCluster>::_pipeline(const StringView &key) {
|
||||
return _redis.pipeline(key);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
Transaction SanityTest<RedisInstance>::_transaction(const StringView &) {
|
||||
return _redis.transaction();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Transaction SanityTest<RedisCluster>::_transaction(const StringView &key) {
|
||||
return _redis.transaction(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_SANITY_TEST_HPP
|
|
@ -0,0 +1,49 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_SCRIPT_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_SCRIPT_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class ScriptCmdTest {
|
||||
public:
|
||||
explicit ScriptCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _run(Redis &instance);
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "script_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_SCRIPT_CMDS_TEST_H
|
|
@ -0,0 +1,97 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_SCRIPT_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_SCRIPT_CMDS_TEST_HPP
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ScriptCmdTest<RedisInstance>::run() {
|
||||
cluster_specializing_test(*this,
|
||||
&ScriptCmdTest<RedisInstance>::_run,
|
||||
_redis);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ScriptCmdTest<RedisInstance>::_run(Redis &instance) {
|
||||
auto key1 = test_key("k1");
|
||||
auto key2 = test_key("k2");
|
||||
|
||||
KeyDeleter<Redis> deleter(instance, {key1, key2});
|
||||
|
||||
std::string script = "redis.call('set', KEYS[1], 1);"
|
||||
"redis.call('set', KEYS[2], 2);"
|
||||
"local first = redis.call('get', KEYS[1]);"
|
||||
"local second = redis.call('get', KEYS[2]);"
|
||||
"return first + second";
|
||||
|
||||
auto num = instance.eval<long long>(script, {key1, key2}, {});
|
||||
REDIS_ASSERT(num == 3, "failed to test scripting for cluster");
|
||||
|
||||
script = "return 1";
|
||||
num = instance.eval<long long>(script, {}, {});
|
||||
REDIS_ASSERT(num == 1, "failed to test eval");
|
||||
|
||||
auto script_with_args = "return {ARGV[1] + 1, ARGV[2] + 2, ARGV[3] + 3}";
|
||||
std::vector<long long> res;
|
||||
instance.eval(script_with_args,
|
||||
{"k"},
|
||||
{"1", "2", "3"},
|
||||
std::back_inserter(res));
|
||||
REDIS_ASSERT(res == std::vector<long long>({2, 4, 6}),
|
||||
"failed to test eval with array reply");
|
||||
|
||||
auto sha1 = instance.script_load(script);
|
||||
num = instance.evalsha<long long>(sha1, {}, {});
|
||||
REDIS_ASSERT(num == 1, "failed to test evalsha");
|
||||
|
||||
auto sha2 = instance.script_load(script_with_args);
|
||||
res.clear();
|
||||
instance.evalsha(sha2,
|
||||
{"k"},
|
||||
{"1", "2", "3"},
|
||||
std::back_inserter(res));
|
||||
REDIS_ASSERT(res == std::vector<long long>({2, 4, 6}),
|
||||
"failed to test evalsha with array reply");
|
||||
|
||||
std::list<bool> exist_res;
|
||||
instance.script_exists({sha1, sha2, std::string("not exist")}, std::back_inserter(exist_res));
|
||||
REDIS_ASSERT(exist_res == std::list<bool>({true, true, false}),
|
||||
"failed to test script exists");
|
||||
|
||||
instance.script_flush();
|
||||
exist_res.clear();
|
||||
instance.script_exists({sha1, sha2, std::string("not exist")}, std::back_inserter(exist_res));
|
||||
REDIS_ASSERT(exist_res == std::list<bool>({false, false, false}),
|
||||
"failed to test script flush");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_SCRIPT_CMDS_TEST_HPP
|
|
@ -0,0 +1,53 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_SET_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_SET_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class SetCmdTest {
|
||||
public:
|
||||
explicit SetCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _test_set();
|
||||
|
||||
void _test_multi_set();
|
||||
|
||||
void _test_sscan();
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "set_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_SET_CMDS_TEST_H
|
184
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/set_cmds_test.hpp
Normal file
184
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/set_cmds_test.hpp
Normal file
|
@ -0,0 +1,184 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_SET_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_SET_CMDS_TEST_HPP
|
||||
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SetCmdTest<RedisInstance>::run() {
|
||||
_test_set();
|
||||
|
||||
_test_multi_set();
|
||||
|
||||
_test_sscan();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SetCmdTest<RedisInstance>::_test_set() {
|
||||
auto key = test_key("set");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
std::string m1("m1");
|
||||
std::string m2("m2");
|
||||
std::string m3("m3");
|
||||
|
||||
REDIS_ASSERT(_redis.sadd(key, m1) == 1, "failed to test sadd");
|
||||
|
||||
auto members = {m1, m2, m3};
|
||||
REDIS_ASSERT(_redis.sadd(key, members) == 2, "failed to test sadd with multiple members");
|
||||
|
||||
REDIS_ASSERT(_redis.scard(key) == 3, "failed to test scard");
|
||||
|
||||
REDIS_ASSERT(_redis.sismember(key, m1), "failed to test sismember");
|
||||
|
||||
std::unordered_set<std::string> res;
|
||||
_redis.smembers(key, std::inserter(res, res.end()));
|
||||
REDIS_ASSERT(res.find(m1) != res.end()
|
||||
&& res.find(m2) != res.end()
|
||||
&& res.find(m3) != res.end(),
|
||||
"failed to test smembers");
|
||||
|
||||
auto ele = _redis.srandmember(key);
|
||||
REDIS_ASSERT(bool(ele) && res.find(*ele) != res.end(), "failed to test srandmember");
|
||||
|
||||
std::vector<std::string> rand_members;
|
||||
_redis.srandmember(key, 2, std::back_inserter(rand_members));
|
||||
REDIS_ASSERT(rand_members.size() == 2, "failed to test srandmember");
|
||||
|
||||
ele = _redis.spop(key);
|
||||
REDIS_ASSERT(bool(ele) && res.find(*ele) != res.end(), "failed to test spop");
|
||||
|
||||
rand_members.clear();
|
||||
_redis.spop(key, 3, std::back_inserter(rand_members));
|
||||
REDIS_ASSERT(rand_members.size() == 2, "failed to test srandmember");
|
||||
|
||||
rand_members.clear();
|
||||
_redis.srandmember(key, 2, std::back_inserter(rand_members));
|
||||
REDIS_ASSERT(rand_members.empty(), "failed to test srandmember with empty set");
|
||||
|
||||
_redis.spop(key, 2, std::back_inserter(rand_members));
|
||||
REDIS_ASSERT(rand_members.empty(), "failed to test spop with empty set");
|
||||
|
||||
_redis.sadd(key, members);
|
||||
REDIS_ASSERT(_redis.srem(key, m1) == 1, "failed to test srem");
|
||||
REDIS_ASSERT(_redis.srem(key, members) == 2, "failed to test srem with mulitple members");
|
||||
REDIS_ASSERT(_redis.srem(key, members) == 0, "failed to test srem with mulitple members");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SetCmdTest<RedisInstance>::_test_multi_set() {
|
||||
auto k1 = test_key("s1");
|
||||
auto k2 = test_key("s2");
|
||||
auto k3 = test_key("s3");
|
||||
auto k4 = test_key("s4");
|
||||
auto k5 = test_key("s5");
|
||||
auto k6 = test_key("s6");
|
||||
|
||||
KeyDeleter<RedisInstance> keys(_redis, {k1, k2, k3, k4, k5, k6});
|
||||
|
||||
_redis.sadd(k1, {"a", "c"});
|
||||
_redis.sadd(k2, {"a", "b"});
|
||||
std::vector<std::string> sdiff;
|
||||
_redis.sdiff({k1, k1}, std::back_inserter(sdiff));
|
||||
REDIS_ASSERT(sdiff.empty(), "failed to test sdiff");
|
||||
|
||||
_redis.sdiff({k1, k2}, std::back_inserter(sdiff));
|
||||
REDIS_ASSERT(sdiff == std::vector<std::string>({"c"}), "failed to test sdiff");
|
||||
|
||||
_redis.sdiffstore(k3, {k1, k2});
|
||||
sdiff.clear();
|
||||
_redis.smembers(k3, std::back_inserter(sdiff));
|
||||
REDIS_ASSERT(sdiff == std::vector<std::string>({"c"}), "failed to test sdiffstore");
|
||||
|
||||
REDIS_ASSERT(_redis.sdiffstore(k3, k1) == 2, "failed to test sdiffstore");
|
||||
|
||||
REDIS_ASSERT(_redis.sinterstore(k3, k1) == 2, "failed to test sinterstore");
|
||||
|
||||
REDIS_ASSERT(_redis.sunionstore(k3, k1) == 2, "failed to test sunionstore");
|
||||
|
||||
std::vector<std::string> sinter;
|
||||
_redis.sinter({k1, k2}, std::back_inserter(sinter));
|
||||
REDIS_ASSERT(sinter == std::vector<std::string>({"a"}), "failed to test sinter");
|
||||
|
||||
_redis.sinterstore(k4, {k1, k2});
|
||||
sinter.clear();
|
||||
_redis.smembers(k4, std::back_inserter(sinter));
|
||||
REDIS_ASSERT(sinter == std::vector<std::string>({"a"}), "failed to test sinterstore");
|
||||
|
||||
std::unordered_set<std::string> sunion;
|
||||
_redis.sunion({k1, k2}, std::inserter(sunion, sunion.end()));
|
||||
REDIS_ASSERT(sunion == std::unordered_set<std::string>({"a", "b", "c"}),
|
||||
"failed to test sunion");
|
||||
|
||||
_redis.sunionstore(k5, {k1, k2});
|
||||
sunion.clear();
|
||||
_redis.smembers(k5, std::inserter(sunion, sunion.end()));
|
||||
REDIS_ASSERT(sunion == std::unordered_set<std::string>({"a", "b", "c"}),
|
||||
"failed to test sunionstore");
|
||||
|
||||
REDIS_ASSERT(_redis.smove(k5, k6, "a"), "failed to test smove");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void SetCmdTest<RedisInstance>::_test_sscan() {
|
||||
auto key = test_key("sscan");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
std::unordered_set<std::string> members = {"m1", "m2", "m3"};
|
||||
_redis.sadd(key, members.begin(), members.end());
|
||||
|
||||
std::unordered_set<std::string> res;
|
||||
long long cursor = 0;
|
||||
while (true) {
|
||||
cursor = _redis.sscan(key, cursor, "m*", 1, std::inserter(res, res.end()));
|
||||
if (cursor == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
REDIS_ASSERT(res == members, "failed to test sscan");
|
||||
|
||||
res.clear();
|
||||
cursor = 0;
|
||||
while (true) {
|
||||
cursor = _redis.sscan(key, cursor, std::inserter(res, res.end()));
|
||||
if (cursor == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
REDIS_ASSERT(res == members, "failed to test sscan");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_SET_CMDS_TEST_HPP
|
|
@ -0,0 +1,54 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_STREAM_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_STREAM_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class StreamCmdsTest {
|
||||
public:
|
||||
explicit StreamCmdsTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
using Item = std::pair<std::string, std::unordered_map<std::string, std::string>>;
|
||||
using Result = std::unordered_map<std::string, std::vector<Item>>;
|
||||
|
||||
void _test_stream_cmds();
|
||||
|
||||
void _test_group_cmds();
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "stream_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_STREAM_CMDS_TEST_H
|
|
@ -0,0 +1,225 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_STREAM_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_STREAM_CMDS_TEST_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <unordered_map>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void StreamCmdsTest<RedisInstance>::run() {
|
||||
_test_stream_cmds();
|
||||
|
||||
_test_group_cmds();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void StreamCmdsTest<RedisInstance>::_test_stream_cmds() {
|
||||
auto key = test_key("stream");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> attrs = {
|
||||
{"f1", "v1"},
|
||||
{"f2", "v2"}
|
||||
};
|
||||
auto id = "1565427842-0";
|
||||
REDIS_ASSERT(_redis.xadd(key, id, attrs.begin(), attrs.end()) == id,
|
||||
"failed to test xadd");
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> keys = {std::make_pair(key, "0-0")};
|
||||
Result result;
|
||||
_redis.xread(keys.begin(), keys.end(), 1, std::inserter(result, result.end()));
|
||||
|
||||
REDIS_ASSERT(result.size() == 1
|
||||
&& result.find(key) != result.end()
|
||||
&& result[key].size() == 1
|
||||
&& result[key][0].first == id
|
||||
&& result[key][0].second.size() == 2,
|
||||
"failed to test xread");
|
||||
|
||||
result.clear();
|
||||
_redis.xread(key, std::string("0-0"), 1, std::inserter(result, result.end()));
|
||||
|
||||
REDIS_ASSERT(result.size() == 1
|
||||
&& result.find(key) != result.end()
|
||||
&& result[key].size() == 1
|
||||
&& result[key][0].first == id
|
||||
&& result[key][0].second.size() == 2,
|
||||
"failed to test xread");
|
||||
|
||||
result.clear();
|
||||
keys = {std::make_pair(key, id)};
|
||||
_redis.xread(keys.begin(),
|
||||
keys.end(),
|
||||
std::chrono::seconds(1),
|
||||
2,
|
||||
std::inserter(result, result.end()));
|
||||
REDIS_ASSERT(result.size() == 0, "failed to test xread");
|
||||
|
||||
_redis.xread(key,
|
||||
id,
|
||||
std::chrono::seconds(1),
|
||||
2,
|
||||
std::inserter(result, result.end()));
|
||||
REDIS_ASSERT(result.size() == 0, "failed to test xread");
|
||||
|
||||
id = "1565427842-1";
|
||||
REDIS_ASSERT(_redis.xadd(key, id, attrs.begin(), attrs.end()) == id,
|
||||
"failed to test xadd");
|
||||
|
||||
REDIS_ASSERT(_redis.xlen(key) == 2, "failed to test xlen");
|
||||
|
||||
REDIS_ASSERT(_redis.xtrim(key, 1, false) == 1, "failed to test xtrim");
|
||||
|
||||
std::vector<Item> items;
|
||||
_redis.xrange(key, "-", "+", std::back_inserter(items));
|
||||
REDIS_ASSERT(items.size() == 1 && items[0].first == id, "failed to test xrange");
|
||||
|
||||
items.clear();
|
||||
_redis.xrevrange(key, "+", "-", std::back_inserter(items));
|
||||
REDIS_ASSERT(items.size() == 1 && items[0].first == id, "failed to test xrevrange");
|
||||
|
||||
REDIS_ASSERT(_redis.xdel(key, {id, "111-111"}) == 1, "failed to test xdel");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void StreamCmdsTest<RedisInstance>::_test_group_cmds() {
|
||||
auto key = test_key("stream");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto group = "group";
|
||||
auto consumer1 = "consumer1";
|
||||
|
||||
_redis.xgroup_create(key, group, "$", true);
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> attrs = {
|
||||
{"f1", "v1"},
|
||||
{"f2", "v2"}
|
||||
};
|
||||
auto id = _redis.xadd(key, "*", attrs.begin(), attrs.end());
|
||||
auto keys = {std::make_pair(key, ">")};
|
||||
|
||||
Result result;
|
||||
_redis.xreadgroup(group,
|
||||
consumer1,
|
||||
keys.begin(),
|
||||
keys.end(),
|
||||
1,
|
||||
std::inserter(result, result.end()));
|
||||
REDIS_ASSERT(result.size() == 1
|
||||
&& result.find(key) != result.end()
|
||||
&& result[key].size() == 1
|
||||
&& result[key][0].first == id,
|
||||
"failed to test xreadgroup");
|
||||
|
||||
result.clear();
|
||||
_redis.xreadgroup(group,
|
||||
consumer1,
|
||||
key,
|
||||
std::string(">"),
|
||||
1,
|
||||
std::inserter(result, result.end()));
|
||||
REDIS_ASSERT(result.size() == 0, "failed to test xreadgroup");
|
||||
|
||||
result.clear();
|
||||
_redis.xreadgroup(group,
|
||||
"not-exist-consumer",
|
||||
keys.begin(),
|
||||
keys.end(),
|
||||
1,
|
||||
std::inserter(result, result.end()));
|
||||
REDIS_ASSERT(result.size() == 0, "failed to test xreadgroup");
|
||||
|
||||
result.clear();
|
||||
_redis.xreadgroup(group,
|
||||
consumer1,
|
||||
keys.begin(),
|
||||
keys.end(),
|
||||
std::chrono::seconds(1),
|
||||
1,
|
||||
std::inserter(result, result.end()));
|
||||
REDIS_ASSERT(result.size() == 0, "failed to test xreadgroup");
|
||||
|
||||
result.clear();
|
||||
_redis.xreadgroup(group,
|
||||
consumer1,
|
||||
key,
|
||||
">",
|
||||
std::chrono::seconds(1),
|
||||
1,
|
||||
std::inserter(result, result.end()));
|
||||
REDIS_ASSERT(result.size() == 0, "failed to test xreadgroup");
|
||||
|
||||
using PendingResult = std::vector<std::tuple<std::string, std::string, long long, long long>>;
|
||||
PendingResult pending_result;
|
||||
_redis.xpending(key, group, "-", "+", 1, consumer1, std::back_inserter(pending_result));
|
||||
|
||||
REDIS_ASSERT(pending_result.size() == 1
|
||||
&& std::get<0>(pending_result[0]) == id
|
||||
&& std::get<1>(pending_result[0]) == consumer1,
|
||||
"failed to test xpending");
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
|
||||
auto consumer2 = "consumer2";
|
||||
std::vector<Item> items;
|
||||
auto ids = {id};
|
||||
_redis.xclaim(key,
|
||||
group,
|
||||
consumer2,
|
||||
std::chrono::milliseconds(10),
|
||||
ids,
|
||||
std::back_inserter(items));
|
||||
REDIS_ASSERT(items.size() == 1 && items[0].first == id, "failed to test xclaim");
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
|
||||
items.clear();
|
||||
_redis.xclaim(key, group, consumer1, std::chrono::milliseconds(10), id, std::back_inserter(items));
|
||||
REDIS_ASSERT(items.size() == 1 && items[0].first == id, "failed to test xclaim: " + std::to_string(items.size()));
|
||||
|
||||
_redis.xack(key, group, id);
|
||||
|
||||
REDIS_ASSERT(_redis.xgroup_delconsumer(key, group, consumer1) == 0,
|
||||
"failed to test xgroup_delconsumer");
|
||||
|
||||
REDIS_ASSERT(_redis.xgroup_delconsumer(key, group, consumer2) == 0,
|
||||
"failed to test xgroup_delconsumer");
|
||||
|
||||
REDIS_ASSERT(_redis.xgroup_destroy(key, group) == 1,
|
||||
"failed to test xgroup_destroy");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_STREAM_CMDS_TEST_HPP
|
|
@ -0,0 +1,57 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_STRING_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_STRING_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class StringCmdTest {
|
||||
public:
|
||||
explicit StringCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _test_str();
|
||||
|
||||
void _test_bit();
|
||||
|
||||
void _test_numeric();
|
||||
|
||||
void _test_getset();
|
||||
|
||||
void _test_mgetset();
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "string_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_STRING_CMDS_TEST_H
|
|
@ -0,0 +1,247 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_STRING_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_STRING_CMDS_TEST_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void StringCmdTest<RedisInstance>::run() {
|
||||
_test_str();
|
||||
|
||||
_test_bit();
|
||||
|
||||
_test_numeric();
|
||||
|
||||
_test_getset();
|
||||
|
||||
_test_mgetset();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void StringCmdTest<RedisInstance>::_test_str() {
|
||||
auto key = test_key("str");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
std::string val("value");
|
||||
|
||||
long long val_size = val.size();
|
||||
|
||||
auto len1 = _redis.append(key, val);
|
||||
REDIS_ASSERT(len1 == val_size, "failed to append to non-existent key");
|
||||
|
||||
auto len2 = _redis.append(key, val);
|
||||
REDIS_ASSERT(len2 == len1 + val_size, "failed to append to non-empty string");
|
||||
|
||||
auto len3 = _redis.append(key, {});
|
||||
REDIS_ASSERT(len3 == len2, "failed to append empty string");
|
||||
|
||||
auto len4 = _redis.strlen(key);
|
||||
REDIS_ASSERT(len4 == len3, "failed to test strlen");
|
||||
|
||||
REDIS_ASSERT(_redis.del(key) == 1, "failed to remove key");
|
||||
|
||||
auto len5 = _redis.append(key, {});
|
||||
REDIS_ASSERT(len5 == 0, "failed to append empty string to non-existent key");
|
||||
|
||||
_redis.del(key);
|
||||
|
||||
REDIS_ASSERT(_redis.getrange(key, 0, 2) == "", "failed to test getrange on non-existent key");
|
||||
|
||||
_redis.set(key, val);
|
||||
|
||||
REDIS_ASSERT(_redis.getrange(key, 1, 2) == val.substr(1, 2), "failed to test getrange");
|
||||
|
||||
long long new_size = val.size() * 2;
|
||||
REDIS_ASSERT(_redis.setrange(key, val.size(), val) == new_size, "failed to test setrange");
|
||||
REDIS_ASSERT(_redis.getrange(key, 0, -1) == val + val, "failed to test setrange");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void StringCmdTest<RedisInstance>::_test_bit() {
|
||||
auto key = test_key("bit");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
REDIS_ASSERT(_redis.bitcount(key) == 0, "failed to test bitcount on non-existent key");
|
||||
|
||||
REDIS_ASSERT(_redis.getbit(key, 5) == 0, "failed to test getbit");
|
||||
|
||||
REDIS_ASSERT(_redis.template command<long long>("SETBIT", key, 1, 1) == 0,
|
||||
"failed to test setbit");
|
||||
REDIS_ASSERT(_redis.template command<long long>("SETBIT", key, 3, 1) == 0,
|
||||
"failed to test setbit");
|
||||
REDIS_ASSERT(_redis.template command<long long>("SETBIT", key, 7, 1) == 0,
|
||||
"failed to test setbit");
|
||||
REDIS_ASSERT(_redis.template command<long long>("SETBIT", key, 10, 1) == 0,
|
||||
"failed to test setbit");
|
||||
REDIS_ASSERT(_redis.template command<long long>("SETBIT", key, 10, 0) == 1,
|
||||
"failed to test setbit");
|
||||
REDIS_ASSERT(_redis.template command<long long>("SETBIT", key, 11, 1) == 0,
|
||||
"failed to test setbit");
|
||||
REDIS_ASSERT(_redis.template command<long long>("SETBIT", key, 21, 1) == 0,
|
||||
"failed to test setbit");
|
||||
|
||||
// key -> 01010001, 00010000, 00000100
|
||||
|
||||
REDIS_ASSERT(_redis.getbit(key, 1) == 1, "failed to test getbit");
|
||||
REDIS_ASSERT(_redis.getbit(key, 2) == 0, "failed to test getbit");
|
||||
REDIS_ASSERT(_redis.getbit(key, 7) == 1, "failed to test getbit");
|
||||
REDIS_ASSERT(_redis.getbit(key, 10) == 0, "failed to test getbit");
|
||||
REDIS_ASSERT(_redis.getbit(key, 100) == 0, "failed to test getbit");
|
||||
|
||||
REDIS_ASSERT(_redis.bitcount(key) == 5, "failed to test bitcount");
|
||||
REDIS_ASSERT(_redis.bitcount(key, 0, 0) == 3, "failed to test bitcount");
|
||||
REDIS_ASSERT(_redis.bitcount(key, 0, 1) == 4, "failed to test bitcount");
|
||||
REDIS_ASSERT(_redis.bitcount(key, -2, -1) == 2, "failed to test bitcount");
|
||||
|
||||
REDIS_ASSERT(_redis.bitpos(key, 1) == 1, "failed to test bitpos");
|
||||
REDIS_ASSERT(_redis.bitpos(key, 0) == 0, "failed to test bitpos");
|
||||
REDIS_ASSERT(_redis.bitpos(key, 1, 1, 1) == 11, "failed to test bitpos");
|
||||
REDIS_ASSERT(_redis.bitpos(key, 0, 1, 1) == 8, "failed to test bitpos");
|
||||
REDIS_ASSERT(_redis.bitpos(key, 1, -1, -1) == 21, "failed to test bitpos");
|
||||
REDIS_ASSERT(_redis.bitpos(key, 0, -1, -1) == 16, "failed to test bitpos");
|
||||
|
||||
auto dest_key = test_key("bitop_dest");
|
||||
auto src_key1 = test_key("bitop_src1");
|
||||
auto src_key2 = test_key("bitop_src2");
|
||||
|
||||
KeyDeleter<RedisInstance> deleters(_redis, {dest_key, src_key1, src_key2});
|
||||
|
||||
// src_key1 -> 00010000
|
||||
_redis.template command<long long>("SETBIT", src_key1, 3, 1);
|
||||
|
||||
// src_key2 -> 00000000, 00001000
|
||||
_redis.template command<long long>("SETBIT", src_key2, 12, 1);
|
||||
|
||||
REDIS_ASSERT(_redis.bitop(BitOp::AND, dest_key, {src_key1, src_key2}) == 2,
|
||||
"failed to test bitop");
|
||||
|
||||
// dest_key -> 00000000, 00000000
|
||||
auto v = _redis.get(dest_key);
|
||||
REDIS_ASSERT(v && *v == std::string(2, 0), "failed to test bitop");
|
||||
|
||||
REDIS_ASSERT(_redis.bitop(BitOp::NOT, dest_key, src_key1) == 1,
|
||||
"failed to test bitop");
|
||||
|
||||
// dest_key -> 11101111
|
||||
v = _redis.get(dest_key);
|
||||
REDIS_ASSERT(v && *v == std::string(1, 0xEF), "failed to test bitop");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void StringCmdTest<RedisInstance>::_test_numeric() {
|
||||
auto key = test_key("numeric");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
REDIS_ASSERT(_redis.incr(key) == 1, "failed to test incr");
|
||||
REDIS_ASSERT(_redis.decr(key) == 0, "failed to test decr");
|
||||
REDIS_ASSERT(_redis.incrby(key, 3) == 3, "failed to test incrby");
|
||||
REDIS_ASSERT(_redis.decrby(key, 3) == 0, "failed to test decrby");
|
||||
REDIS_ASSERT(_redis.incrby(key, -3) == -3, "failed to test incrby");
|
||||
REDIS_ASSERT(_redis.decrby(key, -3) == 0, "failed to test incrby");
|
||||
REDIS_ASSERT(_redis.incrbyfloat(key, 1.5) == 1.5, "failed to test incrbyfloat");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void StringCmdTest<RedisInstance>::_test_getset() {
|
||||
auto key = test_key("getset");
|
||||
auto non_exist_key = test_key("non-existent");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, {key, non_exist_key});
|
||||
|
||||
std::string val("value");
|
||||
REDIS_ASSERT(_redis.set(key, val), "failed to test set");
|
||||
|
||||
auto v = _redis.get(key);
|
||||
REDIS_ASSERT(v && *v == val, "failed to test get");
|
||||
|
||||
v = _redis.getset(key, val + val);
|
||||
REDIS_ASSERT(v && *v == val, "failed to test get");
|
||||
|
||||
REDIS_ASSERT(!_redis.set(key, val, std::chrono::milliseconds(0), UpdateType::NOT_EXIST),
|
||||
"failed to test set with NOT_EXIST type");
|
||||
REDIS_ASSERT(!_redis.set(non_exist_key, val, std::chrono::milliseconds(0), UpdateType::EXIST),
|
||||
"failed to test set with EXIST type");
|
||||
|
||||
REDIS_ASSERT(!_redis.setnx(key, val), "failed to test setnx");
|
||||
REDIS_ASSERT(_redis.setnx(non_exist_key, val), "failed to test setnx");
|
||||
|
||||
auto ttl = std::chrono::seconds(10);
|
||||
|
||||
_redis.set(key, val, ttl);
|
||||
REDIS_ASSERT(_redis.ttl(key) <= ttl.count(), "failed to test set key with ttl");
|
||||
|
||||
_redis.setex(key, ttl, val);
|
||||
REDIS_ASSERT(_redis.ttl(key) <= ttl.count(), "failed to test setex");
|
||||
|
||||
auto pttl = std::chrono::milliseconds(10000);
|
||||
|
||||
_redis.psetex(key, ttl, val);
|
||||
REDIS_ASSERT(_redis.pttl(key) <= pttl.count(), "failed to test psetex");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void StringCmdTest<RedisInstance>::_test_mgetset() {
|
||||
auto kvs = {std::make_pair(test_key("k1"), "v1"),
|
||||
std::make_pair(test_key("k2"), "v2"),
|
||||
std::make_pair(test_key("k3"), "v3")};
|
||||
|
||||
std::vector<std::string> keys;
|
||||
std::vector<std::string> vals;
|
||||
for (const auto &kv : kvs) {
|
||||
keys.push_back(kv.first);
|
||||
vals.push_back(kv.second);
|
||||
}
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, keys.begin(), keys.end());
|
||||
|
||||
_redis.mset(kvs);
|
||||
|
||||
std::vector<OptionalString> res;
|
||||
_redis.mget(keys.begin(), keys.end(), std::back_inserter(res));
|
||||
|
||||
REDIS_ASSERT(res.size() == kvs.size(), "failed to test mget");
|
||||
|
||||
std::vector<std::string> res_vals;
|
||||
for (const auto &ele : res) {
|
||||
REDIS_ASSERT(bool(ele), "failed to test mget");
|
||||
|
||||
res_vals.push_back(*ele);
|
||||
}
|
||||
|
||||
REDIS_ASSERT(vals == res_vals, "failed to test mget");
|
||||
|
||||
REDIS_ASSERT(!_redis.msetnx(kvs), "failed to test msetnx");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_STRING_CMDS_TEST_HPP
|
303
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/test_main.cpp
Normal file
303
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/test_main.cpp
Normal file
|
@ -0,0 +1,303 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <chrono>
|
||||
#include <tuple>
|
||||
#include <iostream>
|
||||
#include <sw/redis++/redis++.h>
|
||||
#include "sanity_test.h"
|
||||
#include "connection_cmds_test.h"
|
||||
#include "keys_cmds_test.h"
|
||||
#include "string_cmds_test.h"
|
||||
#include "list_cmds_test.h"
|
||||
#include "hash_cmds_test.h"
|
||||
#include "set_cmds_test.h"
|
||||
#include "zset_cmds_test.h"
|
||||
#include "hyperloglog_cmds_test.h"
|
||||
#include "geo_cmds_test.h"
|
||||
#include "script_cmds_test.h"
|
||||
#include "pubsub_test.h"
|
||||
#include "pipeline_transaction_test.h"
|
||||
#include "threads_test.h"
|
||||
#include "stream_cmds_test.h"
|
||||
#include "benchmark_test.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void print_help();
|
||||
|
||||
auto parse_options(int argc, char **argv)
|
||||
-> std::tuple<sw::redis::Optional<sw::redis::ConnectionOptions>,
|
||||
sw::redis::Optional<sw::redis::ConnectionOptions>,
|
||||
sw::redis::Optional<sw::redis::test::BenchmarkOptions>>;
|
||||
|
||||
template <typename RedisInstance>
|
||||
void run_test(const sw::redis::ConnectionOptions &opts);
|
||||
|
||||
template <typename RedisInstance>
|
||||
void run_benchmark(const sw::redis::ConnectionOptions &opts,
|
||||
const sw::redis::test::BenchmarkOptions &benchmark_opts);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
try {
|
||||
sw::redis::Optional<sw::redis::ConnectionOptions> opts;
|
||||
sw::redis::Optional<sw::redis::ConnectionOptions> cluster_node_opts;
|
||||
sw::redis::Optional<sw::redis::test::BenchmarkOptions> benchmark_opts;
|
||||
std::tie(opts, cluster_node_opts, benchmark_opts) = parse_options(argc, argv);
|
||||
|
||||
if (opts) {
|
||||
std::cout << "Testing Redis..." << std::endl;
|
||||
|
||||
if (benchmark_opts) {
|
||||
run_benchmark<sw::redis::Redis>(*opts, *benchmark_opts);
|
||||
} else {
|
||||
run_test<sw::redis::Redis>(*opts);
|
||||
}
|
||||
}
|
||||
|
||||
if (cluster_node_opts) {
|
||||
std::cout << "Testing RedisCluster..." << std::endl;
|
||||
|
||||
if (benchmark_opts) {
|
||||
run_benchmark<sw::redis::RedisCluster>(*cluster_node_opts, *benchmark_opts);
|
||||
} else {
|
||||
run_test<sw::redis::RedisCluster>(*cluster_node_opts);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Pass all tests" << std::endl;
|
||||
} catch (const sw::redis::Error &e) {
|
||||
std::cerr << "Test failed: " << e.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void print_help() {
|
||||
std::cerr << "Usage: test_redis++ -h host -p port"
|
||||
<< " -n cluster_node -c cluster_port [-a auth] [-b]\n\n";
|
||||
std::cerr << "See https://github.com/sewenew/redis-plus-plus#run-tests-optional"
|
||||
<< " for details on how to run test" << std::endl;
|
||||
}
|
||||
|
||||
auto parse_options(int argc, char **argv)
|
||||
-> std::tuple<sw::redis::Optional<sw::redis::ConnectionOptions>,
|
||||
sw::redis::Optional<sw::redis::ConnectionOptions>,
|
||||
sw::redis::Optional<sw::redis::test::BenchmarkOptions>> {
|
||||
std::string host;
|
||||
int port = 0;
|
||||
std::string auth;
|
||||
std::string cluster_node;
|
||||
int cluster_port = 0;
|
||||
bool benchmark = false;
|
||||
sw::redis::test::BenchmarkOptions tmp_benchmark_opts;
|
||||
|
||||
int opt = 0;
|
||||
while ((opt = getopt(argc, argv, "h:p:a:n:c:k:v:r:t:bs:")) != -1) {
|
||||
try {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
host = optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
port = std::stoi(optarg);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
auth = optarg;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
cluster_node = optarg;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
cluster_port = std::stoi(optarg);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
benchmark = true;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
tmp_benchmark_opts.key_len = std::stoi(optarg);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
tmp_benchmark_opts.val_len = std::stoi(optarg);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
tmp_benchmark_opts.total_request_num = std::stoi(optarg);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
tmp_benchmark_opts.thread_num = std::stoi(optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
tmp_benchmark_opts.pool_size = std::stoi(optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw sw::redis::Error("Unknow command line option");
|
||||
break;
|
||||
}
|
||||
} catch (const sw::redis::Error &e) {
|
||||
print_help();
|
||||
throw;
|
||||
} catch (const std::exception &e) {
|
||||
print_help();
|
||||
throw sw::redis::Error("Invalid command line option");
|
||||
}
|
||||
}
|
||||
|
||||
sw::redis::Optional<sw::redis::ConnectionOptions> opts;
|
||||
if (!host.empty() && port > 0) {
|
||||
sw::redis::ConnectionOptions tmp;
|
||||
tmp.host = host;
|
||||
tmp.port = port;
|
||||
tmp.password = auth;
|
||||
|
||||
opts = sw::redis::Optional<sw::redis::ConnectionOptions>(tmp);
|
||||
}
|
||||
|
||||
sw::redis::Optional<sw::redis::ConnectionOptions> cluster_opts;
|
||||
if (!cluster_node.empty() && cluster_port > 0) {
|
||||
sw::redis::ConnectionOptions tmp;
|
||||
tmp.host = cluster_node;
|
||||
tmp.port = cluster_port;
|
||||
tmp.password = auth;
|
||||
|
||||
cluster_opts = sw::redis::Optional<sw::redis::ConnectionOptions>(tmp);
|
||||
}
|
||||
|
||||
if (!opts && !cluster_opts) {
|
||||
print_help();
|
||||
throw sw::redis::Error("Invalid connection options");
|
||||
}
|
||||
|
||||
sw::redis::Optional<sw::redis::test::BenchmarkOptions> benchmark_opts;
|
||||
if (benchmark) {
|
||||
benchmark_opts = sw::redis::Optional<sw::redis::test::BenchmarkOptions>(tmp_benchmark_opts);
|
||||
}
|
||||
|
||||
return std::make_tuple(std::move(opts), std::move(cluster_opts), std::move(benchmark_opts));
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void run_test(const sw::redis::ConnectionOptions &opts) {
|
||||
auto instance = RedisInstance(opts);
|
||||
|
||||
sw::redis::test::SanityTest<RedisInstance> sanity_test(opts, instance);
|
||||
sanity_test.run();
|
||||
|
||||
std::cout << "Pass sanity tests" << std::endl;
|
||||
|
||||
sw::redis::test::ConnectionCmdTest<RedisInstance> connection_test(instance);
|
||||
connection_test.run();
|
||||
|
||||
std::cout << "Pass connection commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::KeysCmdTest<RedisInstance> keys_test(instance);
|
||||
keys_test.run();
|
||||
|
||||
std::cout << "Pass keys commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::StringCmdTest<RedisInstance> string_test(instance);
|
||||
string_test.run();
|
||||
|
||||
std::cout << "Pass string commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::ListCmdTest<RedisInstance> list_test(instance);
|
||||
list_test.run();
|
||||
|
||||
std::cout << "Pass list commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::HashCmdTest<RedisInstance> hash_test(instance);
|
||||
hash_test.run();
|
||||
|
||||
std::cout << "Pass hash commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::SetCmdTest<RedisInstance> set_test(instance);
|
||||
set_test.run();
|
||||
|
||||
std::cout << "Pass set commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::ZSetCmdTest<RedisInstance> zset_test(instance);
|
||||
zset_test.run();
|
||||
|
||||
std::cout << "Pass zset commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::HyperloglogCmdTest<RedisInstance> hll_test(instance);
|
||||
hll_test.run();
|
||||
|
||||
std::cout << "Pass hyperloglog commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::GeoCmdTest<RedisInstance> geo_test(instance);
|
||||
geo_test.run();
|
||||
|
||||
std::cout << "Pass geo commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::ScriptCmdTest<RedisInstance> script_test(instance);
|
||||
script_test.run();
|
||||
|
||||
std::cout << "Pass script commands tests" << std::endl;
|
||||
|
||||
sw::redis::test::PubSubTest<RedisInstance> pubsub_test(instance);
|
||||
pubsub_test.run();
|
||||
|
||||
std::cout << "Pass pubsub tests" << std::endl;
|
||||
|
||||
sw::redis::test::PipelineTransactionTest<RedisInstance> pipe_tx_test(instance);
|
||||
pipe_tx_test.run();
|
||||
|
||||
std::cout << "Pass pipeline and transaction tests" << std::endl;
|
||||
|
||||
sw::redis::test::ThreadsTest<RedisInstance> threads_test(opts);
|
||||
threads_test.run();
|
||||
|
||||
std::cout << "Pass threads tests" << std::endl;
|
||||
|
||||
sw::redis::test::StreamCmdsTest<RedisInstance> stream_test(instance);
|
||||
stream_test.run();
|
||||
|
||||
std::cout << "Pass stream commands tests" << std::endl;
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void run_benchmark(const sw::redis::ConnectionOptions &opts,
|
||||
const sw::redis::test::BenchmarkOptions &benchmark_opts) {
|
||||
std::cout << "Benchmark test options:" << std::endl;
|
||||
std::cout << " Thread number: " << benchmark_opts.thread_num << std::endl;
|
||||
std::cout << " Connection pool size: " << benchmark_opts.pool_size << std::endl;
|
||||
std::cout << " Length of key: " << benchmark_opts.key_len << std::endl;
|
||||
std::cout << " Length of value: " << benchmark_opts.val_len << std::endl;
|
||||
|
||||
auto instance = RedisInstance(opts);
|
||||
|
||||
sw::redis::test::BenchmarkTest<RedisInstance> benchmark_test(benchmark_opts, instance);
|
||||
benchmark_test.run();
|
||||
}
|
||||
|
||||
}
|
51
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/threads_test.h
Normal file
51
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/threads_test.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_THREADS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_THREADS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class ThreadsTest {
|
||||
public:
|
||||
explicit ThreadsTest(const ConnectionOptions &opts) : _opts(opts) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _test_multithreads(RedisInstance redis, int threads_num, int times);
|
||||
|
||||
void _test_timeout();
|
||||
|
||||
ConnectionOptions _opts;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "threads_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_THREADS_TEST_H
|
147
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/threads_test.hpp
Normal file
147
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/threads_test.hpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_THREADS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_THREADS_TEST_HPP
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ThreadsTest<RedisInstance>::run() {
|
||||
// 100 * 10000 = 1 million writes
|
||||
auto thread_num = 100;
|
||||
auto times = 10000;
|
||||
|
||||
// Default pool options: single connection and wait forever.
|
||||
_test_multithreads(RedisInstance(_opts), thread_num, times);
|
||||
|
||||
// Pool with 10 connections.
|
||||
ConnectionPoolOptions pool_opts;
|
||||
pool_opts.size = 10;
|
||||
_test_multithreads(RedisInstance(_opts, pool_opts), thread_num, times);
|
||||
|
||||
_test_timeout();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ThreadsTest<RedisInstance>::_test_multithreads(RedisInstance redis,
|
||||
int thread_num,
|
||||
int times) {
|
||||
std::vector<std::string> keys;
|
||||
keys.reserve(thread_num);
|
||||
for (auto idx = 0; idx != thread_num; ++idx) {
|
||||
auto key = test_key("multi-threads::" + std::to_string(idx));
|
||||
keys.push_back(key);
|
||||
}
|
||||
|
||||
using DeleterUPtr = std::unique_ptr<KeyDeleter<RedisInstance>>;
|
||||
std::vector<DeleterUPtr> deleters;
|
||||
for (const auto &key : keys) {
|
||||
deleters.emplace_back(new KeyDeleter<RedisInstance>(redis, key));
|
||||
}
|
||||
|
||||
std::vector<std::thread> workers;
|
||||
workers.reserve(thread_num);
|
||||
for (const auto &key : keys) {
|
||||
workers.emplace_back([&redis, key, times]() {
|
||||
try {
|
||||
for (auto i = 0; i != times; ++i) {
|
||||
redis.incr(key);
|
||||
}
|
||||
} catch (...) {
|
||||
// Something bad happens.
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto &worker : workers) {
|
||||
worker.join();
|
||||
}
|
||||
|
||||
for (const auto &key : keys) {
|
||||
auto val = redis.get(key);
|
||||
REDIS_ASSERT(bool(val), "failed to test multithreads, cannot get value of " + key);
|
||||
|
||||
auto num = std::stoi(*val);
|
||||
REDIS_ASSERT(num == times, "failed to test multithreads, num: "
|
||||
+ *val + ", times: " + std::to_string(times));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ThreadsTest<RedisInstance>::_test_timeout() {
|
||||
using namespace std::chrono;
|
||||
|
||||
ConnectionPoolOptions pool_opts;
|
||||
pool_opts.size = 1;
|
||||
pool_opts.wait_timeout = milliseconds(100);
|
||||
|
||||
auto redis = RedisInstance(_opts, pool_opts);
|
||||
|
||||
auto key = test_key("key");
|
||||
|
||||
std::atomic<bool> slow_get_is_running{false};
|
||||
auto slow_get = [&slow_get_is_running](Connection &connection, const StringView &key) {
|
||||
slow_get_is_running = true;
|
||||
|
||||
// Sleep a while to simulate a slow get.
|
||||
std::this_thread::sleep_for(seconds(5));
|
||||
|
||||
connection.send("GET %b", key.data(), key.size());
|
||||
};
|
||||
auto slow_get_thread = std::thread([&redis, slow_get, &key]() {
|
||||
redis.command(slow_get, key);
|
||||
});
|
||||
|
||||
auto get_thread = std::thread([&redis, &slow_get_is_running, &key]() {
|
||||
try {
|
||||
while (!slow_get_is_running) {
|
||||
std::this_thread::sleep_for(milliseconds(10));
|
||||
}
|
||||
|
||||
redis.get(key);
|
||||
|
||||
// Slow get is running, this thread should
|
||||
// timeout before obtaining the connection.
|
||||
// So it never reaches here.
|
||||
REDIS_ASSERT(false, "failed to test pool timeout");
|
||||
} catch (const Error &err) {
|
||||
// This thread timeout.
|
||||
}
|
||||
});
|
||||
|
||||
slow_get_thread.join();
|
||||
get_thread.join();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_THREADS_TEST_HPP
|
96
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/utils.h
Normal file
96
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/utils.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_UTILS_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
#define REDIS_ASSERT(condition, msg) \
|
||||
sw::redis::test::redis_assert((condition), (msg), __FILE__, __LINE__)
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
inline void redis_assert(bool condition,
|
||||
const std::string &msg,
|
||||
const std::string &file,
|
||||
int line) {
|
||||
if (!condition) {
|
||||
auto err_msg = "ASSERT: " + msg + ". " + file + ":" + std::to_string(line);
|
||||
throw Error(err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string test_key(const std::string &k) {
|
||||
// Key prefix with hash tag,
|
||||
// so that we can call multiple-key commands on RedisCluster.
|
||||
return "{sw::redis::test}::" + k;
|
||||
}
|
||||
|
||||
template <typename Test>
|
||||
void cluster_specializing_test(Test &test, void (Test::*func)(Redis &instance), Redis &instance) {
|
||||
(test.*func)(instance);
|
||||
}
|
||||
|
||||
template <typename Test>
|
||||
void cluster_specializing_test(Test &test,
|
||||
void (Test::*func)(Redis &instance),
|
||||
RedisCluster &cluster) {
|
||||
auto instance = cluster.redis("hash-tag");
|
||||
(test.*func)(instance);
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
class KeyDeleter {
|
||||
public:
|
||||
template <typename Input>
|
||||
KeyDeleter(RedisInstance &redis, Input first, Input last) : _redis(redis), _keys(first, last) {
|
||||
_delete();
|
||||
}
|
||||
|
||||
KeyDeleter(RedisInstance &redis, std::initializer_list<std::string> il) :
|
||||
KeyDeleter(redis, il.begin(), il.end()) {}
|
||||
|
||||
KeyDeleter(RedisInstance &redis, const std::string &key) : KeyDeleter(redis, {key}) {}
|
||||
|
||||
~KeyDeleter() {
|
||||
_delete();
|
||||
}
|
||||
|
||||
private:
|
||||
void _delete() {
|
||||
if (!_keys.empty()) {
|
||||
_redis.del(_keys.begin(), _keys.end());
|
||||
}
|
||||
}
|
||||
|
||||
RedisInstance &_redis;
|
||||
std::vector<std::string> _keys;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_UTILS_H
|
|
@ -0,0 +1,61 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_ZSET_CMDS_TEST_H
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_ZSET_CMDS_TEST_H
|
||||
|
||||
#include <sw/redis++/redis++.h>
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
class ZSetCmdTest {
|
||||
public:
|
||||
explicit ZSetCmdTest(RedisInstance &instance) : _redis(instance) {}
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void _test_zset();
|
||||
|
||||
void _test_zscan();
|
||||
|
||||
void _test_range();
|
||||
|
||||
void _test_lex();
|
||||
|
||||
void _test_multi_zset();
|
||||
|
||||
void _test_zpop();
|
||||
|
||||
void _test_bzpop();
|
||||
|
||||
RedisInstance &_redis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "zset_cmds_test.hpp"
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_ZSET_CMDS_TEST_H
|
350
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/zset_cmds_test.hpp
Normal file
350
ext/redis-plus-plus-1.1.1/test/src/sw/redis++/zset_cmds_test.hpp
Normal file
|
@ -0,0 +1,350 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2017 sewenew
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef SEWENEW_REDISPLUSPLUS_TEST_ZSET_CMDS_TEST_HPP
|
||||
#define SEWENEW_REDISPLUSPLUS_TEST_ZSET_CMDS_TEST_HPP
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "utils.h"
|
||||
|
||||
namespace sw {
|
||||
|
||||
namespace redis {
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ZSetCmdTest<RedisInstance>::run() {
|
||||
_test_zset();
|
||||
|
||||
_test_zscan();
|
||||
|
||||
_test_range();
|
||||
|
||||
_test_lex();
|
||||
|
||||
_test_multi_zset();
|
||||
|
||||
_test_zpop();
|
||||
|
||||
_test_bzpop();
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ZSetCmdTest<RedisInstance>::_test_zset() {
|
||||
auto key = test_key("zset");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
std::map<std::string, double> s = {
|
||||
std::make_pair("m1", 1.2),
|
||||
std::make_pair("m2", 2),
|
||||
std::make_pair("m3", 3),
|
||||
};
|
||||
|
||||
const auto &ele = *(s.begin());
|
||||
REDIS_ASSERT(_redis.zadd(key, ele.first, ele.second, UpdateType::EXIST) == 0,
|
||||
"failed to test zadd with noexistent member");
|
||||
|
||||
REDIS_ASSERT(_redis.zadd(key, s.begin(), s.end()) == 3, "failed to test zadd");
|
||||
|
||||
REDIS_ASSERT(_redis.zadd(key, ele.first, ele.second, UpdateType::NOT_EXIST) == 0,
|
||||
"failed to test zadd with exist member");
|
||||
|
||||
REDIS_ASSERT(_redis.zadd(key, s.begin(), s.end(), UpdateType::ALWAYS, true) == 0,
|
||||
"failed to test zadd");
|
||||
|
||||
REDIS_ASSERT(_redis.zcard(key) == 3, "failed to test zcard");
|
||||
|
||||
auto rank = _redis.zrank(key, "m2");
|
||||
REDIS_ASSERT(bool(rank) && *rank == 1, "failed to test zrank");
|
||||
rank = _redis.zrevrank(key, "m4");
|
||||
REDIS_ASSERT(!rank, "failed to test zrevrank with nonexistent member");
|
||||
|
||||
auto score = _redis.zscore(key, "m4");
|
||||
REDIS_ASSERT(!score, "failed to test zscore with nonexistent member");
|
||||
|
||||
REDIS_ASSERT(_redis.zincrby(key, 1, "m3") == 4, "failed to test zincrby");
|
||||
|
||||
score = _redis.zscore(key, "m3");
|
||||
REDIS_ASSERT(score && *score == 4, "failed to test zscore");
|
||||
|
||||
REDIS_ASSERT(_redis.zrem(key, "m1") == 1, "failed to test zrem");
|
||||
REDIS_ASSERT(_redis.zrem(key, {"m1", "m2", "m3", "m4"}) == 2, "failed to test zrem");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ZSetCmdTest<RedisInstance>::_test_zscan() {
|
||||
auto key = test_key("zscan");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
std::map<std::string, double> s = {
|
||||
std::make_pair("m1", 1.2),
|
||||
std::make_pair("m2", 2),
|
||||
std::make_pair("m3", 3),
|
||||
};
|
||||
_redis.zadd(key, s.begin(), s.end());
|
||||
|
||||
std::map<std::string, double> res;
|
||||
auto cursor = 0;
|
||||
while (true) {
|
||||
cursor = _redis.zscan(key, cursor, "m*", 2, std::inserter(res, res.end()));
|
||||
if (cursor == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
REDIS_ASSERT(res == s, "failed to test zscan");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ZSetCmdTest<RedisInstance>::_test_range() {
|
||||
auto key = test_key("range");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
std::map<std::string, double> s = {
|
||||
std::make_pair("m1", 1),
|
||||
std::make_pair("m2", 2),
|
||||
std::make_pair("m3", 3),
|
||||
};
|
||||
_redis.zadd(key, s.begin(), s.end());
|
||||
|
||||
REDIS_ASSERT(_redis.zcount(key, UnboundedInterval<double>{}) == 3, "failed to test zcount");
|
||||
|
||||
std::vector<std::string> members;
|
||||
_redis.zrange(key, 0, -1, std::back_inserter(members));
|
||||
REDIS_ASSERT(members.size() == s.size(), "failed to test zrange");
|
||||
for (const auto &mem : {"m1", "m2", "m3"}) {
|
||||
REDIS_ASSERT(std::find(members.begin(), members.end(), mem) != members.end(),
|
||||
"failed to test zrange");
|
||||
}
|
||||
|
||||
std::map<std::string, double> res;
|
||||
_redis.zrange(key, 0, -1, std::inserter(res, res.end()));
|
||||
REDIS_ASSERT(s == res, "failed to test zrange with score");
|
||||
|
||||
members.clear();
|
||||
_redis.zrevrange(key, 0, 0, std::back_inserter(members));
|
||||
REDIS_ASSERT(members.size() == 1 && members[0] == "m3", "failed to test zrevrange");
|
||||
|
||||
res.clear();
|
||||
_redis.zrevrange(key, 0, 0, std::inserter(res, res.end()));
|
||||
REDIS_ASSERT(res.size() == 1 && res.find("m3") != res.end() && res["m3"] == 3,
|
||||
"failed to test zrevrange with score");
|
||||
|
||||
members.clear();
|
||||
_redis.zrangebyscore(key, UnboundedInterval<double>{}, std::back_inserter(members));
|
||||
REDIS_ASSERT(members.size() == s.size(), "failed to test zrangebyscore");
|
||||
for (const auto &mem : {"m1", "m2", "m3"}) {
|
||||
REDIS_ASSERT(std::find(members.begin(), members.end(), mem) != members.end(),
|
||||
"failed to test zrangebyscore");
|
||||
}
|
||||
|
||||
members.clear();
|
||||
_redis.zrangebyscore(key,
|
||||
BoundedInterval<double>(1, 2, BoundType::RIGHT_OPEN),
|
||||
std::back_inserter(members));
|
||||
REDIS_ASSERT(members.size() == 1 && members[0] == "m1", "failed to test zrangebyscore");
|
||||
|
||||
res.clear();
|
||||
_redis.zrangebyscore(key,
|
||||
LeftBoundedInterval<double>(2, BoundType::OPEN),
|
||||
std::inserter(res, res.end()));
|
||||
REDIS_ASSERT(res.size() == 1 && res.find("m3") != res.end() && res["m3"] == 3,
|
||||
"failed to test zrangebyscore");
|
||||
|
||||
members.clear();
|
||||
_redis.zrevrangebyscore(key,
|
||||
BoundedInterval<double>(1, 3, BoundType::CLOSED),
|
||||
std::back_inserter(members));
|
||||
REDIS_ASSERT(members == std::vector<std::string>({"m3", "m2", "m1"}),
|
||||
"failed to test zrevrangebyscore");
|
||||
|
||||
res.clear();
|
||||
_redis.zrevrangebyscore(key,
|
||||
RightBoundedInterval<double>(1, BoundType::LEFT_OPEN),
|
||||
std::inserter(res, res.end()));
|
||||
REDIS_ASSERT(res.size() == 1 && res.find("m1") != res.end() && res["m1"] == 1,
|
||||
"failed to test zrevrangebyscore");
|
||||
|
||||
REDIS_ASSERT(_redis.zremrangebyrank(key, 0, 0) == 1, "failed to test zremrangebyrank");
|
||||
|
||||
REDIS_ASSERT(_redis.zremrangebyscore(key,
|
||||
BoundedInterval<double>(2, 3, BoundType::LEFT_OPEN)) == 1,
|
||||
"failed to test zremrangebyscore");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ZSetCmdTest<RedisInstance>::_test_lex() {
|
||||
auto key = test_key("lex");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
auto s = {
|
||||
std::make_pair("m1", 0),
|
||||
std::make_pair("m2", 0),
|
||||
std::make_pair("m3", 0),
|
||||
};
|
||||
_redis.zadd(key, s.begin(), s.end());
|
||||
|
||||
REDIS_ASSERT(_redis.zlexcount(key, UnboundedInterval<std::string>{}) == 3,
|
||||
"failed to test zlexcount");
|
||||
|
||||
std::vector<std::string> members;
|
||||
_redis.zrangebylex(key,
|
||||
LeftBoundedInterval<std::string>("m2", BoundType::OPEN),
|
||||
std::back_inserter(members));
|
||||
REDIS_ASSERT(members.size() == 1 && members[0] == "m3",
|
||||
"failed to test zrangebylex");
|
||||
|
||||
members.clear();
|
||||
_redis.zrevrangebylex(key,
|
||||
RightBoundedInterval<std::string>("m1", BoundType::LEFT_OPEN),
|
||||
std::back_inserter(members));
|
||||
REDIS_ASSERT(members.size() == 1 && members[0] == "m1",
|
||||
"failed to test zrevrangebylex");
|
||||
|
||||
REDIS_ASSERT(_redis.zremrangebylex(key,
|
||||
BoundedInterval<std::string>("m1", "m3", BoundType::OPEN)) == 1,
|
||||
"failed to test zremrangebylex");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ZSetCmdTest<RedisInstance>::_test_multi_zset() {
|
||||
auto k1 = test_key("k1");
|
||||
auto k2 = test_key("k2");
|
||||
auto k3 = test_key("k3");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, {k1, k2, k3});
|
||||
|
||||
_redis.zadd(k1, {std::make_pair("a", 1), std::make_pair("b", 2)});
|
||||
_redis.zadd(k2, {std::make_pair("a", 2), std::make_pair("c", 3)});
|
||||
|
||||
REDIS_ASSERT(_redis.zinterstore(k3, {k1, k2}) == 1, "failed to test zinterstore");
|
||||
auto score = _redis.zscore(k3, "a");
|
||||
REDIS_ASSERT(bool(score) && *score == 3, "failed to test zinterstore");
|
||||
|
||||
REDIS_ASSERT(_redis.zinterstore(k3, k1, 2) == 2, "failed to test zinterstore");
|
||||
|
||||
_redis.del(k3);
|
||||
|
||||
REDIS_ASSERT(_redis.zinterstore(k3, {k1, k2}, Aggregation::MAX) == 1,
|
||||
"failed to test zinterstore");
|
||||
score = _redis.zscore(k3, "a");
|
||||
REDIS_ASSERT(bool(score) && *score == 2, "failed to test zinterstore");
|
||||
|
||||
_redis.del(k3);
|
||||
|
||||
REDIS_ASSERT(_redis.zunionstore(k3,
|
||||
{std::make_pair(k1, 1), std::make_pair(k2, 2)},
|
||||
Aggregation::MIN) == 3,
|
||||
"failed to test zunionstore");
|
||||
std::vector<std::pair<std::string, double>> res;
|
||||
_redis.zrange(k3, 0, -1, std::back_inserter(res));
|
||||
for (const auto &ele : res) {
|
||||
if (ele.first == "a") {
|
||||
REDIS_ASSERT(ele.second == 1, "failed to test zunionstore");
|
||||
} else if (ele.first == "b") {
|
||||
REDIS_ASSERT(ele.second == 2, "failed to test zunionstore");
|
||||
} else if (ele.first == "c") {
|
||||
REDIS_ASSERT(ele.second == 6, "failed to test zunionstore");
|
||||
} else {
|
||||
REDIS_ASSERT(false, "failed to test zuionstore");
|
||||
}
|
||||
}
|
||||
|
||||
REDIS_ASSERT(_redis.zunionstore(k3, k1, 2) == 2, "failed to test zunionstore");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ZSetCmdTest<RedisInstance>::_test_zpop() {
|
||||
auto key = test_key("zpop");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, key);
|
||||
|
||||
_redis.zadd(key, {std::make_pair("m1", 1.1),
|
||||
std::make_pair("m2", 2.2),
|
||||
std::make_pair("m3", 3.3),
|
||||
std::make_pair("m4", 4.4),
|
||||
std::make_pair("m5", 5.5),
|
||||
std::make_pair("m6", 6.6)});
|
||||
|
||||
auto item = _redis.zpopmax(key);
|
||||
REDIS_ASSERT(item && item->first == "m6", "failed to test zpopmax");
|
||||
|
||||
item = _redis.zpopmin(key);
|
||||
REDIS_ASSERT(item && item->first == "m1", "failed to test zpopmin");
|
||||
|
||||
std::vector<std::pair<std::string, double>> vec;
|
||||
_redis.zpopmax(key, 2, std::back_inserter(vec));
|
||||
REDIS_ASSERT(vec.size() == 2 && vec[0].first == "m5" && vec[1].first == "m4",
|
||||
"failed to test zpopmax");
|
||||
|
||||
std::unordered_map<std::string, double> m;
|
||||
_redis.zpopmin(key, 2, std::inserter(m, m.end()));
|
||||
REDIS_ASSERT(m.size() == 2 && m.find("m3") != m.end() && m.find("m2") != m.end(),
|
||||
"failed to test zpopmin");
|
||||
}
|
||||
|
||||
template <typename RedisInstance>
|
||||
void ZSetCmdTest<RedisInstance>::_test_bzpop() {
|
||||
auto key1 = test_key("bzpop1");
|
||||
auto key2 = test_key("bzpop2");
|
||||
|
||||
KeyDeleter<RedisInstance> deleter(_redis, {key1, key2});
|
||||
|
||||
_redis.zadd(key1, {std::make_pair("m1", 1.1),
|
||||
std::make_pair("m2", 2.2),
|
||||
std::make_pair("m3", 3.3),
|
||||
std::make_pair("m4", 4.4),
|
||||
std::make_pair("m5", 5.5),
|
||||
std::make_pair("m6", 6.6)});
|
||||
|
||||
_redis.zadd(key2, {std::make_pair("m1", 1.1),
|
||||
std::make_pair("m2", 2.2),
|
||||
std::make_pair("m3", 3.3),
|
||||
std::make_pair("m4", 4.4),
|
||||
std::make_pair("m5", 5.5),
|
||||
std::make_pair("m6", 6.6)});
|
||||
|
||||
auto item = _redis.bzpopmax(key1);
|
||||
REDIS_ASSERT(item && std::get<0>(*item) == key1 && std::get<1>(*item) == "m6",
|
||||
"failed to test bzpopmax");
|
||||
|
||||
item = _redis.bzpopmin(key1, std::chrono::seconds(1));
|
||||
REDIS_ASSERT(item && std::get<0>(*item) == key1 && std::get<1>(*item) == "m1",
|
||||
"failed to test zpopmin");
|
||||
|
||||
item = _redis.bzpopmax({key1, key2}, std::chrono::seconds(1));
|
||||
REDIS_ASSERT(item && std::get<0>(*item) == key1 && std::get<1>(*item) == "m5",
|
||||
"failed to test zpopmax");
|
||||
|
||||
item = _redis.bzpopmin({key2, key1});
|
||||
REDIS_ASSERT(item && std::get<0>(*item) == key2 && std::get<1>(*item) == "m1",
|
||||
"failed to test zpopmin");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // end SEWENEW_REDISPLUSPLUS_TEST_ZSET_CMDS_TEST_HPP
|
Loading…
Add table
Add a link
Reference in a new issue