Files
go/command_digest_test.go
zeekay 6994cf05aa kv, not redis: rename the package, the extras and the URL scheme
We do not use Redis. The client was a go-redis fork and still said so
everywhere: `package redis`, `redis.NewClient`, `redis://`, `extra/redisotel`.
Consumers wrote `redis.Client` against a Valkey-backed store called KV.

  package redis            -> package kv          (93 decls)
  redis.X                  -> kv.X                (2,794 call sites)
  "redis: …" errors        -> "kv: …"             (206)
  extra/redis{otel,cmd,prometheus,census} -> extra/kv{otel,cmd,prometheus,census}
  redis:// , rediss://     -> kv:// , kvs://      (ParseURL)
  Redis*/‌*Redis* idents    -> KV*/*KV*
  REDIS_VERSION, REDIS_ENDPOINTS_CONFIG_PATH -> KV_*

I previously argued this rename was unsafe because much of it was "wire
contract". That was wrong, and the categorisation shows why: RESP command names
are GET/SET/HSET — they never contain the word. Of 5,771 occurrences only two
kinds were server-visible at all: the ParseURL scheme (we choose what we pass;
our configs already use kv://) and the CLIENT SETINFO lib-name label, which the
server merely records. Nothing here changes a byte of protocol.

Two things deliberately keep the old spelling:
  RediSearch  — names a specific external module the FT.* commands map to.
  StoreDist   — contains the letters by accident (sto-reDis-t), not the word.

Breaking for consumers by design: every import site must move redis.X -> kv.X.
Minor bump, never a major — this module stays v9 forever.
2026-07-26 08:34:19 -07:00

118 lines
2.3 KiB
Go

package kv
import (
"context"
"fmt"
"testing"
"github.com/hanzokv/go/v9/internal/proto"
)
func TestDigestCmd(t *testing.T) {
tests := []struct {
name string
hexStr string
expected uint64
wantErr bool
}{
{
name: "zero value",
hexStr: "0",
expected: 0,
wantErr: false,
},
{
name: "small value",
hexStr: "ff",
expected: 255,
wantErr: false,
},
{
name: "medium value",
hexStr: "1234abcd",
expected: 0x1234abcd,
wantErr: false,
},
{
name: "large value",
hexStr: "ffffffffffffffff",
expected: 0xffffffffffffffff,
wantErr: false,
},
{
name: "uppercase hex",
hexStr: "DEADBEEF",
expected: 0xdeadbeef,
wantErr: false,
},
{
name: "mixed case hex",
hexStr: "DeAdBeEf",
expected: 0xdeadbeef,
wantErr: false,
},
{
name: "typical xxh3 hash",
hexStr: "a1b2c3d4e5f67890",
expected: 0xa1b2c3d4e5f67890,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create a mock reader that returns the hex string in RESP format
// Format: $<length>\r\n<data>\r\n
respData := []byte(fmt.Sprintf("$%d\r\n%s\r\n", len(tt.hexStr), tt.hexStr))
rd := proto.NewReader(newMockConn(respData))
cmd := NewDigestCmd(context.Background(), "digest", "key")
err := cmd.readReply(rd)
if (err != nil) != tt.wantErr {
t.Errorf("DigestCmd.readReply() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && cmd.Val() != tt.expected {
t.Errorf("DigestCmd.Val() = %d (0x%x), want %d (0x%x)", cmd.Val(), cmd.Val(), tt.expected, tt.expected)
}
})
}
}
func TestDigestCmdResult(t *testing.T) {
cmd := NewDigestCmd(context.Background(), "digest", "key")
expected := uint64(0xdeadbeefcafebabe)
cmd.SetVal(expected)
val, err := cmd.Result()
if err != nil {
t.Errorf("DigestCmd.Result() error = %v", err)
}
if val != expected {
t.Errorf("DigestCmd.Result() = %d (0x%x), want %d (0x%x)", val, val, expected, expected)
}
}
// mockConn is a simple mock connection for testing
type mockConn struct {
data []byte
pos int
}
func newMockConn(data []byte) *mockConn {
return &mockConn{data: data}
}
func (c *mockConn) Read(p []byte) (n int, err error) {
if c.pos >= len(c.data) {
return 0, nil
}
n = copy(p, c.data[c.pos:])
c.pos += n
return n, nil
}