mirror of
https://github.com/nalgeon/redka.git
synced 2025-11-01 03:42:41 +08:00
refactor: command - better encapsulation and simpler tests
This commit is contained in:
@@ -14,25 +14,6 @@ import (
|
|||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MustParse[T redis.Cmd](s string) T {
|
|
||||||
parts := strings.Split(s, " ")
|
|
||||||
args := BuildArgs(parts[0], parts[1:]...)
|
|
||||||
cmd, err := Parse(args)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return cmd.(T)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuildArgs(name string, args ...string) [][]byte {
|
|
||||||
rargs := make([][]byte, len(args)+1)
|
|
||||||
rargs[0] = []byte(name)
|
|
||||||
for i, arg := range args {
|
|
||||||
rargs[i+1] = []byte(arg)
|
|
||||||
}
|
|
||||||
return rargs
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse parses a text representation of a command into a Cmd.
|
// Parse parses a text representation of a command into a Cmd.
|
||||||
func Parse(args [][]byte) (redis.Cmd, error) {
|
func Parse(args [][]byte) (redis.Cmd, error) {
|
||||||
name := strings.ToLower(string(args[0]))
|
name := strings.ToLower(string(args[0]))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package conn_test
|
package conn
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ import (
|
|||||||
// https://redis.io/commands/echo
|
// https://redis.io/commands/echo
|
||||||
type Echo struct {
|
type Echo struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Parts []string
|
parts []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseEcho(b redis.BaseCmd) (*Echo, error) {
|
func ParseEcho(b redis.BaseCmd) (*Echo, error) {
|
||||||
cmd := &Echo{BaseCmd: b}
|
cmd := &Echo{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.Strings(&cmd.Parts),
|
parser.Strings(&cmd.parts),
|
||||||
).Required(1).Run(cmd.Args())
|
).Required(1).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmd, err
|
return cmd, err
|
||||||
@@ -27,7 +27,7 @@ func ParseEcho(b redis.BaseCmd) (*Echo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Echo) Run(w redis.Writer, _ redis.Redka) (any, error) {
|
func (c *Echo) Run(w redis.Writer, _ redis.Redka) (any, error) {
|
||||||
out := strings.Join(c.Parts, " ")
|
out := strings.Join(c.parts, " ")
|
||||||
w.WriteAny(out)
|
w.WriteAny(out)
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +1,42 @@
|
|||||||
package conn_test
|
package conn
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/conn"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEchoParse(t *testing.T) {
|
func TestEchoParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
args [][]byte
|
||||||
want []string
|
want []string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "echo",
|
cmd: "echo",
|
||||||
args: command.BuildArgs("echo"),
|
|
||||||
want: []string{},
|
want: []string{},
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "echo hello",
|
cmd: "echo hello",
|
||||||
args: command.BuildArgs("echo", "hello"),
|
|
||||||
want: []string{"hello"},
|
want: []string{"hello"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "echo one two",
|
cmd: "echo one two",
|
||||||
args: command.BuildArgs("echo", "one", "two"),
|
|
||||||
want: []string{"one", "two"},
|
want: []string{"one", "two"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseEcho, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*conn.Echo).Parts, test.want)
|
testx.AssertEqual(t, cmd.parts, test.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -52,29 +47,27 @@ func TestEchoExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
cmd *conn.Echo
|
res any
|
||||||
res any
|
out string
|
||||||
out string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "echo hello",
|
cmd: "echo hello",
|
||||||
cmd: command.MustParse[*conn.Echo]("echo hello"),
|
res: "hello",
|
||||||
res: "hello",
|
out: "hello",
|
||||||
out: "hello",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "echo one two",
|
cmd: "echo one two",
|
||||||
cmd: command.MustParse[*conn.Echo]("echo one two"),
|
res: "one two",
|
||||||
res: "one two",
|
out: "one two",
|
||||||
out: "one two",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := test.cmd.Run(conn, red)
|
cmd := redis.MustParse(ParseEcho, test.cmd)
|
||||||
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, test.res)
|
testx.AssertEqual(t, res, test.res)
|
||||||
testx.AssertEqual(t, conn.Out(), test.out)
|
testx.AssertEqual(t, conn.Out(), test.out)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package conn
|
package conn
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/parser"
|
"github.com/nalgeon/redka/internal/parser"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
)
|
)
|
||||||
@@ -11,18 +9,17 @@ const (
|
|||||||
PONG = "PONG"
|
PONG = "PONG"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Returns PONG if no argument is provided, otherwise return a copy of the argument as a bulk
|
// Returns the server's liveliness response.
|
||||||
// https://redis.io/commands/ping
|
// https://redis.io/commands/ping
|
||||||
type Ping struct {
|
type Ping struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Parts []string
|
message string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func ParsePing(b redis.BaseCmd) (*Ping, error) {
|
func ParsePing(b redis.BaseCmd) (*Ping, error) {
|
||||||
cmd := &Ping{BaseCmd: b}
|
cmd := &Ping{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.Strings(&cmd.Parts),
|
parser.String(&cmd.message),
|
||||||
).Required(0).Run(cmd.Args())
|
).Required(0).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmd, err
|
return cmd, err
|
||||||
@@ -31,11 +28,10 @@ func ParsePing(b redis.BaseCmd) (*Ping, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Ping) Run(w redis.Writer, _ redis.Redka) (any, error) {
|
func (c *Ping) Run(w redis.Writer, _ redis.Redka) (any, error) {
|
||||||
if len(c.Parts) == 0 {
|
if c.message == "" {
|
||||||
w.WriteAny(PONG)
|
w.WriteAny(PONG)
|
||||||
return PONG, nil
|
return PONG, nil
|
||||||
}
|
}
|
||||||
out := strings.Join(c.Parts, " ")
|
w.WriteBulkString(c.message)
|
||||||
w.WriteAny(out)
|
return c.message, nil
|
||||||
return out, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +1,41 @@
|
|||||||
package conn_test
|
package conn
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/conn"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPingParse(t *testing.T) {
|
func TestPingParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want string
|
||||||
want []string
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "ping",
|
cmd: "ping",
|
||||||
args: command.BuildArgs("ping"),
|
want: "",
|
||||||
want: []string(nil),
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ping hello",
|
cmd: "ping hello",
|
||||||
args: command.BuildArgs("ping", "hello"),
|
want: "hello",
|
||||||
want: []string{"hello"},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ping one two",
|
cmd: "ping one two",
|
||||||
args: command.BuildArgs("ping", "one", "two"),
|
want: "",
|
||||||
want: []string{"one", "two"},
|
err: redis.ErrSyntaxError,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParsePing, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*conn.Ping).Parts, test.want)
|
testx.AssertEqual(t, cmd.message, test.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -52,35 +46,27 @@ func TestPingExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
cmd *conn.Ping
|
res any
|
||||||
res any
|
out string
|
||||||
out string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "ping",
|
cmd: "ping",
|
||||||
cmd: command.MustParse[*conn.Ping]("ping"),
|
res: "PONG",
|
||||||
res: "PONG",
|
out: "PONG",
|
||||||
out: "PONG",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ping hello",
|
cmd: "ping hello",
|
||||||
cmd: command.MustParse[*conn.Ping]("ping hello"),
|
res: "hello",
|
||||||
res: "hello",
|
out: "hello",
|
||||||
out: "hello",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ping one two",
|
|
||||||
cmd: command.MustParse[*conn.Ping]("ping one two"),
|
|
||||||
res: "one two",
|
|
||||||
out: "one two",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := test.cmd.Run(conn, red)
|
cmd := redis.MustParse(ParsePing, test.cmd)
|
||||||
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, test.res)
|
testx.AssertEqual(t, res, test.res)
|
||||||
testx.AssertEqual(t, conn.Out(), test.out)
|
testx.AssertEqual(t, conn.Out(), test.out)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ import (
|
|||||||
// https://redis.io/commands/hdel
|
// https://redis.io/commands/hdel
|
||||||
type HDel struct {
|
type HDel struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Fields []string
|
fields []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHDel(b redis.BaseCmd) (*HDel, error) {
|
func ParseHDel(b redis.BaseCmd) (*HDel, error) {
|
||||||
cmd := &HDel{BaseCmd: b}
|
cmd := &HDel{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Strings(&cmd.Fields),
|
parser.Strings(&cmd.fields),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -28,7 +28,7 @@ func ParseHDel(b redis.BaseCmd) (*HDel, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HDel) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HDel) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
count, err := red.Hash().Delete(cmd.Key, cmd.Fields...)
|
count, err := red.Hash().Delete(cmd.key, cmd.fields...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,46 +1,39 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHDelParse(t *testing.T) {
|
func TestHDelParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
key string
|
key string
|
||||||
fields []string
|
fields []string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hdel",
|
cmd: "hdel",
|
||||||
args: command.BuildArgs("hdel"),
|
|
||||||
key: "",
|
key: "",
|
||||||
fields: nil,
|
fields: nil,
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hdel person",
|
cmd: "hdel person",
|
||||||
args: command.BuildArgs("hdel", "person"),
|
|
||||||
key: "",
|
key: "",
|
||||||
fields: nil,
|
fields: nil,
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hdel person name",
|
cmd: "hdel person name",
|
||||||
args: command.BuildArgs("hdel", "person", "name"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
fields: []string{"name"},
|
fields: []string{"name"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hdel person name age",
|
cmd: "hdel person name age",
|
||||||
args: command.BuildArgs("hdel", "person", "name", "age"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
fields: []string{"name", "age"},
|
fields: []string{"name", "age"},
|
||||||
err: nil,
|
err: nil,
|
||||||
@@ -48,13 +41,12 @@ func TestHDelParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHDel, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HDel)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
testx.AssertEqual(t, cmd.fields, test.fields)
|
||||||
testx.AssertEqual(t, cm.Fields, test.fields)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -68,7 +60,7 @@ func TestHDelExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HDel]("hdel person name")
|
cmd := redis.MustParse(ParseHDel, "hdel person name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -89,7 +81,7 @@ func TestHDelExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
_, _ = db.Hash().Set("person", "happy", true)
|
_, _ = db.Hash().Set("person", "happy", true)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HDel]("hdel person name happy city")
|
cmd := redis.MustParse(ParseHDel, "hdel person name happy city")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -111,7 +103,7 @@ func TestHDelExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HDel]("hdel person name age")
|
cmd := redis.MustParse(ParseHDel, "hdel person name age")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/hexists
|
// https://redis.io/commands/hexists
|
||||||
type HExists struct {
|
type HExists struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Field string
|
field string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHExists(b redis.BaseCmd) (*HExists, error) {
|
func ParseHExists(b redis.BaseCmd) (*HExists, error) {
|
||||||
@@ -16,13 +16,13 @@ func ParseHExists(b redis.BaseCmd) (*HExists, error) {
|
|||||||
if len(cmd.Args()) != 2 {
|
if len(cmd.Args()) != 2 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
cmd.Field = string(cmd.Args()[1])
|
cmd.field = string(cmd.Args()[1])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HExists) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HExists) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
ok, err := red.Hash().Exists(cmd.Key, cmd.Field)
|
ok, err := red.Hash().Exists(cmd.key, cmd.field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,46 +1,39 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHExistsParse(t *testing.T) {
|
func TestHExistsParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
key string
|
key string
|
||||||
field string
|
field string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hexists",
|
cmd: "hexists",
|
||||||
args: command.BuildArgs("hexists"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hexists person",
|
cmd: "hexists person",
|
||||||
args: command.BuildArgs("hexists", "person"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hexists person name",
|
cmd: "hexists person name",
|
||||||
args: command.BuildArgs("hexists", "person", "name"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
field: "name",
|
field: "name",
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hexists person name age",
|
cmd: "hexists person name age",
|
||||||
args: command.BuildArgs("hexists", "person", "name", "age"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
@@ -48,13 +41,12 @@ func TestHExistsParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHExists, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HExists)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
testx.AssertEqual(t, cmd.field, test.field)
|
||||||
testx.AssertEqual(t, cm.Field, test.field)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -67,7 +59,7 @@ func TestHExistsExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HExists]("hexists person name")
|
cmd := redis.MustParse(ParseHExists, "hexists person name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -81,7 +73,7 @@ func TestHExistsExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HExists]("hexists person age")
|
cmd := redis.MustParse(ParseHExists, "hexists person age")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -93,7 +85,7 @@ func TestHExistsExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HExists]("hexists person name")
|
cmd := redis.MustParse(ParseHExists, "hexists person name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
// https://redis.io/commands/hget
|
// https://redis.io/commands/hget
|
||||||
type HGet struct {
|
type HGet struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Field string
|
field string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHGet(b redis.BaseCmd) (*HGet, error) {
|
func ParseHGet(b redis.BaseCmd) (*HGet, error) {
|
||||||
@@ -19,13 +19,13 @@ func ParseHGet(b redis.BaseCmd) (*HGet, error) {
|
|||||||
if len(cmd.Args()) != 2 {
|
if len(cmd.Args()) != 2 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
cmd.Field = string(cmd.Args()[1])
|
cmd.field = string(cmd.Args()[1])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HGet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HGet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
val, err := red.Hash().Get(cmd.Key, cmd.Field)
|
val, err := red.Hash().Get(cmd.key, cmd.field)
|
||||||
if err == core.ErrNotFound {
|
if err == core.ErrNotFound {
|
||||||
w.WriteNull()
|
w.WriteNull()
|
||||||
return val, nil
|
return val, nil
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,36 +10,31 @@ import (
|
|||||||
|
|
||||||
func TestHGetParse(t *testing.T) {
|
func TestHGetParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
key string
|
key string
|
||||||
field string
|
field string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hget",
|
cmd: "hget",
|
||||||
args: command.BuildArgs("hget"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hget person",
|
cmd: "hget person",
|
||||||
args: command.BuildArgs("hget", "person"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hget person name",
|
cmd: "hget person name",
|
||||||
args: command.BuildArgs("hget", "person", "name"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
field: "name",
|
field: "name",
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hget person name age",
|
cmd: "hget person name age",
|
||||||
args: command.BuildArgs("hget", "person", "name", "age"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
@@ -49,13 +42,12 @@ func TestHGetParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHGet, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HGet)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
testx.AssertEqual(t, cmd.field, test.field)
|
||||||
testx.AssertEqual(t, cm.Field, test.field)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -68,7 +60,7 @@ func TestHGetExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HGet]("hget person name")
|
cmd := redis.MustParse(ParseHGet, "hget person name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -82,7 +74,7 @@ func TestHGetExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HGet]("hget person age")
|
cmd := redis.MustParse(ParseHGet, "hget person age")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -94,7 +86,7 @@ func TestHGetExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HGet]("hget person name")
|
cmd := redis.MustParse(ParseHGet, "hget person name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/hgetall
|
// https://redis.io/commands/hgetall
|
||||||
type HGetAll struct {
|
type HGetAll struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHGetAll(b redis.BaseCmd) (*HGetAll, error) {
|
func ParseHGetAll(b redis.BaseCmd) (*HGetAll, error) {
|
||||||
@@ -15,12 +15,12 @@ func ParseHGetAll(b redis.BaseCmd) (*HGetAll, error) {
|
|||||||
if len(cmd.Args()) != 1 {
|
if len(cmd.Args()) != 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HGetAll) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HGetAll) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
items, err := red.Hash().Items(cmd.Key)
|
items, err := red.Hash().Items(cmd.key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,38 +10,33 @@ import (
|
|||||||
|
|
||||||
func TestHGetAllParse(t *testing.T) {
|
func TestHGetAllParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
key string
|
||||||
key string
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hgetall",
|
cmd: "hgetall",
|
||||||
args: command.BuildArgs("hgetall"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hgetall person",
|
cmd: "hgetall person",
|
||||||
args: command.BuildArgs("hgetall", "person"),
|
key: "person",
|
||||||
key: "person",
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hgetall person name",
|
cmd: "hgetall person name",
|
||||||
args: command.BuildArgs("hgetall", "person", "name"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHGetAll, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HGetAll)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -57,7 +50,7 @@ func TestHGetAllExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HGetAll]("hgetall person")
|
cmd := redis.MustParse(ParseHGetAll, "hgetall person")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -73,7 +66,7 @@ func TestHGetAllExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HGetAll]("hgetall person")
|
cmd := redis.MustParse(ParseHGetAll, "hgetall person")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -11,17 +11,17 @@ import (
|
|||||||
// https://redis.io/commands/hincrby
|
// https://redis.io/commands/hincrby
|
||||||
type HIncrBy struct {
|
type HIncrBy struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Field string
|
field string
|
||||||
Delta int
|
delta int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHIncrBy(b redis.BaseCmd) (*HIncrBy, error) {
|
func ParseHIncrBy(b redis.BaseCmd) (*HIncrBy, error) {
|
||||||
cmd := &HIncrBy{BaseCmd: b}
|
cmd := &HIncrBy{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.String(&cmd.Field),
|
parser.String(&cmd.field),
|
||||||
parser.Int(&cmd.Delta),
|
parser.Int(&cmd.delta),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -30,7 +30,7 @@ func ParseHIncrBy(b redis.BaseCmd) (*HIncrBy, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HIncrBy) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HIncrBy) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
val, err := red.Hash().Incr(cmd.Key, cmd.Field, cmd.Delta)
|
val, err := red.Hash().Incr(cmd.key, cmd.field, cmd.delta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,37 +10,32 @@ import (
|
|||||||
|
|
||||||
func TestHIncrByParse(t *testing.T) {
|
func TestHIncrByParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
key string
|
key string
|
||||||
field string
|
field string
|
||||||
delta int
|
delta int
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hincrby",
|
cmd: "hincrby",
|
||||||
args: command.BuildArgs("hincrby"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hincrby person",
|
cmd: "hincrby person",
|
||||||
args: command.BuildArgs("hincrby", "person"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hincrby person age",
|
cmd: "hincrby person age",
|
||||||
args: command.BuildArgs("hincrby", "person", "age"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hincrby person age 10",
|
cmd: "hincrby person age 10",
|
||||||
args: command.BuildArgs("hincrby", "person", "age", "10"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
field: "age",
|
field: "age",
|
||||||
delta: 10,
|
delta: 10,
|
||||||
@@ -51,14 +44,13 @@ func TestHIncrByParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHIncrBy, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HIncrBy)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
testx.AssertEqual(t, cmd.field, test.field)
|
||||||
testx.AssertEqual(t, cm.Field, test.field)
|
testx.AssertEqual(t, cmd.delta, test.delta)
|
||||||
testx.AssertEqual(t, cm.Delta, test.delta)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -71,7 +63,7 @@ func TestHIncrByExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HIncrBy]("hincrby person age 10")
|
cmd := redis.MustParse(ParseHIncrBy, "hincrby person age 10")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -88,7 +80,7 @@ func TestHIncrByExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HIncrBy]("hincrby person age -10")
|
cmd := redis.MustParse(ParseHIncrBy, "hincrby person age -10")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -105,7 +97,7 @@ func TestHIncrByExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HIncrBy]("hincrby person age 10")
|
cmd := redis.MustParse(ParseHIncrBy, "hincrby person age 10")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -120,7 +112,7 @@ func TestHIncrByExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HIncrBy]("hincrby person age 10")
|
cmd := redis.MustParse(ParseHIncrBy, "hincrby person age 10")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package hash
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/parser"
|
"github.com/nalgeon/redka/internal/parser"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
)
|
)
|
||||||
@@ -13,17 +11,17 @@ import (
|
|||||||
// https://redis.io/commands/hincrbyfloat
|
// https://redis.io/commands/hincrbyfloat
|
||||||
type HIncrByFloat struct {
|
type HIncrByFloat struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Field string
|
field string
|
||||||
Delta float64
|
delta float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHIncrByFloat(b redis.BaseCmd) (*HIncrByFloat, error) {
|
func ParseHIncrByFloat(b redis.BaseCmd) (*HIncrByFloat, error) {
|
||||||
cmd := &HIncrByFloat{BaseCmd: b}
|
cmd := &HIncrByFloat{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.String(&cmd.Field),
|
parser.String(&cmd.field),
|
||||||
parser.Float(&cmd.Delta),
|
parser.Float(&cmd.delta),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -32,11 +30,11 @@ func ParseHIncrByFloat(b redis.BaseCmd) (*HIncrByFloat, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HIncrByFloat) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HIncrByFloat) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
val, err := red.Hash().IncrFloat(cmd.Key, cmd.Field, cmd.Delta)
|
val, err := red.Hash().IncrFloat(cmd.key, cmd.field, cmd.delta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
w.WriteBulkString(strconv.FormatFloat(val, 'f', -1, 64))
|
redis.WriteFloat(w, val)
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,37 +10,32 @@ import (
|
|||||||
|
|
||||||
func TestHIncrByFloatParse(t *testing.T) {
|
func TestHIncrByFloatParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
key string
|
key string
|
||||||
field string
|
field string
|
||||||
delta float64
|
delta float64
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hincrbyfloat",
|
cmd: "hincrbyfloat",
|
||||||
args: command.BuildArgs("hincrbyfloat"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hincrbyfloat person",
|
cmd: "hincrbyfloat person",
|
||||||
args: command.BuildArgs("hincrbyfloat", "person"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hincrbyfloat person age",
|
cmd: "hincrbyfloat person age",
|
||||||
args: command.BuildArgs("hincrbyfloat", "person", "age"),
|
|
||||||
key: "",
|
key: "",
|
||||||
field: "",
|
field: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hincrbyfloat person age 10.5",
|
cmd: "hincrbyfloat person age 10.5",
|
||||||
args: command.BuildArgs("hincrbyfloat", "person", "age", "10.5"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
field: "age",
|
field: "age",
|
||||||
delta: 10.5,
|
delta: 10.5,
|
||||||
@@ -51,14 +44,13 @@ func TestHIncrByFloatParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHIncrByFloat, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HIncrByFloat)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
testx.AssertEqual(t, cmd.field, test.field)
|
||||||
testx.AssertEqual(t, cm.Field, test.field)
|
testx.AssertEqual(t, cmd.delta, test.delta)
|
||||||
testx.AssertEqual(t, cm.Delta, test.delta)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -71,7 +63,7 @@ func TestHIncrByFloatExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HIncrByFloat]("hincrbyfloat person age 10.5")
|
cmd := redis.MustParse(ParseHIncrByFloat, "hincrbyfloat person age 10.5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -88,7 +80,7 @@ func TestHIncrByFloatExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HIncrByFloat]("hincrbyfloat person age -10.5")
|
cmd := redis.MustParse(ParseHIncrByFloat, "hincrbyfloat person age -10.5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -105,7 +97,7 @@ func TestHIncrByFloatExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HIncrByFloat]("hincrbyfloat person age 10.5")
|
cmd := redis.MustParse(ParseHIncrByFloat, "hincrbyfloat person age 10.5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -120,7 +112,7 @@ func TestHIncrByFloatExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HIncrByFloat]("hincrbyfloat person age 10.5")
|
cmd := redis.MustParse(ParseHIncrByFloat, "hincrbyfloat person age 10.5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/hkeys
|
// https://redis.io/commands/hkeys
|
||||||
type HKeys struct {
|
type HKeys struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHKeys(b redis.BaseCmd) (*HKeys, error) {
|
func ParseHKeys(b redis.BaseCmd) (*HKeys, error) {
|
||||||
@@ -15,12 +15,12 @@ func ParseHKeys(b redis.BaseCmd) (*HKeys, error) {
|
|||||||
if len(cmd.Args()) != 1 {
|
if len(cmd.Args()) != 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HKeys) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HKeys) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
fields, err := red.Hash().Fields(cmd.Key)
|
fields, err := red.Hash().Fields(cmd.key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,48 +1,41 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHKeysParse(t *testing.T) {
|
func TestHKeysParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
key string
|
||||||
key string
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hkeys",
|
cmd: "hkeys",
|
||||||
args: command.BuildArgs("hkeys"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hkeys person",
|
cmd: "hkeys person",
|
||||||
args: command.BuildArgs("hkeys", "person"),
|
key: "person",
|
||||||
key: "person",
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hkeys person name",
|
cmd: "hkeys person name",
|
||||||
args: command.BuildArgs("hkeys", "person", "name"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHKeys, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HKeys)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -56,7 +49,7 @@ func TestHKeysExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HKeys]("hkeys person")
|
cmd := redis.MustParse(ParseHKeys, "hkeys person")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -70,7 +63,7 @@ func TestHKeysExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HKeys]("hkeys person")
|
cmd := redis.MustParse(ParseHKeys, "hkeys person")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/hlen
|
// https://redis.io/commands/hlen
|
||||||
type HLen struct {
|
type HLen struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHLen(b redis.BaseCmd) (*HLen, error) {
|
func ParseHLen(b redis.BaseCmd) (*HLen, error) {
|
||||||
@@ -15,12 +15,12 @@ func ParseHLen(b redis.BaseCmd) (*HLen, error) {
|
|||||||
if len(cmd.Args()) != 1 {
|
if len(cmd.Args()) != 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HLen) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HLen) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
count, err := red.Hash().Len(cmd.Key)
|
count, err := red.Hash().Len(cmd.key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,48 +1,41 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHLenParse(t *testing.T) {
|
func TestHLenParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
key string
|
||||||
key string
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hlen",
|
cmd: "hlen",
|
||||||
args: command.BuildArgs("hlen"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hlen person",
|
cmd: "hlen person",
|
||||||
args: command.BuildArgs("hlen", "person"),
|
key: "person",
|
||||||
key: "person",
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hlen person name",
|
cmd: "hlen person name",
|
||||||
args: command.BuildArgs("hlen", "person", "name"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHLen, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HLen)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -56,7 +49,7 @@ func TestHLenExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HLen]("hlen person")
|
cmd := redis.MustParse(ParseHLen, "hlen person")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -68,7 +61,7 @@ func TestHLenExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HLen]("hlen person")
|
cmd := redis.MustParse(ParseHLen, "hlen person")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ import (
|
|||||||
// https://redis.io/commands/hmget
|
// https://redis.io/commands/hmget
|
||||||
type HMGet struct {
|
type HMGet struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Fields []string
|
fields []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHMGet(b redis.BaseCmd) (*HMGet, error) {
|
func ParseHMGet(b redis.BaseCmd) (*HMGet, error) {
|
||||||
cmd := &HMGet{BaseCmd: b}
|
cmd := &HMGet{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Strings(&cmd.Fields),
|
parser.Strings(&cmd.fields),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -29,7 +29,7 @@ func ParseHMGet(b redis.BaseCmd) (*HMGet, error) {
|
|||||||
|
|
||||||
func (cmd *HMGet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HMGet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
// Get the field-value map for requested fields.
|
// Get the field-value map for requested fields.
|
||||||
items, err := red.Hash().GetMany(cmd.Key, cmd.Fields...)
|
items, err := red.Hash().GetMany(cmd.key, cmd.fields...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -38,8 +38,8 @@ func (cmd *HMGet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
|||||||
// Build the result slice.
|
// Build the result slice.
|
||||||
// It will contain all values in the order of fields.
|
// It will contain all values in the order of fields.
|
||||||
// Missing fields will have nil values.
|
// Missing fields will have nil values.
|
||||||
vals := make([]core.Value, len(cmd.Fields))
|
vals := make([]core.Value, len(cmd.fields))
|
||||||
for i, field := range cmd.Fields {
|
for i, field := range cmd.fields {
|
||||||
vals[i] = items[field]
|
vals[i] = items[field]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,36 +10,31 @@ import (
|
|||||||
|
|
||||||
func TestHMGetParse(t *testing.T) {
|
func TestHMGetParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
key string
|
key string
|
||||||
fields []string
|
fields []string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hmget",
|
cmd: "hmget",
|
||||||
args: command.BuildArgs("hmget"),
|
|
||||||
key: "",
|
key: "",
|
||||||
fields: nil,
|
fields: nil,
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hmget person",
|
cmd: "hmget person",
|
||||||
args: command.BuildArgs("hmget", "person"),
|
|
||||||
key: "",
|
key: "",
|
||||||
fields: nil,
|
fields: nil,
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hmget person name",
|
cmd: "hmget person name",
|
||||||
args: command.BuildArgs("hmget", "person", "name"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
fields: []string{"name"},
|
fields: []string{"name"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hmget person name age",
|
cmd: "hmget person name age",
|
||||||
args: command.BuildArgs("hmget", "person", "name", "age"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
fields: []string{"name", "age"},
|
fields: []string{"name", "age"},
|
||||||
err: nil,
|
err: nil,
|
||||||
@@ -49,13 +42,12 @@ func TestHMGetParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHMGet, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HMGet)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
testx.AssertEqual(t, cmd.fields, test.fields)
|
||||||
testx.AssertEqual(t, cm.Fields, test.fields)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -69,7 +61,7 @@ func TestHMGetExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HMGet]("hmget person name")
|
cmd := redis.MustParse(ParseHMGet, "hmget person name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -87,7 +79,7 @@ func TestHMGetExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
_, _ = db.Hash().Set("person", "happy", true)
|
_, _ = db.Hash().Set("person", "happy", true)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HMGet]("hmget person name happy city")
|
cmd := redis.MustParse(ParseHMGet, "hmget person name happy city")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -106,7 +98,7 @@ func TestHMGetExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HMGet]("hmget person name age")
|
cmd := redis.MustParse(ParseHMGet, "hmget person name age")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ import (
|
|||||||
// https://redis.io/commands/hmset
|
// https://redis.io/commands/hmset
|
||||||
type HMSet struct {
|
type HMSet struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Items map[string]any
|
items map[string]any
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHMSet(b redis.BaseCmd) (*HMSet, error) {
|
func ParseHMSet(b redis.BaseCmd) (*HMSet, error) {
|
||||||
cmd := &HMSet{BaseCmd: b}
|
cmd := &HMSet{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.AnyMap(&cmd.Items),
|
parser.AnyMap(&cmd.items),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -27,7 +27,7 @@ func ParseHMSet(b redis.BaseCmd) (*HMSet, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HMSet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HMSet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
count, err := red.Hash().SetMany(cmd.Key, cmd.Items)
|
count, err := red.Hash().SetMany(cmd.key, cmd.items)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,55 +1,46 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHMSetParse(t *testing.T) {
|
func TestHMSetParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want HMSet
|
||||||
want hash.HMSet
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hmset",
|
cmd: "hmset",
|
||||||
args: command.BuildArgs("hmset"),
|
want: HMSet{},
|
||||||
want: hash.HMSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hmset person",
|
cmd: "hmset person",
|
||||||
args: command.BuildArgs("hmset", "person"),
|
want: HMSet{},
|
||||||
want: hash.HMSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hmset person name",
|
cmd: "hmset person name",
|
||||||
args: command.BuildArgs("hmset", "person", "name"),
|
want: HMSet{},
|
||||||
want: hash.HMSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hmset person name alice",
|
cmd: "hmset person name alice",
|
||||||
args: command.BuildArgs("hmset", "person", "name", "alice"),
|
want: HMSet{key: "person", items: map[string]any{"name": []byte("alice")}},
|
||||||
want: hash.HMSet{Key: "person", Items: map[string]any{"name": []byte("alice")}},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hmset person name alice age",
|
cmd: "hmset person name alice age",
|
||||||
args: command.BuildArgs("hmset", "person", "name", "alice", "age"),
|
want: HMSet{},
|
||||||
want: hash.HMSet{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hmset person name alice age 25",
|
cmd: "hmset person name alice age 25",
|
||||||
args: command.BuildArgs("hmset", "person", "name", "alice", "age", "25"),
|
want: HMSet{key: "person", items: map[string]any{
|
||||||
want: hash.HMSet{Key: "person", Items: map[string]any{
|
|
||||||
"name": []byte("alice"),
|
"name": []byte("alice"),
|
||||||
"age": []byte("25"),
|
"age": []byte("25"),
|
||||||
}},
|
}},
|
||||||
@@ -58,13 +49,12 @@ func TestHMSetParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHMSet, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HMSet)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.items, test.want.items)
|
||||||
testx.AssertEqual(t, cm.Items, test.want.Items)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -75,7 +65,7 @@ func TestHMSetExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HMSet]("hmset person name alice")
|
cmd := redis.MustParse(ParseHMSet, "hmset person name alice")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -90,7 +80,7 @@ func TestHMSetExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HMSet]("hmset person name alice age 25")
|
cmd := redis.MustParse(ParseHMSet, "hmset person name alice age 25")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -109,7 +99,7 @@ func TestHMSetExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HMSet]("hmset person name bob age 50")
|
cmd := redis.MustParse(ParseHMSet, "hmset person name bob age 50")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -129,7 +119,7 @@ func TestHMSetExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HMSet]("hmset person name bob age 50")
|
cmd := redis.MustParse(ParseHMSet, "hmset person name bob age 50")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -10,35 +10,35 @@ import (
|
|||||||
// https://redis.io/commands/hscan
|
// https://redis.io/commands/hscan
|
||||||
type HScan struct {
|
type HScan struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Cursor int
|
cursor int
|
||||||
Match string
|
match string
|
||||||
Count int
|
count int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHScan(b redis.BaseCmd) (*HScan, error) {
|
func ParseHScan(b redis.BaseCmd) (*HScan, error) {
|
||||||
cmd := &HScan{BaseCmd: b}
|
cmd := &HScan{BaseCmd: b}
|
||||||
|
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Int(&cmd.Cursor),
|
parser.Int(&cmd.cursor),
|
||||||
parser.Named("match", parser.String(&cmd.Match)),
|
parser.Named("match", parser.String(&cmd.match)),
|
||||||
parser.Named("count", parser.Int(&cmd.Count)),
|
parser.Named("count", parser.Int(&cmd.count)),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmd, err
|
return cmd, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// all keys by default
|
// all keys by default
|
||||||
if cmd.Match == "" {
|
if cmd.match == "" {
|
||||||
cmd.Match = "*"
|
cmd.match = "*"
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HScan) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HScan) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
res, err := red.Hash().Scan(cmd.Key, cmd.Cursor, cmd.Match, cmd.Count)
|
res, err := red.Hash().Scan(cmd.key, cmd.cursor, cmd.match, cmd.count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/rhash"
|
"github.com/nalgeon/redka/internal/rhash"
|
||||||
@@ -13,8 +11,7 @@ import (
|
|||||||
|
|
||||||
func TestHScanParse(t *testing.T) {
|
func TestHScanParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
key string
|
key string
|
||||||
cursor int
|
cursor int
|
||||||
match string
|
match string
|
||||||
@@ -22,8 +19,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hscan",
|
cmd: "hscan",
|
||||||
args: command.BuildArgs("hscan"),
|
|
||||||
key: "",
|
key: "",
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
match: "*",
|
match: "*",
|
||||||
@@ -31,8 +27,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hscan person",
|
cmd: "hscan person",
|
||||||
args: command.BuildArgs("hscan", "person"),
|
|
||||||
key: "",
|
key: "",
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
match: "*",
|
match: "*",
|
||||||
@@ -40,8 +35,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hscan person 15",
|
cmd: "hscan person 15",
|
||||||
args: command.BuildArgs("hscan", "person", "15"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "*",
|
match: "*",
|
||||||
@@ -49,8 +43,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hscan person 15 match *",
|
cmd: "hscan person 15 match *",
|
||||||
args: command.BuildArgs("hscan", "person", "15", "match", "*"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "*",
|
match: "*",
|
||||||
@@ -58,8 +51,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hscan person 15 match * count 5",
|
cmd: "hscan person 15 match * count 5",
|
||||||
args: command.BuildArgs("hscan", "person", "15", "match", "*", "count", "5"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "*",
|
match: "*",
|
||||||
@@ -67,8 +59,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hscan person 15 count 5 match *",
|
cmd: "hscan person 15 count 5 match *",
|
||||||
args: command.BuildArgs("hscan", "person", "15", "count", "5", "match", "*"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "*",
|
match: "*",
|
||||||
@@ -76,8 +67,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hscan person 15 match k2* count 5",
|
cmd: "hscan person 15 match k2* count 5",
|
||||||
args: command.BuildArgs("hscan", "person", "15", "match", "k2*", "count", "5"),
|
|
||||||
key: "person",
|
key: "person",
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "k2*",
|
match: "k2*",
|
||||||
@@ -85,8 +75,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hscan person ten",
|
cmd: "hscan person ten",
|
||||||
args: command.BuildArgs("hscan", "person", "ten"),
|
|
||||||
key: "",
|
key: "",
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
match: "",
|
match: "",
|
||||||
@@ -94,8 +83,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err: redis.ErrInvalidInt,
|
err: redis.ErrInvalidInt,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hscan person 15 *",
|
cmd: "hscan person 15 *",
|
||||||
args: command.BuildArgs("hscan", "person", "15", "*"),
|
|
||||||
key: "",
|
key: "",
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
match: "",
|
match: "",
|
||||||
@@ -103,8 +91,7 @@ func TestHScanParse(t *testing.T) {
|
|||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hscan person 15 * 5",
|
cmd: "hscan person 15 * 5",
|
||||||
args: command.BuildArgs("hscan", "person", "15", "*", "5"),
|
|
||||||
key: "",
|
key: "",
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
match: "",
|
match: "",
|
||||||
@@ -114,15 +101,14 @@ func TestHScanParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHScan, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
scmd := cmd.(*hash.HScan)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, scmd.Key, test.key)
|
testx.AssertEqual(t, cmd.cursor, test.cursor)
|
||||||
testx.AssertEqual(t, scmd.Cursor, test.cursor)
|
testx.AssertEqual(t, cmd.match, test.match)
|
||||||
testx.AssertEqual(t, scmd.Match, test.match)
|
testx.AssertEqual(t, cmd.count, test.count)
|
||||||
testx.AssertEqual(t, scmd.Count, test.count)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -140,7 +126,7 @@ func TestHScanExec(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("hscan all", func(t *testing.T) {
|
t.Run("hscan all", func(t *testing.T) {
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*hash.HScan]("hscan key 0")
|
cmd := redis.MustParse(ParseHScan, "hscan key 0")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -156,7 +142,7 @@ func TestHScanExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,5,10,f11,11,f12,12,f21,21,f22,22,f31,31")
|
testx.AssertEqual(t, conn.Out(), "2,5,10,f11,11,f12,12,f21,21,f22,22,f31,31")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*hash.HScan]("hscan key 5")
|
cmd := redis.MustParse(ParseHScan, "hscan key 5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -170,7 +156,7 @@ func TestHScanExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("hscan pattern", func(t *testing.T) {
|
t.Run("hscan pattern", func(t *testing.T) {
|
||||||
cmd := command.MustParse[*hash.HScan]("hscan key 0 match f2*")
|
cmd := redis.MustParse(ParseHScan, "hscan key 0 match f2*")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -189,7 +175,7 @@ func TestHScanExec(t *testing.T) {
|
|||||||
t.Run("hscan count", func(t *testing.T) {
|
t.Run("hscan count", func(t *testing.T) {
|
||||||
{
|
{
|
||||||
// page 1
|
// page 1
|
||||||
cmd := command.MustParse[*hash.HScan]("hscan key 0 match * count 2")
|
cmd := redis.MustParse(ParseHScan, "hscan key 0 match * count 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -206,7 +192,7 @@ func TestHScanExec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// page 2
|
// page 2
|
||||||
cmd := command.MustParse[*hash.HScan]("hscan key 2 match * count 2")
|
cmd := redis.MustParse(ParseHScan, "hscan key 2 match * count 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -223,7 +209,7 @@ func TestHScanExec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// page 3
|
// page 3
|
||||||
cmd := command.MustParse[*hash.HScan]("hscan key 4 match * count 2")
|
cmd := redis.MustParse(ParseHScan, "hscan key 4 match * count 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -238,7 +224,7 @@ func TestHScanExec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// no more pages
|
// no more pages
|
||||||
cmd := command.MustParse[*hash.HScan]("hscan key 5 match * count 2")
|
cmd := redis.MustParse(ParseHScan, "hscan key 5 match * count 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ import (
|
|||||||
// https://redis.io/commands/hset
|
// https://redis.io/commands/hset
|
||||||
type HSet struct {
|
type HSet struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Items map[string]any
|
items map[string]any
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHSet(b redis.BaseCmd) (*HSet, error) {
|
func ParseHSet(b redis.BaseCmd) (*HSet, error) {
|
||||||
cmd := &HSet{BaseCmd: b}
|
cmd := &HSet{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.AnyMap(&cmd.Items),
|
parser.AnyMap(&cmd.items),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -27,7 +27,7 @@ func ParseHSet(b redis.BaseCmd) (*HSet, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HSet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HSet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
count, err := red.Hash().SetMany(cmd.Key, cmd.Items)
|
count, err := red.Hash().SetMany(cmd.key, cmd.items)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,55 +1,46 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHSetParse(t *testing.T) {
|
func TestHSetParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want HSet
|
||||||
want hash.HSet
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hset",
|
cmd: "hset",
|
||||||
args: command.BuildArgs("hset"),
|
want: HSet{},
|
||||||
want: hash.HSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hset person",
|
cmd: "hset person",
|
||||||
args: command.BuildArgs("hset", "person"),
|
want: HSet{},
|
||||||
want: hash.HSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hset person name",
|
cmd: "hset person name",
|
||||||
args: command.BuildArgs("hset", "person", "name"),
|
want: HSet{},
|
||||||
want: hash.HSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hset person name alice",
|
cmd: "hset person name alice",
|
||||||
args: command.BuildArgs("hset", "person", "name", "alice"),
|
want: HSet{key: "person", items: map[string]any{"name": []byte("alice")}},
|
||||||
want: hash.HSet{Key: "person", Items: map[string]any{"name": []byte("alice")}},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hset person name alice age",
|
cmd: "hset person name alice age",
|
||||||
args: command.BuildArgs("hset", "person", "name", "alice", "age"),
|
want: HSet{},
|
||||||
want: hash.HSet{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hset person name alice age 25",
|
cmd: "hset person name alice age 25",
|
||||||
args: command.BuildArgs("hset", "person", "name", "alice", "age", "25"),
|
want: HSet{key: "person", items: map[string]any{
|
||||||
want: hash.HSet{Key: "person", Items: map[string]any{
|
|
||||||
"name": []byte("alice"),
|
"name": []byte("alice"),
|
||||||
"age": []byte("25"),
|
"age": []byte("25"),
|
||||||
}},
|
}},
|
||||||
@@ -58,13 +49,12 @@ func TestHSetParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHSet, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HSet)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.items, test.want.items)
|
||||||
testx.AssertEqual(t, cm.Items, test.want.Items)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -75,7 +65,7 @@ func TestHSetExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HSet]("hset person name alice")
|
cmd := redis.MustParse(ParseHSet, "hset person name alice")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -90,7 +80,7 @@ func TestHSetExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HSet]("hset person name alice age 25")
|
cmd := redis.MustParse(ParseHSet, "hset person name alice age 25")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -109,7 +99,7 @@ func TestHSetExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HSet]("hset person name bob age 50")
|
cmd := redis.MustParse(ParseHSet, "hset person name bob age 50")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -129,7 +119,7 @@ func TestHSetExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HSet]("hset person name bob age 50")
|
cmd := redis.MustParse(ParseHSet, "hset person name bob age 50")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/hsetnx
|
// https://redis.io/commands/hsetnx
|
||||||
type HSetNX struct {
|
type HSetNX struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Field string
|
field string
|
||||||
Value []byte
|
value []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHSetNX(b redis.BaseCmd) (*HSetNX, error) {
|
func ParseHSetNX(b redis.BaseCmd) (*HSetNX, error) {
|
||||||
@@ -17,14 +17,14 @@ func ParseHSetNX(b redis.BaseCmd) (*HSetNX, error) {
|
|||||||
if len(cmd.Args()) != 3 {
|
if len(cmd.Args()) != 3 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
cmd.Field = string(cmd.Args()[1])
|
cmd.field = string(cmd.Args()[1])
|
||||||
cmd.Value = cmd.Args()[2]
|
cmd.value = cmd.Args()[2]
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HSetNX) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HSetNX) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
ok, err := red.Hash().SetNotExists(cmd.Key, cmd.Field, cmd.Value)
|
ok, err := red.Hash().SetNotExists(cmd.key, cmd.field, cmd.value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,61 +1,52 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHSetNXParse(t *testing.T) {
|
func TestHSetNXParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want HSetNX
|
||||||
want hash.HSetNX
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hsetnx",
|
cmd: "hsetnx",
|
||||||
args: command.BuildArgs("hsetnx"),
|
want: HSetNX{},
|
||||||
want: hash.HSetNX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hsetnx person",
|
cmd: "hsetnx person",
|
||||||
args: command.BuildArgs("hsetnx", "person"),
|
want: HSetNX{},
|
||||||
want: hash.HSetNX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hsetnx person name",
|
cmd: "hsetnx person name",
|
||||||
args: command.BuildArgs("hsetnx", "person", "name"),
|
want: HSetNX{},
|
||||||
want: hash.HSetNX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hsetnx person name alice",
|
cmd: "hsetnx person name alice",
|
||||||
args: command.BuildArgs("hsetnx", "person", "name", "alice"),
|
want: HSetNX{key: "person", field: "name", value: []byte("alice")},
|
||||||
want: hash.HSetNX{Key: "person", Field: "name", Value: []byte("alice")},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hsetnx person name alice age 25",
|
cmd: "hsetnx person name alice age 25",
|
||||||
args: command.BuildArgs("hsetnx", "person", "name", "alice", "age", "25"),
|
want: HSetNX{},
|
||||||
want: hash.HSetNX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHSetNX, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HSetNX)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.value, test.want.value)
|
||||||
testx.AssertEqual(t, cm.Value, test.want.Value)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -66,7 +57,7 @@ func TestHSetNXExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HSetNX]("hsetnx person name alice")
|
cmd := redis.MustParse(ParseHSetNX, "hsetnx person name alice")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -83,7 +74,7 @@ func TestHSetNXExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HSetNX]("hsetnx person name bob")
|
cmd := redis.MustParse(ParseHSetNX, "hsetnx person name bob")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/hvals
|
// https://redis.io/commands/hvals
|
||||||
type HVals struct {
|
type HVals struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseHVals(b redis.BaseCmd) (*HVals, error) {
|
func ParseHVals(b redis.BaseCmd) (*HVals, error) {
|
||||||
@@ -15,12 +15,12 @@ func ParseHVals(b redis.BaseCmd) (*HVals, error) {
|
|||||||
if len(cmd.Args()) != 1 {
|
if len(cmd.Args()) != 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *HVals) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *HVals) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
vals, err := red.Hash().Values(cmd.Key)
|
vals, err := red.Hash().Values(cmd.key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package hash_test
|
package hash
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/hash"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,38 +10,33 @@ import (
|
|||||||
|
|
||||||
func TestHValsParse(t *testing.T) {
|
func TestHValsParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
key string
|
||||||
key string
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "hvals",
|
cmd: "hvals",
|
||||||
args: command.BuildArgs("hvals"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hvals person",
|
cmd: "hvals person",
|
||||||
args: command.BuildArgs("hvals", "person"),
|
key: "person",
|
||||||
key: "person",
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hvals person name",
|
cmd: "hvals person name",
|
||||||
args: command.BuildArgs("hvals", "person", "name"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseHVals, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*hash.HVals)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.key)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -57,7 +50,7 @@ func TestHValsExec(t *testing.T) {
|
|||||||
_, _ = db.Hash().Set("person", "name", "alice")
|
_, _ = db.Hash().Set("person", "name", "alice")
|
||||||
_, _ = db.Hash().Set("person", "age", 25)
|
_, _ = db.Hash().Set("person", "age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HVals]("hvals person")
|
cmd := redis.MustParse(ParseHVals, "hvals person")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
@@ -69,7 +62,7 @@ func TestHValsExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*hash.HVals]("hvals person")
|
cmd := redis.MustParse(ParseHVals, "hvals person")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import (
|
|||||||
// https://redis.io/commands/del
|
// https://redis.io/commands/del
|
||||||
type Del struct {
|
type Del struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Keys []string
|
keys []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseDel(b redis.BaseCmd) (*Del, error) {
|
func ParseDel(b redis.BaseCmd) (*Del, error) {
|
||||||
cmd := &Del{BaseCmd: b}
|
cmd := &Del{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.Strings(&cmd.Keys),
|
parser.Strings(&cmd.keys),
|
||||||
).Required(1).Run(cmd.Args())
|
).Required(1).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmd, err
|
return cmd, err
|
||||||
@@ -25,7 +25,7 @@ func ParseDel(b redis.BaseCmd) (*Del, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Del) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Del) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
count, err := red.Key().Delete(cmd.Keys...)
|
count, err := red.Key().Delete(cmd.keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,47 +1,41 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDelParse(t *testing.T) {
|
func TestDelParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
want []string
|
want []string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "del",
|
cmd: "del",
|
||||||
args: command.BuildArgs("del"),
|
|
||||||
want: nil,
|
want: nil,
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "del name",
|
cmd: "del name",
|
||||||
args: command.BuildArgs("del", "name"),
|
|
||||||
want: []string{"name"},
|
want: []string{"name"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "del name age",
|
cmd: "del name age",
|
||||||
args: command.BuildArgs("del", "name", "age"),
|
|
||||||
want: []string{"name", "age"},
|
want: []string{"name", "age"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseDel, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*key.Del).Keys, test.want)
|
testx.AssertEqual(t, cmd.keys, test.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -49,33 +43,29 @@ func TestDelParse(t *testing.T) {
|
|||||||
|
|
||||||
func TestDelExec(t *testing.T) {
|
func TestDelExec(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
cmd *key.Del
|
res any
|
||||||
res any
|
out string
|
||||||
out string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "del one",
|
cmd: "del name",
|
||||||
cmd: command.MustParse[*key.Del]("del name"),
|
res: 1,
|
||||||
res: 1,
|
out: "1",
|
||||||
out: "1",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "del all",
|
cmd: "del name age",
|
||||||
cmd: command.MustParse[*key.Del]("del name age"),
|
res: 2,
|
||||||
res: 2,
|
out: "2",
|
||||||
out: "2",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "del some",
|
cmd: "del name age street",
|
||||||
cmd: command.MustParse[*key.Del]("del name age street"),
|
res: 2,
|
||||||
res: 2,
|
out: "2",
|
||||||
out: "2",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
@@ -84,7 +74,8 @@ func TestDelExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("city", "paris")
|
_ = db.Str().Set("city", "paris")
|
||||||
|
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := test.cmd.Run(conn, red)
|
cmd := redis.MustParse(ParseDel, test.cmd)
|
||||||
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, test.res)
|
testx.AssertEqual(t, res, test.res)
|
||||||
testx.AssertEqual(t, conn.Out(), test.out)
|
testx.AssertEqual(t, conn.Out(), test.out)
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import (
|
|||||||
// https://redis.io/commands/exists
|
// https://redis.io/commands/exists
|
||||||
type Exists struct {
|
type Exists struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Keys []string
|
keys []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseExists(b redis.BaseCmd) (*Exists, error) {
|
func ParseExists(b redis.BaseCmd) (*Exists, error) {
|
||||||
cmd := &Exists{BaseCmd: b}
|
cmd := &Exists{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.Strings(&cmd.Keys),
|
parser.Strings(&cmd.keys),
|
||||||
).Required(1).Run(cmd.Args())
|
).Required(1).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmd, err
|
return cmd, err
|
||||||
@@ -25,7 +25,7 @@ func ParseExists(b redis.BaseCmd) (*Exists, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Exists) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Exists) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
count, err := red.Key().Count(cmd.Keys...)
|
count, err := red.Key().Count(cmd.keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,47 +1,41 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExistsParse(t *testing.T) {
|
func TestExistsParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
want []string
|
want []string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "exists",
|
cmd: "exists",
|
||||||
args: command.BuildArgs("exists"),
|
|
||||||
want: nil,
|
want: nil,
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "exists name",
|
cmd: "exists name",
|
||||||
args: command.BuildArgs("exists", "name"),
|
|
||||||
want: []string{"name"},
|
want: []string{"name"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "exists name age",
|
cmd: "exists name age",
|
||||||
args: command.BuildArgs("exists", "name", "age"),
|
|
||||||
want: []string{"name", "age"},
|
want: []string{"name", "age"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseExists, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*key.Exists).Keys, test.want)
|
testx.AssertEqual(t, cmd.keys, test.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -56,35 +50,32 @@ func TestExistsExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("city", "paris")
|
_ = db.Str().Set("city", "paris")
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
cmd *key.Exists
|
res any
|
||||||
res any
|
out string
|
||||||
out string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "exists one",
|
cmd: "exists name",
|
||||||
cmd: command.MustParse[*key.Exists]("exists name"),
|
res: 1,
|
||||||
res: 1,
|
out: "1",
|
||||||
out: "1",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "exists all",
|
cmd: "exists name age",
|
||||||
cmd: command.MustParse[*key.Exists]("exists name age"),
|
res: 2,
|
||||||
res: 2,
|
out: "2",
|
||||||
out: "2",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "exists some",
|
cmd: "exists name age street",
|
||||||
cmd: command.MustParse[*key.Exists]("exists name age street"),
|
res: 2,
|
||||||
res: 2,
|
out: "2",
|
||||||
out: "2",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := test.cmd.Run(conn, red)
|
cmd := redis.MustParse(ParseExists, test.cmd)
|
||||||
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, test.res)
|
testx.AssertEqual(t, res, test.res)
|
||||||
testx.AssertEqual(t, conn.Out(), test.out)
|
testx.AssertEqual(t, conn.Out(), test.out)
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import (
|
|||||||
// https://redis.io/commands/expire
|
// https://redis.io/commands/expire
|
||||||
type Expire struct {
|
type Expire struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
TTL time.Duration
|
ttl time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseExpire(b redis.BaseCmd, multi int) (*Expire, error) {
|
func ParseExpire(b redis.BaseCmd, multi int) (*Expire, error) {
|
||||||
@@ -22,19 +22,19 @@ func ParseExpire(b redis.BaseCmd, multi int) (*Expire, error) {
|
|||||||
|
|
||||||
var ttl int
|
var ttl int
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Int(&ttl),
|
parser.Int(&ttl),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmd, err
|
return cmd, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.TTL = time.Duration(multi*ttl) * time.Millisecond
|
cmd.ttl = time.Duration(multi*ttl) * time.Millisecond
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Expire) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Expire) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
err := red.Key().Expire(cmd.Key, cmd.TTL)
|
err := red.Key().Expire(cmd.key, cmd.ttl)
|
||||||
if err != nil && err != core.ErrNotFound {
|
if err != nil && err != core.ErrNotFound {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,80 +1,79 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExpireParse(t *testing.T) {
|
func TestExpireParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
key string
|
||||||
key string
|
ttl time.Duration
|
||||||
ttl time.Duration
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "expire",
|
cmd: "expire",
|
||||||
args: command.BuildArgs("expire"),
|
key: "",
|
||||||
key: "",
|
ttl: 0,
|
||||||
ttl: 0,
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expire name",
|
cmd: "expire name",
|
||||||
args: command.BuildArgs("expire", "name"),
|
key: "",
|
||||||
key: "",
|
ttl: 0,
|
||||||
ttl: 0,
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expire name 60",
|
cmd: "expire name 60",
|
||||||
args: command.BuildArgs("expire", "name", "60"),
|
key: "name",
|
||||||
key: "name",
|
ttl: 60 * 1000 * time.Millisecond,
|
||||||
ttl: 60 * 1000 * time.Millisecond,
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expire name age",
|
cmd: "expire name age",
|
||||||
args: command.BuildArgs("expire", "name", "age"),
|
key: "",
|
||||||
key: "",
|
ttl: 0,
|
||||||
ttl: 0,
|
err: redis.ErrInvalidInt,
|
||||||
err: redis.ErrInvalidInt,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expire name 60 age 60",
|
cmd: "expire name 60 age 60",
|
||||||
args: command.BuildArgs("expire", "name", "60", "age", "60"),
|
key: "",
|
||||||
key: "",
|
ttl: 0,
|
||||||
ttl: 0,
|
err: redis.ErrSyntaxError,
|
||||||
err: redis.ErrSyntaxError,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse := func(b redis.BaseCmd) (*Expire, error) {
|
||||||
|
return ParseExpire(b, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(parse, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*key.Expire).Key, test.key)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cmd.(*key.Expire).TTL, test.ttl)
|
testx.AssertEqual(t, cmd.ttl, test.ttl)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpireExec(t *testing.T) {
|
func TestExpireExec(t *testing.T) {
|
||||||
|
parse := func(b redis.BaseCmd) (*Expire, error) {
|
||||||
|
return ParseExpire(b, 1000)
|
||||||
|
}
|
||||||
t.Run("create expire", func(t *testing.T) {
|
t.Run("create expire", func(t *testing.T) {
|
||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("expire name 60")
|
cmd := redis.MustParse(parse, "expire name 60")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -92,7 +91,7 @@ func TestExpireExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("expire name 30")
|
cmd := redis.MustParse(parse, "expire name 30")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -110,7 +109,7 @@ func TestExpireExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("expire name 0")
|
cmd := redis.MustParse(parse, "expire name 0")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -127,7 +126,7 @@ func TestExpireExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("expire name -10")
|
cmd := redis.MustParse(parse, "expire name -10")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -144,7 +143,7 @@ func TestExpireExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("expire age 60")
|
cmd := redis.MustParse(parse, "expire age 60")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import (
|
|||||||
// https://redis.io/commands/expireat
|
// https://redis.io/commands/expireat
|
||||||
type ExpireAt struct {
|
type ExpireAt struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
At time.Time
|
at time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseExpireAt(b redis.BaseCmd, multi int) (*ExpireAt, error) {
|
func ParseExpireAt(b redis.BaseCmd, multi int) (*ExpireAt, error) {
|
||||||
@@ -22,19 +22,19 @@ func ParseExpireAt(b redis.BaseCmd, multi int) (*ExpireAt, error) {
|
|||||||
|
|
||||||
var at int
|
var at int
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Int(&at),
|
parser.Int(&at),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmd, err
|
return cmd, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.At = time.UnixMilli(int64(multi * at))
|
cmd.at = time.UnixMilli(int64(multi * at))
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ExpireAt) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ExpireAt) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
err := red.Key().ExpireAt(cmd.Key, cmd.At)
|
err := red.Key().ExpireAt(cmd.key, cmd.at)
|
||||||
if err != nil && err != core.ErrNotFound {
|
if err != nil && err != core.ErrNotFound {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,74 +1,73 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExpireAtParse(t *testing.T) {
|
func TestExpireAtParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
key string
|
||||||
key string
|
at time.Time
|
||||||
at time.Time
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "expireat",
|
cmd: "expireat",
|
||||||
args: command.BuildArgs("expireat"),
|
key: "",
|
||||||
key: "",
|
at: time.Time{},
|
||||||
at: time.Time{},
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expireat name",
|
cmd: "expireat name",
|
||||||
args: command.BuildArgs("expire", "name"),
|
key: "",
|
||||||
key: "",
|
at: time.Time{},
|
||||||
at: time.Time{},
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expireat name 60",
|
cmd: "expireat name 60",
|
||||||
args: command.BuildArgs("expireat", "name", fmt.Sprintf("%d", time.Now().Add(60*time.Second).Unix())),
|
key: "name",
|
||||||
key: "name",
|
at: time.UnixMilli(60 * 1000),
|
||||||
at: time.Now().Add(60 * time.Second),
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expireat name age",
|
cmd: "expireat name age",
|
||||||
args: command.BuildArgs("expireat", "name", "age"),
|
key: "",
|
||||||
key: "",
|
at: time.Time{},
|
||||||
at: time.Time{},
|
err: redis.ErrInvalidInt,
|
||||||
err: redis.ErrInvalidInt,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "expireat name 60 age 60",
|
cmd: "expireat name 60 age 60",
|
||||||
args: command.BuildArgs("expireat", "name", "60", "age", "60"),
|
key: "",
|
||||||
key: "",
|
at: time.Time{},
|
||||||
at: time.Time{},
|
err: redis.ErrSyntaxError,
|
||||||
err: redis.ErrSyntaxError,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse := func(b redis.BaseCmd) (*ExpireAt, error) {
|
||||||
|
return ParseExpireAt(b, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(parse, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*key.ExpireAt).Key, test.key)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cmd.(*key.ExpireAt).At.Unix(), test.at.Unix())
|
testx.AssertEqual(t, cmd.at.Unix(), test.at.Unix())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpireAtExec(t *testing.T) {
|
func TestExpireAtExec(t *testing.T) {
|
||||||
|
parse := func(b redis.BaseCmd) (*ExpireAt, error) {
|
||||||
|
return ParseExpireAt(b, 1000)
|
||||||
|
}
|
||||||
t.Run("create expireat", func(t *testing.T) {
|
t.Run("create expireat", func(t *testing.T) {
|
||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
@@ -76,7 +75,7 @@ func TestExpireAtExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
expireAt := time.Now().Add(60 * time.Second)
|
expireAt := time.Now().Add(60 * time.Second)
|
||||||
cmd := command.MustParse[*key.ExpireAt](fmt.Sprintf("expireat name %d", expireAt.Unix()))
|
cmd := redis.MustParse(parse, fmt.Sprintf("expireat name %d", expireAt.Unix()))
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -94,14 +93,14 @@ func TestExpireAtExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
expireAt := time.Now()
|
expireAt := time.Now()
|
||||||
cmd := command.MustParse[*key.ExpireAt](fmt.Sprintf("expireat name %d", expireAt.Add(60*time.Second).Unix()))
|
cmd := redis.MustParse(parse, fmt.Sprintf("expireat name %d", expireAt.Add(60*time.Second).Unix()))
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, true)
|
testx.AssertEqual(t, res, true)
|
||||||
testx.AssertEqual(t, conn.Out(), "1")
|
testx.AssertEqual(t, conn.Out(), "1")
|
||||||
|
|
||||||
cmd = command.MustParse[*key.ExpireAt](fmt.Sprintf("expireat name %d", expireAt.Add(20*time.Second).Unix()))
|
cmd = redis.MustParse(parse, fmt.Sprintf("expireat name %d", expireAt.Add(20*time.Second).Unix()))
|
||||||
conn = redis.NewFakeConn()
|
conn = redis.NewFakeConn()
|
||||||
res, err = cmd.Run(conn, red)
|
res, err = cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -118,7 +117,7 @@ func TestExpireAtExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.ExpireAt]("expireat name 0")
|
cmd := redis.MustParse(parse, "expireat name 0")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -135,7 +134,7 @@ func TestExpireAtExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.ExpireAt]("expireat name -10")
|
cmd := redis.MustParse(parse, "expireat name -10")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -152,7 +151,7 @@ func TestExpireAtExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.ExpireAt]("expireat age 1700000000")
|
cmd := redis.MustParse(parse, "expireat age 1700000000")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -1,40 +1,34 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFlushDBParse(t *testing.T) {
|
func TestFlushDBParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "flushdb",
|
cmd: "flushdb",
|
||||||
args: command.BuildArgs("flushdb"),
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "flushdb name",
|
cmd: "flushdb name",
|
||||||
args: command.BuildArgs("flushdb", "name"),
|
err: redis.ErrSyntaxError,
|
||||||
err: redis.ErrSyntaxError,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "flushdb 1",
|
cmd: "flushdb 1",
|
||||||
args: command.BuildArgs("flushdb", "1"),
|
err: redis.ErrSyntaxError,
|
||||||
err: redis.ErrSyntaxError,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
_, err := command.Parse(test.args)
|
_, err := redis.Parse(ParseFlushDB, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -48,7 +42,7 @@ func TestFlushDBExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
_ = db.Str().Set("age", 25)
|
_ = db.Str().Set("age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*key.FlushDB]("flushdb")
|
cmd := redis.MustParse(ParseFlushDB, "flushdb")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -63,7 +57,7 @@ func TestFlushDBExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*key.FlushDB]("flushdb")
|
cmd := redis.MustParse(ParseFlushDB, "flushdb")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/keys
|
// https://redis.io/commands/keys
|
||||||
type Keys struct {
|
type Keys struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Pattern string
|
pattern string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseKeys(b redis.BaseCmd) (*Keys, error) {
|
func ParseKeys(b redis.BaseCmd) (*Keys, error) {
|
||||||
@@ -15,12 +15,12 @@ func ParseKeys(b redis.BaseCmd) (*Keys, error) {
|
|||||||
if len(cmd.Args()) != 1 {
|
if len(cmd.Args()) != 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Pattern = string(cmd.Args()[0])
|
cmd.pattern = string(cmd.Args()[0])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Keys) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Keys) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
keys, err := red.Key().Keys(cmd.Pattern)
|
keys, err := red.Key().Keys(cmd.pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,43 +10,38 @@ import (
|
|||||||
|
|
||||||
func TestKeysParse(t *testing.T) {
|
func TestKeysParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
want string
|
want string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "keys",
|
cmd: "keys",
|
||||||
args: command.BuildArgs("keys"),
|
|
||||||
want: "",
|
want: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "keys *",
|
cmd: "keys *",
|
||||||
args: command.BuildArgs("keys", "*"),
|
|
||||||
want: "*",
|
want: "*",
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "keys 2*",
|
cmd: "keys k2*",
|
||||||
args: command.BuildArgs("keys", "k2*"),
|
|
||||||
want: "k2*",
|
want: "k2*",
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "keys * k2*",
|
cmd: "keys * k2*",
|
||||||
args: command.BuildArgs("keys", "*", "k2*"),
|
|
||||||
want: "",
|
want: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseKeys, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*key.Keys).Pattern, test.want)
|
testx.AssertEqual(t, cmd.pattern, test.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -65,41 +58,37 @@ func TestKeysExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("k31", "31")
|
_ = db.Str().Set("k31", "31")
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
cmd *key.Keys
|
res []string
|
||||||
res []string
|
out string
|
||||||
out string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "all keys",
|
cmd: "keys *",
|
||||||
cmd: command.MustParse[*key.Keys]("keys *"),
|
res: []string{"k11", "k12", "k21", "k22", "k31"},
|
||||||
res: []string{"k11", "k12", "k21", "k22", "k31"},
|
out: "5,k11,k12,k21,k22,k31",
|
||||||
out: "5,k11,k12,k21,k22,k31",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "some keys",
|
cmd: "keys k2*",
|
||||||
cmd: command.MustParse[*key.Keys]("keys k2*"),
|
res: []string{"k21", "k22"},
|
||||||
res: []string{"k21", "k22"},
|
out: "2,k21,k22",
|
||||||
out: "2,k21,k22",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "one key",
|
cmd: "keys k12",
|
||||||
cmd: command.MustParse[*key.Keys]("keys k12"),
|
res: []string{"k12"},
|
||||||
res: []string{"k12"},
|
out: "1,k12",
|
||||||
out: "1,k12",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not found",
|
cmd: "keys name",
|
||||||
cmd: command.MustParse[*key.Keys]("keys name"),
|
res: []string{},
|
||||||
res: []string{},
|
out: "0",
|
||||||
out: "0",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
keys, err := test.cmd.Run(conn, red)
|
cmd := redis.MustParse(ParseKeys, test.cmd)
|
||||||
|
keys, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
for i, key := range keys.([]core.Key) {
|
for i, key := range keys.([]core.Key) {
|
||||||
testx.AssertEqual(t, key.Key, test.res[i])
|
testx.AssertEqual(t, key.Key, test.res[i])
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// https://redis.io/commands/persist
|
// https://redis.io/commands/persist
|
||||||
type Persist struct {
|
type Persist struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParsePersist(b redis.BaseCmd) (*Persist, error) {
|
func ParsePersist(b redis.BaseCmd) (*Persist, error) {
|
||||||
@@ -18,12 +18,12 @@ func ParsePersist(b redis.BaseCmd) (*Persist, error) {
|
|||||||
if len(cmd.Args()) != 1 {
|
if len(cmd.Args()) != 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Persist) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Persist) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
err := red.Key().Persist(cmd.Key)
|
err := red.Key().Persist(cmd.key)
|
||||||
if err != nil && err != core.ErrNotFound {
|
if err != nil && err != core.ErrNotFound {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,48 +1,42 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPersistParse(t *testing.T) {
|
func TestPersistParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
key string
|
||||||
key string
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "persist",
|
cmd: "persist",
|
||||||
args: command.BuildArgs("persist"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "persist name",
|
cmd: "persist name",
|
||||||
args: command.BuildArgs("persist", "name"),
|
key: "name",
|
||||||
key: "name",
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "persist name age",
|
cmd: "persist name age",
|
||||||
args: command.BuildArgs("persist", "name", "age"),
|
key: "",
|
||||||
key: "",
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParsePersist, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*key.Persist).Key, test.key)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -55,7 +49,7 @@ func TestPersistExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Persist]("persist name")
|
cmd := redis.MustParse(ParsePersist, "persist name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -72,7 +66,7 @@ func TestPersistExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Persist]("persist name")
|
cmd := redis.MustParse(ParsePersist, "persist name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -89,7 +83,7 @@ func TestPersistExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Persist]("persist age")
|
cmd := redis.MustParse(ParsePersist, "persist age")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -1,80 +1,79 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPExpireParse(t *testing.T) {
|
func TestPExpireParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
key string
|
||||||
key string
|
ttl time.Duration
|
||||||
ttl time.Duration
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "pexpire",
|
cmd: "pexpire",
|
||||||
args: command.BuildArgs("pexpire"),
|
key: "",
|
||||||
key: "",
|
ttl: 0,
|
||||||
ttl: 0,
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "pexpire name",
|
cmd: "pexpire name",
|
||||||
args: command.BuildArgs("pexpire", "name"),
|
key: "",
|
||||||
key: "",
|
ttl: 0,
|
||||||
ttl: 0,
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "pexpire name 5000",
|
cmd: "pexpire name 5000",
|
||||||
args: command.BuildArgs("pexpire", "name", "5000"),
|
key: "name",
|
||||||
key: "name",
|
ttl: 5000 * time.Millisecond,
|
||||||
ttl: 5000 * time.Millisecond,
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "pexpire name age",
|
cmd: "pexpire name age",
|
||||||
args: command.BuildArgs("pexpire", "name", "age"),
|
key: "",
|
||||||
key: "",
|
ttl: 0,
|
||||||
ttl: 0,
|
err: redis.ErrInvalidInt,
|
||||||
err: redis.ErrInvalidInt,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "pexpire name 100 age 100",
|
cmd: "pexpire name 100 age 100",
|
||||||
args: command.BuildArgs("pexpire", "name", "100", "age", "100"),
|
key: "",
|
||||||
key: "",
|
ttl: 0,
|
||||||
ttl: 0,
|
err: redis.ErrSyntaxError,
|
||||||
err: redis.ErrSyntaxError,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse := func(b redis.BaseCmd) (*Expire, error) {
|
||||||
|
return ParseExpire(b, 1)
|
||||||
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(parse, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*key.Expire).Key, test.key)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cmd.(*key.Expire).TTL, test.ttl)
|
testx.AssertEqual(t, cmd.ttl, test.ttl)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPExpireExec(t *testing.T) {
|
func TestPExpireExec(t *testing.T) {
|
||||||
db, red := getDB(t)
|
parse := func(b redis.BaseCmd) (*Expire, error) {
|
||||||
defer db.Close()
|
return ParseExpire(b, 1)
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("create pexpire", func(t *testing.T) {
|
t.Run("create pexpire", func(t *testing.T) {
|
||||||
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("pexpire name 60000")
|
cmd := redis.MustParse(parse, "pexpire name 60000")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -87,9 +86,11 @@ func TestPExpireExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("update pexpire", func(t *testing.T) {
|
t.Run("update pexpire", func(t *testing.T) {
|
||||||
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("pexpire name 30000")
|
cmd := redis.MustParse(parse, "pexpire name 30000")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -102,9 +103,11 @@ func TestPExpireExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("set to zero", func(t *testing.T) {
|
t.Run("set to zero", func(t *testing.T) {
|
||||||
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("pexpire name 0")
|
cmd := redis.MustParse(parse, "pexpire name 0")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -116,9 +119,11 @@ func TestPExpireExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("negative", func(t *testing.T) {
|
t.Run("negative", func(t *testing.T) {
|
||||||
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("pexpire name -1000")
|
cmd := redis.MustParse(parse, "pexpire name -1000")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -130,9 +135,11 @@ func TestPExpireExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("not found", func(t *testing.T) {
|
t.Run("not found", func(t *testing.T) {
|
||||||
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Expire]("pexpire age 1000")
|
cmd := redis.MustParse(parse, "pexpire age 1000")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -13,30 +11,26 @@ import (
|
|||||||
|
|
||||||
func TestRandomKeyParse(t *testing.T) {
|
func TestRandomKeyParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "randomkey",
|
cmd: "randomkey",
|
||||||
args: command.BuildArgs("randomkey"),
|
err: nil,
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "randomkey name",
|
cmd: "randomkey name",
|
||||||
args: command.BuildArgs("randomkey", "name"),
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "randomkey name age",
|
cmd: "randomkey name age",
|
||||||
args: command.BuildArgs("randomkey", "name", "age"),
|
err: redis.ErrInvalidArgNum,
|
||||||
err: redis.ErrInvalidArgNum,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
_, err := command.Parse(test.args)
|
_, err := redis.Parse(ParseRandomKey, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -52,7 +46,7 @@ func TestRandomKeyExec(t *testing.T) {
|
|||||||
keys := []string{"name", "age", "city"}
|
keys := []string{"name", "age", "city"}
|
||||||
|
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
cmd := command.MustParse[*key.RandomKey]("randomkey")
|
cmd := redis.MustParse(ParseRandomKey, "randomkey")
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, slices.Contains(keys, res.(core.Key).Key), true)
|
testx.AssertEqual(t, slices.Contains(keys, res.(core.Key).Key), true)
|
||||||
@@ -62,7 +56,7 @@ func TestRandomKeyExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
cmd := command.MustParse[*key.RandomKey]("randomkey")
|
cmd := redis.MustParse(ParseRandomKey, "randomkey")
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, nil)
|
testx.AssertEqual(t, res, nil)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/rename
|
// https://redis.io/commands/rename
|
||||||
type Rename struct {
|
type Rename struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
NewKey string
|
newKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseRename(b redis.BaseCmd) (*Rename, error) {
|
func ParseRename(b redis.BaseCmd) (*Rename, error) {
|
||||||
@@ -16,13 +16,13 @@ func ParseRename(b redis.BaseCmd) (*Rename, error) {
|
|||||||
if len(cmd.Args()) != 2 {
|
if len(cmd.Args()) != 2 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
cmd.NewKey = string(cmd.Args()[1])
|
cmd.newKey = string(cmd.Args()[1])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Rename) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Rename) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
err := red.Key().Rename(cmd.Key, cmd.NewKey)
|
err := red.Key().Rename(cmd.key, cmd.newKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,29 +10,25 @@ import (
|
|||||||
|
|
||||||
func TestRenameParse(t *testing.T) {
|
func TestRenameParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
key string
|
key string
|
||||||
newKey string
|
newKey string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "rename",
|
cmd: "rename",
|
||||||
args: command.BuildArgs("rename"),
|
|
||||||
key: "",
|
key: "",
|
||||||
newKey: "",
|
newKey: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "rename name",
|
cmd: "rename name",
|
||||||
args: command.BuildArgs("rename", "name"),
|
|
||||||
key: "",
|
key: "",
|
||||||
newKey: "",
|
newKey: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "rename name title",
|
cmd: "rename name title",
|
||||||
args: command.BuildArgs("rename", "name", "title"),
|
|
||||||
key: "name",
|
key: "name",
|
||||||
newKey: "title",
|
newKey: "title",
|
||||||
err: nil,
|
err: nil,
|
||||||
@@ -42,12 +36,12 @@ func TestRenameParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseRename, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*key.Rename).Key, test.key)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cmd.(*key.Rename).NewKey, test.newKey)
|
testx.AssertEqual(t, cmd.newKey, test.newKey)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -60,7 +54,7 @@ func TestRenameExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Rename]("rename name title")
|
cmd := redis.MustParse(ParseRename, "rename name title")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -80,7 +74,7 @@ func TestRenameExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
_ = db.Str().Set("title", "bob")
|
_ = db.Str().Set("title", "bob")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Rename]("rename name title")
|
cmd := redis.MustParse(ParseRename, "rename name title")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -101,7 +95,7 @@ func TestRenameExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Rename]("rename name name")
|
cmd := redis.MustParse(ParseRename, "rename name name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -120,7 +114,7 @@ func TestRenameExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("title", "bob")
|
_ = db.Str().Set("title", "bob")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.Rename]("rename name title")
|
cmd := redis.MustParse(ParseRename, "rename name title")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertEqual(t, err, core.ErrNotFound)
|
testx.AssertEqual(t, err, core.ErrNotFound)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/renamenx
|
// https://redis.io/commands/renamenx
|
||||||
type RenameNX struct {
|
type RenameNX struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
NewKey string
|
newKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseRenameNX(b redis.BaseCmd) (*RenameNX, error) {
|
func ParseRenameNX(b redis.BaseCmd) (*RenameNX, error) {
|
||||||
@@ -16,13 +16,13 @@ func ParseRenameNX(b redis.BaseCmd) (*RenameNX, error) {
|
|||||||
if len(cmd.Args()) != 2 {
|
if len(cmd.Args()) != 2 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
cmd.NewKey = string(cmd.Args()[1])
|
cmd.newKey = string(cmd.Args()[1])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *RenameNX) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *RenameNX) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
ok, err := red.Key().RenameNotExists(cmd.Key, cmd.NewKey)
|
ok, err := red.Key().RenameNotExists(cmd.key, cmd.newKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,29 +10,25 @@ import (
|
|||||||
|
|
||||||
func TestRenameNXParse(t *testing.T) {
|
func TestRenameNXParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
key string
|
key string
|
||||||
newKey string
|
newKey string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "renamenx",
|
cmd: "renamenx",
|
||||||
args: command.BuildArgs("renamenx"),
|
|
||||||
key: "",
|
key: "",
|
||||||
newKey: "",
|
newKey: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "renamenx name",
|
cmd: "renamenx name",
|
||||||
args: command.BuildArgs("renamenx", "name"),
|
|
||||||
key: "",
|
key: "",
|
||||||
newKey: "",
|
newKey: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "renamenx name title",
|
cmd: "renamenx name title",
|
||||||
args: command.BuildArgs("renamenx", "name", "title"),
|
|
||||||
key: "name",
|
key: "name",
|
||||||
newKey: "title",
|
newKey: "title",
|
||||||
err: nil,
|
err: nil,
|
||||||
@@ -42,12 +36,12 @@ func TestRenameNXParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseRenameNX, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*key.RenameNX).Key, test.key)
|
testx.AssertEqual(t, cmd.key, test.key)
|
||||||
testx.AssertEqual(t, cmd.(*key.RenameNX).NewKey, test.newKey)
|
testx.AssertEqual(t, cmd.newKey, test.newKey)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -60,7 +54,7 @@ func TestRenameNXExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.RenameNX]("renamenx name title")
|
cmd := redis.MustParse(ParseRenameNX, "renamenx name title")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -80,7 +74,7 @@ func TestRenameNXExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
_ = db.Str().Set("title", "bob")
|
_ = db.Str().Set("title", "bob")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.RenameNX]("renamenx name title")
|
cmd := redis.MustParse(ParseRenameNX, "renamenx name title")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -103,7 +97,7 @@ func TestRenameNXExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.RenameNX]("renamenx name name")
|
cmd := redis.MustParse(ParseRenameNX, "renamenx name name")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -122,7 +116,7 @@ func TestRenameNXExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("title", "bob")
|
_ = db.Str().Set("title", "bob")
|
||||||
|
|
||||||
cmd := command.MustParse[*key.RenameNX]("renamenx name title")
|
cmd := redis.MustParse(ParseRenameNX, "renamenx name title")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertEqual(t, err, core.ErrNotFound)
|
testx.AssertEqual(t, err, core.ErrNotFound)
|
||||||
|
|||||||
@@ -10,33 +10,33 @@ import (
|
|||||||
// https://redis.io/commands/scan
|
// https://redis.io/commands/scan
|
||||||
type Scan struct {
|
type Scan struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Cursor int
|
cursor int
|
||||||
Match string
|
match string
|
||||||
Count int
|
count int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseScan(b redis.BaseCmd) (*Scan, error) {
|
func ParseScan(b redis.BaseCmd) (*Scan, error) {
|
||||||
cmd := &Scan{BaseCmd: b}
|
cmd := &Scan{BaseCmd: b}
|
||||||
|
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.Int(&cmd.Cursor),
|
parser.Int(&cmd.cursor),
|
||||||
parser.Named("match", parser.String(&cmd.Match)),
|
parser.Named("match", parser.String(&cmd.match)),
|
||||||
parser.Named("count", parser.Int(&cmd.Count)),
|
parser.Named("count", parser.Int(&cmd.count)),
|
||||||
).Required(1).Run(cmd.Args())
|
).Required(1).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmd, err
|
return cmd, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// all keys by default
|
// all keys by default
|
||||||
if cmd.Match == "" {
|
if cmd.match == "" {
|
||||||
cmd.Match = "*"
|
cmd.match = "*"
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Scan) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Scan) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
res, err := red.Key().Scan(cmd.Cursor, cmd.Match, cmd.Count)
|
res, err := red.Key().Scan(cmd.cursor, cmd.match, cmd.count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package key_test
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/key"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/rkey"
|
"github.com/nalgeon/redka/internal/rkey"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,88 +10,77 @@ import (
|
|||||||
|
|
||||||
func TestScanParse(t *testing.T) {
|
func TestScanParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
cursor int
|
cursor int
|
||||||
match string
|
match string
|
||||||
count int
|
count int
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "scan",
|
cmd: "scan",
|
||||||
args: command.BuildArgs("scan"),
|
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
match: "*",
|
match: "*",
|
||||||
count: 0,
|
count: 0,
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scan 15",
|
cmd: "scan 15",
|
||||||
args: command.BuildArgs("scan", "15"),
|
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "*",
|
match: "*",
|
||||||
count: 0,
|
count: 0,
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scan 15 match *",
|
cmd: "scan 15 match *",
|
||||||
args: command.BuildArgs("scan", "15", "match", "*"),
|
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "*",
|
match: "*",
|
||||||
count: 0,
|
count: 0,
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scan 15 match * count 5",
|
cmd: "scan 15 match * count 5",
|
||||||
args: command.BuildArgs("scan", "15", "match", "*", "count", "5"),
|
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "*",
|
match: "*",
|
||||||
count: 5,
|
count: 5,
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scan 15 match * count ok",
|
cmd: "scan 15 match * count ok",
|
||||||
args: command.BuildArgs("scan", "15", "match", "*", "count", "ok"),
|
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "*",
|
match: "*",
|
||||||
count: 0,
|
count: 0,
|
||||||
err: redis.ErrInvalidInt,
|
err: redis.ErrInvalidInt,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scan 15 count 5 match *",
|
cmd: "scan 15 count 5 match *",
|
||||||
args: command.BuildArgs("scan", "15", "count", "5", "match", "*"),
|
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "*",
|
match: "*",
|
||||||
count: 5,
|
count: 5,
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scan 15 match k2* count 5",
|
cmd: "scan 15 match k2* count 5",
|
||||||
args: command.BuildArgs("scan", "15", "match", "k2*", "count", "5"),
|
|
||||||
cursor: 15,
|
cursor: 15,
|
||||||
match: "k2*",
|
match: "k2*",
|
||||||
count: 5,
|
count: 5,
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scan ten",
|
cmd: "scan ten",
|
||||||
args: command.BuildArgs("scan", "ten"),
|
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
match: "",
|
match: "",
|
||||||
count: 0,
|
count: 0,
|
||||||
err: redis.ErrInvalidInt,
|
err: redis.ErrInvalidInt,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scan 15 *",
|
cmd: "scan 15 *",
|
||||||
args: command.BuildArgs("scan", "15", "*"),
|
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
match: "",
|
match: "",
|
||||||
count: 0,
|
count: 0,
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scan 15 * 5",
|
cmd: "scan 15 * 5",
|
||||||
args: command.BuildArgs("scan", "15", "*", "5"),
|
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
match: "",
|
match: "",
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -102,14 +89,13 @@ func TestScanParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseScan, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
scmd := cmd.(*key.Scan)
|
testx.AssertEqual(t, cmd.cursor, test.cursor)
|
||||||
testx.AssertEqual(t, scmd.Cursor, test.cursor)
|
testx.AssertEqual(t, cmd.match, test.match)
|
||||||
testx.AssertEqual(t, scmd.Match, test.match)
|
testx.AssertEqual(t, cmd.count, test.count)
|
||||||
testx.AssertEqual(t, scmd.Count, test.count)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -127,7 +113,7 @@ func TestScanExec(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("scan all", func(t *testing.T) {
|
t.Run("scan all", func(t *testing.T) {
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*key.Scan]("scan 0")
|
cmd := redis.MustParse(ParseScan, "scan 0")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -141,7 +127,7 @@ func TestScanExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,5,5,k11,k12,k21,k22,k31")
|
testx.AssertEqual(t, conn.Out(), "2,5,5,k11,k12,k21,k22,k31")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*key.Scan]("scan 5")
|
cmd := redis.MustParse(ParseScan, "scan 5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -155,7 +141,7 @@ func TestScanExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("scan pattern", func(t *testing.T) {
|
t.Run("scan pattern", func(t *testing.T) {
|
||||||
cmd := command.MustParse[*key.Scan]("scan 0 match k2*")
|
cmd := redis.MustParse(ParseScan, "scan 0 match k2*")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -172,7 +158,7 @@ func TestScanExec(t *testing.T) {
|
|||||||
t.Run("scan count", func(t *testing.T) {
|
t.Run("scan count", func(t *testing.T) {
|
||||||
{
|
{
|
||||||
// page 1
|
// page 1
|
||||||
cmd := command.MustParse[*key.Scan]("scan 0 match * count 2")
|
cmd := redis.MustParse(ParseScan, "scan 0 match * count 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -187,7 +173,7 @@ func TestScanExec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// page 2
|
// page 2
|
||||||
cmd := command.MustParse[*key.Scan]("scan 2 match * count 2")
|
cmd := redis.MustParse(ParseScan, "scan 2 match * count 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -202,7 +188,7 @@ func TestScanExec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// page 3
|
// page 3
|
||||||
cmd := command.MustParse[*key.Scan]("scan 4 match * count 2")
|
cmd := redis.MustParse(ParseScan, "scan 4 match * count 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
@@ -216,7 +202,7 @@ func TestScanExec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// no more pages
|
// no more pages
|
||||||
cmd := command.MustParse[*key.Scan]("scan 5 match * count 2")
|
cmd := redis.MustParse(ParseScan, "scan 5 match * count 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
|
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
|
|||||||
@@ -1,60 +1,61 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDecrParse(t *testing.T) {
|
func TestDecrParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want Incr
|
||||||
want str.Incr
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "decr",
|
cmd: "decr",
|
||||||
args: command.BuildArgs("decr"),
|
want: Incr{},
|
||||||
want: str.Incr{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "decr age",
|
cmd: "decr age",
|
||||||
args: command.BuildArgs("decr", "age"),
|
want: Incr{key: "age", delta: -1},
|
||||||
want: str.Incr{Key: "age", Delta: -1},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "decr age 42",
|
cmd: "decr age 42",
|
||||||
args: command.BuildArgs("decr", "age", "42"),
|
want: Incr{},
|
||||||
want: str.Incr{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse := func(b redis.BaseCmd) (*Incr, error) {
|
||||||
|
return ParseIncr(b, -1)
|
||||||
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(parse, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.Incr)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.delta, test.want.delta)
|
||||||
testx.AssertEqual(t, cm.Delta, test.want.Delta)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDecrExec(t *testing.T) {
|
func TestDecrExec(t *testing.T) {
|
||||||
db, red := getDB(t)
|
parse := func(b redis.BaseCmd) (*Incr, error) {
|
||||||
defer db.Close()
|
return ParseIncr(b, -1)
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("create", func(t *testing.T) {
|
t.Run("create", func(t *testing.T) {
|
||||||
cmd := command.MustParse[*str.Incr]("decr age")
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
cmd := redis.MustParse(parse, "decr age")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -66,9 +67,11 @@ func TestDecrExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("decr", func(t *testing.T) {
|
t.Run("decr", func(t *testing.T) {
|
||||||
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
_ = db.Str().Set("age", "25")
|
_ = db.Str().Set("age", "25")
|
||||||
|
|
||||||
cmd := command.MustParse[*str.Incr]("decr age")
|
cmd := redis.MustParse(parse, "decr age")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -1,60 +1,61 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDecrByParse(t *testing.T) {
|
func TestDecrByParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want IncrBy
|
||||||
want str.IncrBy
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "decrby",
|
cmd: "decrby",
|
||||||
args: command.BuildArgs("decrby"),
|
want: IncrBy{},
|
||||||
want: str.IncrBy{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "decrby age",
|
cmd: "decrby age",
|
||||||
args: command.BuildArgs("decrby", "age"),
|
want: IncrBy{},
|
||||||
want: str.IncrBy{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "decrby age 42",
|
cmd: "decrby age 42",
|
||||||
args: command.BuildArgs("decrby", "age", "42"),
|
want: IncrBy{key: "age", delta: -42},
|
||||||
want: str.IncrBy{Key: "age", Delta: -42},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse := func(b redis.BaseCmd) (*IncrBy, error) {
|
||||||
|
return ParseIncrBy(b, -1)
|
||||||
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(parse, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.IncrBy)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.delta, test.want.delta)
|
||||||
testx.AssertEqual(t, cm.Delta, test.want.Delta)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDecrByExec(t *testing.T) {
|
func TestDecrByExec(t *testing.T) {
|
||||||
db, red := getDB(t)
|
parse := func(b redis.BaseCmd) (*IncrBy, error) {
|
||||||
defer db.Close()
|
return ParseIncrBy(b, -1)
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("create", func(t *testing.T) {
|
t.Run("create", func(t *testing.T) {
|
||||||
cmd := command.MustParse[*str.IncrBy]("decrby age 12")
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
cmd := redis.MustParse(parse, "decrby age 12")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -66,9 +67,11 @@ func TestDecrByExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("decrby", func(t *testing.T) {
|
t.Run("decrby", func(t *testing.T) {
|
||||||
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
_ = db.Str().Set("age", "25")
|
_ = db.Str().Set("age", "25")
|
||||||
|
|
||||||
cmd := command.MustParse[*str.IncrBy]("decrby age 12")
|
cmd := redis.MustParse(parse, "decrby age 12")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// https://redis.io/commands/get
|
// https://redis.io/commands/get
|
||||||
type Get struct {
|
type Get struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseGet(b redis.BaseCmd) (*Get, error) {
|
func ParseGet(b redis.BaseCmd) (*Get, error) {
|
||||||
@@ -18,12 +18,12 @@ func ParseGet(b redis.BaseCmd) (*Get, error) {
|
|||||||
if len(cmd.Args()) != 1 {
|
if len(cmd.Args()) != 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Get) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Get) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
val, err := red.Str().Get(cmd.Key)
|
val, err := red.Str().Get(cmd.key)
|
||||||
if err == core.ErrNotFound {
|
if err == core.ErrNotFound {
|
||||||
w.WriteNull()
|
w.WriteNull()
|
||||||
return val, nil
|
return val, nil
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,37 +10,33 @@ import (
|
|||||||
|
|
||||||
func TestGetParse(t *testing.T) {
|
func TestGetParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
want string
|
want string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "get",
|
cmd: "get",
|
||||||
args: command.BuildArgs("get"),
|
|
||||||
want: "",
|
want: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "get name",
|
cmd: "get name",
|
||||||
args: command.BuildArgs("get", "name"),
|
|
||||||
want: "name",
|
want: "name",
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "get name age",
|
cmd: "get name age",
|
||||||
args: command.BuildArgs("get", "name", "age"),
|
|
||||||
want: "",
|
want: "",
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseGet, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
testx.AssertEqual(t, cmd.(*str.Get).Key, test.want)
|
testx.AssertEqual(t, cmd.key, test.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -55,29 +49,27 @@ func TestGetExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
cmd *str.Get
|
res any
|
||||||
res any
|
out string
|
||||||
out string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "get found",
|
cmd: "get name",
|
||||||
cmd: command.MustParse[*str.Get]("get name"),
|
res: core.Value("alice"),
|
||||||
res: core.Value("alice"),
|
out: "alice",
|
||||||
out: "alice",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "get not found",
|
cmd: "get age",
|
||||||
cmd: command.MustParse[*str.Get]("get age"),
|
res: core.Value(nil),
|
||||||
res: core.Value(nil),
|
out: "(nil)",
|
||||||
out: "(nil)",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := test.cmd.Run(conn, red)
|
cmd := redis.MustParse(ParseGet, test.cmd)
|
||||||
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, test.res)
|
testx.AssertEqual(t, res, test.res)
|
||||||
testx.AssertEqual(t, conn.Out(), test.out)
|
testx.AssertEqual(t, conn.Out(), test.out)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/getset
|
// https://redis.io/commands/getset
|
||||||
type GetSet struct {
|
type GetSet struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Value []byte
|
value []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseGetSet(b redis.BaseCmd) (*GetSet, error) {
|
func ParseGetSet(b redis.BaseCmd) (*GetSet, error) {
|
||||||
@@ -16,13 +16,13 @@ func ParseGetSet(b redis.BaseCmd) (*GetSet, error) {
|
|||||||
if len(cmd.Args()) != 2 {
|
if len(cmd.Args()) != 2 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
cmd.Value = cmd.Args()[1]
|
cmd.value = cmd.Args()[1]
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *GetSet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *GetSet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
out, err := red.Str().SetWith(cmd.Key, cmd.Value).Run()
|
out, err := red.Str().SetWith(cmd.key, cmd.value).Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,45 +10,39 @@ import (
|
|||||||
|
|
||||||
func TestGetSetParse(t *testing.T) {
|
func TestGetSetParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want GetSet
|
||||||
want str.GetSet
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "getset",
|
cmd: "getset",
|
||||||
args: command.BuildArgs("getset"),
|
want: GetSet{},
|
||||||
want: str.GetSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "getset name",
|
cmd: "getset name",
|
||||||
args: command.BuildArgs("getset", "name"),
|
want: GetSet{},
|
||||||
want: str.GetSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "getset name alice",
|
cmd: "getset name alice",
|
||||||
args: command.BuildArgs("getset", "name", "alice"),
|
want: GetSet{key: "name", value: []byte("alice")},
|
||||||
want: str.GetSet{Key: "name", Value: []byte("alice")},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "getset name alice 60",
|
cmd: "getset name alice 60",
|
||||||
args: command.BuildArgs("getset", "name", "alice", "60"),
|
want: GetSet{},
|
||||||
want: str.GetSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseGetSet, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.GetSet)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.value, test.want.value)
|
||||||
testx.AssertEqual(t, cm.Value, test.want.Value)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -61,7 +53,7 @@ func TestGetSetExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*str.GetSet]("getset name alice")
|
cmd := redis.MustParse(ParseGetSet, "getset name alice")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -78,7 +70,7 @@ func TestGetSetExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*str.GetSet]("getset name bob")
|
cmd := redis.MustParse(ParseGetSet, "getset name bob")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/decr
|
// https://redis.io/commands/decr
|
||||||
type Incr struct {
|
type Incr struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Delta int
|
delta int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseIncr(b redis.BaseCmd, sign int) (*Incr, error) {
|
func ParseIncr(b redis.BaseCmd, sign int) (*Incr, error) {
|
||||||
@@ -22,13 +22,13 @@ func ParseIncr(b redis.BaseCmd, sign int) (*Incr, error) {
|
|||||||
if len(cmd.Args()) != 1 {
|
if len(cmd.Args()) != 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
cmd.Delta = sign
|
cmd.delta = sign
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Incr) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Incr) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
val, err := red.Str().Incr(cmd.Key, cmd.Delta)
|
val, err := red.Str().Incr(cmd.key, cmd.delta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,60 +1,61 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIncrParse(t *testing.T) {
|
func TestIncrParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want Incr
|
||||||
want str.Incr
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "incr",
|
cmd: "incr",
|
||||||
args: command.BuildArgs("incr"),
|
want: Incr{},
|
||||||
want: str.Incr{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "incr age",
|
cmd: "incr age",
|
||||||
args: command.BuildArgs("incr", "age"),
|
want: Incr{key: "age", delta: 1},
|
||||||
want: str.Incr{Key: "age", Delta: 1},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "incr age 42",
|
cmd: "incr age 42",
|
||||||
args: command.BuildArgs("incr", "age", "42"),
|
want: Incr{},
|
||||||
want: str.Incr{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse := func(b redis.BaseCmd) (*Incr, error) {
|
||||||
|
return ParseIncr(b, 1)
|
||||||
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(parse, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.Incr)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.delta, test.want.delta)
|
||||||
testx.AssertEqual(t, cm.Delta, test.want.Delta)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIncrExec(t *testing.T) {
|
func TestIncrExec(t *testing.T) {
|
||||||
db, red := getDB(t)
|
parse := func(b redis.BaseCmd) (*Incr, error) {
|
||||||
defer db.Close()
|
return ParseIncr(b, 1)
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("create", func(t *testing.T) {
|
t.Run("create", func(t *testing.T) {
|
||||||
cmd := command.MustParse[*str.Incr]("incr age")
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
cmd := redis.MustParse(parse, "incr age")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -66,9 +67,11 @@ func TestIncrExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("incr", func(t *testing.T) {
|
t.Run("incr", func(t *testing.T) {
|
||||||
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
_ = db.Str().Set("age", "25")
|
_ = db.Str().Set("age", "25")
|
||||||
|
|
||||||
cmd := command.MustParse[*str.Incr]("incr age")
|
cmd := redis.MustParse(parse, "incr age")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -16,25 +16,25 @@ import (
|
|||||||
// https://redis.io/commands/decrby
|
// https://redis.io/commands/decrby
|
||||||
type IncrBy struct {
|
type IncrBy struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Delta int
|
delta int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseIncrBy(b redis.BaseCmd, sign int) (*IncrBy, error) {
|
func ParseIncrBy(b redis.BaseCmd, sign int) (*IncrBy, error) {
|
||||||
cmd := &IncrBy{BaseCmd: b}
|
cmd := &IncrBy{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Int(&cmd.Delta),
|
parser.Int(&cmd.delta),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cmd.Delta *= sign
|
cmd.delta *= sign
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *IncrBy) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *IncrBy) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
val, err := red.Str().Incr(cmd.Key, cmd.Delta)
|
val, err := red.Str().Incr(cmd.key, cmd.delta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,60 +1,61 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIncrByParse(t *testing.T) {
|
func TestIncrByParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want IncrBy
|
||||||
want str.IncrBy
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "incrby",
|
cmd: "incrby",
|
||||||
args: command.BuildArgs("incrby"),
|
want: IncrBy{},
|
||||||
want: str.IncrBy{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "incrby age",
|
cmd: "incrby age",
|
||||||
args: command.BuildArgs("incrby", "age"),
|
want: IncrBy{},
|
||||||
want: str.IncrBy{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "incrby age 42",
|
cmd: "incrby age 42",
|
||||||
args: command.BuildArgs("incrby", "age", "42"),
|
want: IncrBy{key: "age", delta: 42},
|
||||||
want: str.IncrBy{Key: "age", Delta: 42},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse := func(b redis.BaseCmd) (*IncrBy, error) {
|
||||||
|
return ParseIncrBy(b, 1)
|
||||||
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(parse, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.IncrBy)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.delta, test.want.delta)
|
||||||
testx.AssertEqual(t, cm.Delta, test.want.Delta)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIncrByExec(t *testing.T) {
|
func TestIncrByExec(t *testing.T) {
|
||||||
db, red := getDB(t)
|
parse := func(b redis.BaseCmd) (*IncrBy, error) {
|
||||||
defer db.Close()
|
return ParseIncrBy(b, 1)
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("create", func(t *testing.T) {
|
t.Run("create", func(t *testing.T) {
|
||||||
cmd := command.MustParse[*str.IncrBy]("incrby age 42")
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
cmd := redis.MustParse(parse, "incrby age 42")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -66,9 +67,11 @@ func TestIncrByExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("incrby", func(t *testing.T) {
|
t.Run("incrby", func(t *testing.T) {
|
||||||
|
db, red := getDB(t)
|
||||||
|
defer db.Close()
|
||||||
_ = db.Str().Set("age", "25")
|
_ = db.Str().Set("age", "25")
|
||||||
|
|
||||||
cmd := command.MustParse[*str.IncrBy]("incrby age 42")
|
cmd := redis.MustParse(parse, "incrby age 42")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package string
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/parser"
|
"github.com/nalgeon/redka/internal/parser"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
)
|
)
|
||||||
@@ -13,15 +11,15 @@ import (
|
|||||||
// https://redis.io/commands/incrbyfloat
|
// https://redis.io/commands/incrbyfloat
|
||||||
type IncrByFloat struct {
|
type IncrByFloat struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Delta float64
|
delta float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseIncrByFloat(b redis.BaseCmd) (*IncrByFloat, error) {
|
func ParseIncrByFloat(b redis.BaseCmd) (*IncrByFloat, error) {
|
||||||
cmd := &IncrByFloat{BaseCmd: b}
|
cmd := &IncrByFloat{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Float(&cmd.Delta),
|
parser.Float(&cmd.delta),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -30,11 +28,11 @@ func ParseIncrByFloat(b redis.BaseCmd) (*IncrByFloat, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *IncrByFloat) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *IncrByFloat) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
val, err := red.Str().IncrFloat(cmd.Key, cmd.Delta)
|
val, err := red.Str().IncrFloat(cmd.key, cmd.delta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
w.WriteBulkString(strconv.FormatFloat(val, 'f', -1, 64))
|
redis.WriteFloat(w, val)
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +1,52 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIncrByFloatParse(t *testing.T) {
|
func TestIncrByFloatParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want IncrByFloat
|
||||||
want str.IncrByFloat
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "incrbyfloat",
|
cmd: "incrbyfloat",
|
||||||
args: command.BuildArgs("incrbyfloat"),
|
want: IncrByFloat{},
|
||||||
want: str.IncrByFloat{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "incrbyfloat age",
|
cmd: "incrbyfloat age",
|
||||||
args: command.BuildArgs("incrbyfloat", "age"),
|
want: IncrByFloat{},
|
||||||
want: str.IncrByFloat{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "incrbyfloat age 4.2",
|
cmd: "incrbyfloat age 4.2",
|
||||||
args: command.BuildArgs("incrbyfloat", "age", "4.2"),
|
want: IncrByFloat{key: "age", delta: 4.2},
|
||||||
want: str.IncrByFloat{Key: "age", Delta: 4.2},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "incrbyfloat age -4.2",
|
cmd: "incrbyfloat age -4.2",
|
||||||
args: command.BuildArgs("incrbyfloat", "age", "4.2"),
|
want: IncrByFloat{key: "age", delta: -4.2},
|
||||||
want: str.IncrByFloat{Key: "age", Delta: 4.2},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "incrbyfloat age 2.0e2",
|
cmd: "incrbyfloat age 2.0e2",
|
||||||
args: command.BuildArgs("incrbyfloat", "age", "2.0e2"),
|
want: IncrByFloat{key: "age", delta: 2.0e2},
|
||||||
want: str.IncrByFloat{Key: "age", Delta: 2.0e2},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseIncrByFloat, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.IncrByFloat)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.delta, test.want.delta)
|
||||||
testx.AssertEqual(t, cm.Delta, test.want.Delta)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -66,43 +57,39 @@ func TestIncrByFloatExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
cmd *str.IncrByFloat
|
res any
|
||||||
res any
|
out string
|
||||||
out string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "positive",
|
cmd: "incrbyfloat age 4.2",
|
||||||
cmd: command.MustParse[*str.IncrByFloat]("incrbyfloat age 4.2"),
|
res: 29.2,
|
||||||
res: 29.2,
|
out: "29.2",
|
||||||
out: "29.2",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "negative",
|
cmd: "incrbyfloat age -4.2",
|
||||||
cmd: command.MustParse[*str.IncrByFloat]("incrbyfloat age -4.2"),
|
res: 20.8,
|
||||||
res: 20.8,
|
out: "20.8",
|
||||||
out: "20.8",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zero",
|
cmd: "incrbyfloat age 0",
|
||||||
cmd: command.MustParse[*str.IncrByFloat]("incrbyfloat age 0"),
|
res: 25.0,
|
||||||
res: 25.0,
|
out: "25",
|
||||||
out: "25",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "exponential",
|
cmd: "incrbyfloat age 2.0e2",
|
||||||
cmd: command.MustParse[*str.IncrByFloat]("incrbyfloat age 2.0e2"),
|
res: 225.0,
|
||||||
res: 225.0,
|
out: "225",
|
||||||
out: "225",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
_ = db.Str().Set("age", 25)
|
_ = db.Str().Set("age", 25)
|
||||||
|
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := test.cmd.Run(conn, red)
|
cmd := redis.MustParse(ParseIncrByFloat, test.cmd)
|
||||||
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, test.res)
|
testx.AssertEqual(t, res, test.res)
|
||||||
testx.AssertEqual(t, conn.Out(), test.out)
|
testx.AssertEqual(t, conn.Out(), test.out)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// https://redis.io/commands/mget
|
// https://redis.io/commands/mget
|
||||||
type MGet struct {
|
type MGet struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Keys []string
|
keys []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseMGet(b redis.BaseCmd) (*MGet, error) {
|
func ParseMGet(b redis.BaseCmd) (*MGet, error) {
|
||||||
@@ -18,16 +18,16 @@ func ParseMGet(b redis.BaseCmd) (*MGet, error) {
|
|||||||
if len(cmd.Args()) < 1 {
|
if len(cmd.Args()) < 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Keys = make([]string, len(cmd.Args()))
|
cmd.keys = make([]string, len(cmd.Args()))
|
||||||
for i, arg := range cmd.Args() {
|
for i, arg := range cmd.Args() {
|
||||||
cmd.Keys[i] = string(arg)
|
cmd.keys[i] = string(arg)
|
||||||
}
|
}
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *MGet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *MGet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
// Get the key-value map for requested keys.
|
// Get the key-value map for requested keys.
|
||||||
items, err := red.Str().GetMany(cmd.Keys...)
|
items, err := red.Str().GetMany(cmd.keys...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -36,8 +36,8 @@ func (cmd *MGet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
|||||||
// Build the result slice.
|
// Build the result slice.
|
||||||
// It will contain all values in the order of keys.
|
// It will contain all values in the order of keys.
|
||||||
// Missing keys will have nil values.
|
// Missing keys will have nil values.
|
||||||
vals := make([]core.Value, len(cmd.Keys))
|
vals := make([]core.Value, len(cmd.keys))
|
||||||
for i, key := range cmd.Keys {
|
for i, key := range cmd.keys {
|
||||||
vals[i] = items[key]
|
vals[i] = items[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,38 +10,33 @@ import (
|
|||||||
|
|
||||||
func TestMGetParse(t *testing.T) {
|
func TestMGetParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
|
||||||
want []string
|
want []string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "mget",
|
cmd: "mget",
|
||||||
args: command.BuildArgs("mget"),
|
|
||||||
want: nil,
|
want: nil,
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mget name",
|
cmd: "mget name",
|
||||||
args: command.BuildArgs("mget", "name"),
|
|
||||||
want: []string{"name"},
|
want: []string{"name"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mget name age",
|
cmd: "mget name age",
|
||||||
args: command.BuildArgs("mget", "name", "age"),
|
|
||||||
want: []string{"name", "age"},
|
want: []string{"name", "age"},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseMGet, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.MGet)
|
testx.AssertEqual(t, cmd.keys, test.want)
|
||||||
testx.AssertEqual(t, cm.Keys, test.want)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -57,41 +50,37 @@ func TestMGetExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("age", 25)
|
_ = db.Str().Set("age", 25)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
cmd *str.MGet
|
res any
|
||||||
res any
|
out string
|
||||||
out string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "single key",
|
cmd: "mget name",
|
||||||
cmd: command.MustParse[*str.MGet]("mget name"),
|
res: []core.Value{core.Value("alice")},
|
||||||
res: []core.Value{core.Value("alice")},
|
out: "1,alice",
|
||||||
out: "1,alice",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple keys",
|
cmd: "mget name age",
|
||||||
cmd: command.MustParse[*str.MGet]("mget name age"),
|
res: []core.Value{core.Value("alice"), core.Value("25")},
|
||||||
res: []core.Value{core.Value("alice"), core.Value("25")},
|
out: "2,alice,25",
|
||||||
out: "2,alice,25",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "some not found",
|
cmd: "mget name city age",
|
||||||
cmd: command.MustParse[*str.MGet]("mget name city age"),
|
res: []core.Value{core.Value("alice"), core.Value(nil), core.Value("25")},
|
||||||
res: []core.Value{core.Value("alice"), core.Value(nil), core.Value("25")},
|
out: "3,alice,(nil),25",
|
||||||
out: "3,alice,(nil),25",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "all not found",
|
cmd: "mget one two",
|
||||||
cmd: command.MustParse[*str.MGet]("mget one two"),
|
res: []core.Value{core.Value(nil), core.Value(nil)},
|
||||||
res: []core.Value{core.Value(nil), core.Value(nil)},
|
out: "2,(nil),(nil)",
|
||||||
out: "2,(nil),(nil)",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := test.cmd.Run(conn, red)
|
cmd := redis.MustParse(ParseMGet, test.cmd)
|
||||||
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, test.res)
|
testx.AssertEqual(t, res, test.res)
|
||||||
testx.AssertEqual(t, conn.Out(), test.out)
|
testx.AssertEqual(t, conn.Out(), test.out)
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import (
|
|||||||
// https://redis.io/commands/mset
|
// https://redis.io/commands/mset
|
||||||
type MSet struct {
|
type MSet struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Items map[string]any
|
items map[string]any
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseMSet(b redis.BaseCmd) (*MSet, error) {
|
func ParseMSet(b redis.BaseCmd) (*MSet, error) {
|
||||||
cmd := &MSet{BaseCmd: b}
|
cmd := &MSet{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.AnyMap(&cmd.Items),
|
parser.AnyMap(&cmd.items),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -25,7 +25,7 @@ func ParseMSet(b redis.BaseCmd) (*MSet, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *MSet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *MSet) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
err := red.Str().SetMany(cmd.Items)
|
err := red.Str().SetMany(cmd.items)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,49 +1,41 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMSetParse(t *testing.T) {
|
func TestMSetParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want MSet
|
||||||
want str.MSet
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "mset",
|
cmd: "mset",
|
||||||
args: command.BuildArgs("mset"),
|
want: MSet{},
|
||||||
want: str.MSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mset name",
|
cmd: "mset name",
|
||||||
args: command.BuildArgs("mset", "name"),
|
want: MSet{},
|
||||||
want: str.MSet{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mset name alice",
|
cmd: "mset name alice",
|
||||||
args: command.BuildArgs("mset", "name", "alice"),
|
want: MSet{items: map[string]any{"name": []byte("alice")}},
|
||||||
want: str.MSet{Items: map[string]any{"name": []byte("alice")}},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mset name alice age",
|
cmd: "mset name alice age",
|
||||||
args: command.BuildArgs("mset", "name", "alice", "age"),
|
want: MSet{},
|
||||||
want: str.MSet{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mset name alice age 25",
|
cmd: "mset name alice age 25",
|
||||||
args: command.BuildArgs("mset", "name", "alice", "age", "25"),
|
want: MSet{items: map[string]any{
|
||||||
want: str.MSet{Items: map[string]any{
|
|
||||||
"name": []byte("alice"),
|
"name": []byte("alice"),
|
||||||
"age": []byte("25"),
|
"age": []byte("25"),
|
||||||
}},
|
}},
|
||||||
@@ -52,12 +44,11 @@ func TestMSetParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseMSet, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.MSet)
|
testx.AssertEqual(t, cmd.items, test.want.items)
|
||||||
testx.AssertEqual(t, cm.Items, test.want.Items)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -68,7 +59,7 @@ func TestMSetExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*str.MSet]("mset name alice")
|
cmd := redis.MustParse(ParseMSet, "mset name alice")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -83,7 +74,7 @@ func TestMSetExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*str.MSet]("mset name alice age 25")
|
cmd := redis.MustParse(ParseMSet, "mset name alice age 25")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -102,7 +93,7 @@ func TestMSetExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*str.MSet]("mset name bob age 50")
|
cmd := redis.MustParse(ParseMSet, "mset name bob age 50")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -122,7 +113,7 @@ func TestMSetExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
_ = db.Str().Set("age", 25)
|
_ = db.Str().Set("age", 25)
|
||||||
|
|
||||||
cmd := command.MustParse[*str.MSet]("mset name bob age 50")
|
cmd := redis.MustParse(ParseMSet, "mset name bob age 50")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -1,74 +1,73 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPSetEXParse(t *testing.T) {
|
func TestPSetEXParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want SetEX
|
||||||
want str.SetEX
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "psetex",
|
cmd: "psetex",
|
||||||
args: command.BuildArgs("psetex"),
|
want: SetEX{},
|
||||||
want: str.SetEX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "psetex name",
|
cmd: "psetex name",
|
||||||
args: command.BuildArgs("psetex", "name"),
|
want: SetEX{},
|
||||||
want: str.SetEX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "psetex name alice",
|
cmd: "psetex name alice",
|
||||||
args: command.BuildArgs("psetex", "name", "alice"),
|
want: SetEX{},
|
||||||
want: str.SetEX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "psetex name alice 60",
|
cmd: "psetex name alice 60",
|
||||||
args: command.BuildArgs("psetex", "name", "alice", "60"),
|
want: SetEX{},
|
||||||
want: str.SetEX{},
|
|
||||||
err: redis.ErrInvalidInt,
|
err: redis.ErrInvalidInt,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "psetex name 60 alice",
|
cmd: "psetex name 60 alice",
|
||||||
args: command.BuildArgs("psetex", "name", "60", "alice"),
|
want: SetEX{key: "name", value: []byte("alice"), ttl: 60 * time.Millisecond},
|
||||||
want: str.SetEX{Key: "name", Value: []byte("alice"), TTL: 60 * time.Millisecond},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse := func(b redis.BaseCmd) (*SetEX, error) {
|
||||||
|
return ParseSetEX(b, 1)
|
||||||
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(parse, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.SetEX)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.value, test.want.value)
|
||||||
testx.AssertEqual(t, cm.Value, test.want.Value)
|
testx.AssertEqual(t, cmd.ttl, test.want.ttl)
|
||||||
testx.AssertEqual(t, cm.TTL, test.want.TTL)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPSetEXExec(t *testing.T) {
|
func TestPSetEXExec(t *testing.T) {
|
||||||
|
parse := func(b redis.BaseCmd) (*SetEX, error) {
|
||||||
|
return ParseSetEX(b, 1)
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("create", func(t *testing.T) {
|
t.Run("create", func(t *testing.T) {
|
||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*str.SetEX]("psetex name 60000 alice")
|
cmd := redis.MustParse(parse, "psetex name 60000 alice")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -89,7 +88,7 @@ func TestPSetEXExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*str.SetEX]("psetex name 60000 bob")
|
cmd := redis.MustParse(parse, "psetex name 60000 bob")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -110,7 +109,7 @@ func TestPSetEXExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
||||||
|
|
||||||
cmd := command.MustParse[*str.SetEX]("psetex name 10000 bob")
|
cmd := redis.MustParse(parse, "psetex name 10000 bob")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ import (
|
|||||||
// https://redis.io/commands/set
|
// https://redis.io/commands/set
|
||||||
type Set struct {
|
type Set struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Value []byte
|
value []byte
|
||||||
IfNX bool
|
ifNX bool
|
||||||
IfXX bool
|
ifXX bool
|
||||||
Get bool
|
get bool
|
||||||
TTL time.Duration
|
ttl time.Duration
|
||||||
At time.Time
|
at time.Time
|
||||||
KeepTTL bool
|
keepTTL bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseSet(b redis.BaseCmd) (*Set, error) {
|
func ParseSet(b redis.BaseCmd) (*Set, error) {
|
||||||
@@ -30,19 +30,19 @@ func ParseSet(b redis.BaseCmd) (*Set, error) {
|
|||||||
// Parse the command arguments.
|
// Parse the command arguments.
|
||||||
var ttlSec, ttlMs, atSec, atMs int
|
var ttlSec, ttlMs, atSec, atMs int
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Bytes(&cmd.Value),
|
parser.Bytes(&cmd.value),
|
||||||
parser.OneOf(
|
parser.OneOf(
|
||||||
parser.Flag("nx", &cmd.IfNX),
|
parser.Flag("nx", &cmd.ifNX),
|
||||||
parser.Flag("xx", &cmd.IfXX),
|
parser.Flag("xx", &cmd.ifXX),
|
||||||
),
|
),
|
||||||
parser.Flag("get", &cmd.Get),
|
parser.Flag("get", &cmd.get),
|
||||||
parser.OneOf(
|
parser.OneOf(
|
||||||
parser.Named("ex", parser.Int(&ttlSec)),
|
parser.Named("ex", parser.Int(&ttlSec)),
|
||||||
parser.Named("px", parser.Int(&ttlMs)),
|
parser.Named("px", parser.Int(&ttlMs)),
|
||||||
parser.Named("exat", parser.Int(&atSec)),
|
parser.Named("exat", parser.Int(&atSec)),
|
||||||
parser.Named("pxat", parser.Int(&atMs)),
|
parser.Named("pxat", parser.Int(&atMs)),
|
||||||
parser.Flag("keepttl", &cmd.KeepTTL),
|
parser.Flag("keepttl", &cmd.keepTTL),
|
||||||
),
|
),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -51,15 +51,15 @@ func ParseSet(b redis.BaseCmd) (*Set, error) {
|
|||||||
|
|
||||||
// Set the expiration time.
|
// Set the expiration time.
|
||||||
if ttlSec > 0 {
|
if ttlSec > 0 {
|
||||||
cmd.TTL = time.Duration(ttlSec) * time.Second
|
cmd.ttl = time.Duration(ttlSec) * time.Second
|
||||||
} else if ttlMs > 0 {
|
} else if ttlMs > 0 {
|
||||||
cmd.TTL = time.Duration(ttlMs) * time.Millisecond
|
cmd.ttl = time.Duration(ttlMs) * time.Millisecond
|
||||||
} else if atSec > 0 {
|
} else if atSec > 0 {
|
||||||
cmd.At = time.Unix(int64(atSec), 0)
|
cmd.at = time.Unix(int64(atSec), 0)
|
||||||
} else if atMs > 0 {
|
} else if atMs > 0 {
|
||||||
cmd.At = time.Unix(0, int64(atMs)*int64(time.Millisecond))
|
cmd.at = time.Unix(0, int64(atMs)*int64(time.Millisecond))
|
||||||
}
|
}
|
||||||
if cmd.TTL < 0 {
|
if cmd.ttl < 0 {
|
||||||
return cmd, redis.ErrInvalidExpireTime
|
return cmd, redis.ErrInvalidExpireTime
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,9 +67,9 @@ func ParseSet(b redis.BaseCmd) (*Set, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Set) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *Set) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
if !cmd.IfNX && !cmd.IfXX && !cmd.Get && !cmd.KeepTTL && cmd.At.IsZero() {
|
if !cmd.ifNX && !cmd.ifXX && !cmd.get && !cmd.keepTTL && cmd.at.IsZero() {
|
||||||
// Simple SET without additional options (except ttl).
|
// Simple SET without additional options (except ttl).
|
||||||
err := red.Str().SetExpires(cmd.Key, cmd.Value, cmd.TTL)
|
err := red.Str().SetExpires(cmd.key, cmd.value, cmd.ttl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -79,26 +79,26 @@ func (cmd *Set) Run(w redis.Writer, red redis.Redka) (any, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SET with additional options.
|
// SET with additional options.
|
||||||
op := red.Str().SetWith(cmd.Key, cmd.Value)
|
op := red.Str().SetWith(cmd.key, cmd.value)
|
||||||
if cmd.IfXX {
|
if cmd.ifXX {
|
||||||
op = op.IfExists()
|
op = op.IfExists()
|
||||||
} else if cmd.IfNX {
|
} else if cmd.ifNX {
|
||||||
op = op.IfNotExists()
|
op = op.IfNotExists()
|
||||||
}
|
}
|
||||||
if cmd.TTL > 0 {
|
if cmd.ttl > 0 {
|
||||||
op = op.TTL(cmd.TTL)
|
op = op.TTL(cmd.ttl)
|
||||||
} else if !cmd.At.IsZero() {
|
} else if !cmd.at.IsZero() {
|
||||||
op = op.At(cmd.At)
|
op = op.At(cmd.at)
|
||||||
} else if cmd.KeepTTL {
|
} else if cmd.keepTTL {
|
||||||
op = op.KeepTTL()
|
op = op.KeepTTL()
|
||||||
}
|
}
|
||||||
out, err := op.Run()
|
out, err := op.Run()
|
||||||
|
|
||||||
// Determine the output status.
|
// Determine the output status.
|
||||||
var ok bool
|
var ok bool
|
||||||
if cmd.IfXX {
|
if cmd.ifXX {
|
||||||
ok = out.Updated
|
ok = out.Updated
|
||||||
} else if cmd.IfNX {
|
} else if cmd.ifNX {
|
||||||
ok = out.Created
|
ok = out.Created
|
||||||
} else {
|
} else {
|
||||||
ok = err == nil
|
ok = err == nil
|
||||||
@@ -110,7 +110,7 @@ func (cmd *Set) Run(w redis.Writer, red redis.Redka) (any, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.Get {
|
if cmd.get {
|
||||||
// GET given: The key didn't exist before the SET.
|
// GET given: The key didn't exist before the SET.
|
||||||
if !out.Prev.Exists() {
|
if !out.Prev.Exists() {
|
||||||
w.WriteNull()
|
w.WriteNull()
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -13,128 +11,125 @@ import (
|
|||||||
|
|
||||||
func TestSetParse(t *testing.T) {
|
func TestSetParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want Set
|
||||||
want str.Set
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "set",
|
cmd: "set",
|
||||||
args: command.BuildArgs("set"),
|
want: Set{},
|
||||||
want: str.Set{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name",
|
cmd: "set name",
|
||||||
args: command.BuildArgs("set", "name"),
|
want: Set{},
|
||||||
want: str.Set{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice",
|
cmd: "set name alice",
|
||||||
args: command.BuildArgs("set", "name", "alice"),
|
want: Set{key: "name", value: []byte("alice")},
|
||||||
want: str.Set{Key: "name", Value: []byte("alice")},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice nx",
|
cmd: "set name alice nx",
|
||||||
args: command.BuildArgs("set", "name", "alice", "nx"),
|
want: Set{key: "name", value: []byte("alice"), ifNX: true},
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), IfNX: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice xx",
|
cmd: "set name alice xx",
|
||||||
args: command.BuildArgs("set", "name", "alice", "xx"),
|
want: Set{key: "name", value: []byte("alice"), ifXX: true},
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), IfXX: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice nx xx",
|
cmd: "set name alice nx xx",
|
||||||
args: command.BuildArgs("set", "name", "alice", "nx", "xx"),
|
want: Set{},
|
||||||
want: str.Set{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice ex 10",
|
cmd: "set name alice ex 10",
|
||||||
args: command.BuildArgs("set", "name", "alice", "ex", "10"),
|
want: Set{key: "name", value: []byte("alice"), ttl: 10 * time.Second},
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), TTL: 10 * time.Second},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice ex 0",
|
cmd: "set name alice ex 0",
|
||||||
args: command.BuildArgs("set", "name", "alice", "ex", "0"),
|
want: Set{key: "name", value: []byte("alice"), ttl: 0},
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), TTL: 0},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice px 10",
|
cmd: "set name alice px 10",
|
||||||
args: command.BuildArgs("set", "name", "alice", "px", "10"),
|
want: Set{key: "name", value: []byte("alice"), ttl: 10 * time.Millisecond},
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), TTL: 10 * time.Millisecond},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice exat 1577882096",
|
cmd: "set name alice exat 1577882096",
|
||||||
args: command.BuildArgs("set", "name", "alice", "exat", "1577882096"),
|
want: Set{
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"),
|
key: "name", value: []byte("alice"),
|
||||||
At: time.Date(2020, 1, 1, 12, 34, 56, 0, time.UTC)},
|
at: time.Date(2020, 1, 1, 12, 34, 56, 0, time.UTC),
|
||||||
|
},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice pxat 1577882096000",
|
cmd: "set name alice pxat 1577882096000",
|
||||||
args: command.BuildArgs("set", "name", "alice", "exat", "1577882096000"),
|
want: Set{
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"),
|
key: "name", value: []byte("alice"),
|
||||||
At: time.Date(2020, 1, 1, 12, 34, 56, 0, time.UTC)},
|
at: time.Date(2020, 1, 1, 12, 34, 56, 0, time.UTC),
|
||||||
|
},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice keepttl",
|
cmd: "set name alice keepttl",
|
||||||
args: command.BuildArgs("set", "name", "alice", "keepttl"),
|
want: Set{key: "name", value: []byte("alice"), keepTTL: true},
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), KeepTTL: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice ex 10 keepttl",
|
cmd: "set name alice ex 10 keepttl",
|
||||||
args: command.BuildArgs("set", "name", "alice", "ex", "10", "keepttl"),
|
want: Set{},
|
||||||
want: str.Set{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice nx ex 10",
|
cmd: "set name alice nx ex 10",
|
||||||
args: command.BuildArgs("set", "name", "alice", "nx", "ex", "10"),
|
want: Set{
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), IfNX: true, TTL: 10 * time.Second},
|
key: "name", value: []byte("alice"),
|
||||||
err: nil,
|
ifNX: true, ttl: 10 * time.Second,
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice xx px 10",
|
cmd: "set name alice xx px 10",
|
||||||
args: command.BuildArgs("set", "name", "alice", "xx", "px", "10"),
|
want: Set{
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), IfXX: true, TTL: 10 * time.Millisecond},
|
key: "name", value: []byte("alice"),
|
||||||
err: nil,
|
ifXX: true, ttl: 10 * time.Millisecond,
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice ex 10 nx",
|
cmd: "set name alice ex 10 nx",
|
||||||
args: command.BuildArgs("set", "name", "alice", "ex", "10", "nx"),
|
want: Set{
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), IfNX: true, TTL: 10 * time.Second},
|
key: "name", value: []byte("alice"),
|
||||||
err: nil,
|
ifNX: true, ttl: 10 * time.Second,
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set name alice nx get ex 10",
|
cmd: "set name alice nx get ex 10",
|
||||||
args: command.BuildArgs("set", "name", "alice", "nx", "ex", "10"),
|
want: Set{
|
||||||
want: str.Set{Key: "name", Value: []byte("alice"), IfNX: true, Get: true, TTL: 10 * time.Second},
|
key: "name", value: []byte("alice"),
|
||||||
err: nil,
|
ifNX: true, get: true, ttl: 10 * time.Second,
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseSet, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
setCmd := cmd.(*str.Set)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, setCmd.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.value, test.want.value)
|
||||||
testx.AssertEqual(t, setCmd.Value, test.want.Value)
|
testx.AssertEqual(t, cmd.ifNX, test.want.ifNX)
|
||||||
testx.AssertEqual(t, setCmd.IfNX, test.want.IfNX)
|
testx.AssertEqual(t, cmd.ifXX, test.want.ifXX)
|
||||||
testx.AssertEqual(t, setCmd.IfXX, test.want.IfXX)
|
testx.AssertEqual(t, cmd.ttl, test.want.ttl)
|
||||||
testx.AssertEqual(t, setCmd.TTL, test.want.TTL)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -145,77 +140,67 @@ func TestSetExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
cmd *str.Set
|
res any
|
||||||
res any
|
out string
|
||||||
out string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "set",
|
cmd: "set name alice",
|
||||||
cmd: command.MustParse[*str.Set]("set name alice"),
|
res: true,
|
||||||
res: true,
|
out: "OK",
|
||||||
out: "OK",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set nx conflict",
|
cmd: "set name alice nx",
|
||||||
cmd: command.MustParse[*str.Set]("set name alice nx"),
|
res: false,
|
||||||
res: false,
|
out: "(nil)",
|
||||||
out: "(nil)",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set nx",
|
cmd: "set age alice nx",
|
||||||
cmd: command.MustParse[*str.Set]("set age alice nx"),
|
res: true,
|
||||||
res: true,
|
out: "OK",
|
||||||
out: "OK",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set xx",
|
cmd: "set name bob xx",
|
||||||
cmd: command.MustParse[*str.Set]("set name bob xx"),
|
res: true,
|
||||||
res: true,
|
out: "OK",
|
||||||
out: "OK",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set xx conflict",
|
cmd: "set city paris xx",
|
||||||
cmd: command.MustParse[*str.Set]("set city paris xx"),
|
res: false,
|
||||||
res: false,
|
out: "(nil)",
|
||||||
out: "(nil)",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set ex",
|
cmd: "set name alice ex 10",
|
||||||
cmd: command.MustParse[*str.Set]("set name alice ex 10"),
|
res: true,
|
||||||
res: true,
|
out: "OK",
|
||||||
out: "OK",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set keepttl",
|
cmd: "set name alice keepttl",
|
||||||
cmd: command.MustParse[*str.Set]("set name alice keepttl"),
|
res: true,
|
||||||
res: true,
|
out: "OK",
|
||||||
out: "OK",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set nx ex",
|
cmd: "set color blue nx ex 10",
|
||||||
cmd: command.MustParse[*str.Set]("set color blue nx ex 10"),
|
res: true,
|
||||||
res: true,
|
out: "OK",
|
||||||
out: "OK",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set get",
|
cmd: "set name bob get",
|
||||||
cmd: command.MustParse[*str.Set]("set name bob get"),
|
res: core.Value("alice"),
|
||||||
res: core.Value("alice"),
|
out: "alice",
|
||||||
out: "alice",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "set get nil",
|
cmd: "set country france get",
|
||||||
cmd: command.MustParse[*str.Set]("set country france get"),
|
res: core.Value(nil),
|
||||||
res: core.Value(nil),
|
out: "(nil)",
|
||||||
out: "(nil)",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := test.cmd.Run(conn, red)
|
cmd := redis.MustParse(ParseSet, test.cmd)
|
||||||
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
testx.AssertEqual(t, res, test.res)
|
testx.AssertEqual(t, res, test.res)
|
||||||
testx.AssertEqual(t, conn.Out(), test.out)
|
testx.AssertEqual(t, conn.Out(), test.out)
|
||||||
|
|||||||
@@ -13,28 +13,28 @@ import (
|
|||||||
// https://redis.io/commands/setex
|
// https://redis.io/commands/setex
|
||||||
type SetEX struct {
|
type SetEX struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Value []byte
|
value []byte
|
||||||
TTL time.Duration
|
ttl time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseSetEX(b redis.BaseCmd, multi int) (*SetEX, error) {
|
func ParseSetEX(b redis.BaseCmd, multi int) (*SetEX, error) {
|
||||||
cmd := &SetEX{BaseCmd: b}
|
cmd := &SetEX{BaseCmd: b}
|
||||||
var ttl int
|
var ttl int
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Int(&ttl),
|
parser.Int(&ttl),
|
||||||
parser.Bytes(&cmd.Value),
|
parser.Bytes(&cmd.value),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cmd.TTL = time.Duration(multi*ttl) * time.Millisecond
|
cmd.ttl = time.Duration(multi*ttl) * time.Millisecond
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *SetEX) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *SetEX) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
err := red.Str().SetExpires(cmd.Key, cmd.Value, cmd.TTL)
|
err := red.Str().SetExpires(cmd.key, cmd.value, cmd.ttl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,74 +1,73 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetEXParse(t *testing.T) {
|
func TestSetEXParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want SetEX
|
||||||
want str.SetEX
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "setex",
|
cmd: "setex",
|
||||||
args: command.BuildArgs("setex"),
|
want: SetEX{},
|
||||||
want: str.SetEX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "setex name",
|
cmd: "setex name",
|
||||||
args: command.BuildArgs("setex", "name"),
|
want: SetEX{},
|
||||||
want: str.SetEX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "setex name alice",
|
cmd: "setex name alice",
|
||||||
args: command.BuildArgs("setex", "name", "alice"),
|
want: SetEX{},
|
||||||
want: str.SetEX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "setex name alice 60",
|
cmd: "setex name alice 60",
|
||||||
args: command.BuildArgs("setex", "name", "alice", "60"),
|
want: SetEX{},
|
||||||
want: str.SetEX{},
|
|
||||||
err: redis.ErrInvalidInt,
|
err: redis.ErrInvalidInt,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "setex name 60 alice",
|
cmd: "setex name 60 alice",
|
||||||
args: command.BuildArgs("setex", "name", "60", "alice"),
|
want: SetEX{key: "name", value: []byte("alice"), ttl: 60 * 1000 * time.Millisecond},
|
||||||
want: str.SetEX{Key: "name", Value: []byte("alice"), TTL: 60 * 1000 * time.Millisecond},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse := func(b redis.BaseCmd) (*SetEX, error) {
|
||||||
|
return ParseSetEX(b, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(parse, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.SetEX)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.value, test.want.value)
|
||||||
testx.AssertEqual(t, cm.Value, test.want.Value)
|
testx.AssertEqual(t, cmd.ttl, test.want.ttl)
|
||||||
testx.AssertEqual(t, cm.TTL, test.want.TTL)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetEXExec(t *testing.T) {
|
func TestSetEXExec(t *testing.T) {
|
||||||
|
parse := func(b redis.BaseCmd) (*SetEX, error) {
|
||||||
|
return ParseSetEX(b, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("create", func(t *testing.T) {
|
t.Run("create", func(t *testing.T) {
|
||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*str.SetEX]("setex name 60 alice")
|
cmd := redis.MustParse(parse, "setex name 60 alice")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -89,7 +88,7 @@ func TestSetEXExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*str.SetEX]("setex name 60 bob")
|
cmd := redis.MustParse(parse, "setex name 60 bob")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -110,7 +109,7 @@ func TestSetEXExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
|
||||||
|
|
||||||
cmd := command.MustParse[*str.SetEX]("setex name 10 bob")
|
cmd := redis.MustParse(parse, "setex name 10 bob")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/setnx
|
// https://redis.io/commands/setnx
|
||||||
type SetNX struct {
|
type SetNX struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Value []byte
|
value []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseSetNX(b redis.BaseCmd) (*SetNX, error) {
|
func ParseSetNX(b redis.BaseCmd) (*SetNX, error) {
|
||||||
@@ -16,13 +16,13 @@ func ParseSetNX(b redis.BaseCmd) (*SetNX, error) {
|
|||||||
if len(cmd.Args()) != 2 {
|
if len(cmd.Args()) != 2 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
cmd.Value = cmd.Args()[1]
|
cmd.value = cmd.Args()[1]
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *SetNX) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *SetNX) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
out, err := red.Str().SetWith(cmd.Key, cmd.Value).IfNotExists().Run()
|
out, err := red.Str().SetWith(cmd.key, cmd.value).IfNotExists().Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,55 +1,47 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
str "github.com/nalgeon/redka/internal/command/string"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetNXParse(t *testing.T) {
|
func TestSetNXParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want SetNX
|
||||||
want str.SetNX
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "setnx",
|
cmd: "setnx",
|
||||||
args: command.BuildArgs("setnx"),
|
want: SetNX{},
|
||||||
want: str.SetNX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "setnx name",
|
cmd: "setnx name",
|
||||||
args: command.BuildArgs("setnx", "name"),
|
want: SetNX{},
|
||||||
want: str.SetNX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "setnx name alice",
|
cmd: "setnx name alice",
|
||||||
args: command.BuildArgs("setnx", "name", "alice"),
|
want: SetNX{key: "name", value: []byte("alice")},
|
||||||
want: str.SetNX{Key: "name", Value: []byte("alice")},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "setnx name alice 60",
|
cmd: "setnx name alice 60",
|
||||||
args: command.BuildArgs("setnx", "name", "alice", "60"),
|
want: SetNX{},
|
||||||
want: str.SetNX{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseSetNX, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*str.SetNX)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.value, test.want.value)
|
||||||
testx.AssertEqual(t, cm.Value, test.want.Value)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -60,7 +52,7 @@ func TestSetNXExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*str.SetNX]("setnx name alice")
|
cmd := redis.MustParse(ParseSetNX, "setnx name alice")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -77,7 +69,7 @@ func TestSetNXExec(t *testing.T) {
|
|||||||
|
|
||||||
_ = db.Str().Set("name", "alice")
|
_ = db.Str().Set("name", "alice")
|
||||||
|
|
||||||
cmd := command.MustParse[*str.SetNX]("setnx name bob")
|
cmd := redis.MustParse(ParseSetNX, "setnx name bob")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package string_test
|
package string
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ import (
|
|||||||
// https://redis.io/commands/zadd
|
// https://redis.io/commands/zadd
|
||||||
type ZAdd struct {
|
type ZAdd struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Items map[any]float64
|
items map[any]float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZAdd(b redis.BaseCmd) (*ZAdd, error) {
|
func ParseZAdd(b redis.BaseCmd) (*ZAdd, error) {
|
||||||
cmd := &ZAdd{BaseCmd: b}
|
cmd := &ZAdd{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.FloatMap(&cmd.Items),
|
parser.FloatMap(&cmd.items),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -28,7 +28,7 @@ func ParseZAdd(b redis.BaseCmd) (*ZAdd, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZAdd) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZAdd) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
count, err := red.ZSet().AddMany(cmd.Key, cmd.Items)
|
count, err := red.ZSet().AddMany(cmd.key, cmd.items)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,55 +1,46 @@
|
|||||||
package zset_test
|
package zset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/zset"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestZAddParse(t *testing.T) {
|
func TestZAddParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want ZAdd
|
||||||
want zset.ZAdd
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zadd",
|
cmd: "zadd",
|
||||||
args: command.BuildArgs("zadd"),
|
want: ZAdd{},
|
||||||
want: zset.ZAdd{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zadd key",
|
cmd: "zadd key",
|
||||||
args: command.BuildArgs("zadd", "key"),
|
want: ZAdd{},
|
||||||
want: zset.ZAdd{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zadd key one",
|
cmd: "zadd key one",
|
||||||
args: command.BuildArgs("zadd", "key", "one"),
|
want: ZAdd{},
|
||||||
want: zset.ZAdd{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zadd key 1 one",
|
cmd: "zadd key 1.1 one",
|
||||||
args: command.BuildArgs("zadd", "key", "1.1", "one"),
|
want: ZAdd{key: "key", items: map[any]float64{"one": 1.1}},
|
||||||
want: zset.ZAdd{Key: "key", Items: map[any]float64{"one": 1.1}},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zadd key 1 one 2",
|
cmd: "zadd key 1.1 one 2.2",
|
||||||
args: command.BuildArgs("zadd", "key", "1.1", "one", "2.2"),
|
want: ZAdd{},
|
||||||
want: zset.ZAdd{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zadd key one 1.1 two 2.2",
|
cmd: "zadd key 1.1 one 2.2 two",
|
||||||
args: command.BuildArgs("zadd", "key", "1.1", "one", "2.2", "two"),
|
want: ZAdd{key: "key", items: map[any]float64{
|
||||||
want: zset.ZAdd{Key: "key", Items: map[any]float64{
|
|
||||||
"one": 1.1,
|
"one": 1.1,
|
||||||
"two": 2.2,
|
"two": 2.2,
|
||||||
}},
|
}},
|
||||||
@@ -58,13 +49,12 @@ func TestZAddParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseZAdd, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*zset.ZAdd)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.items, test.want.items)
|
||||||
testx.AssertEqual(t, cm.Items, test.want.Items)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -75,7 +65,7 @@ func TestZAddExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZAdd]("zadd key 11 one")
|
cmd := redis.MustParse(ParseZAdd, "zadd key 11 one")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -89,7 +79,7 @@ func TestZAddExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZAdd]("zadd key 11 one 22 two")
|
cmd := redis.MustParse(ParseZAdd, "zadd key 11 one 22 two")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -108,7 +98,7 @@ func TestZAddExec(t *testing.T) {
|
|||||||
|
|
||||||
_, _ = db.ZSet().Add("key", "one", 11)
|
_, _ = db.ZSet().Add("key", "one", 11)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZAdd]("zadd key 12 one 22 two")
|
cmd := redis.MustParse(ParseZAdd, "zadd key 12 one 22 two")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -127,7 +117,7 @@ func TestZAddExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "one", 11)
|
_, _ = db.ZSet().Add("key", "one", 11)
|
||||||
_, _ = db.ZSet().Add("key", "two", 22)
|
_, _ = db.ZSet().Add("key", "two", 22)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZAdd]("zadd key 12 one 23 two")
|
cmd := redis.MustParse(ParseZAdd, "zadd key 12 one 23 two")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -144,7 +134,7 @@ func TestZAddExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_ = db.Str().Set("key", "value")
|
_ = db.Str().Set("key", "value")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZAdd]("zadd key 11 one")
|
cmd := redis.MustParse(ParseZAdd, "zadd key 11 one")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import "github.com/nalgeon/redka/internal/redis"
|
|||||||
// https://redis.io/commands/zcard
|
// https://redis.io/commands/zcard
|
||||||
type ZCard struct {
|
type ZCard struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZCard(b redis.BaseCmd) (*ZCard, error) {
|
func ParseZCard(b redis.BaseCmd) (*ZCard, error) {
|
||||||
@@ -15,12 +15,12 @@ func ParseZCard(b redis.BaseCmd) (*ZCard, error) {
|
|||||||
if len(cmd.Args()) != 1 {
|
if len(cmd.Args()) != 1 {
|
||||||
return cmd, redis.ErrInvalidArgNum
|
return cmd, redis.ErrInvalidArgNum
|
||||||
}
|
}
|
||||||
cmd.Key = string(cmd.Args()[0])
|
cmd.key = string(cmd.Args()[0])
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZCard) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZCard) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
n, err := red.ZSet().Len(cmd.Key)
|
n, err := red.ZSet().Len(cmd.key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,48 +1,41 @@
|
|||||||
package zset_test
|
package zset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/zset"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestZCardParse(t *testing.T) {
|
func TestZCardParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want ZCard
|
||||||
want zset.ZCard
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zcard",
|
cmd: "zcard",
|
||||||
args: command.BuildArgs("zcard"),
|
want: ZCard{},
|
||||||
want: zset.ZCard{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zcard key",
|
cmd: "zcard key",
|
||||||
args: command.BuildArgs("zcard", "key"),
|
want: ZCard{key: "key"},
|
||||||
want: zset.ZCard{Key: "key"},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zcard key one",
|
cmd: "zcard key one",
|
||||||
args: command.BuildArgs("zcard", "key", "one"),
|
want: ZCard{},
|
||||||
want: zset.ZCard{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseZCard, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*zset.ZCard)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -55,7 +48,7 @@ func TestZCardExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "one", 11)
|
_, _ = db.ZSet().Add("key", "one", 11)
|
||||||
_, _ = db.ZSet().Add("key", "two", 22)
|
_, _ = db.ZSet().Add("key", "two", 22)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZCard]("zcard key")
|
cmd := redis.MustParse(ParseZCard, "zcard key")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -68,7 +61,7 @@ func TestZCardExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "one", 11)
|
_, _ = db.ZSet().Add("key", "one", 11)
|
||||||
_, _ = db.ZSet().Delete("key", "one")
|
_, _ = db.ZSet().Delete("key", "one")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZCard]("zcard key")
|
cmd := redis.MustParse(ParseZCard, "zcard key")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -79,7 +72,7 @@ func TestZCardExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZCard]("zcard key")
|
cmd := redis.MustParse(ParseZCard, "zcard key")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -91,7 +84,7 @@ func TestZCardExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_ = db.Str().Set("key", "value")
|
_ = db.Str().Set("key", "value")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZCard]("zcard key")
|
cmd := redis.MustParse(ParseZCard, "zcard key")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -10,17 +10,17 @@ import (
|
|||||||
// https://redis.io/commands/zcount
|
// https://redis.io/commands/zcount
|
||||||
type ZCount struct {
|
type ZCount struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Min float64
|
min float64
|
||||||
Max float64
|
max float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZCount(b redis.BaseCmd) (*ZCount, error) {
|
func ParseZCount(b redis.BaseCmd) (*ZCount, error) {
|
||||||
cmd := &ZCount{BaseCmd: b}
|
cmd := &ZCount{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Float(&cmd.Min),
|
parser.Float(&cmd.min),
|
||||||
parser.Float(&cmd.Max),
|
parser.Float(&cmd.max),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -29,7 +29,7 @@ func ParseZCount(b redis.BaseCmd) (*ZCount, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZCount) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZCount) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
n, err := red.ZSet().Count(cmd.Key, cmd.Min, cmd.Max)
|
n, err := red.ZSet().Count(cmd.key, cmd.min, cmd.max)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,62 +1,53 @@
|
|||||||
package zset_test
|
package zset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/zset"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestZCountParse(t *testing.T) {
|
func TestZCountParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want ZCount
|
||||||
want zset.ZCount
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zcount",
|
cmd: "zcount",
|
||||||
args: command.BuildArgs("zcount"),
|
want: ZCount{},
|
||||||
want: zset.ZCount{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zcount key",
|
cmd: "zcount key",
|
||||||
args: command.BuildArgs("zcount", "key"),
|
want: ZCount{},
|
||||||
want: zset.ZCount{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zcount key 11",
|
cmd: "zcount key 1.1",
|
||||||
args: command.BuildArgs("zcount", "key", "11"),
|
want: ZCount{},
|
||||||
want: zset.ZCount{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zcount key 11 22",
|
cmd: "zcount key 1.1 2.2",
|
||||||
args: command.BuildArgs("zcount", "key", "1.1", "2.2"),
|
want: ZCount{key: "key", min: 1.1, max: 2.2},
|
||||||
want: zset.ZCount{Key: "key", Min: 1.1, Max: 2.2},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zcount key 11 22 33",
|
cmd: "zcount key 1.1 2.2 3.3",
|
||||||
args: command.BuildArgs("zcount", "key", "1.1", "2.2", "3.3"),
|
want: ZCount{},
|
||||||
want: zset.ZCount{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseZCount, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*zset.ZCount)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.min, test.want.min)
|
||||||
testx.AssertEqual(t, cm.Min, test.want.Min)
|
testx.AssertEqual(t, cmd.max, test.want.max)
|
||||||
testx.AssertEqual(t, cm.Max, test.want.Max)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -70,7 +61,7 @@ func TestZCountExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "two", 22)
|
_, _ = db.ZSet().Add("key", "two", 22)
|
||||||
_, _ = db.ZSet().Add("key", "thr", 33)
|
_, _ = db.ZSet().Add("key", "thr", 33)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZCount]("zcount key 15 25")
|
cmd := redis.MustParse(ParseZCount, "zcount key 15 25")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -84,7 +75,7 @@ func TestZCountExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "two", 22)
|
_, _ = db.ZSet().Add("key", "two", 22)
|
||||||
_, _ = db.ZSet().Add("key", "thr", 33)
|
_, _ = db.ZSet().Add("key", "thr", 33)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZCount]("zcount key 11 33")
|
cmd := redis.MustParse(ParseZCount, "zcount key 11 33")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -98,7 +89,7 @@ func TestZCountExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "two", 22)
|
_, _ = db.ZSet().Add("key", "two", 22)
|
||||||
_, _ = db.ZSet().Add("key", "thr", 33)
|
_, _ = db.ZSet().Add("key", "thr", 33)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZCount]("zcount key 44 55")
|
cmd := redis.MustParse(ParseZCount, "zcount key 44 55")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -109,7 +100,7 @@ func TestZCountExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZCount]("zcount key 11 33")
|
cmd := redis.MustParse(ParseZCount, "zcount key 11 33")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -121,7 +112,7 @@ func TestZCountExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_ = db.Str().Set("key", "value")
|
_ = db.Str().Set("key", "value")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZCount]("zcount key 11 33")
|
cmd := redis.MustParse(ParseZCount, "zcount key 11 33")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -10,17 +10,17 @@ import (
|
|||||||
// https://redis.io/commands/zincrby
|
// https://redis.io/commands/zincrby
|
||||||
type ZIncrBy struct {
|
type ZIncrBy struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Delta float64
|
delta float64
|
||||||
Member string
|
member string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZIncrBy(b redis.BaseCmd) (*ZIncrBy, error) {
|
func ParseZIncrBy(b redis.BaseCmd) (*ZIncrBy, error) {
|
||||||
cmd := &ZIncrBy{BaseCmd: b}
|
cmd := &ZIncrBy{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Float(&cmd.Delta),
|
parser.Float(&cmd.delta),
|
||||||
parser.String(&cmd.Member),
|
parser.String(&cmd.member),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -29,7 +29,7 @@ func ParseZIncrBy(b redis.BaseCmd) (*ZIncrBy, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZIncrBy) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZIncrBy) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
score, err := red.ZSet().Incr(cmd.Key, cmd.Member, cmd.Delta)
|
score, err := red.ZSet().Incr(cmd.key, cmd.member, cmd.delta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,56 +1,48 @@
|
|||||||
package zset_test
|
package zset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/zset"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestZIncrByParse(t *testing.T) {
|
func TestZIncrByParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want ZIncrBy
|
||||||
want zset.ZIncrBy
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zincrby",
|
cmd: "zincrby",
|
||||||
args: command.BuildArgs("zincrby"),
|
want: ZIncrBy{},
|
||||||
want: zset.ZIncrBy{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zincrby key",
|
cmd: "zincrby key",
|
||||||
args: command.BuildArgs("zincrby", "key"),
|
want: ZIncrBy{},
|
||||||
want: zset.ZIncrBy{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zincrby key one",
|
cmd: "zincrby key one",
|
||||||
args: command.BuildArgs("zincrby", "key", "one"),
|
want: ZIncrBy{},
|
||||||
want: zset.ZIncrBy{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zincrby key 11 one",
|
cmd: "zincrby key 11 one",
|
||||||
args: command.BuildArgs("zincrby", "key", "11", "one"),
|
want: ZIncrBy{key: "key", member: "one", delta: 11.0},
|
||||||
want: zset.ZIncrBy{Key: "key", Member: "one", Delta: 11.0},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseZIncrBy, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*zset.ZIncrBy)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.member, test.want.member)
|
||||||
testx.AssertEqual(t, cm.Member, test.want.Member)
|
testx.AssertEqual(t, cmd.delta, test.want.delta)
|
||||||
testx.AssertEqual(t, cm.Delta, test.want.Delta)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -61,7 +53,7 @@ func TestZIncrByExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZIncrBy]("zincrby key 25.5 one")
|
cmd := redis.MustParse(ParseZIncrBy, "zincrby key 25.5 one")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -76,7 +68,7 @@ func TestZIncrByExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_, _ = db.ZSet().Add("key", "one", 10)
|
_, _ = db.ZSet().Add("key", "one", 10)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZIncrBy]("zincrby key 25.5 two")
|
cmd := redis.MustParse(ParseZIncrBy, "zincrby key 25.5 two")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -91,7 +83,7 @@ func TestZIncrByExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_, _ = db.ZSet().Add("key", "one", 25.5)
|
_, _ = db.ZSet().Add("key", "one", 25.5)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZIncrBy]("zincrby key 10.5 one")
|
cmd := redis.MustParse(ParseZIncrBy, "zincrby key 10.5 one")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -106,7 +98,7 @@ func TestZIncrByExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_, _ = db.ZSet().Add("key", "one", 25.5)
|
_, _ = db.ZSet().Add("key", "one", 25.5)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZIncrBy]("zincrby key -10.5 one")
|
cmd := redis.MustParse(ParseZIncrBy, "zincrby key -10.5 one")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -121,7 +113,7 @@ func TestZIncrByExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_ = red.Str().Set("key", "one")
|
_ = red.Str().Set("key", "one")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZIncrBy]("zincrby key 25.5 one")
|
cmd := redis.MustParse(ParseZIncrBy, "zincrby key 25.5 one")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import (
|
|||||||
// https://redis.io/commands/zinter
|
// https://redis.io/commands/zinter
|
||||||
type ZInter struct {
|
type ZInter struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Keys []string
|
keys []string
|
||||||
Aggregate string
|
aggregate string
|
||||||
WithScores bool
|
withScores bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZInter(b redis.BaseCmd) (*ZInter, error) {
|
func ParseZInter(b redis.BaseCmd) (*ZInter, error) {
|
||||||
@@ -21,9 +21,9 @@ func ParseZInter(b redis.BaseCmd) (*ZInter, error) {
|
|||||||
var nKeys int
|
var nKeys int
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.Int(&nKeys),
|
parser.Int(&nKeys),
|
||||||
parser.StringsN(&cmd.Keys, &nKeys),
|
parser.StringsN(&cmd.keys, &nKeys),
|
||||||
parser.Named("aggregate", parser.Enum(&cmd.Aggregate, sqlx.Sum, sqlx.Min, sqlx.Max)),
|
parser.Named("aggregate", parser.Enum(&cmd.aggregate, sqlx.Sum, sqlx.Min, sqlx.Max)),
|
||||||
parser.Flag("withscores", &cmd.WithScores),
|
parser.Flag("withscores", &cmd.withScores),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -32,8 +32,8 @@ func ParseZInter(b redis.BaseCmd) (*ZInter, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZInter) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZInter) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
inter := red.ZSet().InterWith(cmd.Keys...)
|
inter := red.ZSet().InterWith(cmd.keys...)
|
||||||
switch cmd.Aggregate {
|
switch cmd.aggregate {
|
||||||
case sqlx.Min:
|
case sqlx.Min:
|
||||||
inter = inter.Min()
|
inter = inter.Min()
|
||||||
case sqlx.Max:
|
case sqlx.Max:
|
||||||
@@ -48,7 +48,7 @@ func (cmd *ZInter) Run(w redis.Writer, red redis.Redka) (any, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.WithScores {
|
if cmd.withScores {
|
||||||
w.WriteArray(len(items) * 2)
|
w.WriteArray(len(items) * 2)
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
w.WriteBulk(item.Elem)
|
w.WriteBulk(item.Elem)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package zset_test
|
package zset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/zset"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/rzset"
|
"github.com/nalgeon/redka/internal/rzset"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,82 +10,70 @@ import (
|
|||||||
|
|
||||||
func TestZInterParse(t *testing.T) {
|
func TestZInterParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want ZInter
|
||||||
want zset.ZInter
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zinter",
|
cmd: "zinter",
|
||||||
args: command.BuildArgs("zinter"),
|
want: ZInter{},
|
||||||
want: zset.ZInter{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinter 1",
|
cmd: "zinter 1",
|
||||||
args: command.BuildArgs("zinter", "1"),
|
want: ZInter{},
|
||||||
want: zset.ZInter{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinter 1 key",
|
cmd: "zinter 1 key",
|
||||||
args: command.BuildArgs("zinter", "1", "key"),
|
want: ZInter{keys: []string{"key"}},
|
||||||
want: zset.ZInter{Keys: []string{"key"}},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinter 2 k1 k2",
|
cmd: "zinter 2 k1 k2",
|
||||||
args: command.BuildArgs("zinter", "2", "k1", "k2"),
|
want: ZInter{keys: []string{"k1", "k2"}},
|
||||||
want: zset.ZInter{Keys: []string{"k1", "k2"}},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinter 1 k1 k2",
|
cmd: "zinter 1 k1 k2",
|
||||||
args: command.BuildArgs("zinter", "1", "k1", "k2"),
|
want: ZInter{},
|
||||||
want: zset.ZInter{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinter 2 k1 k2 min",
|
cmd: "zinter 2 k1 k2 min",
|
||||||
args: command.BuildArgs("zinter", "2", "k1", "k2", "min"),
|
want: ZInter{},
|
||||||
want: zset.ZInter{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinter 2 k1 k2 aggregate min",
|
cmd: "zinter 2 k1 k2 aggregate min",
|
||||||
args: command.BuildArgs("zinter", "2", "k1", "k2", "aggregate", "min"),
|
want: ZInter{keys: []string{"k1", "k2"}, aggregate: "min"},
|
||||||
want: zset.ZInter{Keys: []string{"k1", "k2"}, Aggregate: "min"},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinter 2 k1 k2 aggregate avg",
|
cmd: "zinter 2 k1 k2 aggregate avg",
|
||||||
args: command.BuildArgs("zinter", "2", "k1", "k2", "aggregate", "avg"),
|
want: ZInter{},
|
||||||
want: zset.ZInter{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinter 2 k1 k2 withscores",
|
cmd: "zinter 2 k1 k2 withscores",
|
||||||
args: command.BuildArgs("zinter", "2", "k1", "k2", "withscores"),
|
want: ZInter{keys: []string{"k1", "k2"}, withScores: true},
|
||||||
want: zset.ZInter{Keys: []string{"k1", "k2"}, WithScores: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinter 3 k1 k2 k3 withscores aggregate sum",
|
cmd: "zinter 3 k1 k2 k3 withscores aggregate sum",
|
||||||
args: command.BuildArgs("zinter", "3", "k1", "k2", "k3", "withscores", "aggregate", "sum"),
|
want: ZInter{keys: []string{"k1", "k2", "k3"}, aggregate: "sum", withScores: true},
|
||||||
want: zset.ZInter{Keys: []string{"k1", "k2", "k3"}, Aggregate: "sum", WithScores: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseZInter, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*zset.ZInter)
|
testx.AssertEqual(t, cmd.keys, test.want.keys)
|
||||||
testx.AssertEqual(t, cm.Keys, test.want.Keys)
|
testx.AssertEqual(t, cmd.aggregate, test.want.aggregate)
|
||||||
testx.AssertEqual(t, cm.Aggregate, test.want.Aggregate)
|
testx.AssertEqual(t, cmd.withScores, test.want.withScores)
|
||||||
testx.AssertEqual(t, cm.WithScores, test.want.WithScores)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -114,7 +100,7 @@ func TestZInterExec(t *testing.T) {
|
|||||||
"fou": 400,
|
"fou": 400,
|
||||||
})
|
})
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInter]("zinter 3 key1 key2 key3")
|
cmd := redis.MustParse(ParseZInter, "zinter 3 key1 key2 key3")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -141,7 +127,7 @@ func TestZInterExec(t *testing.T) {
|
|||||||
"fou": 400,
|
"fou": 400,
|
||||||
})
|
})
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInter]("zinter 3 key1 key2 key3 withscores")
|
cmd := redis.MustParse(ParseZInter, "zinter 3 key1 key2 key3 withscores")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -168,7 +154,7 @@ func TestZInterExec(t *testing.T) {
|
|||||||
"fou": 400,
|
"fou": 400,
|
||||||
})
|
})
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInter]("zinter 3 key1 key2 key3 aggregate min withscores")
|
cmd := redis.MustParse(ParseZInter, "zinter 3 key1 key2 key3 aggregate min withscores")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -184,7 +170,7 @@ func TestZInterExec(t *testing.T) {
|
|||||||
"thr": 3,
|
"thr": 3,
|
||||||
})
|
})
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInter]("zinter 1 key1")
|
cmd := redis.MustParse(ParseZInter, "zinter 1 key1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -198,7 +184,7 @@ func TestZInterExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key2", "two", 1)
|
_, _ = db.ZSet().Add("key2", "two", 1)
|
||||||
_, _ = db.ZSet().Add("key3", "thr", 1)
|
_, _ = db.ZSet().Add("key3", "thr", 1)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInter]("zinter 3 key1 key2 key3")
|
cmd := redis.MustParse(ParseZInter, "zinter 3 key1 key2 key3")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -209,7 +195,7 @@ func TestZInterExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInter]("zinter 1 key")
|
cmd := redis.MustParse(ParseZInter, "zinter 1 key")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -221,7 +207,7 @@ func TestZInterExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_ = db.Str().Set("key", "value")
|
_ = db.Str().Set("key", "value")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInter]("zinter 1 key")
|
cmd := redis.MustParse(ParseZInter, "zinter 1 key")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -11,19 +11,19 @@ import (
|
|||||||
// https://redis.io/commands/zinterstore
|
// https://redis.io/commands/zinterstore
|
||||||
type ZInterStore struct {
|
type ZInterStore struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Dest string
|
dest string
|
||||||
Keys []string
|
keys []string
|
||||||
Aggregate string
|
aggregate string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZInterStore(b redis.BaseCmd) (*ZInterStore, error) {
|
func ParseZInterStore(b redis.BaseCmd) (*ZInterStore, error) {
|
||||||
cmd := &ZInterStore{BaseCmd: b}
|
cmd := &ZInterStore{BaseCmd: b}
|
||||||
var nKeys int
|
var nKeys int
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Dest),
|
parser.String(&cmd.dest),
|
||||||
parser.Int(&nKeys),
|
parser.Int(&nKeys),
|
||||||
parser.StringsN(&cmd.Keys, &nKeys),
|
parser.StringsN(&cmd.keys, &nKeys),
|
||||||
parser.Named("aggregate", parser.Enum(&cmd.Aggregate, sqlx.Sum, sqlx.Min, sqlx.Max)),
|
parser.Named("aggregate", parser.Enum(&cmd.aggregate, sqlx.Sum, sqlx.Min, sqlx.Max)),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -32,8 +32,8 @@ func ParseZInterStore(b redis.BaseCmd) (*ZInterStore, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZInterStore) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZInterStore) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
inter := red.ZSet().InterWith(cmd.Keys...).Dest(cmd.Dest)
|
inter := red.ZSet().InterWith(cmd.keys...).Dest(cmd.dest)
|
||||||
switch cmd.Aggregate {
|
switch cmd.aggregate {
|
||||||
case sqlx.Min:
|
case sqlx.Min:
|
||||||
inter = inter.Min()
|
inter = inter.Min()
|
||||||
case sqlx.Max:
|
case sqlx.Max:
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package zset_test
|
package zset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/zset"
|
|
||||||
"github.com/nalgeon/redka/internal/core"
|
"github.com/nalgeon/redka/internal/core"
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,76 +10,65 @@ import (
|
|||||||
|
|
||||||
func TestZInterStoreParse(t *testing.T) {
|
func TestZInterStoreParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want ZInterStore
|
||||||
want zset.ZInterStore
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zinterstore",
|
cmd: "zinterstore",
|
||||||
args: command.BuildArgs("zinterstore"),
|
want: ZInterStore{},
|
||||||
want: zset.ZInterStore{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinterstore dest",
|
cmd: "zinterstore dest",
|
||||||
args: command.BuildArgs("zinterstore", "dest"),
|
want: ZInterStore{},
|
||||||
want: zset.ZInterStore{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinterstore dest 1",
|
cmd: "zinterstore dest 1",
|
||||||
args: command.BuildArgs("zinterstore", "dest", "1"),
|
want: ZInterStore{},
|
||||||
want: zset.ZInterStore{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinterstore dest 1 key",
|
cmd: "zinterstore dest 1 key",
|
||||||
args: command.BuildArgs("zinterstore", "dest", "1", "key"),
|
want: ZInterStore{dest: "dest", keys: []string{"key"}},
|
||||||
want: zset.ZInterStore{Dest: "dest", Keys: []string{"key"}},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinterstore dest 2 k1 k2",
|
cmd: "zinterstore dest 2 k1 k2",
|
||||||
args: command.BuildArgs("zinterstore", "dest", "2", "k1", "k2"),
|
want: ZInterStore{dest: "dest", keys: []string{"k1", "k2"}},
|
||||||
want: zset.ZInterStore{Dest: "dest", Keys: []string{"k1", "k2"}},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinterstore dest 1 k1 k2",
|
cmd: "zinterstore dest 1 k1 k2",
|
||||||
args: command.BuildArgs("zinterstore", "dest", "1", "k1", "k2"),
|
want: ZInterStore{},
|
||||||
want: zset.ZInterStore{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinterstore dest 2 k1 k2 min",
|
cmd: "zinterstore dest 2 k1 k2 min",
|
||||||
args: command.BuildArgs("zinterstore", "dest", "2", "k1", "k2", "min"),
|
want: ZInterStore{},
|
||||||
want: zset.ZInterStore{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinterstore dest 2 k1 k2 aggregate min",
|
cmd: "zinterstore dest 2 k1 k2 aggregate min",
|
||||||
args: command.BuildArgs("zinterstore", "dest", "2", "k1", "k2", "aggregate", "min"),
|
want: ZInterStore{dest: "dest", keys: []string{"k1", "k2"}, aggregate: "min"},
|
||||||
want: zset.ZInterStore{Dest: "dest", Keys: []string{"k1", "k2"}, Aggregate: "min"},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zinterstore dest 2 k1 k2 aggregate avg",
|
cmd: "zinterstore dest 2 k1 k2 aggregate avg",
|
||||||
args: command.BuildArgs("zinterstore", "dest", "2", "k1", "k2", "aggregate", "avg"),
|
want: ZInterStore{},
|
||||||
want: zset.ZInterStore{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseZInterStore, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*zset.ZInterStore)
|
testx.AssertEqual(t, cmd.dest, test.want.dest)
|
||||||
testx.AssertEqual(t, cm.Dest, test.want.Dest)
|
testx.AssertEqual(t, cmd.keys, test.want.keys)
|
||||||
testx.AssertEqual(t, cm.Keys, test.want.Keys)
|
testx.AssertEqual(t, cmd.aggregate, test.want.aggregate)
|
||||||
testx.AssertEqual(t, cm.Aggregate, test.want.Aggregate)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -108,7 +95,7 @@ func TestZInterStoreExec(t *testing.T) {
|
|||||||
"fou": 400,
|
"fou": 400,
|
||||||
})
|
})
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInterStore]("zinterstore dest 3 key1 key2 key3")
|
cmd := redis.MustParse(ParseZInterStore, "zinterstore dest 3 key1 key2 key3")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -139,7 +126,7 @@ func TestZInterStoreExec(t *testing.T) {
|
|||||||
})
|
})
|
||||||
_, _ = db.ZSet().Add("dest", "one", 1)
|
_, _ = db.ZSet().Add("dest", "one", 1)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInterStore]("zinterstore dest 3 key1 key2 key3")
|
cmd := redis.MustParse(ParseZInterStore, "zinterstore dest 3 key1 key2 key3")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -171,7 +158,7 @@ func TestZInterStoreExec(t *testing.T) {
|
|||||||
"fou": 400,
|
"fou": 400,
|
||||||
})
|
})
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInterStore]("zinterstore dest 3 key1 key2 key3 aggregate min")
|
cmd := redis.MustParse(ParseZInterStore, "zinterstore dest 3 key1 key2 key3 aggregate min")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -192,7 +179,7 @@ func TestZInterStoreExec(t *testing.T) {
|
|||||||
"thr": 3,
|
"thr": 3,
|
||||||
})
|
})
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInterStore]("zinterstore dest 1 key1")
|
cmd := redis.MustParse(ParseZInterStore, "zinterstore dest 1 key1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -209,7 +196,7 @@ func TestZInterStoreExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key2", "two", 1)
|
_, _ = db.ZSet().Add("key2", "two", 1)
|
||||||
_, _ = db.ZSet().Add("key3", "thr", 1)
|
_, _ = db.ZSet().Add("key3", "thr", 1)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInterStore]("zinterstore dest 3 key1 key2 key3")
|
cmd := redis.MustParse(ParseZInterStore, "zinterstore dest 3 key1 key2 key3")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -225,7 +212,7 @@ func TestZInterStoreExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key1", "one", 1)
|
_, _ = db.ZSet().Add("key1", "one", 1)
|
||||||
_, _ = db.ZSet().Add("dest", "one", 1)
|
_, _ = db.ZSet().Add("dest", "one", 1)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInterStore]("zinterstore dest 2 key1 key2")
|
cmd := redis.MustParse(ParseZInterStore, "zinterstore dest 2 key1 key2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -241,7 +228,7 @@ func TestZInterStoreExec(t *testing.T) {
|
|||||||
_ = db.Str().Set("key", "value")
|
_ = db.Str().Set("key", "value")
|
||||||
_, _ = db.ZSet().Add("dest", "one", 1)
|
_, _ = db.ZSet().Add("dest", "one", 1)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInterStore]("zinterstore dest 1 key")
|
cmd := redis.MustParse(ParseZInterStore, "zinterstore dest 1 key")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -257,7 +244,7 @@ func TestZInterStoreExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "one", 1)
|
_, _ = db.ZSet().Add("key", "one", 1)
|
||||||
_ = db.Str().Set("dest", "value")
|
_ = db.Str().Set("dest", "value")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZInterStore]("zinterstore dest 1 key")
|
cmd := redis.MustParse(ParseZInterStore, "zinterstore dest 1 key")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -10,26 +10,26 @@ import (
|
|||||||
// https://redis.io/commands/zrange
|
// https://redis.io/commands/zrange
|
||||||
type ZRange struct {
|
type ZRange struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Start float64
|
start float64
|
||||||
Stop float64
|
stop float64
|
||||||
ByScore bool
|
byScore bool
|
||||||
Rev bool
|
rev bool
|
||||||
Offset int
|
offset int
|
||||||
Count int
|
count int
|
||||||
WithScores bool
|
withScores bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZRange(b redis.BaseCmd) (*ZRange, error) {
|
func ParseZRange(b redis.BaseCmd) (*ZRange, error) {
|
||||||
cmd := &ZRange{BaseCmd: b}
|
cmd := &ZRange{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Float(&cmd.Start),
|
parser.Float(&cmd.start),
|
||||||
parser.Float(&cmd.Stop),
|
parser.Float(&cmd.stop),
|
||||||
parser.Flag("byscore", &cmd.ByScore),
|
parser.Flag("byscore", &cmd.byScore),
|
||||||
parser.Flag("rev", &cmd.Rev),
|
parser.Flag("rev", &cmd.rev),
|
||||||
parser.Named("limit", parser.Int(&cmd.Offset), parser.Int(&cmd.Count)),
|
parser.Named("limit", parser.Int(&cmd.offset), parser.Int(&cmd.count)),
|
||||||
parser.Flag("withscores", &cmd.WithScores),
|
parser.Flag("withscores", &cmd.withScores),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -38,26 +38,26 @@ func ParseZRange(b redis.BaseCmd) (*ZRange, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZRange) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZRange) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
rang := red.ZSet().RangeWith(cmd.Key)
|
rang := red.ZSet().RangeWith(cmd.key)
|
||||||
|
|
||||||
// filter by score or rank
|
// filter by score or rank
|
||||||
if cmd.ByScore {
|
if cmd.byScore {
|
||||||
rang = rang.ByScore(cmd.Start, cmd.Stop)
|
rang = rang.ByScore(cmd.start, cmd.stop)
|
||||||
} else {
|
} else {
|
||||||
rang = rang.ByRank(int(cmd.Start), int(cmd.Stop))
|
rang = rang.ByRank(int(cmd.start), int(cmd.stop))
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort direction
|
// sort direction
|
||||||
if cmd.Rev {
|
if cmd.rev {
|
||||||
rang = rang.Desc()
|
rang = rang.Desc()
|
||||||
}
|
}
|
||||||
|
|
||||||
// limit and offset
|
// limit and offset
|
||||||
if cmd.Offset > 0 {
|
if cmd.offset > 0 {
|
||||||
rang = rang.Offset(cmd.Offset)
|
rang = rang.Offset(cmd.offset)
|
||||||
}
|
}
|
||||||
if cmd.Count > 0 {
|
if cmd.count > 0 {
|
||||||
rang = rang.Count(cmd.Count)
|
rang = rang.Count(cmd.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the command
|
// run the command
|
||||||
@@ -68,7 +68,7 @@ func (cmd *ZRange) Run(w redis.Writer, red redis.Redka) (any, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write the response with/without scores
|
// write the response with/without scores
|
||||||
if cmd.WithScores {
|
if cmd.withScores {
|
||||||
w.WriteArray(len(items) * 2)
|
w.WriteArray(len(items) * 2)
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
w.WriteBulk(item.Elem)
|
w.WriteBulk(item.Elem)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package zset_test
|
package zset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/zset"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/rzset"
|
"github.com/nalgeon/redka/internal/rzset"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,95 +10,85 @@ import (
|
|||||||
|
|
||||||
func TestZRangeParse(t *testing.T) {
|
func TestZRangeParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want ZRange
|
||||||
want zset.ZRange
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zrange",
|
cmd: "zrange",
|
||||||
args: command.BuildArgs("zrange"),
|
want: ZRange{},
|
||||||
want: zset.ZRange{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key",
|
cmd: "zrange key",
|
||||||
args: command.BuildArgs("zrange", "key"),
|
want: ZRange{},
|
||||||
want: zset.ZRange{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key 11",
|
cmd: "zrange key 11",
|
||||||
args: command.BuildArgs("zrange", "key", "11"),
|
want: ZRange{},
|
||||||
want: zset.ZRange{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key 11 22",
|
cmd: "zrange key 11 22",
|
||||||
args: command.BuildArgs("zrange", "key", "11", "22"),
|
want: ZRange{key: "key", start: 11.0, stop: 22.0},
|
||||||
want: zset.ZRange{Key: "key", Start: 11.0, Stop: 22.0},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key 1.1 2.2 byscore",
|
cmd: "zrange key 1.1 2.2 byscore",
|
||||||
args: command.BuildArgs("zrange", "key", "1.1", "2.2", "byscore"),
|
want: ZRange{key: "key", start: 1.1, stop: 2.2, byScore: true},
|
||||||
want: zset.ZRange{Key: "key", Start: 1.1, Stop: 2.2, ByScore: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key byscore exclusive",
|
cmd: "zrange key (1 (2 byscore",
|
||||||
args: command.BuildArgs("zrange", "key", "(1", "(2", "byscore"),
|
want: ZRange{},
|
||||||
want: zset.ZRange{},
|
|
||||||
err: redis.ErrInvalidFloat,
|
err: redis.ErrInvalidFloat,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key 11 22 rev",
|
cmd: "zrange key 11 22 rev",
|
||||||
args: command.BuildArgs("zrange", "key", "11", "22", "rev"),
|
want: ZRange{key: "key", start: 11.0, stop: 22.0, rev: true},
|
||||||
want: zset.ZRange{Key: "key", Start: 11.0, Stop: 22.0, Rev: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key 11 22 byscore limit 10",
|
cmd: "zrange key 11 22 byscore limit 10",
|
||||||
args: command.BuildArgs("zrange", "key", "11", "22", "byscore", "limit", "10"),
|
want: ZRange{},
|
||||||
want: zset.ZRange{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key 11 22 byscore limit 10 5",
|
cmd: "zrange key 11 22 byscore limit 10 5",
|
||||||
args: command.BuildArgs("zrange", "key", "11", "22", "byscore", "limit", "10", "5"),
|
want: ZRange{key: "key", start: 11.0, stop: 22.0, byScore: true, offset: 10, count: 5},
|
||||||
want: zset.ZRange{Key: "key", Start: 11.0, Stop: 22.0, ByScore: true, Offset: 10, Count: 5},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key 11 22 withscores",
|
cmd: "zrange key 11 22 withscores",
|
||||||
args: command.BuildArgs("zrange", "key", "11", "22", "withscores"),
|
want: ZRange{key: "key", start: 11.0, stop: 22.0, withScores: true},
|
||||||
want: zset.ZRange{Key: "key", Start: 11.0, Stop: 22.0, WithScores: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrange key 11 22 limit 10 5 rev byscore withscores",
|
cmd: "zrange key 11 22 limit 10 5 rev byscore withscores",
|
||||||
args: command.BuildArgs("zrange", "key", "11", "22", "limit", "10", "5",
|
want: ZRange{
|
||||||
"rev", "byscore", "withscores"),
|
key: "key", start: 11.0, stop: 22.0,
|
||||||
want: zset.ZRange{Key: "key", Start: 11.0, Stop: 22.0, ByScore: true,
|
byScore: true, rev: true,
|
||||||
Rev: true, Offset: 10, Count: 5, WithScores: true},
|
offset: 10, count: 5,
|
||||||
|
withScores: true,
|
||||||
|
},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseZRange, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*zset.ZRange)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.start, test.want.start)
|
||||||
testx.AssertEqual(t, cm.Start, test.want.Start)
|
testx.AssertEqual(t, cmd.stop, test.want.stop)
|
||||||
testx.AssertEqual(t, cm.Stop, test.want.Stop)
|
testx.AssertEqual(t, cmd.byScore, test.want.byScore)
|
||||||
testx.AssertEqual(t, cm.ByScore, test.want.ByScore)
|
testx.AssertEqual(t, cmd.rev, test.want.rev)
|
||||||
testx.AssertEqual(t, cm.Rev, test.want.Rev)
|
testx.AssertEqual(t, cmd.offset, test.want.offset)
|
||||||
testx.AssertEqual(t, cm.Offset, test.want.Offset)
|
testx.AssertEqual(t, cmd.count, test.want.count)
|
||||||
testx.AssertEqual(t, cm.Count, test.want.Count)
|
testx.AssertEqual(t, cmd.withScores, test.want.withScores)
|
||||||
testx.AssertEqual(t, cm.WithScores, test.want.WithScores)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -116,7 +104,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "2nd", 2)
|
_, _ = db.ZSet().Add("key", "2nd", 2)
|
||||||
|
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 1")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -124,7 +112,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,one,2nd")
|
testx.AssertEqual(t, conn.Out(), "2,one,2nd")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 5")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -132,7 +120,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "4,one,2nd,two,thr")
|
testx.AssertEqual(t, conn.Out(), "4,one,2nd,two,thr")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 3 5")
|
cmd := redis.MustParse(ParseZRange, "zrange key 3 5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -140,7 +128,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "1,thr")
|
testx.AssertEqual(t, conn.Out(), "1,thr")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 4 5")
|
cmd := redis.MustParse(ParseZRange, "zrange key 4 5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -157,7 +145,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "2nd", 2)
|
_, _ = db.ZSet().Add("key", "2nd", 2)
|
||||||
|
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 1 rev")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 1 rev")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -165,7 +153,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,thr,two")
|
testx.AssertEqual(t, conn.Out(), "2,thr,two")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 5 rev")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 5 rev")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -173,7 +161,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "4,thr,two,2nd,one")
|
testx.AssertEqual(t, conn.Out(), "4,thr,two,2nd,one")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 3 5 rev")
|
cmd := redis.MustParse(ParseZRange, "zrange key 3 5 rev")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -181,7 +169,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "1,one")
|
testx.AssertEqual(t, conn.Out(), "1,one")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 4 5 rev")
|
cmd := redis.MustParse(ParseZRange, "zrange key 4 5 rev")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -198,7 +186,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "2nd", 20)
|
_, _ = db.ZSet().Add("key", "2nd", 20)
|
||||||
|
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 10 byscore")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 10 byscore")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -206,7 +194,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "1,one")
|
testx.AssertEqual(t, conn.Out(), "1,one")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 50 byscore")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 50 byscore")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -214,7 +202,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "4,one,2nd,two,thr")
|
testx.AssertEqual(t, conn.Out(), "4,one,2nd,two,thr")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 30 50 byscore")
|
cmd := redis.MustParse(ParseZRange, "zrange key 30 50 byscore")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -222,7 +210,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "1,thr")
|
testx.AssertEqual(t, conn.Out(), "1,thr")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 40 50 byscore")
|
cmd := redis.MustParse(ParseZRange, "zrange key 40 50 byscore")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -239,7 +227,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "2nd", 20)
|
_, _ = db.ZSet().Add("key", "2nd", 20)
|
||||||
|
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 10 byscore rev")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 10 byscore rev")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -247,7 +235,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "1,one")
|
testx.AssertEqual(t, conn.Out(), "1,one")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 50 byscore rev")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 50 byscore rev")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -255,7 +243,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "4,thr,two,2nd,one")
|
testx.AssertEqual(t, conn.Out(), "4,thr,two,2nd,one")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 30 50 byscore rev")
|
cmd := redis.MustParse(ParseZRange, "zrange key 30 50 byscore rev")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -263,7 +251,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "1,thr")
|
testx.AssertEqual(t, conn.Out(), "1,thr")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 40 50 byscore rev")
|
cmd := redis.MustParse(ParseZRange, "zrange key 40 50 byscore rev")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -280,7 +268,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "2nd", 20)
|
_, _ = db.ZSet().Add("key", "2nd", 20)
|
||||||
|
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 50 byscore limit 0 2")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 50 byscore limit 0 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -288,7 +276,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,one,2nd")
|
testx.AssertEqual(t, conn.Out(), "2,one,2nd")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 50 byscore limit 1 2")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 50 byscore limit 1 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -296,7 +284,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,2nd,two")
|
testx.AssertEqual(t, conn.Out(), "2,2nd,two")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 50 byscore limit 2 5")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 50 byscore limit 2 5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -304,7 +292,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,two,thr")
|
testx.AssertEqual(t, conn.Out(), "2,two,thr")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 50 byscore limit 1 -1")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 50 byscore limit 1 -1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -320,7 +308,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "thr", 3)
|
_, _ = db.ZSet().Add("key", "thr", 3)
|
||||||
_, _ = db.ZSet().Add("key", "2nd", 2)
|
_, _ = db.ZSet().Add("key", "2nd", 2)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 5 withscores")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 5 withscores")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -335,7 +323,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "thr", 3)
|
_, _ = db.ZSet().Add("key", "thr", 3)
|
||||||
_, _ = db.ZSet().Add("key", "2nd", 2)
|
_, _ = db.ZSet().Add("key", "2nd", 2)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key -2 -1")
|
cmd := redis.MustParse(ParseZRange, "zrange key -2 -1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -346,7 +334,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 1")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -358,7 +346,7 @@ func TestZRangeExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_ = db.Str().Set("key", "value")
|
_ = db.Str().Set("key", "value")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRange]("zrange key 0 1")
|
cmd := redis.MustParse(ParseZRange, "zrange key 0 1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -10,22 +10,22 @@ import (
|
|||||||
// https://redis.io/commands/zrangebyscore
|
// https://redis.io/commands/zrangebyscore
|
||||||
type ZRangeByScore struct {
|
type ZRangeByScore struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Min float64
|
min float64
|
||||||
Max float64
|
max float64
|
||||||
WithScores bool
|
withScores bool
|
||||||
Offset int
|
offset int
|
||||||
Count int
|
count int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZRangeByScore(b redis.BaseCmd) (*ZRangeByScore, error) {
|
func ParseZRangeByScore(b redis.BaseCmd) (*ZRangeByScore, error) {
|
||||||
cmd := &ZRangeByScore{BaseCmd: b}
|
cmd := &ZRangeByScore{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Float(&cmd.Min),
|
parser.Float(&cmd.min),
|
||||||
parser.Float(&cmd.Max),
|
parser.Float(&cmd.max),
|
||||||
parser.Flag("withscores", &cmd.WithScores),
|
parser.Flag("withscores", &cmd.withScores),
|
||||||
parser.Named("limit", parser.Int(&cmd.Offset), parser.Int(&cmd.Count)),
|
parser.Named("limit", parser.Int(&cmd.offset), parser.Int(&cmd.count)),
|
||||||
).Required(3).Run(cmd.Args())
|
).Required(3).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -34,14 +34,14 @@ func ParseZRangeByScore(b redis.BaseCmd) (*ZRangeByScore, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZRangeByScore) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZRangeByScore) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
rang := red.ZSet().RangeWith(cmd.Key).ByScore(cmd.Min, cmd.Max)
|
rang := red.ZSet().RangeWith(cmd.key).ByScore(cmd.min, cmd.max)
|
||||||
|
|
||||||
// limit and offset
|
// limit and offset
|
||||||
if cmd.Offset > 0 {
|
if cmd.offset > 0 {
|
||||||
rang = rang.Offset(cmd.Offset)
|
rang = rang.Offset(cmd.offset)
|
||||||
}
|
}
|
||||||
if cmd.Count > 0 {
|
if cmd.count > 0 {
|
||||||
rang = rang.Count(cmd.Count)
|
rang = rang.Count(cmd.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the command
|
// run the command
|
||||||
@@ -52,7 +52,7 @@ func (cmd *ZRangeByScore) Run(w redis.Writer, red redis.Redka) (any, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write the response with/without scores
|
// write the response with/without scores
|
||||||
if cmd.WithScores {
|
if cmd.withScores {
|
||||||
w.WriteArray(len(items) * 2)
|
w.WriteArray(len(items) * 2)
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
w.WriteBulk(item.Elem)
|
w.WriteBulk(item.Elem)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package zset_test
|
package zset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/zset"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/rzset"
|
"github.com/nalgeon/redka/internal/rzset"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
@@ -12,81 +10,72 @@ import (
|
|||||||
|
|
||||||
func TestZRangeByScoreParse(t *testing.T) {
|
func TestZRangeByScoreParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want ZRangeByScore
|
||||||
want zset.ZRangeByScore
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zrangebyscore",
|
cmd: "zrangebyscore",
|
||||||
args: command.BuildArgs("zrangebyscore"),
|
want: ZRangeByScore{},
|
||||||
want: zset.ZRangeByScore{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrangebyscore key",
|
cmd: "zrangebyscore key",
|
||||||
args: command.BuildArgs("zrangebyscore", "key"),
|
want: ZRangeByScore{},
|
||||||
want: zset.ZRangeByScore{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrangebyscore key 11",
|
cmd: "zrangebyscore key 11",
|
||||||
args: command.BuildArgs("zrangebyscore", "key", "11"),
|
want: ZRangeByScore{},
|
||||||
want: zset.ZRangeByScore{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrangebyscore key 11 22",
|
cmd: "zrangebyscore key 11 22",
|
||||||
args: command.BuildArgs("zrangebyscore", "key", "11", "22"),
|
want: ZRangeByScore{key: "key", min: 11.0, max: 22.0},
|
||||||
want: zset.ZRangeByScore{Key: "key", Min: 11.0, Max: 22.0},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrangebyscore key exclusive",
|
cmd: "zrangebyscore key (1 (2",
|
||||||
args: command.BuildArgs("zrangebyscore", "key", "(1", "(2"),
|
want: ZRangeByScore{},
|
||||||
want: zset.ZRangeByScore{},
|
|
||||||
err: redis.ErrInvalidFloat,
|
err: redis.ErrInvalidFloat,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrangebyscore key 11 22 limit 10",
|
cmd: "zrangebyscore key 11 22 limit 10",
|
||||||
args: command.BuildArgs("zrangebyscore", "key", "11", "22", "limit", "10"),
|
want: ZRangeByScore{},
|
||||||
want: zset.ZRangeByScore{},
|
|
||||||
err: redis.ErrSyntaxError,
|
err: redis.ErrSyntaxError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrangebyscore key 11 22 limit 10 5",
|
cmd: "zrangebyscore key 11 22 limit 10 5",
|
||||||
args: command.BuildArgs("zrangebyscore", "key", "11", "22", "limit", "10", "5"),
|
want: ZRangeByScore{key: "key", min: 11.0, max: 22.0, offset: 10, count: 5},
|
||||||
want: zset.ZRangeByScore{Key: "key", Min: 11.0, Max: 22.0, Offset: 10, Count: 5},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrangebyscore key 11 22 withscores",
|
cmd: "zrangebyscore key 11 22 withscores",
|
||||||
args: command.BuildArgs("zrangebyscore", "key", "11", "22", "withscores"),
|
want: ZRangeByScore{key: "key", min: 11.0, max: 22.0, withScores: true},
|
||||||
want: zset.ZRangeByScore{Key: "key", Min: 11.0, Max: 22.0, WithScores: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrangebyscore key 11 22 limit 10 5 withscores",
|
cmd: "zrangebyscore key 11 22 limit 10 5 withscores",
|
||||||
args: command.BuildArgs("zrangebyscore", "key", "11", "22",
|
want: ZRangeByScore{
|
||||||
"limit", "10", "5", "withscores"),
|
key: "key", min: 11.0, max: 22.0,
|
||||||
want: zset.ZRangeByScore{Key: "key", Min: 11.0, Max: 22.0,
|
offset: 10, count: 5,
|
||||||
Offset: 10, Count: 5, WithScores: true},
|
withScores: true,
|
||||||
|
},
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseZRangeByScore, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*zset.ZRangeByScore)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.min, test.want.min)
|
||||||
testx.AssertEqual(t, cm.Min, test.want.Min)
|
testx.AssertEqual(t, cmd.max, test.want.max)
|
||||||
testx.AssertEqual(t, cm.Max, test.want.Max)
|
testx.AssertEqual(t, cmd.offset, test.want.offset)
|
||||||
testx.AssertEqual(t, cm.Offset, test.want.Offset)
|
testx.AssertEqual(t, cmd.count, test.want.count)
|
||||||
testx.AssertEqual(t, cm.Count, test.want.Count)
|
testx.AssertEqual(t, cmd.withScores, test.want.withScores)
|
||||||
testx.AssertEqual(t, cm.WithScores, test.want.WithScores)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -102,7 +91,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "2nd", 20)
|
_, _ = db.ZSet().Add("key", "2nd", 20)
|
||||||
|
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 0 10")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 0 10")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -110,7 +99,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "1,one")
|
testx.AssertEqual(t, conn.Out(), "1,one")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 0 50")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 0 50")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -118,7 +107,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "4,one,2nd,two,thr")
|
testx.AssertEqual(t, conn.Out(), "4,one,2nd,two,thr")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 30 50")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 30 50")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -126,7 +115,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "1,thr")
|
testx.AssertEqual(t, conn.Out(), "1,thr")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 40 50")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 40 50")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -143,7 +132,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "2nd", 20)
|
_, _ = db.ZSet().Add("key", "2nd", 20)
|
||||||
|
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 0 50 limit 0 2")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 0 50 limit 0 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -151,7 +140,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,one,2nd")
|
testx.AssertEqual(t, conn.Out(), "2,one,2nd")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 0 50 limit 1 2")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 0 50 limit 1 2")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -159,7 +148,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,2nd,two")
|
testx.AssertEqual(t, conn.Out(), "2,2nd,two")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 0 50 limit 2 5")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 0 50 limit 2 5")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -167,7 +156,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
testx.AssertEqual(t, conn.Out(), "2,two,thr")
|
testx.AssertEqual(t, conn.Out(), "2,two,thr")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 0 50 limit 1 -1")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 0 50 limit 1 -1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -183,7 +172,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "thr", 30)
|
_, _ = db.ZSet().Add("key", "thr", 30)
|
||||||
_, _ = db.ZSet().Add("key", "2nd", 20)
|
_, _ = db.ZSet().Add("key", "2nd", 20)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 10 50 withscores")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 10 50 withscores")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -198,7 +187,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "thr", -30)
|
_, _ = db.ZSet().Add("key", "thr", -30)
|
||||||
_, _ = db.ZSet().Add("key", "2nd", -20)
|
_, _ = db.ZSet().Add("key", "2nd", -20)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key -20 -10")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key -20 -10")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -209,7 +198,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 0 1")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 0 1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -221,7 +210,7 @@ func TestZRangeByScoreExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_ = db.Str().Set("key", "value")
|
_ = db.Str().Set("key", "value")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRangeByScore]("zrangebyscore key 0 1")
|
cmd := redis.MustParse(ParseZRangeByScore, "zrangebyscore key 0 1")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -11,17 +11,17 @@ import (
|
|||||||
// https://redis.io/commands/zrank
|
// https://redis.io/commands/zrank
|
||||||
type ZRank struct {
|
type ZRank struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Member string
|
member string
|
||||||
WithScore bool
|
withScore bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZRank(b redis.BaseCmd) (*ZRank, error) {
|
func ParseZRank(b redis.BaseCmd) (*ZRank, error) {
|
||||||
cmd := &ZRank{BaseCmd: b}
|
cmd := &ZRank{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.String(&cmd.Member),
|
parser.String(&cmd.member),
|
||||||
parser.Flag("withscore", &cmd.WithScore),
|
parser.Flag("withscore", &cmd.withScore),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -30,7 +30,7 @@ func ParseZRank(b redis.BaseCmd) (*ZRank, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZRank) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZRank) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
rank, score, err := red.ZSet().GetRank(cmd.Key, cmd.Member)
|
rank, score, err := red.ZSet().GetRank(cmd.key, cmd.member)
|
||||||
if err == core.ErrNotFound {
|
if err == core.ErrNotFound {
|
||||||
w.WriteNull()
|
w.WriteNull()
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -39,7 +39,7 @@ func (cmd *ZRank) Run(w redis.Writer, red redis.Redka) (any, error) {
|
|||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cmd.WithScore {
|
if cmd.withScore {
|
||||||
w.WriteArray(2)
|
w.WriteArray(2)
|
||||||
w.WriteInt(rank)
|
w.WriteInt(rank)
|
||||||
redis.WriteFloat(w, score)
|
redis.WriteFloat(w, score)
|
||||||
|
|||||||
@@ -1,56 +1,48 @@
|
|||||||
package zset_test
|
package zset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nalgeon/redka/internal/command"
|
|
||||||
"github.com/nalgeon/redka/internal/command/zset"
|
|
||||||
"github.com/nalgeon/redka/internal/redis"
|
"github.com/nalgeon/redka/internal/redis"
|
||||||
"github.com/nalgeon/redka/internal/testx"
|
"github.com/nalgeon/redka/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestZRankParse(t *testing.T) {
|
func TestZRankParse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
cmd string
|
||||||
args [][]byte
|
want ZRank
|
||||||
want zset.ZRank
|
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "zrank",
|
cmd: "zrank",
|
||||||
args: command.BuildArgs("zrank"),
|
want: ZRank{},
|
||||||
want: zset.ZRank{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrank key",
|
cmd: "zrank key",
|
||||||
args: command.BuildArgs("zrank", "key"),
|
want: ZRank{},
|
||||||
want: zset.ZRank{},
|
|
||||||
err: redis.ErrInvalidArgNum,
|
err: redis.ErrInvalidArgNum,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrank key member",
|
cmd: "zrank key member",
|
||||||
args: command.BuildArgs("zrank", "key", "member"),
|
want: ZRank{key: "key", member: "member"},
|
||||||
want: zset.ZRank{Key: "key", Member: "member"},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "zrank key member withscore",
|
cmd: "zrank key member withscore",
|
||||||
args: command.BuildArgs("zrank", "key", "member", "withscore"),
|
want: ZRank{key: "key", member: "member", withScore: true},
|
||||||
want: zset.ZRank{Key: "key", Member: "member", WithScore: true},
|
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.cmd, func(t *testing.T) {
|
||||||
cmd, err := command.Parse(test.args)
|
cmd, err := redis.Parse(ParseZRank, test.cmd)
|
||||||
testx.AssertEqual(t, err, test.err)
|
testx.AssertEqual(t, err, test.err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cm := cmd.(*zset.ZRank)
|
testx.AssertEqual(t, cmd.key, test.want.key)
|
||||||
testx.AssertEqual(t, cm.Key, test.want.Key)
|
testx.AssertEqual(t, cmd.member, test.want.member)
|
||||||
testx.AssertEqual(t, cm.Member, test.want.Member)
|
testx.AssertEqual(t, cmd.withScore, test.want.withScore)
|
||||||
testx.AssertEqual(t, cm.WithScore, test.want.WithScore)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -63,7 +55,7 @@ func TestZRankExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "one", 11)
|
_, _ = db.ZSet().Add("key", "one", 11)
|
||||||
_, _ = db.ZSet().Add("key", "two", 22)
|
_, _ = db.ZSet().Add("key", "two", 22)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRank]("zrank key two")
|
cmd := redis.MustParse(ParseZRank, "zrank key two")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -76,7 +68,7 @@ func TestZRankExec(t *testing.T) {
|
|||||||
_, _ = db.ZSet().Add("key", "one", 11)
|
_, _ = db.ZSet().Add("key", "one", 11)
|
||||||
_, _ = db.ZSet().Add("key", "two", 22)
|
_, _ = db.ZSet().Add("key", "two", 22)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRank]("zrank key two withscore")
|
cmd := redis.MustParse(ParseZRank, "zrank key two withscore")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -88,7 +80,7 @@ func TestZRankExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_, _ = db.ZSet().Add("key", "one", 11)
|
_, _ = db.ZSet().Add("key", "one", 11)
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRank]("zrank key two")
|
cmd := redis.MustParse(ParseZRank, "zrank key two")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -99,7 +91,7 @@ func TestZRankExec(t *testing.T) {
|
|||||||
db, red := getDB(t)
|
db, red := getDB(t)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRank]("zrank key two")
|
cmd := redis.MustParse(ParseZRank, "zrank key two")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
@@ -111,7 +103,7 @@ func TestZRankExec(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
_ = db.Str().Set("key", "value")
|
_ = db.Str().Set("key", "value")
|
||||||
|
|
||||||
cmd := command.MustParse[*zset.ZRank]("zrank key two")
|
cmd := redis.MustParse(ParseZRank, "zrank key two")
|
||||||
conn := redis.NewFakeConn()
|
conn := redis.NewFakeConn()
|
||||||
res, err := cmd.Run(conn, red)
|
res, err := cmd.Run(conn, red)
|
||||||
testx.AssertNoErr(t, err)
|
testx.AssertNoErr(t, err)
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ import (
|
|||||||
// https://redis.io/commands/zrem
|
// https://redis.io/commands/zrem
|
||||||
type ZRem struct {
|
type ZRem struct {
|
||||||
redis.BaseCmd
|
redis.BaseCmd
|
||||||
Key string
|
key string
|
||||||
Members []any
|
members []any
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseZRem(b redis.BaseCmd) (*ZRem, error) {
|
func ParseZRem(b redis.BaseCmd) (*ZRem, error) {
|
||||||
cmd := &ZRem{BaseCmd: b}
|
cmd := &ZRem{BaseCmd: b}
|
||||||
err := parser.New(
|
err := parser.New(
|
||||||
parser.String(&cmd.Key),
|
parser.String(&cmd.key),
|
||||||
parser.Anys(&cmd.Members),
|
parser.Anys(&cmd.members),
|
||||||
).Required(2).Run(cmd.Args())
|
).Required(2).Run(cmd.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -27,7 +27,7 @@ func ParseZRem(b redis.BaseCmd) (*ZRem, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZRem) Run(w redis.Writer, red redis.Redka) (any, error) {
|
func (cmd *ZRem) Run(w redis.Writer, red redis.Redka) (any, error) {
|
||||||
n, err := red.ZSet().Delete(cmd.Key, cmd.Members...)
|
n, err := red.ZSet().Delete(cmd.key, cmd.members...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteError(cmd.Error(err))
|
w.WriteError(cmd.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user