mirror of
https://github.com/nalgeon/redka.git
synced 2025-10-05 16:06:50 +08:00
241 lines
5.3 KiB
Go
241 lines
5.3 KiB
Go
package set
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/nalgeon/be"
|
|
"github.com/nalgeon/redka/internal/core"
|
|
"github.com/nalgeon/redka/internal/redis"
|
|
"github.com/nalgeon/redka/internal/rset"
|
|
)
|
|
|
|
func TestSScanParse(t *testing.T) {
|
|
tests := []struct {
|
|
cmd string
|
|
key string
|
|
cursor int
|
|
match string
|
|
count int
|
|
err error
|
|
}{
|
|
{
|
|
cmd: "sscan",
|
|
key: "",
|
|
cursor: 0,
|
|
match: "*",
|
|
count: 0,
|
|
err: redis.ErrInvalidArgNum,
|
|
},
|
|
{
|
|
cmd: "sscan key",
|
|
key: "",
|
|
cursor: 0,
|
|
match: "*",
|
|
count: 0,
|
|
err: redis.ErrInvalidArgNum,
|
|
},
|
|
{
|
|
cmd: "sscan key 15",
|
|
key: "key",
|
|
cursor: 15,
|
|
match: "*",
|
|
count: 0,
|
|
err: nil,
|
|
},
|
|
{
|
|
cmd: "sscan key 15 match *",
|
|
key: "key",
|
|
cursor: 15,
|
|
match: "*",
|
|
count: 0,
|
|
err: nil,
|
|
},
|
|
{
|
|
cmd: "sscan key 15 match * count 5",
|
|
key: "key",
|
|
cursor: 15,
|
|
match: "*",
|
|
count: 5,
|
|
err: nil,
|
|
},
|
|
{
|
|
cmd: "sscan key 15 count 5 match *",
|
|
key: "key",
|
|
cursor: 15,
|
|
match: "*",
|
|
count: 5,
|
|
err: nil,
|
|
},
|
|
{
|
|
cmd: "sscan key 15 match m2* count 5",
|
|
key: "key",
|
|
cursor: 15,
|
|
match: "m2*",
|
|
count: 5,
|
|
err: nil,
|
|
},
|
|
{
|
|
cmd: "sscan key ten",
|
|
key: "",
|
|
cursor: 0,
|
|
match: "",
|
|
count: 0,
|
|
err: redis.ErrInvalidInt,
|
|
},
|
|
{
|
|
cmd: "sscan key 15 *",
|
|
key: "",
|
|
cursor: 0,
|
|
match: "",
|
|
count: 0,
|
|
err: redis.ErrSyntaxError,
|
|
},
|
|
{
|
|
cmd: "sscan key 15 * 5",
|
|
key: "",
|
|
cursor: 0,
|
|
match: "",
|
|
count: 0,
|
|
err: redis.ErrSyntaxError,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.cmd, func(t *testing.T) {
|
|
cmd, err := redis.Parse(ParseSScan, test.cmd)
|
|
be.Equal(t, err, test.err)
|
|
if err == nil {
|
|
be.Equal(t, cmd.key, test.key)
|
|
be.Equal(t, cmd.cursor, test.cursor)
|
|
be.Equal(t, cmd.match, test.match)
|
|
be.Equal(t, cmd.count, test.count)
|
|
} else {
|
|
be.Equal(t, cmd, SScan{})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSScanExec(t *testing.T) {
|
|
red := getRedka(t)
|
|
_, _ = red.Set().Add("key", "m11", "m12", "m21", "m22", "m31")
|
|
|
|
t.Run("sscan all", func(t *testing.T) {
|
|
var cursor int
|
|
{
|
|
cmd := redis.MustParse(ParseSScan, "sscan key 0")
|
|
conn := redis.NewFakeConn()
|
|
|
|
res, err := cmd.Run(conn, red)
|
|
be.Err(t, err, nil)
|
|
|
|
sres := res.(rset.ScanResult)
|
|
be.True(t, sres.Cursor > 0)
|
|
be.Equal(t, len(sres.Items), 5)
|
|
be.Equal(t, sres.Items[0], core.Value("m11"))
|
|
be.Equal(t, sres.Items[4], core.Value("m31"))
|
|
wantOut := fmt.Sprintf("2,%d,5,m11,m12,m21,m22,m31", sres.Cursor)
|
|
be.Equal(t, conn.Out(), wantOut)
|
|
cursor = sres.Cursor
|
|
}
|
|
{
|
|
next := fmt.Sprintf("sscan key %d", cursor)
|
|
cmd := redis.MustParse(ParseSScan, next)
|
|
conn := redis.NewFakeConn()
|
|
|
|
res, err := cmd.Run(conn, red)
|
|
be.Err(t, err, nil)
|
|
|
|
sres := res.(rset.ScanResult)
|
|
be.Equal(t, sres.Cursor, 0)
|
|
be.Equal(t, len(sres.Items), 0)
|
|
be.Equal(t, conn.Out(), "2,0,0")
|
|
}
|
|
})
|
|
t.Run("sscan pattern", func(t *testing.T) {
|
|
cmd := redis.MustParse(ParseSScan, "sscan key 0 match m2*")
|
|
conn := redis.NewFakeConn()
|
|
|
|
res, err := cmd.Run(conn, red)
|
|
be.Err(t, err, nil)
|
|
|
|
sres := res.(rset.ScanResult)
|
|
be.True(t, sres.Cursor > 0)
|
|
be.Equal(t, len(sres.Items), 2)
|
|
be.Equal(t, sres.Items[0].String(), "m21")
|
|
be.Equal(t, sres.Items[1].String(), "m22")
|
|
wantOut := fmt.Sprintf("2,%d,2,m21,m22", sres.Cursor)
|
|
be.Equal(t, conn.Out(), wantOut)
|
|
})
|
|
t.Run("sscan count", func(t *testing.T) {
|
|
var cursor int
|
|
{
|
|
// page 1
|
|
cmd := redis.MustParse(ParseSScan, "sscan key 0 match * count 2")
|
|
conn := redis.NewFakeConn()
|
|
|
|
res, err := cmd.Run(conn, red)
|
|
be.Err(t, err, nil)
|
|
|
|
sres := res.(rset.ScanResult)
|
|
be.True(t, sres.Cursor > 0)
|
|
be.Equal(t, len(sres.Items), 2)
|
|
be.Equal(t, sres.Items[0].String(), "m11")
|
|
be.Equal(t, sres.Items[1].String(), "m12")
|
|
wantOut := fmt.Sprintf("2,%d,2,m11,m12", sres.Cursor)
|
|
be.Equal(t, conn.Out(), wantOut)
|
|
cursor = sres.Cursor
|
|
}
|
|
{
|
|
// page 2
|
|
next := fmt.Sprintf("sscan key %d match * count 2", cursor)
|
|
cmd := redis.MustParse(ParseSScan, next)
|
|
conn := redis.NewFakeConn()
|
|
|
|
res, err := cmd.Run(conn, red)
|
|
be.Err(t, err, nil)
|
|
|
|
sres := res.(rset.ScanResult)
|
|
be.True(t, sres.Cursor > cursor)
|
|
be.Equal(t, len(sres.Items), 2)
|
|
be.Equal(t, sres.Items[0].String(), "m21")
|
|
be.Equal(t, sres.Items[1].String(), "m22")
|
|
wantOut := fmt.Sprintf("2,%d,2,m21,m22", sres.Cursor)
|
|
be.Equal(t, conn.Out(), wantOut)
|
|
cursor = sres.Cursor
|
|
}
|
|
{
|
|
// page 3
|
|
next := fmt.Sprintf("sscan key %d match * count 2", cursor)
|
|
cmd := redis.MustParse(ParseSScan, next)
|
|
conn := redis.NewFakeConn()
|
|
|
|
res, err := cmd.Run(conn, red)
|
|
be.Err(t, err, nil)
|
|
|
|
sres := res.(rset.ScanResult)
|
|
be.True(t, sres.Cursor > cursor)
|
|
be.Equal(t, len(sres.Items), 1)
|
|
be.Equal(t, sres.Items[0].String(), "m31")
|
|
wantOut := fmt.Sprintf("2,%d,1,m31", sres.Cursor)
|
|
be.Equal(t, conn.Out(), wantOut)
|
|
cursor = sres.Cursor
|
|
}
|
|
{
|
|
// no more pages
|
|
next := fmt.Sprintf("sscan key %d match * count 2", cursor)
|
|
cmd := redis.MustParse(ParseSScan, next)
|
|
conn := redis.NewFakeConn()
|
|
|
|
res, err := cmd.Run(conn, red)
|
|
be.Err(t, err, nil)
|
|
|
|
sres := res.(rset.ScanResult)
|
|
be.Equal(t, sres.Cursor, 0)
|
|
be.Equal(t, len(sres.Items), 0)
|
|
be.Equal(t, conn.Out(), "2,0,0")
|
|
}
|
|
})
|
|
}
|