Passover cleanups.

1. Add ttl with reload test.
2. Removed several LOG(FATAL) messages and replaced them with error propagation.
3. Added scan test for all the options.
This commit is contained in:
Roman Gershman 2022-04-13 11:52:59 +03:00
parent 997d2dcb69
commit 6e5de7ac59
10 changed files with 77 additions and 35 deletions

View file

@ -20,7 +20,7 @@ class RespExpr {
using Vec = std::vector<RespExpr>; using Vec = std::vector<RespExpr>;
Type type; Type type;
bool has_support; // whether pointers in this item are supported by external storage. bool has_support; // whether pointers in this item are supported by the external storage.
std::variant<int64_t, Buffer, Vec*> u; std::variant<int64_t, Buffer, Vec*> u;

View file

@ -33,7 +33,7 @@ namespace rdb {
enum errc { enum errc {
wrong_signature = 1, wrong_signature = 1,
bad_version = 2, bad_version = 2,
module_not_supported = 3, feature_not_supported = 3,
duplicate_key = 4, duplicate_key = 4,
rdb_file_corrupted = 5, rdb_file_corrupted = 5,
bad_checksum = 6, bad_checksum = 6,

View file

@ -153,4 +153,33 @@ TEST_F(GenericFamilyTest, RenameBinary) {
EXPECT_THAT(Run({"get", kKey2}), RespEq("bar")); EXPECT_THAT(Run({"get", kKey2}), RespEq("bar"));
} }
using testing::Each;
using testing::StartsWith;
using testing::AnyOf;
TEST_F(GenericFamilyTest, Scan) {
for (unsigned i = 0; i < 10; ++i)
Run({"set", absl::StrCat("key", i), "bar"});
for (unsigned i = 0; i < 10; ++i)
Run({"set", absl::StrCat("str", i), "bar"});
for (unsigned i = 0; i < 10; ++i)
Run({"sadd", absl::StrCat("set", i), "bar"});
for (unsigned i = 0; i < 10; ++i)
Run({"zadd", absl::StrCat("zset", i), "0", "bar"});
auto resp = Run({"scan", "0", "count", "20", "type", "string"});
EXPECT_EQ(2, resp.size());
auto vec = StrArray(resp[1]);
EXPECT_GT(vec.size(), 10);
EXPECT_THAT(vec, Each(AnyOf(StartsWith("str"), StartsWith("key"))));
resp = Run({"scan", "0", "count", "20", "match", "zset*"});
vec = StrArray(resp[1]);
EXPECT_EQ(10, vec.size());
EXPECT_THAT(vec, Each(StartsWith("zset")));
}
} // namespace dfly } // namespace dfly

View file

@ -380,23 +380,24 @@ void ListFamily::BPopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cn
BPopper popper(dir); BPopper popper(dir);
OpStatus result = popper.Run(transaction, unsigned(timeout * 1000)); OpStatus result = popper.Run(transaction, unsigned(timeout * 1000));
if (result == OpStatus::OK) {
CHECK(popper.found());
VLOG(1) << "BLPop returned ";
auto res = popper.result();
std::string_view str_arr[2] = {res.first, res.second};
return (*cntx)->SendStringArr(str_arr);
}
switch (result) { switch (result) {
case OpStatus::WRONG_TYPE: case OpStatus::WRONG_TYPE:
return (*cntx)->SendError(kWrongTypeErr); return (*cntx)->SendError(kWrongTypeErr);
case OpStatus::OK:
break;
case OpStatus::TIMED_OUT: case OpStatus::TIMED_OUT:
return (*cntx)->SendNullArray(); return (*cntx)->SendNullArray();
default: default:
LOG(FATAL) << "Unexpected error " << result; LOG(ERROR) << "Unexpected error " << result;
} }
return (*cntx)->SendNullArray();
CHECK(popper.found());
VLOG(1) << "BLPop returned ";
auto res = popper.result();
std::string_view str_arr[2] = {res.first, res.second};
return (*cntx)->SendStringArr(str_arr);
} }
void ListFamily::PushGeneric(ListDir dir, bool skip_notexists, CmdArgList args, void ListFamily::PushGeneric(ListDir dir, bool skip_notexists, CmdArgList args,

View file

@ -332,7 +332,8 @@ error_code RdbLoader::Load(io::Source* src) {
} }
if (type == RDB_OPCODE_MODULE_AUX) { if (type == RDB_OPCODE_MODULE_AUX) {
return RdbError(errc::module_not_supported); LOG(ERROR) << "Modules are not supported";
return RdbError(errc::feature_not_supported);
} }
if (!rdbIsObjectType(type)) { if (!rdbIsObjectType(type)) {
@ -416,7 +417,8 @@ auto RdbLoader::LoadLen(bool* is_encoded) -> io::Result<uint64_t> {
res = absl::big_endian::Load64(mem_buf_.InputBuffer().data()); res = absl::big_endian::Load64(mem_buf_.InputBuffer().data());
mem_buf_.ConsumeInput(8); mem_buf_.ConsumeInput(8);
} else { } else {
LOG(FATAL) << "Unknown length encoding " << type << " in rdbLoadLen()"; LOG(ERROR) << "Bad length encoding " << type << " in rdbLoadLen()";
return Unexpected(errc::rdb_file_corrupted);
} }
return res; return res;
@ -501,7 +503,8 @@ error_code RdbLoader::HandleAux() {
} else if (!strcasecmp((char*)auxkey->ptr, "repl-offset")) { } else if (!strcasecmp((char*)auxkey->ptr, "repl-offset")) {
// TODO // TODO
} else if (!strcasecmp((char*)auxkey->ptr, "lua")) { } else if (!strcasecmp((char*)auxkey->ptr, "lua")) {
LOG(FATAL) << "Lua scripts are not supported"; LOG(ERROR) << "Lua scripts are not supported";
return RdbError(errc::feature_not_supported);
} else if (!strcasecmp((char*)auxkey->ptr, "redis-ver")) { } else if (!strcasecmp((char*)auxkey->ptr, "redis-ver")) {
LOG(INFO) << "Loading RDB produced by version " << (char*)auxval->ptr; LOG(INFO) << "Loading RDB produced by version " << (char*)auxval->ptr;
} else if (!strcasecmp((char*)auxkey->ptr, "ctime")) { } else if (!strcasecmp((char*)auxkey->ptr, "ctime")) {
@ -575,7 +578,8 @@ auto RdbLoader::FetchGenericString(int flags) -> io::Result<OpaqueBuf> {
case RDB_ENC_LZF: case RDB_ENC_LZF:
return FetchLzfStringObject(flags); return FetchLzfStringObject(flags);
default: default:
LOG(FATAL) << "Unknown RDB string encoding type " << len; LOG(ERROR) << "Unknown RDB string encoding len " << len;
return Unexpected(errc::rdb_file_corrupted);
} }
} }

View file

@ -216,8 +216,8 @@ error_code RdbSerializer::SaveObject(const PrimeValue& pv) {
return SaveZSetObject(pv.AsRObj()); return SaveZSetObject(pv.AsRObj());
} }
LOG(FATAL) << "Not implemented " << obj_type; LOG(ERROR) << "Not implemented " << obj_type;
return error_code{}; return make_error_code(errc::function_not_supported);
} }
error_code RdbSerializer::SaveListObject(const robj* obj) { error_code RdbSerializer::SaveListObject(const robj* obj) {

View file

@ -83,7 +83,7 @@ TEST_F(RdbTest, LoadSmall6) {
auto ec = loader.Load(&fs); auto ec = loader.Load(&fs);
CHECK(!ec); CHECK(!ec);
auto resp = Run({"scan", "0"}); auto resp = Run({"scan", "0"});
EXPECT_THAT(Array(resp[1]), EXPECT_THAT(StrArray(resp[1]),
UnorderedElementsAre("list1", "hset_zl", "list2", "zset_sl", "intset", "set1", UnorderedElementsAre("list1", "hset_zl", "list2", "zset_sl", "intset", "set1",
"zset_zl", "hset_ht", "intkey", "strkey")); "zset_zl", "hset_ht", "intkey", "strkey"));
resp = Run({"smembers", "intset"}); resp = Run({"smembers", "intset"});
@ -125,4 +125,11 @@ TEST_F(RdbTest, Reload) {
EXPECT_EQ(2, CheckedInt({"ZCARD", "zs2"})); EXPECT_EQ(2, CheckedInt({"ZCARD", "zs2"}));
} }
TEST_F(RdbTest, ReloadTtl) {
Run({"set", "key", "val"});
Run({"expire", "key", "1000"});
Run({"debug", "reload"});
EXPECT_LT(990, CheckedInt({"ttl", "key"}));
}
} // namespace dfly } // namespace dfly

View file

@ -287,13 +287,18 @@ auto BaseFamilyTest::AddFindConn(Protocol proto, std::string_view id) -> TestCon
return it->second.get(); return it->second.get();
} }
RespVec BaseFamilyTest::Array(const RespExpr& expr) { vector<string> BaseFamilyTest::StrArray(const RespExpr& expr) {
CHECK(expr.type == RespExpr::ARRAY || expr.type == RespExpr::NIL_ARRAY); CHECK(expr.type == RespExpr::ARRAY || expr.type == RespExpr::NIL_ARRAY);
if (expr.type == RespExpr::NIL_ARRAY) if (expr.type == RespExpr::NIL_ARRAY)
return RespVec{}; return vector<string>{};
const RespVec* src = get<RespVec*>(expr.u); const RespVec* src = get<RespVec*>(expr.u);
return *src; vector<string> res(src->size());
for (size_t i = 0; i < src->size(); ++i) {
res[i] = ToSV(src->at(i).GetBuf());
}
return res;
} }
} // namespace dfly } // namespace dfly

View file

@ -66,7 +66,7 @@ class BaseFamilyTest : public ::testing::Test {
} }
TestConnWrapper* AddFindConn(Protocol proto, std::string_view id); TestConnWrapper* AddFindConn(Protocol proto, std::string_view id);
static RespVec Array(const RespExpr& expr); static std::vector<std::string> StrArray(const RespExpr& expr);
// ts is ms // ts is ms
void UpdateTime(uint64_t ms); void UpdateTime(uint64_t ms);

View file

@ -193,7 +193,8 @@ void IntervalVisitor::ActionRange(unsigned start, unsigned end) {
Next(zl, &eptr, &sptr); Next(zl, &eptr, &sptr);
} }
} else if (zobj_->encoding == OBJ_ENCODING_SKIPLIST) { } else {
CHECK_EQ(zobj_->encoding, OBJ_ENCODING_SKIPLIST);
zset* zs = (zset*)zobj_->ptr; zset* zs = (zset*)zobj_->ptr;
zskiplist* zsl = zs->zsl; zskiplist* zsl = zs->zsl;
zskiplistNode* ln; zskiplistNode* ln;
@ -216,18 +217,15 @@ void IntervalVisitor::ActionRange(unsigned start, unsigned end) {
result_.emplace_back(string(ele, sdslen(ele)), ln->score); result_.emplace_back(string(ele, sdslen(ele)), ln->score);
ln = params_.reverse ? ln->backward : ln->level[0].forward; ln = params_.reverse ? ln->backward : ln->level[0].forward;
} }
} else {
LOG(FATAL) << "Unknown sorted set encoding" << zobj_->encoding;
} }
} }
void IntervalVisitor::ActionRange(const zrangespec& range) { void IntervalVisitor::ActionRange(const zrangespec& range) {
if (zobj_->encoding == OBJ_ENCODING_LISTPACK) { if (zobj_->encoding == OBJ_ENCODING_LISTPACK) {
ExtractListPack(range); ExtractListPack(range);
} else if (zobj_->encoding == OBJ_ENCODING_SKIPLIST) {
ExtractSkipList(range);
} else { } else {
LOG(FATAL) << "Unknown sorted set encoding " << zobj_->encoding; CHECK_EQ(zobj_->encoding, OBJ_ENCODING_SKIPLIST);
ExtractSkipList(range);
} }
} }
@ -238,11 +236,10 @@ void IntervalVisitor::ActionRem(unsigned start, unsigned end) {
removed_ = (end - start) + 1; removed_ = (end - start) + 1;
zl = lpDeleteRange(zl, 2 * start, 2 * removed_); zl = lpDeleteRange(zl, 2 * start, 2 * removed_);
zobj_->ptr = zl; zobj_->ptr = zl;
} else if (zobj_->encoding == OBJ_ENCODING_SKIPLIST) { } else {
CHECK_EQ(OBJ_ENCODING_SKIPLIST, zobj_->encoding);
zset* zs = (zset*)zobj_->ptr; zset* zs = (zset*)zobj_->ptr;
removed_ = zslDeleteRangeByRank(zs->zsl, start + 1, end + 1, zs->dict); removed_ = zslDeleteRangeByRank(zs->zsl, start + 1, end + 1, zs->dict);
} else {
LOG(FATAL) << "Unknown sorted set encoding" << zobj_->encoding;
} }
} }
@ -253,11 +250,10 @@ void IntervalVisitor::ActionRem(const zrangespec& range) {
zl = zzlDeleteRangeByScore(zl, &range, &deleted); zl = zzlDeleteRangeByScore(zl, &range, &deleted);
zobj_->ptr = zl; zobj_->ptr = zl;
removed_ = deleted; removed_ = deleted;
} else if (zobj_->encoding == OBJ_ENCODING_SKIPLIST) { } else {
CHECK_EQ(OBJ_ENCODING_SKIPLIST, zobj_->encoding);
zset* zs = (zset*)zobj_->ptr; zset* zs = (zset*)zobj_->ptr;
removed_ = zslDeleteRangeByScore(zs->zsl, &range, zs->dict); removed_ = zslDeleteRangeByScore(zs->zsl, &range, zs->dict);
} else {
LOG(FATAL) << "Unknown sorted set encoding" << zobj_->encoding;
} }
} }