mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 02:15:45 +02:00
Simplify testing framework. Run(...) now returns RespExpr instead of vector of RespExpr
This commit is contained in:
parent
f1c5e4d702
commit
ec64f4e9e1
14 changed files with 369 additions and 309 deletions
|
@ -57,6 +57,9 @@ void RespMatcher::DescribeTo(std::ostream* os) const {
|
||||||
case RespExpr::INT64:
|
case RespExpr::INT64:
|
||||||
*os << exp_str_;
|
*os << exp_str_;
|
||||||
break;
|
break;
|
||||||
|
case RespExpr::ARRAY:
|
||||||
|
*os << "array of length " << exp_int_;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
*os << "TBD";
|
*os << "TBD";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -50,10 +50,6 @@ class RespTypeMatcher {
|
||||||
RespExpr::Type type_;
|
RespExpr::Type type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline ::testing::PolymorphicMatcher<RespMatcher> StrArg(std::string_view str) {
|
|
||||||
return ::testing::MakePolymorphicMatcher(RespMatcher(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::testing::PolymorphicMatcher<RespMatcher> ErrArg(std::string_view str) {
|
inline ::testing::PolymorphicMatcher<RespMatcher> ErrArg(std::string_view str) {
|
||||||
return ::testing::MakePolymorphicMatcher(RespMatcher(str, RespExpr::ERROR));
|
return ::testing::MakePolymorphicMatcher(RespMatcher(str, RespExpr::ERROR));
|
||||||
}
|
}
|
||||||
|
@ -70,14 +66,10 @@ inline ::testing::PolymorphicMatcher<RespTypeMatcher> ArgType(RespExpr::Type t)
|
||||||
return ::testing::MakePolymorphicMatcher(RespTypeMatcher(t));
|
return ::testing::MakePolymorphicMatcher(RespTypeMatcher(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(const RespExpr& left, const char* s) {
|
inline bool operator==(const RespExpr& left, std::string_view s) {
|
||||||
return left.type == RespExpr::STRING && ToSV(left.GetBuf()) == s;
|
return left.type == RespExpr::STRING && ToSV(left.GetBuf()) == s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintTo(const RespExpr::Vec& vec, std::ostream* os);
|
void PrintTo(const RespExpr::Vec& vec, std::ostream* os);
|
||||||
|
|
||||||
MATCHER_P(RespEq, val, "") {
|
|
||||||
return ::testing::ExplainMatchResult(::testing::ElementsAre(StrArg(val)), arg, result_listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace facade
|
} // namespace facade
|
||||||
|
|
|
@ -60,7 +60,7 @@ TEST_F(RedisParserTest, Inline) {
|
||||||
|
|
||||||
ASSERT_EQ(RedisParser::OK, Parse(kCmd1));
|
ASSERT_EQ(RedisParser::OK, Parse(kCmd1));
|
||||||
EXPECT_EQ(strlen(kCmd1), consumed_);
|
EXPECT_EQ(strlen(kCmd1), consumed_);
|
||||||
EXPECT_THAT(args_, ElementsAre(StrArg("KEY"), StrArg("VAL")));
|
EXPECT_THAT(args_, ElementsAre("KEY", "VAL"));
|
||||||
|
|
||||||
ASSERT_EQ(RedisParser::INPUT_PENDING, Parse("KEY"));
|
ASSERT_EQ(RedisParser::INPUT_PENDING, Parse("KEY"));
|
||||||
EXPECT_EQ(3, consumed_);
|
EXPECT_EQ(3, consumed_);
|
||||||
|
@ -70,7 +70,7 @@ TEST_F(RedisParserTest, Inline) {
|
||||||
EXPECT_EQ(4, consumed_);
|
EXPECT_EQ(4, consumed_);
|
||||||
ASSERT_EQ(RedisParser::OK, Parse(" \r\n "));
|
ASSERT_EQ(RedisParser::OK, Parse(" \r\n "));
|
||||||
EXPECT_EQ(3, consumed_);
|
EXPECT_EQ(3, consumed_);
|
||||||
EXPECT_THAT(args_, ElementsAre(StrArg("KEY"), StrArg("FOO"), StrArg("BAR")));
|
EXPECT_THAT(args_, ElementsAre("KEY", "FOO", "BAR"));
|
||||||
|
|
||||||
ASSERT_EQ(RedisParser::INPUT_PENDING, Parse(" 1 2"));
|
ASSERT_EQ(RedisParser::INPUT_PENDING, Parse(" 1 2"));
|
||||||
EXPECT_EQ(4, consumed_);
|
EXPECT_EQ(4, consumed_);
|
||||||
|
@ -78,7 +78,7 @@ TEST_F(RedisParserTest, Inline) {
|
||||||
EXPECT_EQ(3, consumed_);
|
EXPECT_EQ(3, consumed_);
|
||||||
ASSERT_EQ(RedisParser::OK, Parse("\r\n"));
|
ASSERT_EQ(RedisParser::OK, Parse("\r\n"));
|
||||||
EXPECT_EQ(2, consumed_);
|
EXPECT_EQ(2, consumed_);
|
||||||
EXPECT_THAT(args_, ElementsAre(StrArg("1"), StrArg("2"), StrArg("45")));
|
EXPECT_THAT(args_, ElementsAre("1", "2", "45"));
|
||||||
|
|
||||||
// Empty queries return RESP_OK.
|
// Empty queries return RESP_OK.
|
||||||
EXPECT_EQ(RedisParser::OK, Parse("\r\n"));
|
EXPECT_EQ(RedisParser::OK, Parse("\r\n"));
|
||||||
|
@ -101,7 +101,7 @@ TEST_F(RedisParserTest, Multi1) {
|
||||||
ASSERT_EQ(RedisParser::OK, Parse("PING\r\n"));
|
ASSERT_EQ(RedisParser::OK, Parse("PING\r\n"));
|
||||||
EXPECT_EQ(6, consumed_);
|
EXPECT_EQ(6, consumed_);
|
||||||
EXPECT_EQ(0, parser_.parselen_hint());
|
EXPECT_EQ(0, parser_.parselen_hint());
|
||||||
EXPECT_THAT(args_, ElementsAre(StrArg("PING")));
|
EXPECT_THAT(args_, ElementsAre("PING"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RedisParserTest, Multi2) {
|
TEST_F(RedisParserTest, Multi2) {
|
||||||
|
@ -140,7 +140,7 @@ TEST_F(RedisParserTest, ClientMode) {
|
||||||
EXPECT_THAT(args_, ElementsAre(IntArg(-1)));
|
EXPECT_THAT(args_, ElementsAre(IntArg(-1)));
|
||||||
|
|
||||||
ASSERT_EQ(RedisParser::OK, Parse("+OK\r\n"));
|
ASSERT_EQ(RedisParser::OK, Parse("+OK\r\n"));
|
||||||
EXPECT_THAT(args_, RespEq("OK"));
|
EXPECT_EQ(args_[0], "OK");
|
||||||
|
|
||||||
ASSERT_EQ(RedisParser::OK, Parse("-ERR foo bar\r\n"));
|
ASSERT_EQ(RedisParser::OK, Parse("-ERR foo bar\r\n"));
|
||||||
EXPECT_THAT(args_, ElementsAre(ErrArg("ERR foo")));
|
EXPECT_THAT(args_, ElementsAre(ErrArg("ERR foo")));
|
||||||
|
@ -152,8 +152,8 @@ TEST_F(RedisParserTest, Hierarchy) {
|
||||||
const char* kThirdArg = "*2\r\n$3\r\n100\r\n$3\r\n200\r\n";
|
const char* kThirdArg = "*2\r\n$3\r\n100\r\n$3\r\n200\r\n";
|
||||||
string resp = absl::StrCat("*3\r\n$3\r\n900\r\n$3\r\n800\r\n", kThirdArg);
|
string resp = absl::StrCat("*3\r\n$3\r\n900\r\n$3\r\n800\r\n", kThirdArg);
|
||||||
ASSERT_EQ(RedisParser::OK, Parse(resp));
|
ASSERT_EQ(RedisParser::OK, Parse(resp));
|
||||||
EXPECT_THAT(args_, ElementsAre(StrArg("900"), StrArg("800"), ArrArg(2)));
|
EXPECT_THAT(args_, ElementsAre("900", "800", ArrArg(2)));
|
||||||
EXPECT_THAT(*get<RespVec*>(args_[2].u), ElementsAre(StrArg("100"), StrArg("200")));
|
EXPECT_THAT(*get<RespVec*>(args_[2].u), ElementsAre("100", "200"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RedisParserTest, InvalidMult1) {
|
TEST_F(RedisParserTest, InvalidMult1) {
|
||||||
|
|
|
@ -35,6 +35,10 @@ class RespExpr {
|
||||||
return std::get<Buffer>(u);
|
return std::get<Buffer>(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Vec& GetVec() const {
|
||||||
|
return *std::get<Vec*>(u);
|
||||||
|
}
|
||||||
|
|
||||||
static const char* TypeName(Type t);
|
static const char* TypeName(Type t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2021, Roman Gershman. All rights reserved.
|
// Copyright 2022, Roman Gershman. All rights reserved.
|
||||||
// See LICENSE for licensing terms.
|
// See LICENSE for licensing terms.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -79,17 +79,18 @@ TEST_F(DflyEngineTest, Sds) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, Multi) {
|
TEST_F(DflyEngineTest, Multi) {
|
||||||
RespVec resp = Run({"multi"});
|
RespExpr resp = Run({"multi"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
|
|
||||||
resp = Run({"get", kKey1});
|
resp = Run({"get", kKey1});
|
||||||
ASSERT_THAT(resp, RespEq("QUEUED"));
|
ASSERT_EQ(resp, "QUEUED");
|
||||||
|
|
||||||
resp = Run({"get", kKey4});
|
resp = Run({"get", kKey4});
|
||||||
ASSERT_THAT(resp, RespEq("QUEUED"));
|
ASSERT_EQ(resp, "QUEUED");
|
||||||
|
|
||||||
resp = Run({"exec"});
|
resp = Run({"exec"});
|
||||||
ASSERT_THAT(resp, ElementsAre(ArgType(RespExpr::NIL), ArgType(RespExpr::NIL)));
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
|
ASSERT_THAT(resp.GetVec(), ElementsAre(ArgType(RespExpr::NIL), ArgType(RespExpr::NIL)));
|
||||||
|
|
||||||
atomic_bool tx_empty = true;
|
atomic_bool tx_empty = true;
|
||||||
|
|
||||||
|
@ -100,7 +101,7 @@ TEST_F(DflyEngineTest, Multi) {
|
||||||
EXPECT_TRUE(tx_empty);
|
EXPECT_TRUE(tx_empty);
|
||||||
|
|
||||||
resp = Run({"get", kKey4});
|
resp = Run({"get", kKey4});
|
||||||
ASSERT_THAT(resp, ElementsAre(ArgType(RespExpr::NIL)));
|
ASSERT_THAT(resp, ArgType(RespExpr::NIL));
|
||||||
|
|
||||||
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
||||||
ASSERT_FALSE(service_->IsLocked(0, kKey4));
|
ASSERT_FALSE(service_->IsLocked(0, kKey4));
|
||||||
|
@ -108,71 +109,76 @@ TEST_F(DflyEngineTest, Multi) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, MultiEmpty) {
|
TEST_F(DflyEngineTest, MultiEmpty) {
|
||||||
RespVec resp = Run({"multi"});
|
RespExpr resp = Run({"multi"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
resp = Run({"exec"});
|
resp = Run({"exec"});
|
||||||
|
|
||||||
ASSERT_THAT(resp[0], ArrLen(0));
|
ASSERT_THAT(resp, ArrLen(0));
|
||||||
ASSERT_FALSE(service_->IsShardSetLocked());
|
ASSERT_FALSE(service_->IsShardSetLocked());
|
||||||
|
|
||||||
Run({"multi"});
|
Run({"multi"});
|
||||||
ASSERT_THAT(Run({"ping", "foo"}), RespEq("QUEUED"));
|
ASSERT_EQ(Run({"ping", "foo"}), "QUEUED");
|
||||||
EXPECT_THAT(Run({"exec"}), ElementsAre("foo"));
|
resp = Run({"exec"});
|
||||||
|
// one cell arrays are promoted to respexpr.
|
||||||
|
EXPECT_EQ(resp, "foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, MultiSeq) {
|
TEST_F(DflyEngineTest, MultiSeq) {
|
||||||
RespVec resp = Run({"multi"});
|
RespExpr resp = Run({"multi"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
|
|
||||||
resp = Run({"set", kKey1, absl::StrCat(1)});
|
resp = Run({"set", kKey1, absl::StrCat(1)});
|
||||||
ASSERT_THAT(resp, RespEq("QUEUED"));
|
ASSERT_EQ(resp, "QUEUED");
|
||||||
resp = Run({"get", kKey1});
|
resp = Run({"get", kKey1});
|
||||||
ASSERT_THAT(resp, RespEq("QUEUED"));
|
ASSERT_EQ(resp, "QUEUED");
|
||||||
resp = Run({"mget", kKey1, kKey4});
|
resp = Run({"mget", kKey1, kKey4});
|
||||||
ASSERT_THAT(resp, RespEq("QUEUED"));
|
ASSERT_EQ(resp, "QUEUED");
|
||||||
resp = Run({"exec"});
|
resp = Run({"exec"});
|
||||||
|
|
||||||
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
||||||
ASSERT_FALSE(service_->IsLocked(0, kKey4));
|
ASSERT_FALSE(service_->IsLocked(0, kKey4));
|
||||||
ASSERT_FALSE(service_->IsShardSetLocked());
|
ASSERT_FALSE(service_->IsShardSetLocked());
|
||||||
|
|
||||||
EXPECT_THAT(resp, ElementsAre(StrArg("OK"), StrArg("1"), ArrLen(2)));
|
ASSERT_THAT(resp, ArrLen(3));
|
||||||
const RespExpr::Vec& arr = *get<RespVec*>(resp[2].u);
|
const auto& arr = resp.GetVec();
|
||||||
ASSERT_THAT(arr, ElementsAre("1", ArgType(RespExpr::NIL)));
|
EXPECT_THAT(arr, ElementsAre("OK", "1", ArrLen(2)));
|
||||||
|
|
||||||
|
ASSERT_THAT(arr[2].GetVec(), ElementsAre("1", ArgType(RespExpr::NIL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, MultiConsistent) {
|
TEST_F(DflyEngineTest, MultiConsistent) {
|
||||||
auto mset_fb = pp_->at(0)->LaunchFiber([&] {
|
auto mset_fb = pp_->at(0)->LaunchFiber([&] {
|
||||||
for (size_t i = 1; i < 10; ++i) {
|
for (size_t i = 1; i < 10; ++i) {
|
||||||
string base = StrCat(i * 900);
|
string base = StrCat(i * 900);
|
||||||
RespVec resp = Run({"mset", kKey1, base, kKey4, base});
|
RespExpr resp = Run({"mset", kKey1, base, kKey4, base});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
auto fb = pp_->at(1)->LaunchFiber([&] {
|
auto fb = pp_->at(1)->LaunchFiber([&] {
|
||||||
RespVec resp = Run({"multi"});
|
RespExpr resp = Run({"multi"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
this_fiber::sleep_for(1ms);
|
this_fiber::sleep_for(1ms);
|
||||||
|
|
||||||
resp = Run({"get", kKey1});
|
resp = Run({"get", kKey1});
|
||||||
ASSERT_THAT(resp, RespEq("QUEUED"));
|
ASSERT_EQ(resp, "QUEUED");
|
||||||
|
|
||||||
resp = Run({"get", kKey4});
|
resp = Run({"get", kKey4});
|
||||||
ASSERT_THAT(resp, RespEq("QUEUED"));
|
ASSERT_EQ(resp, "QUEUED");
|
||||||
|
|
||||||
resp = Run({"mget", kKey4, kKey1});
|
resp = Run({"mget", kKey4, kKey1});
|
||||||
ASSERT_THAT(resp, RespEq("QUEUED"));
|
ASSERT_EQ(resp, "QUEUED");
|
||||||
|
|
||||||
resp = Run({"exec"});
|
resp = Run({"exec"});
|
||||||
|
ASSERT_THAT(resp, ArrLen(3));
|
||||||
EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::STRING), ArgType(RespExpr::STRING),
|
const RespVec& resp_arr = resp.GetVec();
|
||||||
ArgType(RespExpr::ARRAY)));
|
ASSERT_THAT(resp_arr, ElementsAre(ArgType(RespExpr::STRING), ArgType(RespExpr::STRING),
|
||||||
ASSERT_EQ(resp[0].GetBuf(), resp[1].GetBuf());
|
ArgType(RespExpr::ARRAY)));
|
||||||
const RespVec& arr = *get<RespVec*>(resp[2].u);
|
ASSERT_EQ(resp_arr[0].GetBuf(), resp_arr[1].GetBuf());
|
||||||
EXPECT_THAT(arr, ElementsAre(ArgType(RespExpr::STRING), ArgType(RespExpr::STRING)));
|
const RespVec& sub_arr = resp_arr[2].GetVec();
|
||||||
EXPECT_EQ(arr[0].GetBuf(), arr[1].GetBuf());
|
EXPECT_THAT(sub_arr, ElementsAre(ArgType(RespExpr::STRING), ArgType(RespExpr::STRING)));
|
||||||
EXPECT_EQ(arr[0].GetBuf(), resp[0].GetBuf());
|
EXPECT_EQ(sub_arr[0].GetBuf(), sub_arr[1].GetBuf());
|
||||||
|
EXPECT_EQ(sub_arr[0].GetBuf(), resp_arr[0].GetBuf());
|
||||||
});
|
});
|
||||||
|
|
||||||
mset_fb.join();
|
mset_fb.join();
|
||||||
|
@ -184,20 +190,21 @@ TEST_F(DflyEngineTest, MultiConsistent) {
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, MultiWeirdCommands) {
|
TEST_F(DflyEngineTest, MultiWeirdCommands) {
|
||||||
Run({"multi"});
|
Run({"multi"});
|
||||||
ASSERT_THAT(Run({"eval", "return 42", "0"}), RespEq("QUEUED"));
|
ASSERT_EQ(Run({"eval", "return 42", "0"}), "QUEUED");
|
||||||
EXPECT_THAT(Run({"exec"}), ElementsAre(IntArg(42)));
|
EXPECT_THAT(Run({"exec"}), IntArg(42));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, MultiRename) {
|
TEST_F(DflyEngineTest, MultiRename) {
|
||||||
RespVec resp = Run({"multi"});
|
RespExpr resp = Run({"multi"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
Run({"set", kKey1, "1"});
|
Run({"set", kKey1, "1"});
|
||||||
|
|
||||||
resp = Run({"rename", kKey1, kKey4});
|
resp = Run({"rename", kKey1, kKey4});
|
||||||
ASSERT_THAT(resp, RespEq("QUEUED"));
|
ASSERT_EQ(resp, "QUEUED");
|
||||||
resp = Run({"exec"});
|
resp = Run({"exec"});
|
||||||
|
|
||||||
EXPECT_THAT(resp, ElementsAre(StrArg("OK"), StrArg("OK")));
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(resp.GetVec(), ElementsAre("OK", "OK"));
|
||||||
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
||||||
ASSERT_FALSE(service_->IsLocked(0, kKey4));
|
ASSERT_FALSE(service_->IsLocked(0, kKey4));
|
||||||
ASSERT_FALSE(service_->IsShardSetLocked());
|
ASSERT_FALSE(service_->IsShardSetLocked());
|
||||||
|
@ -209,11 +216,11 @@ TEST_F(DflyEngineTest, MultiHop) {
|
||||||
auto p1_fb = pp_->at(1)->LaunchFiber([&] {
|
auto p1_fb = pp_->at(1)->LaunchFiber([&] {
|
||||||
for (int i = 0; i < 100; ++i) {
|
for (int i = 0; i < 100; ++i) {
|
||||||
auto resp = Run({"rename", kKey1, kKey2});
|
auto resp = Run({"rename", kKey1, kKey2});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
EXPECT_EQ(2, GetDebugInfo("IO1").shards_count);
|
EXPECT_EQ(2, GetDebugInfo("IO1").shards_count);
|
||||||
|
|
||||||
resp = Run({"rename", kKey2, kKey1});
|
resp = Run({"rename", kKey2, kKey1});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -233,7 +240,7 @@ TEST_F(DflyEngineTest, MultiHop) {
|
||||||
TEST_F(DflyEngineTest, FlushDb) {
|
TEST_F(DflyEngineTest, FlushDb) {
|
||||||
Run({"mset", kKey1, "1", kKey4, "2"});
|
Run({"mset", kKey1, "1", kKey4, "2"});
|
||||||
auto resp = Run({"flushdb"});
|
auto resp = Run({"flushdb"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
|
|
||||||
auto fb0 = pp_->at(0)->LaunchFiber([&] {
|
auto fb0 = pp_->at(0)->LaunchFiber([&] {
|
||||||
for (unsigned i = 0; i < 100; ++i) {
|
for (unsigned i = 0; i < 100; ++i) {
|
||||||
|
@ -244,8 +251,7 @@ TEST_F(DflyEngineTest, FlushDb) {
|
||||||
pp_->at(1)->Await([&] {
|
pp_->at(1)->Await([&] {
|
||||||
for (unsigned i = 0; i < 100; ++i) {
|
for (unsigned i = 0; i < 100; ++i) {
|
||||||
Run({"mset", kKey1, "1", kKey4, "2"});
|
Run({"mset", kKey1, "1", kKey4, "2"});
|
||||||
auto resp = Run({"exists", kKey1, kKey4});
|
int64_t ival = CheckedInt({"exists", kKey1, kKey4});
|
||||||
int64_t ival = get<int64_t>(resp[0].u);
|
|
||||||
ASSERT_TRUE(ival == 0 || ival == 2) << i << " " << ival;
|
ASSERT_TRUE(ival == 0 || ival == 2) << i << " " << ival;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -259,21 +265,21 @@ TEST_F(DflyEngineTest, FlushDb) {
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, Eval) {
|
TEST_F(DflyEngineTest, Eval) {
|
||||||
auto resp = Run({"incrby", "foo", "42"});
|
auto resp = Run({"incrby", "foo", "42"});
|
||||||
EXPECT_THAT(resp[0], IntArg(42));
|
EXPECT_THAT(resp, IntArg(42));
|
||||||
|
|
||||||
resp = Run({"eval", "return redis.call('get', 'foo')", "0"});
|
resp = Run({"eval", "return redis.call('get', 'foo')", "0"});
|
||||||
EXPECT_THAT(resp[0], ErrArg("undeclared"));
|
EXPECT_THAT(resp, ErrArg("undeclared"));
|
||||||
|
|
||||||
resp = Run({"eval", "return redis.call('get', 'foo')", "1", "bar"});
|
resp = Run({"eval", "return redis.call('get', 'foo')", "1", "bar"});
|
||||||
EXPECT_THAT(resp[0], ErrArg("undeclared"));
|
EXPECT_THAT(resp, ErrArg("undeclared"));
|
||||||
|
|
||||||
ASSERT_FALSE(service_->IsLocked(0, "foo"));
|
ASSERT_FALSE(service_->IsLocked(0, "foo"));
|
||||||
|
|
||||||
resp = Run({"eval", "return redis.call('get', 'foo')", "1", "foo"});
|
resp = Run({"eval", "return redis.call('get', 'foo')", "1", "foo"});
|
||||||
EXPECT_THAT(resp[0], StrArg("42"));
|
EXPECT_THAT(resp, "42");
|
||||||
|
|
||||||
resp = Run({"eval", "return redis.call('get', KEYS[1])", "1", "foo"});
|
resp = Run({"eval", "return redis.call('get', KEYS[1])", "1", "foo"});
|
||||||
EXPECT_THAT(resp[0], StrArg("42"));
|
EXPECT_THAT(resp, "42");
|
||||||
|
|
||||||
ASSERT_FALSE(service_->IsLocked(0, "foo"));
|
ASSERT_FALSE(service_->IsLocked(0, "foo"));
|
||||||
ASSERT_FALSE(service_->IsShardSetLocked());
|
ASSERT_FALSE(service_->IsShardSetLocked());
|
||||||
|
@ -281,30 +287,31 @@ TEST_F(DflyEngineTest, Eval) {
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, EvalResp) {
|
TEST_F(DflyEngineTest, EvalResp) {
|
||||||
auto resp = Run({"eval", "return 43", "0"});
|
auto resp = Run({"eval", "return 43", "0"});
|
||||||
EXPECT_THAT(resp[0], IntArg(43));
|
EXPECT_THAT(resp, IntArg(43));
|
||||||
|
|
||||||
resp = Run({"eval", "return {5, 'foo', 17.5}", "0"});
|
resp = Run({"eval", "return {5, 'foo', 17.5}", "0"});
|
||||||
EXPECT_THAT(resp, ElementsAre(IntArg(5), "foo", "17.5"));
|
ASSERT_THAT(resp, ArrLen(3));
|
||||||
|
EXPECT_THAT(resp.GetVec(), ElementsAre(IntArg(5), "foo", "17.5"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, EvalSha) {
|
TEST_F(DflyEngineTest, EvalSha) {
|
||||||
auto resp = Run({"script", "load", "return 5"});
|
auto resp = Run({"script", "load", "return 5"});
|
||||||
EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::STRING)));
|
EXPECT_THAT(resp, ArgType(RespExpr::STRING));
|
||||||
|
|
||||||
string sha{ToSV(resp[0].GetBuf())};
|
string sha{ToSV(resp.GetBuf())};
|
||||||
|
|
||||||
resp = Run({"evalsha", sha, "0"});
|
resp = Run({"evalsha", sha, "0"});
|
||||||
EXPECT_THAT(resp[0], IntArg(5));
|
EXPECT_THAT(resp, IntArg(5));
|
||||||
|
|
||||||
resp = Run({"script", "load", " return 5 "});
|
resp = Run({"script", "load", " return 5 "});
|
||||||
EXPECT_THAT(resp, ElementsAre(StrArg(sha)));
|
EXPECT_EQ(resp, sha);
|
||||||
|
|
||||||
absl::AsciiStrToUpper(&sha);
|
absl::AsciiStrToUpper(&sha);
|
||||||
resp = Run({"evalsha", sha, "0"});
|
resp = Run({"evalsha", sha, "0"});
|
||||||
EXPECT_THAT(resp[0], IntArg(5));
|
EXPECT_THAT(resp, IntArg(5));
|
||||||
|
|
||||||
resp = Run({"evalsha", "foobar", "0"});
|
resp = Run({"evalsha", "foobar", "0"});
|
||||||
EXPECT_THAT(resp[0], ErrArg("No matching"));
|
EXPECT_THAT(resp, ErrArg("No matching"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, Memcache) {
|
TEST_F(DflyEngineTest, Memcache) {
|
||||||
|
@ -345,7 +352,7 @@ TEST_F(DflyEngineTest, LimitMemory) {
|
||||||
string blob(128, 'a');
|
string blob(128, 'a');
|
||||||
for (size_t i = 0; i < 10000; ++i) {
|
for (size_t i = 0; i < 10000; ++i) {
|
||||||
auto resp = Run({"set", absl::StrCat(blob, i), blob});
|
auto resp = Run({"set", absl::StrCat(blob, i), blob});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,26 +29,26 @@ TEST_F(GenericFamilyTest, Expire) {
|
||||||
Run({"set", "key", "val"});
|
Run({"set", "key", "val"});
|
||||||
auto resp = Run({"expire", "key", "1"});
|
auto resp = Run({"expire", "key", "1"});
|
||||||
|
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
UpdateTime(expire_now_ + 1000);
|
UpdateTime(expire_now_ + 1000);
|
||||||
resp = Run({"get", "key"});
|
resp = Run({"get", "key"});
|
||||||
EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::NIL)));
|
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||||
|
|
||||||
Run({"set", "key", "val"});
|
Run({"set", "key", "val"});
|
||||||
resp = Run({"pexpireat", "key", absl::StrCat(expire_now_ + 2000)});
|
resp = Run({"pexpireat", "key", absl::StrCat(expire_now_ + 2000)});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
// override
|
// override
|
||||||
resp = Run({"pexpireat", "key", absl::StrCat(expire_now_ + 3000)});
|
resp = Run({"pexpireat", "key", absl::StrCat(expire_now_ + 3000)});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
UpdateTime(expire_now_ + 2999);
|
UpdateTime(expire_now_ + 2999);
|
||||||
resp = Run({"get", "key"});
|
resp = Run({"get", "key"});
|
||||||
EXPECT_THAT(resp[0], "val");
|
EXPECT_THAT(resp, "val");
|
||||||
|
|
||||||
UpdateTime(expire_now_ + 3000);
|
UpdateTime(expire_now_ + 3000);
|
||||||
resp = Run({"get", "key"});
|
resp = Run({"get", "key"});
|
||||||
EXPECT_THAT(resp[0], ArgType(RespExpr::NIL));
|
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(GenericFamilyTest, Del) {
|
TEST_F(GenericFamilyTest, Del) {
|
||||||
|
@ -88,28 +88,28 @@ TEST_F(GenericFamilyTest, TTL) {
|
||||||
TEST_F(GenericFamilyTest, Exists) {
|
TEST_F(GenericFamilyTest, Exists) {
|
||||||
Run({"mset", "x", "0", "y", "1"});
|
Run({"mset", "x", "0", "y", "1"});
|
||||||
auto resp = Run({"exists", "x", "y", "x"});
|
auto resp = Run({"exists", "x", "y", "x"});
|
||||||
EXPECT_THAT(resp[0], IntArg(3));
|
EXPECT_THAT(resp, IntArg(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(GenericFamilyTest, Rename) {
|
TEST_F(GenericFamilyTest, Rename) {
|
||||||
RespVec resp;
|
RespExpr resp;
|
||||||
string b_val(32, 'b');
|
string b_val(32, 'b');
|
||||||
string x_val(32, 'x');
|
string x_val(32, 'x');
|
||||||
|
|
||||||
resp = Run({"mset", "x", x_val, "b", b_val});
|
resp = Run({"mset", "x", x_val, "b", b_val});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
ASSERT_EQ(2, last_cmd_dbg_info_.shards_count);
|
ASSERT_EQ(2, last_cmd_dbg_info_.shards_count);
|
||||||
|
|
||||||
resp = Run({"rename", "z", "b"});
|
resp = Run({"rename", "z", "b"});
|
||||||
ASSERT_THAT(resp[0], ErrArg("no such key"));
|
ASSERT_THAT(resp, ErrArg("no such key"));
|
||||||
|
|
||||||
resp = Run({"rename", "x", "b"});
|
resp = Run({"rename", "x", "b"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
|
|
||||||
int64_t val = CheckedInt({"get", "x"});
|
int64_t val = CheckedInt({"get", "x"});
|
||||||
ASSERT_EQ(kint64min, val); // does not exist
|
ASSERT_EQ(kint64min, val); // does not exist
|
||||||
|
|
||||||
ASSERT_THAT(Run({"get", "b"}), RespEq(x_val)); // swapped.
|
ASSERT_EQ(Run({"get", "b"}), x_val); // swapped.
|
||||||
|
|
||||||
EXPECT_EQ(CheckedInt({"exists", "x", "b"}), 1);
|
EXPECT_EQ(CheckedInt({"exists", "x", "b"}), 1);
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ TEST_F(GenericFamilyTest, Rename) {
|
||||||
for (size_t i = 0; i < 200; ++i) {
|
for (size_t i = 0; i < 200; ++i) {
|
||||||
int j = i % 2;
|
int j = i % 2;
|
||||||
auto resp = Run({"rename", keys[j], keys[1 - j]});
|
auto resp = Run({"rename", keys[j], keys[1 - j]});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ TEST_F(GenericFamilyTest, Rename) {
|
||||||
TEST_F(GenericFamilyTest, RenameNonString) {
|
TEST_F(GenericFamilyTest, RenameNonString) {
|
||||||
EXPECT_EQ(1, CheckedInt({"lpush", "x", "elem"}));
|
EXPECT_EQ(1, CheckedInt({"lpush", "x", "elem"}));
|
||||||
auto resp = Run({"rename", "x", "b"});
|
auto resp = Run({"rename", "x", "b"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
ASSERT_EQ(2, last_cmd_dbg_info_.shards_count);
|
ASSERT_EQ(2, last_cmd_dbg_info_.shards_count);
|
||||||
|
|
||||||
EXPECT_EQ(0, CheckedInt({"del", "x"}));
|
EXPECT_EQ(0, CheckedInt({"del", "x"}));
|
||||||
|
@ -149,13 +149,13 @@ TEST_F(GenericFamilyTest, RenameBinary) {
|
||||||
|
|
||||||
Run({"set", kKey1, "bar"});
|
Run({"set", kKey1, "bar"});
|
||||||
Run({"rename", kKey1, kKey2});
|
Run({"rename", kKey1, kKey2});
|
||||||
EXPECT_THAT(Run({"get", kKey1}), ElementsAre(ArgType(RespExpr::NIL)));
|
EXPECT_THAT(Run({"get", kKey1}), ArgType(RespExpr::NIL));
|
||||||
EXPECT_THAT(Run({"get", kKey2}), RespEq("bar"));
|
EXPECT_EQ(Run({"get", kKey2}), "bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using testing::AnyOf;
|
||||||
using testing::Each;
|
using testing::Each;
|
||||||
using testing::StartsWith;
|
using testing::StartsWith;
|
||||||
using testing::AnyOf;
|
|
||||||
|
|
||||||
TEST_F(GenericFamilyTest, Scan) {
|
TEST_F(GenericFamilyTest, Scan) {
|
||||||
for (unsigned i = 0; i < 10; ++i)
|
for (unsigned i = 0; i < 10; ++i)
|
||||||
|
@ -171,13 +171,13 @@ TEST_F(GenericFamilyTest, Scan) {
|
||||||
Run({"zadd", absl::StrCat("zset", i), "0", "bar"});
|
Run({"zadd", absl::StrCat("zset", i), "0", "bar"});
|
||||||
|
|
||||||
auto resp = Run({"scan", "0", "count", "20", "type", "string"});
|
auto resp = Run({"scan", "0", "count", "20", "type", "string"});
|
||||||
EXPECT_EQ(2, resp.size());
|
EXPECT_THAT(resp, ArrLen(2));
|
||||||
auto vec = StrArray(resp[1]);
|
auto vec = StrArray(resp.GetVec()[1]);
|
||||||
EXPECT_GT(vec.size(), 10);
|
EXPECT_GT(vec.size(), 10);
|
||||||
EXPECT_THAT(vec, Each(AnyOf(StartsWith("str"), StartsWith("key"))));
|
EXPECT_THAT(vec, Each(AnyOf(StartsWith("str"), StartsWith("key"))));
|
||||||
|
|
||||||
resp = Run({"scan", "0", "count", "20", "match", "zset*"});
|
resp = Run({"scan", "0", "count", "20", "match", "zset*"});
|
||||||
vec = StrArray(resp[1]);
|
vec = StrArray(resp.GetVec()[1]);
|
||||||
EXPECT_EQ(10, vec.size());
|
EXPECT_EQ(10, vec.size());
|
||||||
EXPECT_THAT(vec, Each(StartsWith("zset")));
|
EXPECT_THAT(vec, Each(StartsWith("zset")));
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,9 @@ TEST_F(HSetFamilyTest, Hash) {
|
||||||
|
|
||||||
TEST_F(HSetFamilyTest, Basic) {
|
TEST_F(HSetFamilyTest, Basic) {
|
||||||
auto resp = Run({"hset", "x", "a"});
|
auto resp = Run({"hset", "x", "a"});
|
||||||
EXPECT_THAT(resp[0], ErrArg("wrong number"));
|
EXPECT_THAT(resp, ErrArg("wrong number"));
|
||||||
|
|
||||||
EXPECT_THAT(Run({"HSET", "hs", "key1", "val1", "key2"}), ElementsAre(ErrArg("wrong number")));
|
EXPECT_THAT(Run({"HSET", "hs", "key1", "val1", "key2"}), ErrArg("wrong number"));
|
||||||
|
|
||||||
EXPECT_EQ(1, CheckedInt({"hset", "x", "a", "b"}));
|
EXPECT_EQ(1, CheckedInt({"hset", "x", "a", "b"}));
|
||||||
EXPECT_EQ(1, CheckedInt({"hlen", "x"}));
|
EXPECT_EQ(1, CheckedInt({"hlen", "x"}));
|
||||||
|
@ -57,7 +57,7 @@ TEST_F(HSetFamilyTest, Basic) {
|
||||||
EXPECT_EQ(2, CheckedInt({"hset", "y", "a", "c", "d", "e"}));
|
EXPECT_EQ(2, CheckedInt({"hset", "y", "a", "c", "d", "e"}));
|
||||||
EXPECT_EQ(2, CheckedInt({"hdel", "y", "a", "d"}));
|
EXPECT_EQ(2, CheckedInt({"hdel", "y", "a", "d"}));
|
||||||
|
|
||||||
EXPECT_THAT(Run({"hdel", "nokey", "a"}), ElementsAre(IntArg(0)));
|
EXPECT_THAT(Run({"hdel", "nokey", "a"}), IntArg(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HSetFamilyTest, HSet) {
|
TEST_F(HSetFamilyTest, HSet) {
|
||||||
|
@ -72,37 +72,42 @@ TEST_F(HSetFamilyTest, HSet) {
|
||||||
|
|
||||||
TEST_F(HSetFamilyTest, Get) {
|
TEST_F(HSetFamilyTest, Get) {
|
||||||
auto resp = Run({"hset", "x", "a", "1", "b", "2", "c", "3"});
|
auto resp = Run({"hset", "x", "a", "1", "b", "2", "c", "3"});
|
||||||
EXPECT_THAT(resp[0], IntArg(3));
|
EXPECT_THAT(resp, IntArg(3));
|
||||||
|
|
||||||
resp = Run({"hmget", "unkwn", "a", "c"});
|
resp = Run({"hmget", "unkwn", "a", "c"});
|
||||||
EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::NIL), ArgType(RespExpr::NIL)));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), ElementsAre(ArgType(RespExpr::NIL), ArgType(RespExpr::NIL)));
|
||||||
|
|
||||||
resp = Run({"hkeys", "x"});
|
resp = Run({"hkeys", "x"});
|
||||||
EXPECT_THAT(resp, UnorderedElementsAre("a", "b", "c"));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), UnorderedElementsAre("a", "b", "c"));
|
||||||
|
|
||||||
resp = Run({"hvals", "x"});
|
resp = Run({"hvals", "x"});
|
||||||
EXPECT_THAT(resp, UnorderedElementsAre("1", "2", "3"));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), UnorderedElementsAre("1", "2", "3"));
|
||||||
|
|
||||||
resp = Run({"hmget", "x", "a", "c", "d"});
|
resp = Run({"hmget", "x", "a", "c", "d"});
|
||||||
EXPECT_THAT(resp, ElementsAre("1", "3", ArgType(RespExpr::NIL)));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), ElementsAre("1", "3", ArgType(RespExpr::NIL)));
|
||||||
|
|
||||||
resp = Run({"hgetall", "x"});
|
resp = Run({"hgetall", "x"});
|
||||||
EXPECT_THAT(resp, ElementsAre("a", "1", "b", "2", "c", "3"));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), ElementsAre("a", "1", "b", "2", "c", "3"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HSetFamilyTest, HSetNx) {
|
TEST_F(HSetFamilyTest, HSetNx) {
|
||||||
EXPECT_EQ(1, CheckedInt({"hsetnx", "key", "field", "val"}));
|
EXPECT_EQ(1, CheckedInt({"hsetnx", "key", "field", "val"}));
|
||||||
EXPECT_THAT(Run({"hget", "key", "field"}), RespEq("val"));
|
EXPECT_EQ(Run({"hget", "key", "field"}), "val");
|
||||||
|
|
||||||
EXPECT_EQ(0, CheckedInt({"hsetnx", "key", "field", "val2"}));
|
EXPECT_EQ(0, CheckedInt({"hsetnx", "key", "field", "val2"}));
|
||||||
EXPECT_THAT(Run({"hget", "key", "field"}), RespEq("val"));
|
EXPECT_EQ(Run({"hget", "key", "field"}), "val");
|
||||||
|
|
||||||
EXPECT_EQ(1, CheckedInt({"hsetnx", "key", "field2", "val2"}));
|
EXPECT_EQ(1, CheckedInt({"hsetnx", "key", "field2", "val2"}));
|
||||||
EXPECT_THAT(Run({"hget", "key", "field2"}), RespEq("val2"));
|
EXPECT_EQ(Run({"hget", "key", "field2"}), "val2");
|
||||||
|
|
||||||
// check dict path
|
// check dict path
|
||||||
EXPECT_EQ(0, CheckedInt({"hsetnx", "key", "field2", string(512, 'a')}));
|
EXPECT_EQ(0, CheckedInt({"hsetnx", "key", "field2", string(512, 'a')}));
|
||||||
EXPECT_THAT(Run({"hget", "key", "field2"}), RespEq("val2"));
|
EXPECT_EQ(Run({"hget", "key", "field2"}), "val2");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HSetFamilyTest, HIncr) {
|
TEST_F(HSetFamilyTest, HIncr) {
|
||||||
|
@ -110,7 +115,7 @@ TEST_F(HSetFamilyTest, HIncr) {
|
||||||
|
|
||||||
Run({"hset", "key", "a", " 1"});
|
Run({"hset", "key", "a", " 1"});
|
||||||
auto resp = Run({"hincrby", "key", "a", "10"});
|
auto resp = Run({"hincrby", "key", "a", "10"});
|
||||||
EXPECT_THAT(resp[0], ErrArg("hash value is not an integer"));
|
EXPECT_THAT(resp, ErrArg("hash value is not an integer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
|
@ -38,46 +38,48 @@ const char kKey3[] = "c";
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, Basic) {
|
TEST_F(ListFamilyTest, Basic) {
|
||||||
auto resp = Run({"lpush", kKey1, "1"});
|
auto resp = Run({"lpush", kKey1, "1"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
resp = Run({"lpush", kKey2, "2"});
|
resp = Run({"lpush", kKey2, "2"});
|
||||||
ASSERT_THAT(resp[0], IntArg(1));
|
ASSERT_THAT(resp, IntArg(1));
|
||||||
resp = Run({"llen", kKey1});
|
resp = Run({"llen", kKey1});
|
||||||
ASSERT_THAT(resp[0], IntArg(1));
|
ASSERT_THAT(resp, IntArg(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, Expire) {
|
TEST_F(ListFamilyTest, Expire) {
|
||||||
auto resp = Run({"lpush", kKey1, "1"});
|
auto resp = Run({"lpush", kKey1, "1"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
resp = Run({"expire", kKey1, "1"});
|
resp = Run({"expire", kKey1, "1"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
UpdateTime(expire_now_ + 1000);
|
UpdateTime(expire_now_ + 1000);
|
||||||
resp = Run({"lpush", kKey1, "1"});
|
resp = Run({"lpush", kKey1, "1"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, BLPopUnblocking) {
|
TEST_F(ListFamilyTest, BLPopUnblocking) {
|
||||||
auto resp = Run({"lpush", kKey1, "1"});
|
auto resp = Run({"lpush", kKey1, "1"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
resp = Run({"lpush", kKey2, "2"});
|
resp = Run({"lpush", kKey2, "2"});
|
||||||
ASSERT_THAT(resp, ElementsAre(IntArg(1)));
|
ASSERT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
resp = Run({"blpop", kKey1, kKey2}); // missing "0" delimiter.
|
resp = Run({"blpop", kKey1, kKey2}); // missing "0" delimiter.
|
||||||
ASSERT_THAT(resp[0], ErrArg("timeout is not a float"));
|
ASSERT_THAT(resp, ErrArg("timeout is not a float"));
|
||||||
|
|
||||||
resp = Run({"blpop", kKey1, kKey2, "0"});
|
resp = Run({"blpop", kKey1, kKey2, "0"});
|
||||||
ASSERT_EQ(2, GetDebugInfo().shards_count);
|
ASSERT_EQ(2, GetDebugInfo().shards_count);
|
||||||
EXPECT_THAT(resp, ElementsAre(kKey1, "1"));
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(resp.GetVec(), ElementsAre(kKey1, "1"));
|
||||||
|
|
||||||
resp = Run({"blpop", kKey1, kKey2, "0"});
|
resp = Run({"blpop", kKey1, kKey2, "0"});
|
||||||
EXPECT_THAT(resp, ElementsAre(kKey2, "2"));
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(resp.GetVec(), ElementsAre(kKey2, "2"));
|
||||||
|
|
||||||
Run({"set", "z", "1"});
|
Run({"set", "z", "1"});
|
||||||
|
|
||||||
resp = Run({"blpop", "z", "0"});
|
resp = Run({"blpop", "z", "0"});
|
||||||
ASSERT_THAT(resp[0], ErrArg("WRONGTYPE "));
|
ASSERT_THAT(resp, ErrArg("WRONGTYPE "));
|
||||||
|
|
||||||
ASSERT_FALSE(IsLocked(0, "x"));
|
ASSERT_FALSE(IsLocked(0, "x"));
|
||||||
ASSERT_FALSE(IsLocked(0, "y"));
|
ASSERT_FALSE(IsLocked(0, "y"));
|
||||||
|
@ -85,7 +87,7 @@ TEST_F(ListFamilyTest, BLPopUnblocking) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, BLPopBlocking) {
|
TEST_F(ListFamilyTest, BLPopBlocking) {
|
||||||
RespVec resp0, resp1;
|
RespExpr resp0, resp1;
|
||||||
|
|
||||||
// Run the fiber at creation.
|
// Run the fiber at creation.
|
||||||
auto fb0 = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
auto fb0 = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
||||||
|
@ -110,16 +112,16 @@ TEST_F(ListFamilyTest, BLPopBlocking) {
|
||||||
int64_t epoch0 = GetDebugInfo("IO0").clock;
|
int64_t epoch0 = GetDebugInfo("IO0").clock;
|
||||||
int64_t epoch1 = GetDebugInfo("IO1").clock;
|
int64_t epoch1 = GetDebugInfo("IO1").clock;
|
||||||
ASSERT_LT(epoch0, epoch1);
|
ASSERT_LT(epoch0, epoch1);
|
||||||
|
ASSERT_THAT(resp0, ArrLen(2));
|
||||||
EXPECT_THAT(resp0, ElementsAre("x", "1"));
|
EXPECT_THAT(resp0.GetVec(), ElementsAre("x", "1"));
|
||||||
ASSERT_FALSE(IsLocked(0, "x"));
|
ASSERT_FALSE(IsLocked(0, "x"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, BLPopMultiple) {
|
TEST_F(ListFamilyTest, BLPopMultiple) {
|
||||||
RespVec resp0, resp1;
|
RespExpr resp0, resp1;
|
||||||
|
|
||||||
resp0 = Run({"blpop", kKey1, kKey2, "0.01"}); // timeout
|
resp0 = Run({"blpop", kKey1, kKey2, "0.01"}); // timeout
|
||||||
EXPECT_THAT(resp0, ElementsAre(ArgType(RespExpr::NIL_ARRAY)));
|
EXPECT_THAT(resp0, ArgType(RespExpr::NIL_ARRAY));
|
||||||
ASSERT_EQ(2, GetDebugInfo().shards_count);
|
ASSERT_EQ(2, GetDebugInfo().shards_count);
|
||||||
|
|
||||||
ASSERT_FALSE(IsLocked(0, kKey1));
|
ASSERT_FALSE(IsLocked(0, kKey1));
|
||||||
|
@ -131,65 +133,74 @@ TEST_F(ListFamilyTest, BLPopMultiple) {
|
||||||
|
|
||||||
pp_->at(1)->Await([&] { Run({"lpush", kKey1, "1", "2", "3"}); });
|
pp_->at(1)->Await([&] { Run({"lpush", kKey1, "1", "2", "3"}); });
|
||||||
fb1.join();
|
fb1.join();
|
||||||
EXPECT_THAT(resp0, ElementsAre(StrArg(kKey1), StrArg("3")));
|
|
||||||
|
ASSERT_THAT(resp0, ArrLen(2));
|
||||||
|
EXPECT_THAT(resp0.GetVec(), ElementsAre(kKey1, "3"));
|
||||||
ASSERT_FALSE(IsLocked(0, kKey1));
|
ASSERT_FALSE(IsLocked(0, kKey1));
|
||||||
ASSERT_FALSE(IsLocked(0, kKey2));
|
ASSERT_FALSE(IsLocked(0, kKey2));
|
||||||
ess_->RunBriefInParallel([](EngineShard* es) { ASSERT_FALSE(es->HasAwakedTransaction()); });
|
ess_->RunBriefInParallel([](EngineShard* es) { ASSERT_FALSE(es->HasAwakedTransaction()); });
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, BLPopTimeout) {
|
TEST_F(ListFamilyTest, BLPopTimeout) {
|
||||||
RespVec resp = Run({"blpop", kKey1, kKey2, kKey3, "0.01"});
|
RespExpr resp = Run({"blpop", kKey1, kKey2, kKey3, "0.01"});
|
||||||
EXPECT_THAT(resp[0], ArgType(RespExpr::NIL_ARRAY));
|
EXPECT_THAT(resp, ArgType(RespExpr::NIL_ARRAY));
|
||||||
EXPECT_EQ(3, GetDebugInfo().shards_count);
|
EXPECT_EQ(3, GetDebugInfo().shards_count);
|
||||||
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
||||||
|
|
||||||
// Under Multi
|
// Under Multi
|
||||||
resp = Run({"multi"});
|
resp = Run({"multi"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
|
|
||||||
Run({"blpop", kKey1, "0"});
|
Run({"blpop", kKey1, "0"});
|
||||||
resp = Run({"exec"});
|
resp = Run({"exec"});
|
||||||
|
|
||||||
EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::NIL_ARRAY)));
|
EXPECT_THAT(resp, ArgType(RespExpr::NIL_ARRAY));
|
||||||
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
ASSERT_FALSE(service_->IsLocked(0, kKey1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, LRem) {
|
TEST_F(ListFamilyTest, LRem) {
|
||||||
auto resp = Run({"rpush", kKey1, "a", "b", "a", "c"});
|
auto resp = Run({"rpush", kKey1, "a", "b", "a", "c"});
|
||||||
ASSERT_THAT(resp, ElementsAre(IntArg(4)));
|
ASSERT_THAT(resp, IntArg(4));
|
||||||
resp = Run({"lrem", kKey1, "2", "a"});
|
resp = Run({"lrem", kKey1, "2", "a"});
|
||||||
ASSERT_THAT(resp, ElementsAre(IntArg(2)));
|
ASSERT_THAT(resp, IntArg(2));
|
||||||
ASSERT_THAT(Run({"lrange", kKey1, "0", "1"}), ElementsAre("b", "c"));
|
|
||||||
|
resp = Run({"lrange", kKey1, "0", "1"});
|
||||||
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
|
ASSERT_THAT(resp.GetVec(), ElementsAre("b", "c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, LTrim) {
|
TEST_F(ListFamilyTest, LTrim) {
|
||||||
Run({"rpush", kKey1, "a", "b", "c", "d"});
|
Run({"rpush", kKey1, "a", "b", "c", "d"});
|
||||||
ASSERT_THAT(Run({"ltrim", kKey1, "-2", "-1"}), RespEq("OK"));
|
ASSERT_EQ(Run({"ltrim", kKey1, "-2", "-1"}), "OK");
|
||||||
ASSERT_THAT(Run({"lrange", kKey1, "0", "1"}), ElementsAre("c", "d"));
|
auto resp = Run({"lrange", kKey1, "0", "1"});
|
||||||
ASSERT_THAT(Run({"ltrim", kKey1, "0", "0"}), RespEq("OK"));
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
ASSERT_THAT(Run({"lrange", kKey1, "0", "1"}), ElementsAre("c"));
|
ASSERT_THAT(resp.GetVec(), ElementsAre("c", "d"));
|
||||||
|
ASSERT_EQ(Run({"ltrim", kKey1, "0", "0"}), "OK");
|
||||||
|
ASSERT_EQ(Run({"lrange", kKey1, "0", "1"}), "c");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, LRange) {
|
TEST_F(ListFamilyTest, LRange) {
|
||||||
auto resp = Run({"lrange", kKey1, "0", "5"});
|
auto resp = Run({"lrange", kKey1, "0", "5"});
|
||||||
ASSERT_THAT(resp[0], ArrLen(0));
|
ASSERT_THAT(resp, ArrLen(0));
|
||||||
Run({"rpush", kKey1, "0", "1", "2"});
|
Run({"rpush", kKey1, "0", "1", "2"});
|
||||||
resp = Run({"lrange", kKey1, "-2", "-1"});
|
resp = Run({"lrange", kKey1, "-2", "-1"});
|
||||||
ASSERT_THAT(resp, ElementsAre("1", "2"));
|
|
||||||
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
|
ASSERT_THAT(resp.GetVec(), ElementsAre("1", "2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, Lset) {
|
TEST_F(ListFamilyTest, Lset) {
|
||||||
Run({"rpush", kKey1, "0", "1", "2"});
|
Run({"rpush", kKey1, "0", "1", "2"});
|
||||||
ASSERT_THAT(Run({"lset", kKey1, "0", "bar"}), RespEq("OK"));
|
ASSERT_EQ(Run({"lset", kKey1, "0", "bar"}), "OK");
|
||||||
ASSERT_THAT(Run({"lpop", kKey1}), RespEq("bar"));
|
ASSERT_EQ(Run({"lpop", kKey1}), "bar");
|
||||||
ASSERT_THAT(Run({"lset", kKey1, "-1", "foo"}), RespEq("OK"));
|
ASSERT_EQ(Run({"lset", kKey1, "-1", "foo"}), "OK");
|
||||||
ASSERT_THAT(Run({"rpop", kKey1}), RespEq("foo"));
|
ASSERT_EQ(Run({"rpop", kKey1}), "foo");
|
||||||
Run({"rpush", kKey2, "a"});
|
Run({"rpush", kKey2, "a"});
|
||||||
ASSERT_THAT(Run({"lset", kKey2, "1", "foo"}), ElementsAre(ErrArg("index out of range")));
|
ASSERT_THAT(Run({"lset", kKey2, "1", "foo"}), ErrArg("index out of range"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, BLPopSerialize) {
|
TEST_F(ListFamilyTest, BLPopSerialize) {
|
||||||
RespVec blpop_resp;
|
RespExpr blpop_resp;
|
||||||
|
|
||||||
auto pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
auto pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
||||||
blpop_resp = Run({"blpop", kKey1, kKey2, kKey3, "0"});
|
blpop_resp = Run({"blpop", kKey1, kKey2, kKey3, "0"});
|
||||||
|
@ -202,11 +213,10 @@ TEST_F(ListFamilyTest, BLPopSerialize) {
|
||||||
LOG(INFO) << "Starting multi";
|
LOG(INFO) << "Starting multi";
|
||||||
|
|
||||||
TxClock cl1, cl2;
|
TxClock cl1, cl2;
|
||||||
unsigned key1_len1 = 0, key1_len2 = 0;
|
|
||||||
|
|
||||||
auto p1_fb = pp_->at(1)->LaunchFiber([&] {
|
auto p1_fb = pp_->at(1)->LaunchFiber([&] {
|
||||||
auto resp = Run({"multi"}); // We use multi to assign ts to lpush.
|
auto resp = Run({"multi"}); // We use multi to assign ts to lpush.
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
Run({"lpush", kKey1, "A"});
|
Run({"lpush", kKey1, "A"});
|
||||||
resp = Run({"exec"});
|
resp = Run({"exec"});
|
||||||
|
|
||||||
|
@ -214,20 +224,20 @@ TEST_F(ListFamilyTest, BLPopSerialize) {
|
||||||
// In any case it must be that between 2 invocations of lpush (wrapped in multi)
|
// In any case it must be that between 2 invocations of lpush (wrapped in multi)
|
||||||
// blpop will be triggerred and it will empty the list again. Hence, in any case
|
// blpop will be triggerred and it will empty the list again. Hence, in any case
|
||||||
// lpush kKey1 here and below should return 1.
|
// lpush kKey1 here and below should return 1.
|
||||||
EXPECT_THAT(resp, ElementsAre(IntArg(1)));
|
ASSERT_THAT(resp, IntArg(1));
|
||||||
key1_len1 = get<int64_t>(resp[0].u);
|
|
||||||
cl1 = GetDebugInfo("IO1").clock;
|
cl1 = GetDebugInfo("IO1").clock;
|
||||||
LOG(INFO) << "push1 ts: " << cl1;
|
LOG(INFO) << "push1 ts: " << cl1;
|
||||||
});
|
});
|
||||||
|
|
||||||
auto p2_fb = pp_->at(2)->LaunchFiber([&] {
|
auto p2_fb = pp_->at(2)->LaunchFiber([&] {
|
||||||
auto resp = Run({"multi"}); // We use multi to assign ts to lpush.
|
auto resp = Run({"multi"}); // We use multi to assign ts to lpush.
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
Run({"lpush", kKey1, "B"});
|
Run({"lpush", kKey1, "B"});
|
||||||
Run({"lpush", kKey2, "C"});
|
Run({"lpush", kKey2, "C"});
|
||||||
resp = Run({"exec"});
|
resp = Run({"exec"});
|
||||||
EXPECT_THAT(resp, ElementsAre(IntArg(1), IntArg(1)));
|
|
||||||
key1_len2 = get<int64_t>(resp[0].u);
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(resp.GetVec(), ElementsAre(IntArg(1), IntArg(1)));
|
||||||
cl2 = GetDebugInfo("IO2").clock;
|
cl2 = GetDebugInfo("IO2").clock;
|
||||||
LOG(INFO) << "push2 ts: " << cl2;
|
LOG(INFO) << "push2 ts: " << cl2;
|
||||||
});
|
});
|
||||||
|
@ -236,17 +246,19 @@ TEST_F(ListFamilyTest, BLPopSerialize) {
|
||||||
p2_fb.join();
|
p2_fb.join();
|
||||||
|
|
||||||
pop_fb.join();
|
pop_fb.join();
|
||||||
EXPECT_THAT(blpop_resp, ElementsAre(StrArg(kKey1), ArgType(RespExpr::STRING)));
|
ASSERT_THAT(blpop_resp, ArrLen(2));
|
||||||
|
auto resp_arr = blpop_resp.GetVec();
|
||||||
|
EXPECT_THAT(resp_arr, ElementsAre(kKey1, ArgType(RespExpr::STRING)));
|
||||||
|
|
||||||
if (cl2 < cl1) {
|
if (cl2 < cl1) {
|
||||||
EXPECT_EQ(blpop_resp[1], "B");
|
EXPECT_EQ(resp_arr[1], "B");
|
||||||
} else {
|
} else {
|
||||||
EXPECT_EQ(blpop_resp[1], "A");
|
EXPECT_EQ(resp_arr[1], "A");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, WrongTypeDoesNotWake) {
|
TEST_F(ListFamilyTest, WrongTypeDoesNotWake) {
|
||||||
RespVec blpop_resp;
|
RespExpr blpop_resp;
|
||||||
|
|
||||||
auto pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
auto pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
||||||
blpop_resp = Run({"blpop", kKey1, "0"});
|
blpop_resp = Run({"blpop", kKey1, "0"});
|
||||||
|
@ -262,7 +274,7 @@ TEST_F(ListFamilyTest, WrongTypeDoesNotWake) {
|
||||||
Run({"set", kKey1, "foo"});
|
Run({"set", kKey1, "foo"});
|
||||||
|
|
||||||
auto resp = Run({"exec"});
|
auto resp = Run({"exec"});
|
||||||
EXPECT_THAT(resp, ElementsAre(IntArg(1), "OK"));
|
EXPECT_THAT(resp.GetVec(), ElementsAre(IntArg(1), "OK"));
|
||||||
|
|
||||||
Run({"del", kKey1});
|
Run({"del", kKey1});
|
||||||
Run({"lpush", kKey1, "B"});
|
Run({"lpush", kKey1, "B"});
|
||||||
|
@ -270,11 +282,12 @@ TEST_F(ListFamilyTest, WrongTypeDoesNotWake) {
|
||||||
|
|
||||||
p1_fb.join();
|
p1_fb.join();
|
||||||
pop_fb.join();
|
pop_fb.join();
|
||||||
EXPECT_THAT(blpop_resp, ElementsAre(kKey1, "B"));
|
ASSERT_THAT(blpop_resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(blpop_resp.GetVec(), ElementsAre(kKey1, "B"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, BPopSameKeyTwice) {
|
TEST_F(ListFamilyTest, BPopSameKeyTwice) {
|
||||||
RespVec blpop_resp;
|
RespExpr blpop_resp;
|
||||||
|
|
||||||
auto pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
auto pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
||||||
blpop_resp = Run({"blpop", kKey1, kKey2, kKey2, kKey1, "0"});
|
blpop_resp = Run({"blpop", kKey1, kKey2, kKey2, kKey1, "0"});
|
||||||
|
@ -288,7 +301,9 @@ TEST_F(ListFamilyTest, BPopSameKeyTwice) {
|
||||||
EXPECT_EQ(1, CheckedInt({"lpush", kKey1, "bar"}));
|
EXPECT_EQ(1, CheckedInt({"lpush", kKey1, "bar"}));
|
||||||
});
|
});
|
||||||
pop_fb.join();
|
pop_fb.join();
|
||||||
EXPECT_THAT(blpop_resp, ElementsAre(kKey1, "bar"));
|
|
||||||
|
ASSERT_THAT(blpop_resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(blpop_resp.GetVec(), ElementsAre(kKey1, "bar"));
|
||||||
|
|
||||||
pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] {
|
||||||
blpop_resp = Run({"blpop", kKey1, kKey2, kKey2, kKey1, "0"});
|
blpop_resp = Run({"blpop", kKey1, kKey2, kKey2, kKey1, "0"});
|
||||||
|
@ -302,11 +317,13 @@ TEST_F(ListFamilyTest, BPopSameKeyTwice) {
|
||||||
EXPECT_EQ(1, CheckedInt({"lpush", kKey2, "bar"}));
|
EXPECT_EQ(1, CheckedInt({"lpush", kKey2, "bar"}));
|
||||||
});
|
});
|
||||||
pop_fb.join();
|
pop_fb.join();
|
||||||
EXPECT_THAT(blpop_resp, ElementsAre(kKey2, "bar"));
|
|
||||||
|
ASSERT_THAT(blpop_resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(blpop_resp.GetVec(), ElementsAre(kKey2, "bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListFamilyTest, BPopRename) {
|
TEST_F(ListFamilyTest, BPopRename) {
|
||||||
RespVec blpop_resp;
|
RespExpr blpop_resp;
|
||||||
|
|
||||||
Run({"exists", kKey1, kKey2});
|
Run({"exists", kKey1, kKey2});
|
||||||
ASSERT_EQ(2, GetDebugInfo().shards_count);
|
ASSERT_EQ(2, GetDebugInfo().shards_count);
|
||||||
|
@ -324,7 +341,9 @@ TEST_F(ListFamilyTest, BPopRename) {
|
||||||
Run({"rename", "a", kKey1});
|
Run({"rename", "a", kKey1});
|
||||||
});
|
});
|
||||||
pop_fb.join();
|
pop_fb.join();
|
||||||
EXPECT_THAT(blpop_resp, ElementsAre(kKey1, "bar"));
|
|
||||||
|
ASSERT_THAT(blpop_resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(blpop_resp.GetVec(), ElementsAre(kKey1, "bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
|
@ -83,14 +83,18 @@ 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(StrArray(resp[1]),
|
|
||||||
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(StrArray(resp.GetVec()[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"});
|
||||||
EXPECT_THAT(resp, UnorderedElementsAre("111", "222", "1234", "3333", "4444", "67899", "76554"));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(),
|
||||||
|
UnorderedElementsAre("111", "222", "1234", "3333", "4444", "67899", "76554"));
|
||||||
|
|
||||||
// TODO: when we implement PEXPIRETIME we will be able to do it directly.
|
// TODO: when we implement PEXPIRETIME we will be able to do it directly.
|
||||||
int ttl = CheckedInt({"ttl", "set1"}); // should expire at 1747008000.
|
int ttl = CheckedInt({"ttl", "set1"}); // should expire at 1747008000.
|
||||||
EXPECT_GT(ttl + time(NULL), 1747007000); // left 1000 seconds margin in case the clock is off.
|
EXPECT_GT(ttl + time(NULL), 1747007000); // left 1000 seconds margin in case the clock is off.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,23 +23,23 @@ class SetFamilyTest : public BaseFamilyTest {
|
||||||
|
|
||||||
TEST_F(SetFamilyTest, SAdd) {
|
TEST_F(SetFamilyTest, SAdd) {
|
||||||
auto resp = Run({"sadd", "x", "1", "2", "3"});
|
auto resp = Run({"sadd", "x", "1", "2", "3"});
|
||||||
EXPECT_THAT(resp[0], IntArg(3));
|
EXPECT_THAT(resp, IntArg(3));
|
||||||
resp = Run({"sadd", "x", "2", "3"});
|
resp = Run({"sadd", "x", "2", "3"});
|
||||||
EXPECT_THAT(resp[0], IntArg(0));
|
EXPECT_THAT(resp, IntArg(0));
|
||||||
Run({"set", "a", "foo"});
|
Run({"set", "a", "foo"});
|
||||||
resp = Run({"sadd", "a", "b"});
|
resp = Run({"sadd", "a", "b"});
|
||||||
EXPECT_THAT(resp[0], ErrArg("WRONGTYPE "));
|
EXPECT_THAT(resp, ErrArg("WRONGTYPE "));
|
||||||
resp = Run({"type", "x"});
|
resp = Run({"type", "x"});
|
||||||
EXPECT_THAT(resp, RespEq("set"));
|
EXPECT_EQ(resp, "set");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SetFamilyTest, IntConv) {
|
TEST_F(SetFamilyTest, IntConv) {
|
||||||
auto resp = Run({"sadd", "x", "134"});
|
auto resp = Run({"sadd", "x", "134"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
resp = Run({"sadd", "x", "abc"});
|
resp = Run({"sadd", "x", "abc"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
resp = Run({"sadd", "x", "134"});
|
resp = Run({"sadd", "x", "134"});
|
||||||
EXPECT_THAT(resp[0], IntArg(0));
|
EXPECT_THAT(resp, IntArg(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SetFamilyTest, SUnionStore) {
|
TEST_F(SetFamilyTest, SUnionStore) {
|
||||||
|
@ -47,25 +47,29 @@ TEST_F(SetFamilyTest, SUnionStore) {
|
||||||
Run({"sadd", "c", "10", "11"});
|
Run({"sadd", "c", "10", "11"});
|
||||||
Run({"set", "a", "foo"});
|
Run({"set", "a", "foo"});
|
||||||
resp = Run({"sunionstore", "a", "b", "c"});
|
resp = Run({"sunionstore", "a", "b", "c"});
|
||||||
EXPECT_THAT(resp[0], IntArg(5));
|
EXPECT_THAT(resp, IntArg(5));
|
||||||
resp = Run({"type", "a"});
|
resp = Run({"type", "a"});
|
||||||
ASSERT_THAT(resp, RespEq("set"));
|
ASSERT_EQ(resp, "set");
|
||||||
|
|
||||||
resp = Run({"smembers", "a"});
|
resp = Run({"smembers", "a"});
|
||||||
EXPECT_THAT(resp, UnorderedElementsAre("11", "10", "1", "2", "3"));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), UnorderedElementsAre("11", "10", "1", "2", "3"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SetFamilyTest, SDiff) {
|
TEST_F(SetFamilyTest, SDiff) {
|
||||||
auto resp = Run({"sadd", "b", "1", "2", "3"});
|
auto resp = Run({"sadd", "b", "1", "2", "3"});
|
||||||
Run({"sadd", "c", "10", "11"});
|
Run({"sadd", "c", "10", "11"});
|
||||||
Run({"set", "a", "foo"});
|
Run({"set", "a", "foo"});
|
||||||
|
|
||||||
resp = Run({"sdiff", "b", "c"});
|
resp = Run({"sdiff", "b", "c"});
|
||||||
EXPECT_THAT(resp, UnorderedElementsAre("1", "2", "3"));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), UnorderedElementsAre("1", "2", "3"));
|
||||||
|
|
||||||
resp = Run({"sdiffstore", "a", "b", "c"});
|
resp = Run({"sdiffstore", "a", "b", "c"});
|
||||||
EXPECT_THAT(resp[0], IntArg(3));
|
EXPECT_THAT(resp, IntArg(3));
|
||||||
|
|
||||||
Run({"set", "str", "foo"});
|
Run({"set", "str", "foo"});
|
||||||
EXPECT_THAT(Run({"sdiff", "b", "str"}), ElementsAre(ErrArg("WRONGTYPE ")));
|
EXPECT_THAT(Run({"sdiff", "b", "str"}), ErrArg("WRONGTYPE "));
|
||||||
|
|
||||||
Run({"sadd", "bar", "x", "a", "b", "c"});
|
Run({"sadd", "bar", "x", "a", "b", "c"});
|
||||||
Run({"sadd", "foo", "c"});
|
Run({"sadd", "foo", "c"});
|
||||||
|
@ -77,50 +81,53 @@ TEST_F(SetFamilyTest, SInter) {
|
||||||
auto resp = Run({"sadd", "a", "1", "2", "3", "4"});
|
auto resp = Run({"sadd", "a", "1", "2", "3", "4"});
|
||||||
Run({"sadd", "b", "3", "5", "6", "2"});
|
Run({"sadd", "b", "3", "5", "6", "2"});
|
||||||
resp = Run({"sinterstore", "d", "a", "b"});
|
resp = Run({"sinterstore", "d", "a", "b"});
|
||||||
EXPECT_THAT(resp[0], IntArg(2));
|
EXPECT_THAT(resp, IntArg(2));
|
||||||
resp = Run({"smembers", "d"});
|
resp = Run({"smembers", "d"});
|
||||||
EXPECT_THAT(resp, UnorderedElementsAre("3", "2"));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), UnorderedElementsAre("3", "2"));
|
||||||
|
|
||||||
Run({"set", "y", ""});
|
Run({"set", "y", ""});
|
||||||
resp = Run({"sinter", "x", "y"});
|
resp = Run({"sinter", "x", "y"});
|
||||||
ASSERT_EQ(1, GetDebugInfo("IO0").shards_count);
|
ASSERT_EQ(1, GetDebugInfo("IO0").shards_count);
|
||||||
EXPECT_THAT(resp, ElementsAre(ErrArg("WRONGTYPE Operation against a key")));
|
EXPECT_THAT(resp, ErrArg("WRONGTYPE Operation against a key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SetFamilyTest, SMove) {
|
TEST_F(SetFamilyTest, SMove) {
|
||||||
auto resp = Run({"sadd", "a", "1", "2", "3", "4"});
|
auto resp = Run({"sadd", "a", "1", "2", "3", "4"});
|
||||||
Run({"sadd", "b", "3", "5", "6", "2"});
|
Run({"sadd", "b", "3", "5", "6", "2"});
|
||||||
resp = Run({"smove", "a", "b", "1"});
|
resp = Run({"smove", "a", "b", "1"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
Run({"sadd", "x", "a", "b", "c"});
|
Run({"sadd", "x", "a", "b", "c"});
|
||||||
Run({"sadd", "y", "c"});
|
Run({"sadd", "y", "c"});
|
||||||
EXPECT_THAT(Run({"smove", "x", "y", "c"}), ElementsAre(IntArg(1)));
|
EXPECT_THAT(Run({"smove", "x", "y", "c"}), IntArg(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SetFamilyTest, SPop) {
|
TEST_F(SetFamilyTest, SPop) {
|
||||||
auto resp = Run({"sadd", "x", "1", "2", "3"});
|
auto resp = Run({"sadd", "x", "1", "2", "3"});
|
||||||
resp = Run({"spop", "x", "3"});
|
resp = Run({"spop", "x", "3"});
|
||||||
EXPECT_THAT(resp, UnorderedElementsAre("1", "2", "3"));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), UnorderedElementsAre("1", "2", "3"));
|
||||||
resp = Run({"type", "x"});
|
resp = Run({"type", "x"});
|
||||||
EXPECT_THAT(resp, RespEq("none"));
|
EXPECT_EQ(resp, "none");
|
||||||
|
|
||||||
Run({"sadd", "x", "1", "2", "3"});
|
Run({"sadd", "x", "1", "2", "3"});
|
||||||
resp = Run({"spop", "x", "2"});
|
resp = Run({"spop", "x", "2"});
|
||||||
EXPECT_THAT(resp, IsSubsetOf({"1", "2", "3"}));
|
|
||||||
EXPECT_EQ(2, resp.size());
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
|
EXPECT_THAT(resp.GetVec(), IsSubsetOf({"1", "2", "3"}));
|
||||||
|
|
||||||
resp = Run({"scard", "x"});
|
resp = Run({"scard", "x"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
Run({"sadd", "y", "a", "b", "c"});
|
Run({"sadd", "y", "a", "b", "c"});
|
||||||
resp = Run({"spop", "y", "1"});
|
resp = Run({"spop", "y", "1"});
|
||||||
EXPECT_THAT(resp, IsSubsetOf({"a", "b", "c"}));
|
EXPECT_THAT(resp, ArgType(RespExpr::STRING));
|
||||||
EXPECT_EQ(1, resp.size());
|
EXPECT_THAT(resp, testing::AnyOf("a", "b", "c"));
|
||||||
|
|
||||||
resp = Run({"smembers", "y"});
|
resp = Run({"smembers", "y"});
|
||||||
EXPECT_THAT(resp, IsSubsetOf({"a", "b", "c"}));
|
ASSERT_THAT(resp, ArrLen(2));
|
||||||
EXPECT_EQ(2, resp.size());
|
EXPECT_THAT(resp.GetVec(), IsSubsetOf({"a", "b", "c"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
|
@ -26,83 +26,98 @@ class StringFamilyTest : public BaseFamilyTest {
|
||||||
protected:
|
protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vector<int64_t> ToIntArr(const RespExpr& e) {
|
||||||
|
vector<int64_t> res;
|
||||||
|
CHECK_EQ(e.type, RespExpr::ARRAY);
|
||||||
|
const RespVec* vec = get<RespVec*>(e.u);
|
||||||
|
for (auto a : *vec) {
|
||||||
|
int64_t val;
|
||||||
|
std::string_view s = ToSV(a.GetBuf());
|
||||||
|
CHECK(absl::SimpleAtoi(s, &val)) << s;
|
||||||
|
res.push_back(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(StringFamilyTest, SetGet) {
|
TEST_F(StringFamilyTest, SetGet) {
|
||||||
auto resp = Run({"set", "key", "val"});
|
auto resp = Run({"set", "key", "val"});
|
||||||
|
|
||||||
EXPECT_THAT(resp, RespEq("OK"));
|
EXPECT_EQ(resp, "OK");
|
||||||
EXPECT_THAT(Run({"get", "key"}), RespEq("val"));
|
EXPECT_EQ(Run({"get", "key"}), "val");
|
||||||
EXPECT_THAT(Run({"set", "key1", "1"}), RespEq("OK"));
|
EXPECT_EQ(Run({"set", "key1", "1"}), "OK");
|
||||||
EXPECT_THAT(Run({"get", "key1"}), RespEq("1"));
|
EXPECT_EQ(Run({"get", "key1"}), "1");
|
||||||
EXPECT_THAT(Run({"set", "key", "2"}), RespEq("OK"));
|
EXPECT_EQ(Run({"set", "key", "2"}), "OK");
|
||||||
EXPECT_THAT(Run({"get", "key"}), RespEq("2"));
|
EXPECT_EQ(Run({"get", "key"}), "2");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StringFamilyTest, Incr) {
|
TEST_F(StringFamilyTest, Incr) {
|
||||||
ASSERT_THAT(Run({"set", "key", "0"}), RespEq("OK"));
|
ASSERT_EQ(Run({"set", "key", "0"}), "OK");
|
||||||
ASSERT_THAT(Run({"incr", "key"}), ElementsAre(IntArg(1)));
|
ASSERT_THAT(Run({"incr", "key"}), IntArg(1));
|
||||||
|
|
||||||
ASSERT_THAT(Run({"set", "key1", "123456789"}), RespEq("OK"));
|
ASSERT_EQ(Run({"set", "key1", "123456789"}), "OK");
|
||||||
ASSERT_THAT(Run({"incrby", "key1", "0"}), ElementsAre(IntArg(123456789)));
|
ASSERT_THAT(Run({"incrby", "key1", "0"}), IntArg(123456789));
|
||||||
|
|
||||||
ASSERT_THAT(Run({"set", "key1", "-123456789"}), RespEq("OK"));
|
ASSERT_EQ(Run({"set", "key1", "-123456789"}), "OK");
|
||||||
ASSERT_THAT(Run({"incrby", "key1", "0"}), ElementsAre(IntArg(-123456789)));
|
ASSERT_THAT(Run({"incrby", "key1", "0"}), IntArg(-123456789));
|
||||||
|
|
||||||
ASSERT_THAT(Run({"set", "key1", " -123 "}), RespEq("OK"));
|
ASSERT_EQ(Run({"set", "key1", " -123 "}), "OK");
|
||||||
ASSERT_THAT(Run({"incrby", "key1", "1"}), ElementsAre(ErrArg("ERR value is not an integer")));
|
ASSERT_THAT(Run({"incrby", "key1", "1"}), ErrArg("ERR value is not an integer"));
|
||||||
|
|
||||||
ASSERT_THAT(Run({"incrby", "ne", "0"}), ElementsAre(IntArg(0)));
|
ASSERT_THAT(Run({"incrby", "ne", "0"}), IntArg(0));
|
||||||
ASSERT_THAT(Run({"decrby", "a", "-9223372036854775808"}), ElementsAre(ErrArg("overflow")));
|
ASSERT_THAT(Run({"decrby", "a", "-9223372036854775808"}), ErrArg("overflow"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StringFamilyTest, Append) {
|
TEST_F(StringFamilyTest, Append) {
|
||||||
Run({"setex", "key", "100", "val"});
|
Run({"setex", "key", "100", "val"});
|
||||||
EXPECT_THAT(Run({"append", "key", "bar"}), ElementsAre(IntArg(6)));
|
EXPECT_THAT(Run({"append", "key", "bar"}), IntArg(6));
|
||||||
EXPECT_THAT(Run({"ttl", "key"}), ElementsAre(IntArg(100)));
|
EXPECT_THAT(Run({"ttl", "key"}), IntArg(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StringFamilyTest, Expire) {
|
TEST_F(StringFamilyTest, Expire) {
|
||||||
ASSERT_THAT(Run({"set", "key", "val", "PX", "20"}), RespEq("OK"));
|
ASSERT_EQ(Run({"set", "key", "val", "PX", "20"}), "OK");
|
||||||
|
|
||||||
UpdateTime(expire_now_ + 10);
|
UpdateTime(expire_now_ + 10);
|
||||||
EXPECT_THAT(Run({"get", "key"}), RespEq("val"));
|
EXPECT_EQ(Run({"get", "key"}), "val");
|
||||||
|
|
||||||
UpdateTime(expire_now_ + 20);
|
UpdateTime(expire_now_ + 20);
|
||||||
|
|
||||||
EXPECT_THAT(Run({"get", "key"}), ElementsAre(ArgType(RespExpr::NIL)));
|
EXPECT_THAT(Run({"get", "key"}), ArgType(RespExpr::NIL));
|
||||||
|
|
||||||
ASSERT_THAT(Run({"set", "i", "1", "PX", "10"}), RespEq("OK"));
|
ASSERT_THAT(Run({"set", "i", "1", "PX", "10"}), "OK");
|
||||||
ASSERT_THAT(Run({"incr", "i"}), ElementsAre(IntArg(2)));
|
ASSERT_THAT(Run({"incr", "i"}), IntArg(2));
|
||||||
|
|
||||||
UpdateTime(expire_now_ + 30);
|
UpdateTime(expire_now_ + 30);
|
||||||
ASSERT_THAT(Run({"incr", "i"}), ElementsAre(IntArg(1)));
|
ASSERT_THAT(Run({"incr", "i"}), IntArg(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StringFamilyTest, Set) {
|
TEST_F(StringFamilyTest, Set) {
|
||||||
auto resp = Run({"set", "foo", "bar", "XX"});
|
auto resp = Run({"set", "foo", "bar", "XX"});
|
||||||
EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::NIL)));
|
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||||
|
|
||||||
resp = Run({"set", "foo", "bar", "NX"});
|
resp = Run({"set", "foo", "bar", "NX"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_THAT(resp, "OK");
|
||||||
resp = Run({"set", "foo", "bar", "NX"});
|
resp = Run({"set", "foo", "bar", "NX"});
|
||||||
EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::NIL)));
|
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||||
|
|
||||||
resp = Run({"set", "foo", "bar", "xx"});
|
resp = Run({"set", "foo", "bar", "xx"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_THAT(resp, "OK");
|
||||||
|
|
||||||
resp = Run({"set", "foo", "bar", "ex", "abc"});
|
resp = Run({"set", "foo", "bar", "ex", "abc"});
|
||||||
ASSERT_THAT(resp, ElementsAre(ErrArg(kInvalidIntErr)));
|
ASSERT_THAT(resp, ErrArg(kInvalidIntErr));
|
||||||
|
|
||||||
resp = Run({"set", "foo", "bar", "ex", "-1"});
|
resp = Run({"set", "foo", "bar", "ex", "-1"});
|
||||||
ASSERT_THAT(resp, ElementsAre(ErrArg("invalid expire time")));
|
ASSERT_THAT(resp, ErrArg("invalid expire time"));
|
||||||
|
|
||||||
resp = Run({"set", "foo", "bar", "ex", "1"});
|
resp = Run({"set", "foo", "bar", "ex", "1"});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_THAT(resp, "OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StringFamilyTest, MGetSet) {
|
TEST_F(StringFamilyTest, MGetSet) {
|
||||||
Run({"mset", "z", "0"}); // single key
|
Run({"mset", "z", "0"}); // single key
|
||||||
auto resp = Run({"mget", "z"}); // single key
|
auto resp = Run({"mget", "z"}); // single key
|
||||||
EXPECT_THAT(resp, RespEq("0"));
|
EXPECT_THAT(resp, "0");
|
||||||
|
|
||||||
Run({"mset", "x", "0", "b", "0"});
|
Run({"mset", "x", "0", "b", "0"});
|
||||||
|
|
||||||
|
@ -110,8 +125,8 @@ TEST_F(StringFamilyTest, MGetSet) {
|
||||||
|
|
||||||
auto mget_fb = pp_->at(0)->LaunchFiber([&] {
|
auto mget_fb = pp_->at(0)->LaunchFiber([&] {
|
||||||
for (size_t i = 0; i < 1000; ++i) {
|
for (size_t i = 0; i < 1000; ++i) {
|
||||||
auto resp = Run({"mget", "b", "x"});
|
RespExpr resp = Run({"mget", "b", "x"});
|
||||||
ASSERT_EQ(2, resp.size());
|
ASSERT_EQ(RespExpr::ARRAY, resp.type);
|
||||||
auto ivec = ToIntArr(resp);
|
auto ivec = ToIntArr(resp);
|
||||||
|
|
||||||
ASSERT_GE(ivec[1], ivec[0]);
|
ASSERT_GE(ivec[1], ivec[0]);
|
||||||
|
@ -147,8 +162,8 @@ TEST_F(StringFamilyTest, MSetGet) {
|
||||||
|
|
||||||
auto mset_fb = pp_->at(0)->LaunchFiber([&] {
|
auto mset_fb = pp_->at(0)->LaunchFiber([&] {
|
||||||
for (size_t i = 0; i < 1000; ++i) {
|
for (size_t i = 0; i < 1000; ++i) {
|
||||||
RespVec resp = Run({"mset", "x", StrCat(i), "b", StrCat(i)});
|
RespExpr resp = Run({"mset", "x", StrCat(i), "b", StrCat(i)});
|
||||||
ASSERT_THAT(resp, RespEq("OK")) << i;
|
ASSERT_EQ(resp, "OK") << i;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -187,7 +202,7 @@ TEST_F(StringFamilyTest, MSetDel) {
|
||||||
TEST_F(StringFamilyTest, IntKey) {
|
TEST_F(StringFamilyTest, IntKey) {
|
||||||
Run({"mset", "1", "1", "-1000", "-1000"});
|
Run({"mset", "1", "1", "-1000", "-1000"});
|
||||||
auto resp = Run({"get", "1"});
|
auto resp = Run({"get", "1"});
|
||||||
ASSERT_THAT(resp, RespEq("1"));
|
ASSERT_THAT(resp, "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StringFamilyTest, SingleShard) {
|
TEST_F(StringFamilyTest, SingleShard) {
|
||||||
|
@ -238,7 +253,7 @@ TEST_F(StringFamilyTest, MSetIncr) {
|
||||||
for (size_t i = 1; i < 1000; ++i) {
|
for (size_t i = 1; i < 1000; ++i) {
|
||||||
string base = StrCat(i * 900);
|
string base = StrCat(i * 900);
|
||||||
auto resp = Run({"mset", "b", base, "a", base, "c", base});
|
auto resp = Run({"mset", "b", base, "a", base, "c", base});
|
||||||
ASSERT_THAT(resp, RespEq("OK"));
|
ASSERT_EQ(resp, "OK");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -260,21 +275,21 @@ TEST_F(StringFamilyTest, MSetIncr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StringFamilyTest, SetEx) {
|
TEST_F(StringFamilyTest, SetEx) {
|
||||||
ASSERT_THAT(Run({"setex", "key", "1", "val"}), RespEq("OK"));
|
ASSERT_EQ(Run({"setex", "key", "1", "val"}), "OK");
|
||||||
ASSERT_THAT(Run({"setex", "key", "10", "val"}), RespEq("OK"));
|
ASSERT_EQ(Run({"setex", "key", "10", "val"}), "OK");
|
||||||
ASSERT_THAT(Run({"ttl", "key"}), ElementsAre(IntArg(10)));
|
ASSERT_THAT(Run({"ttl", "key"}), IntArg(10));
|
||||||
ASSERT_THAT(Run({"setex", "key", "0", "val"}), ElementsAre(ErrArg("invalid expire time")));
|
ASSERT_THAT(Run({"setex", "key", "0", "val"}), ErrArg("invalid expire time"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(StringFamilyTest, Range) {
|
TEST_F(StringFamilyTest, Range) {
|
||||||
Run({"set", "key1", "Hello World"});
|
Run({"set", "key1", "Hello World"});
|
||||||
EXPECT_THAT(Run({"getrange", "key1", "5", "3"}), RespEq(""));
|
EXPECT_EQ(Run({"getrange", "key1", "5", "3"}), "");
|
||||||
|
|
||||||
Run({"SETRANGE", "key1", "6", "Earth"});
|
Run({"SETRANGE", "key1", "6", "Earth"});
|
||||||
EXPECT_THAT(Run({"get", "key1"}), RespEq("Hello Earth"));
|
EXPECT_EQ(Run({"get", "key1"}), "Hello Earth");
|
||||||
|
|
||||||
Run({"SETRANGE", "key2", "2", "Earth"});
|
Run({"SETRANGE", "key2", "2", "Earth"});
|
||||||
EXPECT_THAT(Run({"get", "key2"}), RespEq(string_view("\000\000Earth", 7)));
|
EXPECT_EQ(Run({"get", "key2"}), string_view("\000\000Earth", 7));
|
||||||
|
|
||||||
Run({"SETRANGE", "key3", "0", ""});
|
Run({"SETRANGE", "key3", "0", ""});
|
||||||
EXPECT_EQ(0, CheckedInt({"exists", "key3"}));
|
EXPECT_EQ(0, CheckedInt({"exists", "key3"}));
|
||||||
|
@ -283,13 +298,13 @@ TEST_F(StringFamilyTest, Range) {
|
||||||
EXPECT_EQ(1, CheckedInt({"exists", "key3"}));
|
EXPECT_EQ(1, CheckedInt({"exists", "key3"}));
|
||||||
|
|
||||||
Run({"SET", "key3", "123"});
|
Run({"SET", "key3", "123"});
|
||||||
EXPECT_THAT(Run({"getrange", "key3", "2", "3"}), RespEq("3"));
|
EXPECT_EQ(Run({"getrange", "key3", "2", "3"}), "3");
|
||||||
EXPECT_THAT(Run({"getrange", "key3", "3", "3"}), RespEq(""));
|
EXPECT_EQ(Run({"getrange", "key3", "3", "3"}), "");
|
||||||
EXPECT_THAT(Run({"getrange", "key3", "4", "5"}), RespEq(""));
|
EXPECT_EQ(Run({"getrange", "key3", "4", "5"}), "");
|
||||||
|
|
||||||
Run({"SET", "num", "1234"});
|
Run({"SET", "num", "1234"});
|
||||||
EXPECT_THAT(Run({"getrange","num", "3", "5000"}), RespEq("4"));
|
EXPECT_EQ(Run({"getrange","num", "3", "5000"}), "4");
|
||||||
EXPECT_THAT(Run({"getrange","num", "-5000", "10000"}), RespEq("1234"));
|
EXPECT_EQ(Run({"getrange","num", "-5000", "10000"}), "1234");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
|
@ -34,17 +34,6 @@ static vector<string> SplitLines(const std::string& src) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int64_t> ToIntArr(const RespVec& vec) {
|
|
||||||
vector<int64_t> res;
|
|
||||||
for (auto a : vec) {
|
|
||||||
int64_t val;
|
|
||||||
std::string_view s = ToSV(a.GetBuf());
|
|
||||||
CHECK(absl::SimpleAtoi(s, &val)) << s;
|
|
||||||
res.push_back(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseFamilyTest::TestConnWrapper::TestConnWrapper(Protocol proto)
|
BaseFamilyTest::TestConnWrapper::TestConnWrapper(Protocol proto)
|
||||||
: dummy_conn(new facade::Connection(proto, nullptr, nullptr, nullptr)),
|
: dummy_conn(new facade::Connection(proto, nullptr, nullptr, nullptr)),
|
||||||
|
@ -58,6 +47,8 @@ BaseFamilyTest::BaseFamilyTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseFamilyTest::~BaseFamilyTest() {
|
BaseFamilyTest::~BaseFamilyTest() {
|
||||||
|
for (auto* v : resp_vec_)
|
||||||
|
delete v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseFamilyTest::SetUpTestSuite() {
|
void BaseFamilyTest::SetUpTestSuite() {
|
||||||
|
@ -100,7 +91,7 @@ void BaseFamilyTest::UpdateTime(uint64_t ms) {
|
||||||
ess_->RunBriefInParallel(cb);
|
ess_->RunBriefInParallel(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
RespVec BaseFamilyTest::Run(initializer_list<std::string_view> list) {
|
RespExpr BaseFamilyTest::Run(initializer_list<std::string_view> list) {
|
||||||
if (!ProactorBase::IsProactorThread()) {
|
if (!ProactorBase::IsProactorThread()) {
|
||||||
return pp_->at(0)->Await([&] { return this->Run(list); });
|
return pp_->at(0)->Await([&] { return this->Run(list); });
|
||||||
}
|
}
|
||||||
|
@ -108,7 +99,7 @@ RespVec BaseFamilyTest::Run(initializer_list<std::string_view> list) {
|
||||||
return Run(GetId(), list);
|
return Run(GetId(), list);
|
||||||
}
|
}
|
||||||
|
|
||||||
RespVec BaseFamilyTest::Run(std::string_view id, std::initializer_list<std::string_view> list) {
|
RespExpr BaseFamilyTest::Run(std::string_view id, std::initializer_list<std::string_view> list) {
|
||||||
TestConnWrapper* conn = AddFindConn(Protocol::REDIS, id);
|
TestConnWrapper* conn = AddFindConn(Protocol::REDIS, id);
|
||||||
|
|
||||||
CmdArgVec args = conn->Args(list);
|
CmdArgVec args = conn->Args(list);
|
||||||
|
@ -126,8 +117,15 @@ RespVec BaseFamilyTest::Run(std::string_view id, std::initializer_list<std::stri
|
||||||
last_cmd_dbg_info_ = context.last_command_debug;
|
last_cmd_dbg_info_ = context.last_command_debug;
|
||||||
|
|
||||||
RespVec vec = conn->ParseResponse();
|
RespVec vec = conn->ParseResponse();
|
||||||
|
if (vec.size() == 1)
|
||||||
|
return vec.front();
|
||||||
|
RespVec* new_vec = new RespVec(vec);
|
||||||
|
resp_vec_.push_back(new_vec);
|
||||||
|
RespExpr e;
|
||||||
|
e.type = RespExpr::ARRAY;
|
||||||
|
e.u = new_vec;
|
||||||
|
|
||||||
return vec;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BaseFamilyTest::RunMC(MP::CmdType cmd_type, string_view key, string_view value, uint32_t flags,
|
auto BaseFamilyTest::RunMC(MP::CmdType cmd_type, string_view key, string_view value, uint32_t flags,
|
||||||
|
@ -203,16 +201,16 @@ auto BaseFamilyTest::GetMC(MP::CmdType cmd_type, std::initializer_list<std::stri
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t BaseFamilyTest::CheckedInt(std::initializer_list<std::string_view> list) {
|
int64_t BaseFamilyTest::CheckedInt(std::initializer_list<std::string_view> list) {
|
||||||
RespVec resp = Run(list);
|
RespExpr resp = Run(list);
|
||||||
CHECK_EQ(1u, resp.size());
|
if (resp.type == RespExpr::INT64) {
|
||||||
if (resp.front().type == RespExpr::INT64) {
|
return get<int64_t>(resp.u);
|
||||||
return get<int64_t>(resp.front().u);
|
|
||||||
}
|
}
|
||||||
if (resp.front().type == RespExpr::NIL) {
|
if (resp.type == RespExpr::NIL) {
|
||||||
return INT64_MIN;
|
return INT64_MIN;
|
||||||
}
|
}
|
||||||
CHECK_EQ(RespExpr::STRING, int(resp.front().type)) << list;
|
|
||||||
string_view sv = ToSV(resp.front().GetBuf());
|
CHECK_EQ(RespExpr::STRING, int(resp.type)) << list;
|
||||||
|
string_view sv = ToSV(resp.GetBuf());
|
||||||
int64_t res;
|
int64_t res;
|
||||||
CHECK(absl::SimpleAtoi(sv, &res)) << "|" << sv << "|";
|
CHECK(absl::SimpleAtoi(sv, &res)) << "|" << sv << "|";
|
||||||
return res;
|
return res;
|
||||||
|
@ -297,7 +295,7 @@ vector<string> BaseFamilyTest::StrArray(const RespExpr& expr) {
|
||||||
for (size_t i = 0; i < src->size(); ++i) {
|
for (size_t i = 0; i < src->size(); ++i) {
|
||||||
res[i] = ToSV(src->at(i).GetBuf());
|
res[i] = ToSV(src->at(i).GetBuf());
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
namespace dfly {
|
namespace dfly {
|
||||||
using namespace facade;
|
using namespace facade;
|
||||||
|
|
||||||
std::vector<int64_t> ToIntArr(const RespVec& vec);
|
|
||||||
|
|
||||||
class BaseFamilyTest : public ::testing::Test {
|
class BaseFamilyTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
BaseFamilyTest();
|
BaseFamilyTest();
|
||||||
|
@ -47,8 +45,8 @@ class BaseFamilyTest : public ::testing::Test {
|
||||||
RespVec ParseResponse();
|
RespVec ParseResponse();
|
||||||
};
|
};
|
||||||
|
|
||||||
RespVec Run(std::initializer_list<std::string_view> list);
|
RespExpr Run(std::initializer_list<std::string_view> list);
|
||||||
RespVec Run(std::string_view id, std::initializer_list<std::string_view> list);
|
RespExpr Run(std::string_view id, std::initializer_list<std::string_view> list);
|
||||||
|
|
||||||
using MCResponse = std::vector<std::string>;
|
using MCResponse = std::vector<std::string>;
|
||||||
MCResponse RunMC(MemcacheParser::CmdType cmd_type, std::string_view key, std::string_view value,
|
MCResponse RunMC(MemcacheParser::CmdType cmd_type, std::string_view key, std::string_view value,
|
||||||
|
@ -82,6 +80,7 @@ class BaseFamilyTest : public ::testing::Test {
|
||||||
::boost::fibers::mutex mu_;
|
::boost::fibers::mutex mu_;
|
||||||
ConnectionContext::DebugInfo last_cmd_dbg_info_;
|
ConnectionContext::DebugInfo last_cmd_dbg_info_;
|
||||||
uint64_t expire_now_;
|
uint64_t expire_now_;
|
||||||
|
std::vector<RespVec*> resp_vec_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
|
@ -23,53 +23,56 @@ class ZSetFamilyTest : public BaseFamilyTest {
|
||||||
|
|
||||||
TEST_F(ZSetFamilyTest, Add) {
|
TEST_F(ZSetFamilyTest, Add) {
|
||||||
auto resp = Run({"zadd", "x", "1.1", "a"});
|
auto resp = Run({"zadd", "x", "1.1", "a"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
resp = Run({"zscore", "x", "a"});
|
resp = Run({"zscore", "x", "a"});
|
||||||
EXPECT_THAT(resp[0], StrArg("1.1"));
|
EXPECT_THAT(resp, "1.1");
|
||||||
|
|
||||||
resp = Run({"zadd", "x", "2", "a"});
|
resp = Run({"zadd", "x", "2", "a"});
|
||||||
EXPECT_THAT(resp[0], IntArg(0));
|
EXPECT_THAT(resp, IntArg(0));
|
||||||
resp = Run({"zscore", "x", "a"});
|
resp = Run({"zscore", "x", "a"});
|
||||||
EXPECT_THAT(resp[0], StrArg("2"));
|
EXPECT_THAT(resp, "2");
|
||||||
|
|
||||||
resp = Run({"zadd", "x", "ch", "3", "a"});
|
resp = Run({"zadd", "x", "ch", "3", "a"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
resp = Run({"zscore", "x", "a"});
|
resp = Run({"zscore", "x", "a"});
|
||||||
EXPECT_THAT(resp[0], StrArg("3"));
|
EXPECT_EQ(resp, "3");
|
||||||
|
|
||||||
resp = Run({"zcard", "x"});
|
resp = Run({"zcard", "x"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
EXPECT_THAT(Run({"zadd", "x", "", "a"}), ElementsAre(ErrArg("not a valid float")));
|
EXPECT_THAT(Run({"zadd", "x", "", "a"}), ErrArg("not a valid float"));
|
||||||
|
|
||||||
EXPECT_THAT(Run({"zadd", "ztmp", "xx", "10", "member"}), ElementsAre(IntArg(0)));
|
EXPECT_THAT(Run({"zadd", "ztmp", "xx", "10", "member"}), IntArg(0));
|
||||||
|
|
||||||
const char kHighPrecision[] = "0.79028573343077946";
|
const char kHighPrecision[] = "0.79028573343077946";
|
||||||
|
|
||||||
Run({"zadd", "zs", kHighPrecision, "a"});
|
Run({"zadd", "zs", kHighPrecision, "a"});
|
||||||
EXPECT_THAT(Run({"zscore", "zs", "a"}), ElementsAre("0.7902857334307795"));
|
EXPECT_EQ(Run({"zscore", "zs", "a"}), "0.7902857334307795");
|
||||||
EXPECT_EQ(0.79028573343077946, 0.7902857334307795);
|
EXPECT_EQ(0.79028573343077946, 0.7902857334307795);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ZSetFamilyTest, ZRem) {
|
TEST_F(ZSetFamilyTest, ZRem) {
|
||||||
auto resp = Run({"zadd", "x", "1.1", "b", "2.1", "a"});
|
auto resp = Run({"zadd", "x", "1.1", "b", "2.1", "a"});
|
||||||
EXPECT_THAT(resp[0], IntArg(2));
|
EXPECT_THAT(resp, IntArg(2));
|
||||||
|
|
||||||
resp = Run({"zrem", "x", "b", "c"});
|
resp = Run({"zrem", "x", "b", "c"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
|
|
||||||
resp = Run({"zcard", "x"});
|
resp = Run({"zcard", "x"});
|
||||||
EXPECT_THAT(resp[0], IntArg(1));
|
EXPECT_THAT(resp, IntArg(1));
|
||||||
EXPECT_THAT(Run({"zrange", "x", "0", "3", "byscore"}), ElementsAre("a"));
|
EXPECT_THAT(Run({"zrange", "x", "0", "3", "byscore"}), "a");
|
||||||
EXPECT_THAT(Run({"zrange", "x", "(-inf", "(+inf", "byscore"}), ElementsAre("a"));
|
EXPECT_THAT(Run({"zrange", "x", "(-inf", "(+inf", "byscore"}), "a");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ZSetFamilyTest, ZRangeRank) {
|
TEST_F(ZSetFamilyTest, ZRangeRank) {
|
||||||
Run({"zadd", "x", "1.1", "a", "2.1", "b"});
|
Run({"zadd", "x", "1.1", "a", "2.1", "b"});
|
||||||
EXPECT_THAT(Run({"zrangebyscore", "x", "0", "(1.1"}), ElementsAre(ArrLen(0)));
|
EXPECT_THAT(Run({"zrangebyscore", "x", "0", "(1.1"}), ArrLen(0));
|
||||||
EXPECT_THAT(Run({"zrangebyscore", "x", "-inf", "1.1"}), ElementsAre("a"));
|
EXPECT_THAT(Run({"zrangebyscore", "x", "-inf", "1.1"}), "a");
|
||||||
EXPECT_THAT(Run({"zrevrangebyscore", "x", "-inf", "+inf"}), ElementsAre("b", "a"));
|
|
||||||
|
auto resp = Run({"zrevrangebyscore", "x", "-inf", "+inf"});
|
||||||
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
ASSERT_THAT(resp.GetVec(), ElementsAre("b", "a"));
|
||||||
|
|
||||||
EXPECT_EQ(2, CheckedInt({"zcount", "x", "1.1", "2.1"}));
|
EXPECT_EQ(2, CheckedInt({"zcount", "x", "1.1", "2.1"}));
|
||||||
EXPECT_EQ(1, CheckedInt({"zcount", "x", "(1.1", "2.1"}));
|
EXPECT_EQ(1, CheckedInt({"zcount", "x", "(1.1", "2.1"}));
|
||||||
|
@ -79,39 +82,38 @@ TEST_F(ZSetFamilyTest, ZRangeRank) {
|
||||||
EXPECT_EQ(1, CheckedInt({"zrank", "x", "b"}));
|
EXPECT_EQ(1, CheckedInt({"zrank", "x", "b"}));
|
||||||
EXPECT_EQ(1, CheckedInt({"zrevrank", "x", "a"}));
|
EXPECT_EQ(1, CheckedInt({"zrevrank", "x", "a"}));
|
||||||
EXPECT_EQ(0, CheckedInt({"zrevrank", "x", "b"}));
|
EXPECT_EQ(0, CheckedInt({"zrevrank", "x", "b"}));
|
||||||
EXPECT_THAT(Run({"zrevrank", "x", "c"}), ElementsAre(ArgType(RespExpr::NIL)));
|
EXPECT_THAT(Run({"zrevrank", "x", "c"}), ArgType(RespExpr::NIL));
|
||||||
EXPECT_THAT(Run({"zrank", "y", "c"}), ElementsAre(ArgType(RespExpr::NIL)));
|
EXPECT_THAT(Run({"zrank", "y", "c"}), ArgType(RespExpr::NIL));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ZSetFamilyTest, ZRemRangeRank) {
|
TEST_F(ZSetFamilyTest, ZRemRangeRank) {
|
||||||
Run({"zadd", "x", "1.1", "a", "2.1", "b"});
|
Run({"zadd", "x", "1.1", "a", "2.1", "b"});
|
||||||
EXPECT_THAT(Run({"ZREMRANGEBYRANK", "y", "0", "1"}), ElementsAre(IntArg(0)));
|
EXPECT_THAT(Run({"ZREMRANGEBYRANK", "y", "0", "1"}), IntArg(0));
|
||||||
EXPECT_THAT(Run({"ZREMRANGEBYRANK", "x", "0", "0"}), ElementsAre(IntArg(1)));
|
EXPECT_THAT(Run({"ZREMRANGEBYRANK", "x", "0", "0"}), IntArg(1));
|
||||||
EXPECT_THAT(Run({"zrange", "x", "0", "5"}), ElementsAre("b"));
|
EXPECT_EQ(Run({"zrange", "x", "0", "5"}), "b");
|
||||||
EXPECT_THAT(Run({"ZREMRANGEBYRANK", "x", "0", "1"}), ElementsAre(IntArg(1)));
|
EXPECT_THAT(Run({"ZREMRANGEBYRANK", "x", "0", "1"}), IntArg(1));
|
||||||
EXPECT_THAT(Run({"type", "x"}), ElementsAre("none"));
|
EXPECT_EQ(Run({"type", "x"}), "none");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ZSetFamilyTest, ZRemRangeScore) {
|
TEST_F(ZSetFamilyTest, ZRemRangeScore) {
|
||||||
Run({"zadd", "x", "1.1", "a", "2.1", "b"});
|
Run({"zadd", "x", "1.1", "a", "2.1", "b"});
|
||||||
EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "y", "0", "1"}), ElementsAre(IntArg(0)));
|
EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "y", "0", "1"}), IntArg(0));
|
||||||
EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "x", "-inf", "1.1"}), ElementsAre(IntArg(1)));
|
EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "x", "-inf", "1.1"}), IntArg(1));
|
||||||
EXPECT_THAT(Run({"zrange", "x", "0", "5"}), ElementsAre("b"));
|
EXPECT_EQ(Run({"zrange", "x", "0", "5"}), "b");
|
||||||
EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "x", "(2.0", "+inf"}), ElementsAre(IntArg(1)));
|
EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "x", "(2.0", "+inf"}), IntArg(1));
|
||||||
EXPECT_THAT(Run({"type", "x"}), ElementsAre("none"));
|
EXPECT_EQ(Run({"type", "x"}), "none");
|
||||||
EXPECT_THAT(Run({"zremrangebyscore", "x", "1", "NaN"}),
|
EXPECT_THAT(Run({"zremrangebyscore", "x", "1", "NaN"}), ErrArg("min or max is not a float"));
|
||||||
ElementsAre(ErrArg("min or max is not a float")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ZSetFamilyTest, IncrBy) {
|
TEST_F(ZSetFamilyTest, IncrBy) {
|
||||||
auto resp = Run({"zadd", "key", "xx", "incr", "2.1", "member"});
|
auto resp = Run({"zadd", "key", "xx", "incr", "2.1", "member"});
|
||||||
EXPECT_THAT(resp[0], ArgType(RespExpr::NIL));
|
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||||
|
|
||||||
resp = Run({"zadd", "key", "nx", "incr", "2.1", "member"});
|
resp = Run({"zadd", "key", "nx", "incr", "2.1", "member"});
|
||||||
EXPECT_THAT(resp[0], "2.1");
|
EXPECT_THAT(resp, "2.1");
|
||||||
|
|
||||||
resp = Run({"zadd", "key", "nx", "incr", "4.9", "member"});
|
resp = Run({"zadd", "key", "nx", "incr", "4.9", "member"});
|
||||||
EXPECT_THAT(resp[0], ArgType(RespExpr::NIL));
|
EXPECT_THAT(resp, ArgType(RespExpr::NIL));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ZSetFamilyTest, ByLex) {
|
TEST_F(ZSetFamilyTest, ByLex) {
|
||||||
|
@ -119,12 +121,17 @@ TEST_F(ZSetFamilyTest, ByLex) {
|
||||||
"zadd", "key", "0", "alpha", "0", "bar", "0", "cool", "0", "down",
|
"zadd", "key", "0", "alpha", "0", "bar", "0", "cool", "0", "down",
|
||||||
"0", "elephant", "0", "foo", "0", "great", "0", "hill", "0", "omega",
|
"0", "elephant", "0", "foo", "0", "great", "0", "hill", "0", "omega",
|
||||||
});
|
});
|
||||||
|
|
||||||
auto resp = Run({"zrangebylex", "key", "-", "[cool"});
|
auto resp = Run({"zrangebylex", "key", "-", "[cool"});
|
||||||
EXPECT_THAT(resp, ElementsAre("alpha", "bar", "cool"));
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
EXPECT_THAT(resp.GetVec(), ElementsAre("alpha", "bar", "cool"));
|
||||||
|
|
||||||
EXPECT_EQ(3, CheckedInt({"ZLEXCOUNT", "key", "(foo", "+"}));
|
EXPECT_EQ(3, CheckedInt({"ZLEXCOUNT", "key", "(foo", "+"}));
|
||||||
EXPECT_EQ(3, CheckedInt({"ZREMRANGEBYLEX", "key", "(foo", "+"}));
|
EXPECT_EQ(3, CheckedInt({"ZREMRANGEBYLEX", "key", "(foo", "+"}));
|
||||||
EXPECT_THAT(Run({"zrangebylex", "key", "[a", "+"}),
|
|
||||||
ElementsAre("alpha", "bar", "cool", "down", "elephant", "foo"));
|
resp = Run({"zrangebylex", "key", "[a", "+"});
|
||||||
|
ASSERT_THAT(resp, ArgType(RespExpr::ARRAY));
|
||||||
|
ASSERT_THAT(resp.GetVec(), ElementsAre("alpha", "bar", "cool", "down", "elephant", "foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue