diff --git a/src/facade/facade_test.cc b/src/facade/facade_test.cc index f710d5f5f..3b612670d 100644 --- a/src/facade/facade_test.cc +++ b/src/facade/facade_test.cc @@ -57,6 +57,9 @@ void RespMatcher::DescribeTo(std::ostream* os) const { case RespExpr::INT64: *os << exp_str_; break; + case RespExpr::ARRAY: + *os << "array of length " << exp_int_; + break; default: *os << "TBD"; break; diff --git a/src/facade/facade_test.h b/src/facade/facade_test.h index 986a66191..7f9d30ac7 100644 --- a/src/facade/facade_test.h +++ b/src/facade/facade_test.h @@ -50,10 +50,6 @@ class RespTypeMatcher { RespExpr::Type type_; }; -inline ::testing::PolymorphicMatcher StrArg(std::string_view str) { - return ::testing::MakePolymorphicMatcher(RespMatcher(str)); -} - inline ::testing::PolymorphicMatcher ErrArg(std::string_view str) { return ::testing::MakePolymorphicMatcher(RespMatcher(str, RespExpr::ERROR)); } @@ -70,14 +66,10 @@ inline ::testing::PolymorphicMatcher ArgType(RespExpr::Type 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; } 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 diff --git a/src/facade/redis_parser_test.cc b/src/facade/redis_parser_test.cc index c691807c2..0be6dc614 100644 --- a/src/facade/redis_parser_test.cc +++ b/src/facade/redis_parser_test.cc @@ -60,7 +60,7 @@ TEST_F(RedisParserTest, Inline) { ASSERT_EQ(RedisParser::OK, Parse(kCmd1)); 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")); EXPECT_EQ(3, consumed_); @@ -70,7 +70,7 @@ TEST_F(RedisParserTest, Inline) { EXPECT_EQ(4, consumed_); ASSERT_EQ(RedisParser::OK, Parse(" \r\n ")); 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")); EXPECT_EQ(4, consumed_); @@ -78,7 +78,7 @@ TEST_F(RedisParserTest, Inline) { EXPECT_EQ(3, consumed_); ASSERT_EQ(RedisParser::OK, Parse("\r\n")); 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. EXPECT_EQ(RedisParser::OK, Parse("\r\n")); @@ -101,7 +101,7 @@ TEST_F(RedisParserTest, Multi1) { ASSERT_EQ(RedisParser::OK, Parse("PING\r\n")); EXPECT_EQ(6, consumed_); EXPECT_EQ(0, parser_.parselen_hint()); - EXPECT_THAT(args_, ElementsAre(StrArg("PING"))); + EXPECT_THAT(args_, ElementsAre("PING")); } TEST_F(RedisParserTest, Multi2) { @@ -140,7 +140,7 @@ TEST_F(RedisParserTest, ClientMode) { EXPECT_THAT(args_, ElementsAre(IntArg(-1))); 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")); 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"; string resp = absl::StrCat("*3\r\n$3\r\n900\r\n$3\r\n800\r\n", kThirdArg); ASSERT_EQ(RedisParser::OK, Parse(resp)); - EXPECT_THAT(args_, ElementsAre(StrArg("900"), StrArg("800"), ArrArg(2))); - EXPECT_THAT(*get(args_[2].u), ElementsAre(StrArg("100"), StrArg("200"))); + EXPECT_THAT(args_, ElementsAre("900", "800", ArrArg(2))); + EXPECT_THAT(*get(args_[2].u), ElementsAre("100", "200")); } TEST_F(RedisParserTest, InvalidMult1) { diff --git a/src/facade/resp_expr.h b/src/facade/resp_expr.h index f927db64a..bfc81cb77 100644 --- a/src/facade/resp_expr.h +++ b/src/facade/resp_expr.h @@ -35,6 +35,10 @@ class RespExpr { return std::get(u); } + const Vec& GetVec() const { + return *std::get(u); + } + static const char* TypeName(Type t); }; diff --git a/src/server/dragonfly_test.cc b/src/server/dragonfly_test.cc index 622a782cc..2ffe4fca0 100644 --- a/src/server/dragonfly_test.cc +++ b/src/server/dragonfly_test.cc @@ -1,4 +1,4 @@ -// Copyright 2021, Roman Gershman. All rights reserved. +// Copyright 2022, Roman Gershman. All rights reserved. // See LICENSE for licensing terms. // @@ -79,17 +79,18 @@ TEST_F(DflyEngineTest, Sds) { } TEST_F(DflyEngineTest, Multi) { - RespVec resp = Run({"multi"}); - ASSERT_THAT(resp, RespEq("OK")); + RespExpr resp = Run({"multi"}); + ASSERT_EQ(resp, "OK"); resp = Run({"get", kKey1}); - ASSERT_THAT(resp, RespEq("QUEUED")); + ASSERT_EQ(resp, "QUEUED"); resp = Run({"get", kKey4}); - ASSERT_THAT(resp, RespEq("QUEUED")); + ASSERT_EQ(resp, "QUEUED"); 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; @@ -100,7 +101,7 @@ TEST_F(DflyEngineTest, Multi) { EXPECT_TRUE(tx_empty); 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, kKey4)); @@ -108,71 +109,76 @@ TEST_F(DflyEngineTest, Multi) { } TEST_F(DflyEngineTest, MultiEmpty) { - RespVec resp = Run({"multi"}); - ASSERT_THAT(resp, RespEq("OK")); + RespExpr resp = Run({"multi"}); + ASSERT_EQ(resp, "OK"); resp = Run({"exec"}); - ASSERT_THAT(resp[0], ArrLen(0)); + ASSERT_THAT(resp, ArrLen(0)); ASSERT_FALSE(service_->IsShardSetLocked()); Run({"multi"}); - ASSERT_THAT(Run({"ping", "foo"}), RespEq("QUEUED")); - EXPECT_THAT(Run({"exec"}), ElementsAre("foo")); + ASSERT_EQ(Run({"ping", "foo"}), "QUEUED"); + resp = Run({"exec"}); + // one cell arrays are promoted to respexpr. + EXPECT_EQ(resp, "foo"); } TEST_F(DflyEngineTest, MultiSeq) { - RespVec resp = Run({"multi"}); - ASSERT_THAT(resp, RespEq("OK")); + RespExpr resp = Run({"multi"}); + ASSERT_EQ(resp, "OK"); resp = Run({"set", kKey1, absl::StrCat(1)}); - ASSERT_THAT(resp, RespEq("QUEUED")); + ASSERT_EQ(resp, "QUEUED"); resp = Run({"get", kKey1}); - ASSERT_THAT(resp, RespEq("QUEUED")); + ASSERT_EQ(resp, "QUEUED"); resp = Run({"mget", kKey1, kKey4}); - ASSERT_THAT(resp, RespEq("QUEUED")); + ASSERT_EQ(resp, "QUEUED"); resp = Run({"exec"}); ASSERT_FALSE(service_->IsLocked(0, kKey1)); ASSERT_FALSE(service_->IsLocked(0, kKey4)); ASSERT_FALSE(service_->IsShardSetLocked()); - EXPECT_THAT(resp, ElementsAre(StrArg("OK"), StrArg("1"), ArrLen(2))); - const RespExpr::Vec& arr = *get(resp[2].u); - ASSERT_THAT(arr, ElementsAre("1", ArgType(RespExpr::NIL))); + ASSERT_THAT(resp, ArrLen(3)); + const auto& arr = resp.GetVec(); + EXPECT_THAT(arr, ElementsAre("OK", "1", ArrLen(2))); + + ASSERT_THAT(arr[2].GetVec(), ElementsAre("1", ArgType(RespExpr::NIL))); } TEST_F(DflyEngineTest, MultiConsistent) { auto mset_fb = pp_->at(0)->LaunchFiber([&] { for (size_t i = 1; i < 10; ++i) { string base = StrCat(i * 900); - RespVec resp = Run({"mset", kKey1, base, kKey4, base}); - ASSERT_THAT(resp, RespEq("OK")); + RespExpr resp = Run({"mset", kKey1, base, kKey4, base}); + ASSERT_EQ(resp, "OK"); } }); auto fb = pp_->at(1)->LaunchFiber([&] { - RespVec resp = Run({"multi"}); - ASSERT_THAT(resp, RespEq("OK")); + RespExpr resp = Run({"multi"}); + ASSERT_EQ(resp, "OK"); this_fiber::sleep_for(1ms); resp = Run({"get", kKey1}); - ASSERT_THAT(resp, RespEq("QUEUED")); + ASSERT_EQ(resp, "QUEUED"); resp = Run({"get", kKey4}); - ASSERT_THAT(resp, RespEq("QUEUED")); + ASSERT_EQ(resp, "QUEUED"); resp = Run({"mget", kKey4, kKey1}); - ASSERT_THAT(resp, RespEq("QUEUED")); + ASSERT_EQ(resp, "QUEUED"); resp = Run({"exec"}); - - EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::STRING), ArgType(RespExpr::STRING), - ArgType(RespExpr::ARRAY))); - ASSERT_EQ(resp[0].GetBuf(), resp[1].GetBuf()); - const RespVec& arr = *get(resp[2].u); - EXPECT_THAT(arr, ElementsAre(ArgType(RespExpr::STRING), ArgType(RespExpr::STRING))); - EXPECT_EQ(arr[0].GetBuf(), arr[1].GetBuf()); - EXPECT_EQ(arr[0].GetBuf(), resp[0].GetBuf()); + ASSERT_THAT(resp, ArrLen(3)); + const RespVec& resp_arr = resp.GetVec(); + ASSERT_THAT(resp_arr, ElementsAre(ArgType(RespExpr::STRING), ArgType(RespExpr::STRING), + ArgType(RespExpr::ARRAY))); + ASSERT_EQ(resp_arr[0].GetBuf(), resp_arr[1].GetBuf()); + const RespVec& sub_arr = resp_arr[2].GetVec(); + EXPECT_THAT(sub_arr, ElementsAre(ArgType(RespExpr::STRING), ArgType(RespExpr::STRING))); + EXPECT_EQ(sub_arr[0].GetBuf(), sub_arr[1].GetBuf()); + EXPECT_EQ(sub_arr[0].GetBuf(), resp_arr[0].GetBuf()); }); mset_fb.join(); @@ -184,20 +190,21 @@ TEST_F(DflyEngineTest, MultiConsistent) { TEST_F(DflyEngineTest, MultiWeirdCommands) { Run({"multi"}); - ASSERT_THAT(Run({"eval", "return 42", "0"}), RespEq("QUEUED")); - EXPECT_THAT(Run({"exec"}), ElementsAre(IntArg(42))); + ASSERT_EQ(Run({"eval", "return 42", "0"}), "QUEUED"); + EXPECT_THAT(Run({"exec"}), IntArg(42)); } TEST_F(DflyEngineTest, MultiRename) { - RespVec resp = Run({"multi"}); - ASSERT_THAT(resp, RespEq("OK")); + RespExpr resp = Run({"multi"}); + ASSERT_EQ(resp, "OK"); Run({"set", kKey1, "1"}); resp = Run({"rename", kKey1, kKey4}); - ASSERT_THAT(resp, RespEq("QUEUED")); + ASSERT_EQ(resp, "QUEUED"); 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, kKey4)); ASSERT_FALSE(service_->IsShardSetLocked()); @@ -209,11 +216,11 @@ TEST_F(DflyEngineTest, MultiHop) { auto p1_fb = pp_->at(1)->LaunchFiber([&] { for (int i = 0; i < 100; ++i) { auto resp = Run({"rename", kKey1, kKey2}); - ASSERT_THAT(resp, RespEq("OK")); + ASSERT_EQ(resp, "OK"); EXPECT_EQ(2, GetDebugInfo("IO1").shards_count); 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) { Run({"mset", kKey1, "1", kKey4, "2"}); auto resp = Run({"flushdb"}); - ASSERT_THAT(resp, RespEq("OK")); + ASSERT_EQ(resp, "OK"); auto fb0 = pp_->at(0)->LaunchFiber([&] { for (unsigned i = 0; i < 100; ++i) { @@ -244,8 +251,7 @@ TEST_F(DflyEngineTest, FlushDb) { pp_->at(1)->Await([&] { for (unsigned i = 0; i < 100; ++i) { Run({"mset", kKey1, "1", kKey4, "2"}); - auto resp = Run({"exists", kKey1, kKey4}); - int64_t ival = get(resp[0].u); + int64_t ival = CheckedInt({"exists", kKey1, kKey4}); ASSERT_TRUE(ival == 0 || ival == 2) << i << " " << ival; } }); @@ -259,21 +265,21 @@ TEST_F(DflyEngineTest, FlushDb) { TEST_F(DflyEngineTest, Eval) { 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"}); - EXPECT_THAT(resp[0], ErrArg("undeclared")); + EXPECT_THAT(resp, ErrArg("undeclared")); 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")); 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"}); - EXPECT_THAT(resp[0], StrArg("42")); + EXPECT_THAT(resp, "42"); ASSERT_FALSE(service_->IsLocked(0, "foo")); ASSERT_FALSE(service_->IsShardSetLocked()); @@ -281,30 +287,31 @@ TEST_F(DflyEngineTest, Eval) { TEST_F(DflyEngineTest, EvalResp) { 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"}); - 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) { 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"}); - EXPECT_THAT(resp[0], IntArg(5)); + EXPECT_THAT(resp, IntArg(5)); resp = Run({"script", "load", " return 5 "}); - EXPECT_THAT(resp, ElementsAre(StrArg(sha))); + EXPECT_EQ(resp, sha); absl::AsciiStrToUpper(&sha); resp = Run({"evalsha", sha, "0"}); - EXPECT_THAT(resp[0], IntArg(5)); + EXPECT_THAT(resp, IntArg(5)); resp = Run({"evalsha", "foobar", "0"}); - EXPECT_THAT(resp[0], ErrArg("No matching")); + EXPECT_THAT(resp, ErrArg("No matching")); } TEST_F(DflyEngineTest, Memcache) { @@ -345,7 +352,7 @@ TEST_F(DflyEngineTest, LimitMemory) { string blob(128, 'a'); for (size_t i = 0; i < 10000; ++i) { auto resp = Run({"set", absl::StrCat(blob, i), blob}); - ASSERT_THAT(resp, RespEq("OK")); + ASSERT_EQ(resp, "OK"); } } diff --git a/src/server/generic_family_test.cc b/src/server/generic_family_test.cc index 3b4185173..6690ad0dc 100644 --- a/src/server/generic_family_test.cc +++ b/src/server/generic_family_test.cc @@ -29,26 +29,26 @@ TEST_F(GenericFamilyTest, Expire) { Run({"set", "key", "val"}); auto resp = Run({"expire", "key", "1"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); UpdateTime(expire_now_ + 1000); resp = Run({"get", "key"}); - EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::NIL))); + EXPECT_THAT(resp, ArgType(RespExpr::NIL)); Run({"set", "key", "val"}); resp = Run({"pexpireat", "key", absl::StrCat(expire_now_ + 2000)}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); // override resp = Run({"pexpireat", "key", absl::StrCat(expire_now_ + 3000)}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); UpdateTime(expire_now_ + 2999); resp = Run({"get", "key"}); - EXPECT_THAT(resp[0], "val"); + EXPECT_THAT(resp, "val"); UpdateTime(expire_now_ + 3000); resp = Run({"get", "key"}); - EXPECT_THAT(resp[0], ArgType(RespExpr::NIL)); + EXPECT_THAT(resp, ArgType(RespExpr::NIL)); } TEST_F(GenericFamilyTest, Del) { @@ -88,28 +88,28 @@ TEST_F(GenericFamilyTest, TTL) { TEST_F(GenericFamilyTest, Exists) { Run({"mset", "x", "0", "y", "1"}); auto resp = Run({"exists", "x", "y", "x"}); - EXPECT_THAT(resp[0], IntArg(3)); + EXPECT_THAT(resp, IntArg(3)); } TEST_F(GenericFamilyTest, Rename) { - RespVec resp; + RespExpr resp; string b_val(32, 'b'); string x_val(32, 'x'); 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); 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"}); - ASSERT_THAT(resp, RespEq("OK")); + ASSERT_EQ(resp, "OK"); int64_t val = CheckedInt({"get", "x"}); 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); @@ -118,7 +118,7 @@ TEST_F(GenericFamilyTest, Rename) { for (size_t i = 0; i < 200; ++i) { int j = i % 2; 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) { EXPECT_EQ(1, CheckedInt({"lpush", "x", "elem"})); auto resp = Run({"rename", "x", "b"}); - ASSERT_THAT(resp, RespEq("OK")); + ASSERT_EQ(resp, "OK"); ASSERT_EQ(2, last_cmd_dbg_info_.shards_count); EXPECT_EQ(0, CheckedInt({"del", "x"})); @@ -149,13 +149,13 @@ TEST_F(GenericFamilyTest, RenameBinary) { Run({"set", kKey1, "bar"}); Run({"rename", kKey1, kKey2}); - EXPECT_THAT(Run({"get", kKey1}), ElementsAre(ArgType(RespExpr::NIL))); - EXPECT_THAT(Run({"get", kKey2}), RespEq("bar")); + EXPECT_THAT(Run({"get", kKey1}), ArgType(RespExpr::NIL)); + EXPECT_EQ(Run({"get", kKey2}), "bar"); } +using testing::AnyOf; using testing::Each; using testing::StartsWith; -using testing::AnyOf; TEST_F(GenericFamilyTest, Scan) { for (unsigned i = 0; i < 10; ++i) @@ -171,13 +171,13 @@ TEST_F(GenericFamilyTest, Scan) { 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_THAT(resp, ArrLen(2)); + auto vec = StrArray(resp.GetVec()[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]); + vec = StrArray(resp.GetVec()[1]); EXPECT_EQ(10, vec.size()); EXPECT_THAT(vec, Each(StartsWith("zset"))); } diff --git a/src/server/hset_family_test.cc b/src/server/hset_family_test.cc index 1ed3c4001..f2d9b5b69 100644 --- a/src/server/hset_family_test.cc +++ b/src/server/hset_family_test.cc @@ -39,9 +39,9 @@ TEST_F(HSetFamilyTest, Hash) { TEST_F(HSetFamilyTest, Basic) { 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({"hlen", "x"})); @@ -57,7 +57,7 @@ TEST_F(HSetFamilyTest, Basic) { EXPECT_EQ(2, CheckedInt({"hset", "y", "a", "c", "d", "e"})); 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) { @@ -72,37 +72,42 @@ TEST_F(HSetFamilyTest, HSet) { TEST_F(HSetFamilyTest, Get) { 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"}); - 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"}); - 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"}); - 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"}); - 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"}); - 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) { 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_THAT(Run({"hget", "key", "field"}), RespEq("val")); + EXPECT_EQ(Run({"hget", "key", "field"}), "val"); 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 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) { @@ -110,7 +115,7 @@ TEST_F(HSetFamilyTest, HIncr) { Run({"hset", "key", "a", " 1"}); 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 diff --git a/src/server/list_family_test.cc b/src/server/list_family_test.cc index b74030786..ba25153e1 100644 --- a/src/server/list_family_test.cc +++ b/src/server/list_family_test.cc @@ -38,46 +38,48 @@ const char kKey3[] = "c"; TEST_F(ListFamilyTest, Basic) { auto resp = Run({"lpush", kKey1, "1"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); resp = Run({"lpush", kKey2, "2"}); - ASSERT_THAT(resp[0], IntArg(1)); + ASSERT_THAT(resp, IntArg(1)); resp = Run({"llen", kKey1}); - ASSERT_THAT(resp[0], IntArg(1)); + ASSERT_THAT(resp, IntArg(1)); } TEST_F(ListFamilyTest, Expire) { auto resp = Run({"lpush", kKey1, "1"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); resp = Run({"expire", kKey1, "1"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); UpdateTime(expire_now_ + 1000); resp = Run({"lpush", kKey1, "1"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); } TEST_F(ListFamilyTest, BLPopUnblocking) { auto resp = Run({"lpush", kKey1, "1"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); resp = Run({"lpush", kKey2, "2"}); - ASSERT_THAT(resp, ElementsAre(IntArg(1))); + ASSERT_THAT(resp, IntArg(1)); 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"}); 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"}); - EXPECT_THAT(resp, ElementsAre(kKey2, "2")); + ASSERT_THAT(resp, ArrLen(2)); + EXPECT_THAT(resp.GetVec(), ElementsAre(kKey2, "2")); Run({"set", "z", "1"}); 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, "y")); @@ -85,7 +87,7 @@ TEST_F(ListFamilyTest, BLPopUnblocking) { } TEST_F(ListFamilyTest, BLPopBlocking) { - RespVec resp0, resp1; + RespExpr resp0, resp1; // Run the fiber at creation. 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 epoch1 = GetDebugInfo("IO1").clock; ASSERT_LT(epoch0, epoch1); - - EXPECT_THAT(resp0, ElementsAre("x", "1")); + ASSERT_THAT(resp0, ArrLen(2)); + EXPECT_THAT(resp0.GetVec(), ElementsAre("x", "1")); ASSERT_FALSE(IsLocked(0, "x")); } TEST_F(ListFamilyTest, BLPopMultiple) { - RespVec resp0, resp1; + RespExpr resp0, resp1; 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_FALSE(IsLocked(0, kKey1)); @@ -131,65 +133,74 @@ TEST_F(ListFamilyTest, BLPopMultiple) { pp_->at(1)->Await([&] { Run({"lpush", kKey1, "1", "2", "3"}); }); 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, kKey2)); ess_->RunBriefInParallel([](EngineShard* es) { ASSERT_FALSE(es->HasAwakedTransaction()); }); } TEST_F(ListFamilyTest, BLPopTimeout) { - RespVec resp = Run({"blpop", kKey1, kKey2, kKey3, "0.01"}); - EXPECT_THAT(resp[0], ArgType(RespExpr::NIL_ARRAY)); + RespExpr resp = Run({"blpop", kKey1, kKey2, kKey3, "0.01"}); + EXPECT_THAT(resp, ArgType(RespExpr::NIL_ARRAY)); EXPECT_EQ(3, GetDebugInfo().shards_count); ASSERT_FALSE(service_->IsLocked(0, kKey1)); // Under Multi resp = Run({"multi"}); - ASSERT_THAT(resp, RespEq("OK")); + ASSERT_EQ(resp, "OK"); Run({"blpop", kKey1, "0"}); resp = Run({"exec"}); - EXPECT_THAT(resp, ElementsAre(ArgType(RespExpr::NIL_ARRAY))); + EXPECT_THAT(resp, ArgType(RespExpr::NIL_ARRAY)); ASSERT_FALSE(service_->IsLocked(0, kKey1)); } TEST_F(ListFamilyTest, LRem) { 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"}); - ASSERT_THAT(resp, ElementsAre(IntArg(2))); - ASSERT_THAT(Run({"lrange", kKey1, "0", "1"}), ElementsAre("b", "c")); + ASSERT_THAT(resp, IntArg(2)); + + resp = Run({"lrange", kKey1, "0", "1"}); + ASSERT_THAT(resp, ArrLen(2)); + ASSERT_THAT(resp.GetVec(), ElementsAre("b", "c")); } TEST_F(ListFamilyTest, LTrim) { Run({"rpush", kKey1, "a", "b", "c", "d"}); - ASSERT_THAT(Run({"ltrim", kKey1, "-2", "-1"}), RespEq("OK")); - ASSERT_THAT(Run({"lrange", kKey1, "0", "1"}), ElementsAre("c", "d")); - ASSERT_THAT(Run({"ltrim", kKey1, "0", "0"}), RespEq("OK")); - ASSERT_THAT(Run({"lrange", kKey1, "0", "1"}), ElementsAre("c")); + ASSERT_EQ(Run({"ltrim", kKey1, "-2", "-1"}), "OK"); + auto resp = Run({"lrange", kKey1, "0", "1"}); + ASSERT_THAT(resp, ArrLen(2)); + 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) { auto resp = Run({"lrange", kKey1, "0", "5"}); - ASSERT_THAT(resp[0], ArrLen(0)); + ASSERT_THAT(resp, ArrLen(0)); Run({"rpush", kKey1, "0", "1", "2"}); 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) { Run({"rpush", kKey1, "0", "1", "2"}); - ASSERT_THAT(Run({"lset", kKey1, "0", "bar"}), RespEq("OK")); - ASSERT_THAT(Run({"lpop", kKey1}), RespEq("bar")); - ASSERT_THAT(Run({"lset", kKey1, "-1", "foo"}), RespEq("OK")); - ASSERT_THAT(Run({"rpop", kKey1}), RespEq("foo")); + ASSERT_EQ(Run({"lset", kKey1, "0", "bar"}), "OK"); + ASSERT_EQ(Run({"lpop", kKey1}), "bar"); + ASSERT_EQ(Run({"lset", kKey1, "-1", "foo"}), "OK"); + ASSERT_EQ(Run({"rpop", kKey1}), "foo"); 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) { - RespVec blpop_resp; + RespExpr blpop_resp; auto pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] { blpop_resp = Run({"blpop", kKey1, kKey2, kKey3, "0"}); @@ -202,11 +213,10 @@ TEST_F(ListFamilyTest, BLPopSerialize) { LOG(INFO) << "Starting multi"; TxClock cl1, cl2; - unsigned key1_len1 = 0, key1_len2 = 0; auto p1_fb = pp_->at(1)->LaunchFiber([&] { 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"}); 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) // blpop will be triggerred and it will empty the list again. Hence, in any case // lpush kKey1 here and below should return 1. - EXPECT_THAT(resp, ElementsAre(IntArg(1))); - key1_len1 = get(resp[0].u); + ASSERT_THAT(resp, IntArg(1)); cl1 = GetDebugInfo("IO1").clock; LOG(INFO) << "push1 ts: " << cl1; }); auto p2_fb = pp_->at(2)->LaunchFiber([&] { 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", kKey2, "C"}); resp = Run({"exec"}); - EXPECT_THAT(resp, ElementsAre(IntArg(1), IntArg(1))); - key1_len2 = get(resp[0].u); + + ASSERT_THAT(resp, ArrLen(2)); + EXPECT_THAT(resp.GetVec(), ElementsAre(IntArg(1), IntArg(1))); cl2 = GetDebugInfo("IO2").clock; LOG(INFO) << "push2 ts: " << cl2; }); @@ -236,17 +246,19 @@ TEST_F(ListFamilyTest, BLPopSerialize) { p2_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) { - EXPECT_EQ(blpop_resp[1], "B"); + EXPECT_EQ(resp_arr[1], "B"); } else { - EXPECT_EQ(blpop_resp[1], "A"); + EXPECT_EQ(resp_arr[1], "A"); } } TEST_F(ListFamilyTest, WrongTypeDoesNotWake) { - RespVec blpop_resp; + RespExpr blpop_resp; auto pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] { blpop_resp = Run({"blpop", kKey1, "0"}); @@ -262,7 +274,7 @@ TEST_F(ListFamilyTest, WrongTypeDoesNotWake) { Run({"set", kKey1, "foo"}); auto resp = Run({"exec"}); - EXPECT_THAT(resp, ElementsAre(IntArg(1), "OK")); + EXPECT_THAT(resp.GetVec(), ElementsAre(IntArg(1), "OK")); Run({"del", kKey1}); Run({"lpush", kKey1, "B"}); @@ -270,11 +282,12 @@ TEST_F(ListFamilyTest, WrongTypeDoesNotWake) { p1_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) { - RespVec blpop_resp; + RespExpr blpop_resp; auto pop_fb = pp_->at(0)->LaunchFiber(fibers::launch::dispatch, [&] { blpop_resp = Run({"blpop", kKey1, kKey2, kKey2, kKey1, "0"}); @@ -288,7 +301,9 @@ TEST_F(ListFamilyTest, BPopSameKeyTwice) { EXPECT_EQ(1, CheckedInt({"lpush", kKey1, "bar"})); }); 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, [&] { blpop_resp = Run({"blpop", kKey1, kKey2, kKey2, kKey1, "0"}); @@ -302,11 +317,13 @@ TEST_F(ListFamilyTest, BPopSameKeyTwice) { EXPECT_EQ(1, CheckedInt({"lpush", kKey2, "bar"})); }); 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) { - RespVec blpop_resp; + RespExpr blpop_resp; Run({"exists", kKey1, kKey2}); ASSERT_EQ(2, GetDebugInfo().shards_count); @@ -324,7 +341,9 @@ TEST_F(ListFamilyTest, BPopRename) { Run({"rename", "a", kKey1}); }); 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 diff --git a/src/server/rdb_test.cc b/src/server/rdb_test.cc index ae1ed6e89..09a2cfa67 100644 --- a/src/server/rdb_test.cc +++ b/src/server/rdb_test.cc @@ -83,14 +83,18 @@ TEST_F(RdbTest, LoadSmall6) { auto ec = loader.Load(&fs); CHECK(!ec); 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", "zset_zl", "hset_ht", "intkey", "strkey")); 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. - 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. } diff --git a/src/server/set_family_test.cc b/src/server/set_family_test.cc index 60fe631dd..d2c8fcb74 100644 --- a/src/server/set_family_test.cc +++ b/src/server/set_family_test.cc @@ -23,23 +23,23 @@ class SetFamilyTest : public BaseFamilyTest { TEST_F(SetFamilyTest, SAdd) { 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"}); - EXPECT_THAT(resp[0], IntArg(0)); + EXPECT_THAT(resp, IntArg(0)); Run({"set", "a", "foo"}); resp = Run({"sadd", "a", "b"}); - EXPECT_THAT(resp[0], ErrArg("WRONGTYPE ")); + EXPECT_THAT(resp, ErrArg("WRONGTYPE ")); resp = Run({"type", "x"}); - EXPECT_THAT(resp, RespEq("set")); + EXPECT_EQ(resp, "set"); } TEST_F(SetFamilyTest, IntConv) { auto resp = Run({"sadd", "x", "134"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); resp = Run({"sadd", "x", "abc"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); resp = Run({"sadd", "x", "134"}); - EXPECT_THAT(resp[0], IntArg(0)); + EXPECT_THAT(resp, IntArg(0)); } TEST_F(SetFamilyTest, SUnionStore) { @@ -47,25 +47,29 @@ TEST_F(SetFamilyTest, SUnionStore) { Run({"sadd", "c", "10", "11"}); Run({"set", "a", "foo"}); resp = Run({"sunionstore", "a", "b", "c"}); - EXPECT_THAT(resp[0], IntArg(5)); + EXPECT_THAT(resp, IntArg(5)); resp = Run({"type", "a"}); - ASSERT_THAT(resp, RespEq("set")); + ASSERT_EQ(resp, "set"); 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) { auto resp = Run({"sadd", "b", "1", "2", "3"}); Run({"sadd", "c", "10", "11"}); Run({"set", "a", "foo"}); + 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"}); - EXPECT_THAT(resp[0], IntArg(3)); + EXPECT_THAT(resp, IntArg(3)); 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", "foo", "c"}); @@ -77,50 +81,53 @@ TEST_F(SetFamilyTest, SInter) { auto resp = Run({"sadd", "a", "1", "2", "3", "4"}); Run({"sadd", "b", "3", "5", "6", "2"}); resp = Run({"sinterstore", "d", "a", "b"}); - EXPECT_THAT(resp[0], IntArg(2)); + EXPECT_THAT(resp, IntArg(2)); 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", ""}); resp = Run({"sinter", "x", "y"}); 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) { auto resp = Run({"sadd", "a", "1", "2", "3", "4"}); Run({"sadd", "b", "3", "5", "6", "2"}); 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", "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) { auto resp = Run({"sadd", "x", "1", "2", "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"}); - EXPECT_THAT(resp, RespEq("none")); + EXPECT_EQ(resp, "none"); Run({"sadd", "x", "1", "2", "3"}); 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"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); Run({"sadd", "y", "a", "b", "c"}); resp = Run({"spop", "y", "1"}); - EXPECT_THAT(resp, IsSubsetOf({"a", "b", "c"})); - EXPECT_EQ(1, resp.size()); + EXPECT_THAT(resp, ArgType(RespExpr::STRING)); + EXPECT_THAT(resp, testing::AnyOf("a", "b", "c")); resp = Run({"smembers", "y"}); - EXPECT_THAT(resp, IsSubsetOf({"a", "b", "c"})); - EXPECT_EQ(2, resp.size()); + ASSERT_THAT(resp, ArrLen(2)); + EXPECT_THAT(resp.GetVec(), IsSubsetOf({"a", "b", "c"})); } } // namespace dfly diff --git a/src/server/string_family_test.cc b/src/server/string_family_test.cc index ba2559de1..f7313fb21 100644 --- a/src/server/string_family_test.cc +++ b/src/server/string_family_test.cc @@ -26,83 +26,98 @@ class StringFamilyTest : public BaseFamilyTest { protected: }; +vector ToIntArr(const RespExpr& e) { + vector res; + CHECK_EQ(e.type, RespExpr::ARRAY); + const RespVec* vec = get(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) { auto resp = Run({"set", "key", "val"}); - EXPECT_THAT(resp, RespEq("OK")); - EXPECT_THAT(Run({"get", "key"}), RespEq("val")); - EXPECT_THAT(Run({"set", "key1", "1"}), RespEq("OK")); - EXPECT_THAT(Run({"get", "key1"}), RespEq("1")); - EXPECT_THAT(Run({"set", "key", "2"}), RespEq("OK")); - EXPECT_THAT(Run({"get", "key"}), RespEq("2")); + EXPECT_EQ(resp, "OK"); + EXPECT_EQ(Run({"get", "key"}), "val"); + EXPECT_EQ(Run({"set", "key1", "1"}), "OK"); + EXPECT_EQ(Run({"get", "key1"}), "1"); + EXPECT_EQ(Run({"set", "key", "2"}), "OK"); + EXPECT_EQ(Run({"get", "key"}), "2"); } TEST_F(StringFamilyTest, Incr) { - ASSERT_THAT(Run({"set", "key", "0"}), RespEq("OK")); - ASSERT_THAT(Run({"incr", "key"}), ElementsAre(IntArg(1))); + ASSERT_EQ(Run({"set", "key", "0"}), "OK"); + ASSERT_THAT(Run({"incr", "key"}), IntArg(1)); - ASSERT_THAT(Run({"set", "key1", "123456789"}), RespEq("OK")); - ASSERT_THAT(Run({"incrby", "key1", "0"}), ElementsAre(IntArg(123456789))); + ASSERT_EQ(Run({"set", "key1", "123456789"}), "OK"); + ASSERT_THAT(Run({"incrby", "key1", "0"}), IntArg(123456789)); - ASSERT_THAT(Run({"set", "key1", "-123456789"}), RespEq("OK")); - ASSERT_THAT(Run({"incrby", "key1", "0"}), ElementsAre(IntArg(-123456789))); + ASSERT_EQ(Run({"set", "key1", "-123456789"}), "OK"); + ASSERT_THAT(Run({"incrby", "key1", "0"}), IntArg(-123456789)); - ASSERT_THAT(Run({"set", "key1", " -123 "}), RespEq("OK")); - ASSERT_THAT(Run({"incrby", "key1", "1"}), ElementsAre(ErrArg("ERR value is not an integer"))); + ASSERT_EQ(Run({"set", "key1", " -123 "}), "OK"); + 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({"decrby", "a", "-9223372036854775808"}), ElementsAre(ErrArg("overflow"))); + ASSERT_THAT(Run({"incrby", "ne", "0"}), IntArg(0)); + ASSERT_THAT(Run({"decrby", "a", "-9223372036854775808"}), ErrArg("overflow")); } TEST_F(StringFamilyTest, Append) { Run({"setex", "key", "100", "val"}); - EXPECT_THAT(Run({"append", "key", "bar"}), ElementsAre(IntArg(6))); - EXPECT_THAT(Run({"ttl", "key"}), ElementsAre(IntArg(100))); + EXPECT_THAT(Run({"append", "key", "bar"}), IntArg(6)); + EXPECT_THAT(Run({"ttl", "key"}), IntArg(100)); } 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); - EXPECT_THAT(Run({"get", "key"}), RespEq("val")); + EXPECT_EQ(Run({"get", "key"}), "val"); 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({"incr", "i"}), ElementsAre(IntArg(2))); + ASSERT_THAT(Run({"set", "i", "1", "PX", "10"}), "OK"); + ASSERT_THAT(Run({"incr", "i"}), IntArg(2)); UpdateTime(expire_now_ + 30); - ASSERT_THAT(Run({"incr", "i"}), ElementsAre(IntArg(1))); + ASSERT_THAT(Run({"incr", "i"}), IntArg(1)); } TEST_F(StringFamilyTest, Set) { 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"}); - ASSERT_THAT(resp, RespEq("OK")); + ASSERT_THAT(resp, "OK"); 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"}); - ASSERT_THAT(resp, RespEq("OK")); + ASSERT_THAT(resp, "OK"); 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"}); - ASSERT_THAT(resp, ElementsAre(ErrArg("invalid expire time"))); + ASSERT_THAT(resp, ErrArg("invalid expire time")); resp = Run({"set", "foo", "bar", "ex", "1"}); - ASSERT_THAT(resp, RespEq("OK")); + ASSERT_THAT(resp, "OK"); } TEST_F(StringFamilyTest, MGetSet) { Run({"mset", "z", "0"}); // single key auto resp = Run({"mget", "z"}); // single key - EXPECT_THAT(resp, RespEq("0")); + EXPECT_THAT(resp, "0"); Run({"mset", "x", "0", "b", "0"}); @@ -110,8 +125,8 @@ TEST_F(StringFamilyTest, MGetSet) { auto mget_fb = pp_->at(0)->LaunchFiber([&] { for (size_t i = 0; i < 1000; ++i) { - auto resp = Run({"mget", "b", "x"}); - ASSERT_EQ(2, resp.size()); + RespExpr resp = Run({"mget", "b", "x"}); + ASSERT_EQ(RespExpr::ARRAY, resp.type); auto ivec = ToIntArr(resp); ASSERT_GE(ivec[1], ivec[0]); @@ -147,8 +162,8 @@ TEST_F(StringFamilyTest, MSetGet) { auto mset_fb = pp_->at(0)->LaunchFiber([&] { for (size_t i = 0; i < 1000; ++i) { - RespVec resp = Run({"mset", "x", StrCat(i), "b", StrCat(i)}); - ASSERT_THAT(resp, RespEq("OK")) << i; + RespExpr resp = Run({"mset", "x", StrCat(i), "b", StrCat(i)}); + ASSERT_EQ(resp, "OK") << i; } }); @@ -187,7 +202,7 @@ TEST_F(StringFamilyTest, MSetDel) { TEST_F(StringFamilyTest, IntKey) { Run({"mset", "1", "1", "-1000", "-1000"}); auto resp = Run({"get", "1"}); - ASSERT_THAT(resp, RespEq("1")); + ASSERT_THAT(resp, "1"); } TEST_F(StringFamilyTest, SingleShard) { @@ -238,7 +253,7 @@ TEST_F(StringFamilyTest, MSetIncr) { for (size_t i = 1; i < 1000; ++i) { string base = StrCat(i * 900); 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) { - ASSERT_THAT(Run({"setex", "key", "1", "val"}), RespEq("OK")); - ASSERT_THAT(Run({"setex", "key", "10", "val"}), RespEq("OK")); - ASSERT_THAT(Run({"ttl", "key"}), ElementsAre(IntArg(10))); - ASSERT_THAT(Run({"setex", "key", "0", "val"}), ElementsAre(ErrArg("invalid expire time"))); + ASSERT_EQ(Run({"setex", "key", "1", "val"}), "OK"); + ASSERT_EQ(Run({"setex", "key", "10", "val"}), "OK"); + ASSERT_THAT(Run({"ttl", "key"}), IntArg(10)); + ASSERT_THAT(Run({"setex", "key", "0", "val"}), ErrArg("invalid expire time")); } TEST_F(StringFamilyTest, Range) { 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"}); - EXPECT_THAT(Run({"get", "key1"}), RespEq("Hello Earth")); + EXPECT_EQ(Run({"get", "key1"}), "Hello 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", ""}); EXPECT_EQ(0, CheckedInt({"exists", "key3"})); @@ -283,13 +298,13 @@ TEST_F(StringFamilyTest, Range) { EXPECT_EQ(1, CheckedInt({"exists", "key3"})); Run({"SET", "key3", "123"}); - EXPECT_THAT(Run({"getrange", "key3", "2", "3"}), RespEq("3")); - EXPECT_THAT(Run({"getrange", "key3", "3", "3"}), RespEq("")); - EXPECT_THAT(Run({"getrange", "key3", "4", "5"}), RespEq("")); + EXPECT_EQ(Run({"getrange", "key3", "2", "3"}), "3"); + EXPECT_EQ(Run({"getrange", "key3", "3", "3"}), ""); + EXPECT_EQ(Run({"getrange", "key3", "4", "5"}), ""); Run({"SET", "num", "1234"}); - EXPECT_THAT(Run({"getrange","num", "3", "5000"}), RespEq("4")); - EXPECT_THAT(Run({"getrange","num", "-5000", "10000"}), RespEq("1234")); + EXPECT_EQ(Run({"getrange","num", "3", "5000"}), "4"); + EXPECT_EQ(Run({"getrange","num", "-5000", "10000"}), "1234"); } } // namespace dfly diff --git a/src/server/test_utils.cc b/src/server/test_utils.cc index b6e11c4c7..6ef920bc2 100644 --- a/src/server/test_utils.cc +++ b/src/server/test_utils.cc @@ -34,17 +34,6 @@ static vector SplitLines(const std::string& src) { return res; } -vector ToIntArr(const RespVec& vec) { - vector 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) : dummy_conn(new facade::Connection(proto, nullptr, nullptr, nullptr)), @@ -58,6 +47,8 @@ BaseFamilyTest::BaseFamilyTest() { } BaseFamilyTest::~BaseFamilyTest() { + for (auto* v : resp_vec_) + delete v; } void BaseFamilyTest::SetUpTestSuite() { @@ -100,7 +91,7 @@ void BaseFamilyTest::UpdateTime(uint64_t ms) { ess_->RunBriefInParallel(cb); } -RespVec BaseFamilyTest::Run(initializer_list list) { +RespExpr BaseFamilyTest::Run(initializer_list list) { if (!ProactorBase::IsProactorThread()) { return pp_->at(0)->Await([&] { return this->Run(list); }); } @@ -108,7 +99,7 @@ RespVec BaseFamilyTest::Run(initializer_list list) { return Run(GetId(), list); } -RespVec BaseFamilyTest::Run(std::string_view id, std::initializer_list list) { +RespExpr BaseFamilyTest::Run(std::string_view id, std::initializer_list list) { TestConnWrapper* conn = AddFindConn(Protocol::REDIS, id); CmdArgVec args = conn->Args(list); @@ -126,8 +117,15 @@ RespVec BaseFamilyTest::Run(std::string_view id, std::initializer_listParseResponse(); + 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, @@ -203,16 +201,16 @@ auto BaseFamilyTest::GetMC(MP::CmdType cmd_type, std::initializer_list list) { - RespVec resp = Run(list); - CHECK_EQ(1u, resp.size()); - if (resp.front().type == RespExpr::INT64) { - return get(resp.front().u); + RespExpr resp = Run(list); + if (resp.type == RespExpr::INT64) { + return get(resp.u); } - if (resp.front().type == RespExpr::NIL) { + if (resp.type == RespExpr::NIL) { 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; CHECK(absl::SimpleAtoi(sv, &res)) << "|" << sv << "|"; return res; @@ -297,7 +295,7 @@ vector BaseFamilyTest::StrArray(const RespExpr& expr) { for (size_t i = 0; i < src->size(); ++i) { res[i] = ToSV(src->at(i).GetBuf()); } - + return res; } diff --git a/src/server/test_utils.h b/src/server/test_utils.h index 4f3205c0e..08dc43388 100644 --- a/src/server/test_utils.h +++ b/src/server/test_utils.h @@ -16,8 +16,6 @@ namespace dfly { using namespace facade; -std::vector ToIntArr(const RespVec& vec); - class BaseFamilyTest : public ::testing::Test { protected: BaseFamilyTest(); @@ -47,8 +45,8 @@ class BaseFamilyTest : public ::testing::Test { RespVec ParseResponse(); }; - RespVec Run(std::initializer_list list); - RespVec Run(std::string_view id, std::initializer_list list); + RespExpr Run(std::initializer_list list); + RespExpr Run(std::string_view id, std::initializer_list list); using MCResponse = std::vector; 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_; ConnectionContext::DebugInfo last_cmd_dbg_info_; uint64_t expire_now_; + std::vector resp_vec_; }; } // namespace dfly diff --git a/src/server/zset_family_test.cc b/src/server/zset_family_test.cc index ed3d84e7c..bc247a37f 100644 --- a/src/server/zset_family_test.cc +++ b/src/server/zset_family_test.cc @@ -23,53 +23,56 @@ class ZSetFamilyTest : public BaseFamilyTest { TEST_F(ZSetFamilyTest, Add) { auto resp = Run({"zadd", "x", "1.1", "a"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); resp = Run({"zscore", "x", "a"}); - EXPECT_THAT(resp[0], StrArg("1.1")); + EXPECT_THAT(resp, "1.1"); resp = Run({"zadd", "x", "2", "a"}); - EXPECT_THAT(resp[0], IntArg(0)); + EXPECT_THAT(resp, IntArg(0)); resp = Run({"zscore", "x", "a"}); - EXPECT_THAT(resp[0], StrArg("2")); + EXPECT_THAT(resp, "2"); resp = Run({"zadd", "x", "ch", "3", "a"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); resp = Run({"zscore", "x", "a"}); - EXPECT_THAT(resp[0], StrArg("3")); + EXPECT_EQ(resp, "3"); 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"; 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); } TEST_F(ZSetFamilyTest, ZRem) { 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"}); - EXPECT_THAT(resp[0], IntArg(1)); + EXPECT_THAT(resp, IntArg(1)); resp = Run({"zcard", "x"}); - EXPECT_THAT(resp[0], IntArg(1)); - EXPECT_THAT(Run({"zrange", "x", "0", "3", "byscore"}), ElementsAre("a")); - EXPECT_THAT(Run({"zrange", "x", "(-inf", "(+inf", "byscore"}), ElementsAre("a")); + EXPECT_THAT(resp, IntArg(1)); + EXPECT_THAT(Run({"zrange", "x", "0", "3", "byscore"}), "a"); + EXPECT_THAT(Run({"zrange", "x", "(-inf", "(+inf", "byscore"}), "a"); } TEST_F(ZSetFamilyTest, ZRangeRank) { 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", "-inf", "1.1"}), ElementsAre("a")); - EXPECT_THAT(Run({"zrevrangebyscore", "x", "-inf", "+inf"}), ElementsAre("b", "a")); + EXPECT_THAT(Run({"zrangebyscore", "x", "0", "(1.1"}), ArrLen(0)); + EXPECT_THAT(Run({"zrangebyscore", "x", "-inf", "1.1"}), "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(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({"zrevrank", "x", "a"})); EXPECT_EQ(0, CheckedInt({"zrevrank", "x", "b"})); - EXPECT_THAT(Run({"zrevrank", "x", "c"}), ElementsAre(ArgType(RespExpr::NIL))); - EXPECT_THAT(Run({"zrank", "y", "c"}), ElementsAre(ArgType(RespExpr::NIL))); + EXPECT_THAT(Run({"zrevrank", "x", "c"}), ArgType(RespExpr::NIL)); + EXPECT_THAT(Run({"zrank", "y", "c"}), ArgType(RespExpr::NIL)); } TEST_F(ZSetFamilyTest, ZRemRangeRank) { Run({"zadd", "x", "1.1", "a", "2.1", "b"}); - EXPECT_THAT(Run({"ZREMRANGEBYRANK", "y", "0", "1"}), ElementsAre(IntArg(0))); - EXPECT_THAT(Run({"ZREMRANGEBYRANK", "x", "0", "0"}), ElementsAre(IntArg(1))); - EXPECT_THAT(Run({"zrange", "x", "0", "5"}), ElementsAre("b")); - EXPECT_THAT(Run({"ZREMRANGEBYRANK", "x", "0", "1"}), ElementsAre(IntArg(1))); - EXPECT_THAT(Run({"type", "x"}), ElementsAre("none")); + EXPECT_THAT(Run({"ZREMRANGEBYRANK", "y", "0", "1"}), IntArg(0)); + EXPECT_THAT(Run({"ZREMRANGEBYRANK", "x", "0", "0"}), IntArg(1)); + EXPECT_EQ(Run({"zrange", "x", "0", "5"}), "b"); + EXPECT_THAT(Run({"ZREMRANGEBYRANK", "x", "0", "1"}), IntArg(1)); + EXPECT_EQ(Run({"type", "x"}), "none"); } TEST_F(ZSetFamilyTest, ZRemRangeScore) { Run({"zadd", "x", "1.1", "a", "2.1", "b"}); - EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "y", "0", "1"}), ElementsAre(IntArg(0))); - EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "x", "-inf", "1.1"}), ElementsAre(IntArg(1))); - EXPECT_THAT(Run({"zrange", "x", "0", "5"}), ElementsAre("b")); - EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "x", "(2.0", "+inf"}), ElementsAre(IntArg(1))); - EXPECT_THAT(Run({"type", "x"}), ElementsAre("none")); - EXPECT_THAT(Run({"zremrangebyscore", "x", "1", "NaN"}), - ElementsAre(ErrArg("min or max is not a float"))); + EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "y", "0", "1"}), IntArg(0)); + EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "x", "-inf", "1.1"}), IntArg(1)); + EXPECT_EQ(Run({"zrange", "x", "0", "5"}), "b"); + EXPECT_THAT(Run({"ZREMRANGEBYSCORE", "x", "(2.0", "+inf"}), IntArg(1)); + EXPECT_EQ(Run({"type", "x"}), "none"); + EXPECT_THAT(Run({"zremrangebyscore", "x", "1", "NaN"}), ErrArg("min or max is not a float")); } TEST_F(ZSetFamilyTest, IncrBy) { 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"}); - EXPECT_THAT(resp[0], "2.1"); + EXPECT_THAT(resp, "2.1"); 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) { @@ -119,12 +121,17 @@ TEST_F(ZSetFamilyTest, ByLex) { "zadd", "key", "0", "alpha", "0", "bar", "0", "cool", "0", "down", "0", "elephant", "0", "foo", "0", "great", "0", "hill", "0", "omega", }); + 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({"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