This is an automated email from the ASF dual-hosted git repository.
git-hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 5e79e7089 fix(set): return scalar for SRANDMEMBER without count (#3601)
5e79e7089 is described below
commit 5e79e7089b5b1bb56608a0f0331fbe760f5f2adf
Author: Raghav <[email protected]>
AuthorDate: Wed Sep 2 13:45:07 2026 +0100
fix(set): return scalar for SRANDMEMBER without count (#3601)
## Summary
- return a Redis-compatible bulk string for `SRANDMEMBER key`
- return nil for a missing key when count is omitted
- return a Redis-compatible array for `SRANDMEMBER key count` in both
RESP2 and RESP3, including negative counts that may contain duplicates
- add regression coverage for scalar, counted, missing-key, and raw
RESP3 reply types
Closes #2610.
## Testing
- `./x.py build build-docker --unittest --ninja -j 4`
- `./x.py check format`
- `./x.py check tidy build-docker -j 4`
- `./x.py check golangci-lint`
- `./x.py test go build-docker`
- `/workspace/build-docker/unittest` (623 passed, 1 skipped)
- `/workspace/build-docker/unittest
--gtest_filter=RedisSetTest.TakeWithoutPop`
---------
Co-authored-by: Copilot Autofix powered by AI
<[email protected]>
Co-authored-by: hulk <[email protected]>
---
src/commands/cmd_set.cc | 9 ++++++++-
tests/gocase/unit/protocol/protocol_test.go | 20 ++++++++++++++++++++
tests/gocase/unit/type/set/set_test.go | 17 +++++++++++++++--
3 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/src/commands/cmd_set.cc b/src/commands/cmd_set.cc
index e80dcfe11..664eadedd 100644
--- a/src/commands/cmd_set.cc
+++ b/src/commands/cmd_set.cc
@@ -207,6 +207,7 @@ class CommandSRandMember : public Commander {
}
count_ = *parse_result;
+ with_count_ = true;
}
return Commander::Parse(args);
}
@@ -219,12 +220,18 @@ class CommandSRandMember : public Commander {
if (!s.ok()) {
return {Status::RedisExecErr, s.ToString()};
}
- *output = conn->SetOfBulkStrings(members);
+
+ if (with_count_) {
+ *output = redis::ArrayOfBulkStrings(members);
+ } else {
+ *output = members.empty() ? conn->NilString() :
redis::BulkString(members.front());
+ }
return Status::OK();
}
private:
int count_ = 1;
+ bool with_count_ = false;
};
class CommandSMove : public Commander {
diff --git a/tests/gocase/unit/protocol/protocol_test.go
b/tests/gocase/unit/protocol/protocol_test.go
index fbf9f42c5..193223b01 100644
--- a/tests/gocase/unit/protocol/protocol_test.go
+++ b/tests/gocase/unit/protocol/protocol_test.go
@@ -298,6 +298,26 @@ func TestProtocolRESP3(t *testing.T) {
}
})
+ t.Run("SRANDMEMBER with count returns an array", func(t *testing.T) {
+ require.NoError(t, c.WriteArgs("SADD", "srandmember-resp3",
"member"))
+ c.MustRead(t, ":1")
+
+ require.NoError(t, c.WriteArgs("SRANDMEMBER",
"srandmember-resp3"))
+ c.MustReadBulkString(t, "member")
+
+ require.NoError(t, c.WriteArgs("SRANDMEMBER",
"srandmember-resp3-missing"))
+ c.MustRead(t, "_")
+
+ require.NoError(t, c.WriteArgs("SRANDMEMBER",
"srandmember-resp3-missing", "1"))
+ c.MustRead(t, "*0")
+
+ require.NoError(t, c.WriteArgs("SRANDMEMBER",
"srandmember-resp3", "-2"))
+ c.MustRead(t, "*2")
+ for range 2 {
+ c.MustReadBulkString(t, "member")
+ }
+ })
+
t.Run("multi bulk strings with null", func(t *testing.T) {
require.NoError(t, c.WriteArgs("HSET", "hash", "f1", "v1"))
c.MustRead(t, ":1")
diff --git a/tests/gocase/unit/type/set/set_test.go
b/tests/gocase/unit/type/set/set_test.go
index cb6670bfe..080e99224 100644
--- a/tests/gocase/unit/type/set/set_test.go
+++ b/tests/gocase/unit/type/set/set_test.go
@@ -664,8 +664,21 @@ var setTests = func(t *testing.T, configs
util.KvrocksServerConfigs) {
require.ErrorContains(t, rdb.Do(ctx, "spop", "myset", 1,
1).Err(), "wrong number of arguments")
})
- t.Run("SRANDMEMBER with <count> against non existing key", func(t
*testing.T) {
- require.EqualValues(t, "", rdb.SRandMember(ctx,
"nonexisting_key").Val())
+ t.Run("SRANDMEMBER result type depends on count", func(t *testing.T) {
+ CreateSet(t, rdb, ctx, "myset", []interface{}{"member"})
+
+ member := rdb.SRandMember(ctx, "myset")
+ require.NoError(t, member.Err())
+ require.Equal(t, "member", member.Val())
+
+ members := rdb.SRandMemberN(ctx, "myset", 1)
+ require.NoError(t, members.Err())
+ require.Equal(t, []string{"member"}, members.Val())
+
+ require.ErrorIs(t, rdb.SRandMember(ctx,
"nonexisting_key").Err(), redis.Nil)
+ missingMembers := rdb.SRandMemberN(ctx, "nonexisting_key", 1)
+ require.NoError(t, missingMembers.Err())
+ require.Empty(t, missingMembers.Val())
})
t.Run("SRANDMEMBER the num of arguments is not 2 or 3", func(t
*testing.T) {