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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ Commands which will probably not be implemented:

## &c.

Integration tests are run against Redis 7.2.4. The [./integration](./integration/) subdir
Integration tests are run against Redis 8.4.0. The [./integration](./integration/) subdir
compares miniredis against a real redis instance.

The Redis 6 RESP3 protocol is supported. If there are problems, please open
Expand Down
15 changes: 12 additions & 3 deletions cmd_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func (m *Miniredis) cmdHello(c *server.Peer, cmd string, args []string) {
c.WriteBulk("server")
c.WriteBulk("miniredis")
c.WriteBulk("version")
c.WriteBulk("6.0.5")
c.WriteBulk("8.4.0")
c.WriteBulk("proto")
c.WriteInt(opts.version)
c.WriteBulk("id")
Expand All @@ -186,8 +186,17 @@ func (m *Miniredis) cmdHello(c *server.Peer, cmd string, args []string) {
c.WriteBulk("standalone")
c.WriteBulk("role")
c.WriteBulk("master")
c.WriteBulk("modules")
c.WriteLen(0)
c.WriteBulk("modules") // "modules": [
c.WriteLen(1) // we have 1: "vectorset"
c.WriteMapLen(4) // {
c.WriteBulk("name") //
c.WriteBulk("vectorset") //
c.WriteBulk("ver") //
c.WriteInt(1) //
c.WriteBulk("path") //
c.WriteBulk("") //
c.WriteBulk("args") //
c.WriteLen(0) // ]} end modules
}

// ECHO
Expand Down
12 changes: 9 additions & 3 deletions cmd_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,15 +236,21 @@ func TestSetError(t *testing.T) {
func TestHello(t *testing.T) {
t.Run("default user", func(t *testing.T) {
s, c := runWithClient(t)

payl := proto.Map(
proto.String("server"), proto.String("miniredis"),
proto.String("version"), proto.String("6.0.5"),
proto.String("version"), proto.String("8.4.0"),
proto.String("proto"), proto.Int(3),
proto.String("id"), proto.Int(42),
proto.String("mode"), proto.String("standalone"),
proto.String("role"), proto.String("master"),
proto.String("modules"), proto.Array(),
proto.String("modules"), proto.Array(
proto.Map(
proto.String("name"), proto.String("vectorset"),
proto.String("ver"), proto.Int(1),
proto.String("path"), proto.String(""),
proto.String("args"), proto.Array(),
),
),
)

mustDo(t, c,
Expand Down
1 change: 1 addition & 0 deletions cmd_scripting.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ func (m *Miniredis) runLuaScript(c *server.Peer, sha, script string, readOnly bo
l.Push(mod)
return 1
}))
l.RegisterModule("os", mkLuaOS())

_ = doScript(l, protectGlobals)

Expand Down
67 changes: 36 additions & 31 deletions cmd_scripting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,40 +169,45 @@ func TestScript(t *testing.T) {
"SCRIPT", "FOO",
proto.Error("ERR unknown subcommand 'FOO'. Try SCRIPT HELP."),
)
}

func TestCJSON(t *testing.T) {
_, c := runWithClient(t)
t.Run("CJSON", func(t *testing.T) {
mustDo(t, c,
"EVAL", `return cjson.decode('{"id":"foo"}')['id']`, "0",
proto.String("foo"),
)
mustDo(t, c,
"EVAL", `return cjson.encode({foo=42})`, "0",
proto.String(`{"foo":42}`),
)

mustDo(t, c,
"EVAL", `return cjson.decode('{"id":"foo"}')['id']`, "0",
proto.String("foo"),
)
mustDo(t, c,
"EVAL", `return cjson.encode({foo=42})`, "0",
proto.String(`{"foo":42}`),
)
mustContain(t, c,
"EVAL", `redis.encode()`, "0",
"Error compiling script",
)
mustContain(t, c,
"EVAL", `redis.encode("1", "2")`, "0",
"Error compiling script",
)
mustContain(t, c,
"EVAL", `redis.decode()`, "0",
"Error compiling script",
)
mustContain(t, c,
"EVAL", `redis.decode("{")`, "0",
"Error compiling script",
)
mustContain(t, c,
"EVAL", `redis.decode("1", "2")`, "0",
"Error compiling script",
)
})

mustContain(t, c,
"EVAL", `redis.encode()`, "0",
"Error compiling script",
)
mustContain(t, c,
"EVAL", `redis.encode("1", "2")`, "0",
"Error compiling script",
)
mustContain(t, c,
"EVAL", `redis.decode()`, "0",
"Error compiling script",
)
mustContain(t, c,
"EVAL", `redis.decode("{")`, "0",
"Error compiling script",
)
mustContain(t, c,
"EVAL", `redis.decode("1", "2")`, "0",
"Error compiling script",
)
t.Run("os.", func(t *testing.T) {
mustDo(t, c,
"EVAL", `return os.clock()`, "0",
proto.Int(42),
)
})
}

func TestLog(t *testing.T) {
Expand Down
12 changes: 0 additions & 12 deletions cmd_stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,12 +753,6 @@ parsing:
c,
opts.blockTimeout,
func(c *server.Peer, ctx *connCtx) bool {
if ctx.nested {
setDirty(c)
c.WriteError("ERR XREADGROUP command is not allowed with BLOCK option from scripts")
return false
}

db := m.db(ctx.selectedDB)
res, err := xreadgroup(
db,
Expand Down Expand Up @@ -969,12 +963,6 @@ parsing:
c,
opts.blockTimeout,
func(c *server.Peer, ctx *connCtx) bool {
if ctx.nested {
setDirty(c)
c.WriteError("ERR XREAD command is not allowed with BLOCK option from scripts")
return false
}

db := m.db(ctx.selectedDB)
res := xread(db, opts.streams, opts.ids, opts.count)
if len(res) == 0 {
Expand Down
4 changes: 4 additions & 0 deletions cmd_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,10 @@ func (m *Miniredis) cmdBitcount(c *server.Peer, cmd string, args []string) {
}
args = args[2:]
}
if len(args) != 0 {
c.WriteError(msgSyntaxError)
return
}

withTx(m, c, func(c *server.Peer, ctx *connCtx) {
db := m.db(ctx.selectedDB)
Expand Down
2 changes: 1 addition & 1 deletion integration/get_redis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -eu

VERSION=7.2.4
VERSION=8.4.0

cd "$(dirname "$0")"
rm -rf ./redis_src/
Expand Down
15 changes: 3 additions & 12 deletions integration/script_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,6 @@ func TestScript(t *testing.T) {
})
})

t.Run("blocking", func(t *testing.T) {
testRaw(t, func(c *client) {
c.Do("XADD", "pl", "0-1", "name", "Mercury")
c.Do("EVAL", `redis.call("XINFO", "STREAM", "pl")`, "0")
c.Do("EVAL", `redis.call("XREAD", "STREAMS", "pl", "$")`, "0")
c.Error("not allowed with BLOCK option", "EVAL", `redis.call("XREAD", "BLOCK", "10", "STREAMS", "pl", "$")`, "0")
c.Error("not allowed with BLOCK option", "EVAL", `redis.call("XREADGROUP", "GROUP", "group", "consumer", "BLOCK", 1000, "STREAMS", "pl", ">")`, "0")
})
})

t.Run("setresp", func(t *testing.T) {
testRaw(t, func(c *client) {
c.Do("EVAL", `redis.setresp(3); redis.call("SET", "foo", 12); return redis.call("GET", "foo")`, "0")
Expand Down Expand Up @@ -203,8 +193,9 @@ func TestLua(t *testing.T) {
testRaw(t, func(c *client) {
// c.Do("EVAL", "print(1)", "0")
c.Do("EVAL", `return string.format('%q', "pretty string")`, "0")
c.Error("Script attempted to access nonexistent global variable", "EVAL", "os.clock()", "0")
c.Error("Script attempted to access nonexistent global variable", "EVAL", "os.exit(42)", "0")
c.Error("Script attempted to access nonexistent global variable", "EVAL", "foob.clock()", "0")
c.DoLoosely("EVAL", "os.clock()", "0")
c.Error("attempt to call", "EVAL", "os.exit(42)", "0")
c.Do("EVAL", "return table.concat({1,2,3})", "0")
c.Do("EVAL", "return math.abs(-42)", "0")
c.Error("Script attempted to access nonexistent global variable", "EVAL", `return utf8.len("hello world")`, "0")
Expand Down
2 changes: 1 addition & 1 deletion integration/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ func TestBitcount(t *testing.T) {
c.Error("out of range", "BITCOUNT", "A", "0", "9223372036854775808")

c.Error("wrong number", "BITCOUNT")
c.Do("BITCOUNT", "wrong", "arguments")
c.Error("syntax error", "BITCOUNT", "wrong", "arguments")
c.Error("syntax error", "BITCOUNT", "str", "4", "2", "2", "2", "2")
c.Error("not an integer", "BITCOUNT", "str", "foo", "2")
c.Do("HSET", "aap", "noot", "mies")
Expand Down
11 changes: 11 additions & 0 deletions lua.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,14 @@ func luaStatusReply(msg string) *lua.LTable {
tab.RawSetString("ok", lua.LString(msg))
return tab
}

// Our very minimal "os." lua lib.
func mkLuaOS() map[string]lua.LGFunction {
return map[string]lua.LGFunction{
// > Returns an approximation of the amount in seconds of CPU time used by the program
"clock": func(l *lua.LState) int {
l.Push(lua.LNumber(42))
return 1
},
}
}
Loading