Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions rueidiscompat/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2924,7 +2924,7 @@ func (c *Compat) ClientKillByFilter(ctx context.Context, keys ...string) *IntCmd
func (c *Compat) ClientList(ctx context.Context) *StringCmd {
cmd := c.client.B().ClientList().Build()
resp := c.client.Do(ctx, cmd)
return newStringCmd(resp)
return newTxtStringCmd(resp)
}

func (c *Compat) ClientPause(ctx context.Context, dur time.Duration) *BoolCmd {
Expand Down Expand Up @@ -3030,7 +3030,7 @@ func (c *Compat) FlushDBAsync(ctx context.Context) *StatusCmd {
func (c *Compat) Info(ctx context.Context, section ...string) *StringCmd {
cmd := c.client.B().Info().Section(section...).Build()
resp := c.client.Do(ctx, cmd)
return newStringCmd(resp)
return newTxtStringCmd(resp)
}

// InfoMap returns INFO parsed into sections as map[string]map[string]string
Expand Down Expand Up @@ -3343,7 +3343,7 @@ func (c *Compat) ClusterShards(ctx context.Context) *ClusterShardsCmd {
func (c *Compat) ClusterNodes(ctx context.Context) *StringCmd {
cmd := c.client.B().ClusterNodes().Build()
resp := c.client.Do(ctx, cmd)
return newStringCmd(resp)
return newTxtStringCmd(resp)
}

func (c *Compat) ClusterLinks(ctx context.Context) *ClusterLinksCmd {
Expand Down Expand Up @@ -3385,7 +3385,7 @@ func (c *Compat) ClusterResetHard(ctx context.Context) *StatusCmd {
func (c *Compat) ClusterInfo(ctx context.Context) *StringCmd {
cmd := c.client.B().ClusterInfo().Build()
resp := c.client.Do(ctx, cmd)
return newStringCmd(resp)
return newTxtStringCmd(resp)
}

func (c *Compat) ClusterKeySlot(ctx context.Context, key string) *IntCmd {
Expand Down
14 changes: 9 additions & 5 deletions rueidiscompat/adapter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,11 @@ func testCluster(resp3 bool) {
It("ClusterNodes", func() {
nodes, err := adapter.ClusterNodes(ctx).Result()
Expect(err).NotTo(HaveOccurred())
Expect(strings.Split(strings.TrimSpace(nodes), "\n")).To(HaveLen(3))
lines := strings.Split(strings.TrimSpace(nodes), "\n")
Expect(lines).To(HaveLen(3))
for _, line := range lines {
Expect(line).To(MatchRegexp("^[0-9a-f]{40} "))
}
})
It("ClusterMeet", func() {
Expect(adapter.ClusterMeet(ctx, "localhost", 8080).Err()).To(MatchError("Invalid node address specified: localhost:8080"))
Expand All @@ -217,7 +221,7 @@ func testCluster(resp3 bool) {
It("ClusterInfo", func() {
info, err := adapter.ClusterInfo(ctx).Result()
Expect(err).NotTo(HaveOccurred())
Expect(info).NotTo(BeEmpty())
Expect(info).To(HavePrefix("cluster_state:"))
})
It("ClusterKeySlot", func() {
slot, err := adapter.ClusterKeySlot(ctx, "1").Result()
Expand Down Expand Up @@ -318,7 +322,7 @@ func testAdapter(resp3 bool) {
It("should ClientList", func() {
r := adapter.ClientList(ctx)
Expect(r.Err()).To(BeNil())
Expect(r.Val()).NotTo(Equal(""))
Expect(r.Val()).To(HavePrefix("id="))
})

It("should ClientID", func() {
Expand Down Expand Up @@ -365,7 +369,7 @@ func testAdapter(resp3 bool) {
It("should Info", func() {
info := adapter.Info(ctx)
Expect(info.Err()).NotTo(HaveOccurred())
Expect(info.Val()).NotTo(Equal(""))
Expect(info.Val()).To(HavePrefix("# Server"))
})

It("should InfoMap", func() {
Expand All @@ -380,7 +384,7 @@ func testAdapter(resp3 bool) {
It("should Info cpu", func() {
info := adapter.Info(ctx, "cpu")
Expect(info.Err()).NotTo(HaveOccurred())
Expect(info.Val()).NotTo(Equal(""))
Expect(info.Val()).To(HavePrefix("# CPU"))
Expect(info.Val()).To(ContainSubstring(`used_cpu_sys`))
})

Expand Down
13 changes: 13 additions & 0 deletions rueidiscompat/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ func (cmd *Cmd) BoolSlice() ([]bool, error) {

type StringCmd struct {
baseCmd[string]
// txt drops the "txt:" format prefix of a RESP3 verbatim string reply
txt bool
}

type ZeroCopyStringCmd struct {
Expand All @@ -378,6 +380,9 @@ func (cmd *StringCmd) from(res rueidis.RedisResult) {
err = nil
}
}
if cmd.txt && err == nil {
val = strings.TrimPrefix(val, "txt:")
}
cmd.SetErr(err)
cmd.SetVal(val)
cmd.setIsCacheHit(res.IsCacheHit())
Expand All @@ -389,6 +394,14 @@ func newStringCmd(res rueidis.RedisResult) *StringCmd {
return cmd
}

// newTxtStringCmd is for commands like INFO and CLIENT LIST, which reply with
// a verbatim string in RESP3. Its value doesn't start with "txt:", as in RESP2.
func newTxtStringCmd(res rueidis.RedisResult) *StringCmd {
cmd := &StringCmd{txt: true}
cmd.from(res)
return cmd
}

func (cmd *StringCmd) Bytes() ([]byte, error) {
return []byte(cmd.val), cmd.err
}
Expand Down
41 changes: 41 additions & 0 deletions rueidiscompat/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,47 @@ func TestZSliceSingleCmdFrom(t *testing.T) {
})
}

func TestTxtStringCmdFrom(t *testing.T) {
t.Parallel()

// RESP3 verbatim strings carry a "txt:" format prefix. The mock package has
// no verbatim string, so a blob string with the same content stands in for it.
t.Run("reply with the prefix", func(t *testing.T) {
cmd := newTxtStringCmd(mock.Result(mock.RedisBlobString("txt:# Server\r\nredis_version:8.2.1\r\n")))
if err := cmd.Err(); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := cmd.Val(), "# Server\r\nredis_version:8.2.1\r\n"; got != want {
t.Fatalf("got %q, want %q", got, want)
}
})

t.Run("reply without the prefix", func(t *testing.T) {
cmd := newTxtStringCmd(mock.Result(mock.RedisBlobString("id=1 addr=127.0.0.1:6379\n")))
if err := cmd.Err(); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := cmd.Val(), "id=1 addr=127.0.0.1:6379\n"; got != want {
t.Fatalf("got %q, want %q", got, want)
}
})

t.Run("newStringCmd keeps the value", func(t *testing.T) {
cmd := newStringCmd(mock.Result(mock.RedisBlobString("txt:hello")))
if got, want := cmd.Val(), "txt:hello"; got != want {
t.Fatalf("got %q, want %q", got, want)
}
})

t.Run("error", func(t *testing.T) {
err := errors.New("any")
cmd := newTxtStringCmd(mock.ErrorResult(err))
if cmd.Err() != err {
t.Fatalf("got error %v, want %v", cmd.Err(), err)
}
})
}

// TestCacheHitCmd tests the IsCacheHit and setIsCacheHit functionality for Cmd
func TestCacheHitCmd(t *testing.T) {
cmd := &Cmd{}
Expand Down
10 changes: 10 additions & 0 deletions rueidiscompat/pipeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ func testAdapterPipeline(resp3 bool) {
Expect(reset.Err()).NotTo(HaveOccurred())
})

It("should Pipeline Info and ClientList", func() {
pipe := adapter.Pipeline()
info := pipe.Info(ctx)
clients := pipe.ClientList(ctx)
_, err := pipe.Exec(ctx)
Expect(err).NotTo(HaveOccurred())
Expect(info.Val()).To(HavePrefix("# Server"))
Expect(clients.Val()).To(HavePrefix("id="))
})

It("should panic for GetToBuffer in Pipeline", func() {
pipe := adapter.Pipeline()

Expand Down
Loading