1 start_server
{tags
{"scripting"}} {
2 test
{EVAL
- Does Lua interpreter replies to our requests?
} {
3 r
eval {return 'hello'
} 0
6 test
{EVAL
- Lua integer
-> Redis protocol type conversion
} {
7 r
eval {return 100.5} 0
10 test
{EVAL
- Lua
string -> Redis protocol type conversion
} {
11 r
eval {return 'hello world'
} 0
14 test
{EVAL
- Lua true boolean
-> Redis protocol type conversion
} {
15 r
eval {return true
} 0
18 test
{EVAL
- Lua false boolean
-> Redis protocol type conversion
} {
19 r
eval {return false
} 0
22 test
{EVAL
- Lua status code reply
-> Redis protocol type conversion
} {
23 r
eval {return {ok
='fine'
}} 0
26 test
{EVAL
- Lua
error reply
-> Redis protocol type conversion
} {
28 r
eval {return {err
='this is an
error'
}} 0
33 test
{EVAL
- Lua table
-> Redis protocol type conversion
} {
34 r
eval {return {1,2,3,'ciao'
,{1,2}}} 0
37 test
{EVAL
- Are the KEYS and ARGS arrays populated correctly?
} {
38 r
eval {return {KEYS
[1],KEYS
[2],ARGV
[1],ARGV
[2]}} 2 a b c d
41 test
{EVAL
- is Lua able to call Redis API?
} {
43 r
eval {return redis.call
('get'
,'mykey'
)} 0
46 test
{EVALSHA
- Can we call a SHA1
if already defined?
} {
47 r evalsha
9bd632c7d33e571e9f24556ebed26c3479a87129
0
50 test
{EVALSHA
- Do we get an
error on invalid SHA1?
} {
51 catch {r evalsha NotValidShaSUM
0} e
55 test
{EVALSHA
- Do we get an
error on non defined SHA1?
} {
56 catch {r evalsha ffd632c7d33e571e9f24556ebed26c3479a87130
0} e
60 test
{EVAL
- Redis integer
-> Lua type conversion
} {
62 local foo
= redis.pcall
('
incr'
,'x'
)
63 return {type
(foo
),foo
}
67 test
{EVAL
- Redis bulk
-> Lua type conversion
} {
70 local foo
= redis.pcall
('get'
,'mykey'
)
71 return {type
(foo
),foo
}
75 test
{EVAL
- Redis multi bulk
-> Lua type conversion
} {
81 local foo
= redis.pcall
('
lrange'
,'mylist'
,0,-1)
82 return {type
(foo
),foo
[1],foo
[2],foo
[3],# foo}
86 test
{EVAL
- Redis status reply
-> Lua type conversion
} {
88 local foo
= redis.pcall
('
set'
,'mykey'
,'myval'
)
89 return {type
(foo
),foo
['ok'
]}
93 test
{EVAL
- Redis
error reply
-> Lua type conversion
} {
96 local foo
= redis.pcall
('
incr'
,'mykey'
)
97 return {type
(foo
),foo
['err'
]}
99 } {table
{ERR value is not an integer or out of range
}}
101 test
{EVAL
- Redis nil bulk reply
-> Lua type conversion
} {
104 local foo
= redis.pcall
('get'
,'mykey'
)
105 return {type
(foo
),foo
== false
}
109 test
{EVAL
- Is Lua affecting the currently selected DB?
} {
110 r
set mykey
"this is DB 9"
112 r
set mykey
"this is DB 10"
113 r
eval {return redis.pcall
('get'
,'mykey'
)} 0
116 test
{EVAL
- Is Lua seleced DB retained?
} {
117 r
eval {return redis.pcall
('select'
,'
9'
)} 0
122 test
{EVAL
- Script can't run more than configured
time limit
} {
123 r config
set lua-time-limit
1
127 while true do i
=i
+1 end
134 test
{EVAL
- Scripts can't run certain commands
} {
136 catch {r
eval {return redis.pcall
('spop'
,'x'
)} 0} e
140 test
{EVAL
- Scripts can't run certain commands
} {
143 r
eval "redis.pcall('randomkey'); return redis.pcall('set','x','ciao')" 0
146 } {*not allowed
after*}
148 test
{EVAL
- redis.call variant raises a Lua
error on Redis cmd
error (1)} {
151 r
eval "redis.call('nosuchcommand')" 0
156 test
{EVAL
- redis.call variant raises a Lua
error on Redis cmd
error (1)} {
159 r
eval "redis.call('get','a','b','c')" 0
164 test
{EVAL
- redis.call variant raises a Lua
error on Redis cmd
error (1)} {
168 r
eval "redis.call('lpush','foo','val')" 0
173 test
{SCRIPTING FLUSH
- is able to clear the scripts cache?
} {
175 set v
[r evalsha
9bd632c7d33e571e9f24556ebed26c3479a87129
0]
176 assert_equal
$v myval
179 catch {r evalsha
9bd632c7d33e571e9f24556ebed26c3479a87129
0} e
183 test
{SCRIPT EXISTS
- can detect already defined scripts?
} {
184 r
eval "return 1+1" 0
185 r script exists a27e7e8a43702b7046d4f6a7ccf5b60cef6b9bd9 a27e7e8a43702b7046d4f6a7ccf5b60cef6b9bda
188 test
{SCRIPT LOAD
- is able to register scripts in the scripting cache
} {
190 [r script
load "return 'loaded'"] \
191 [r evalsha b534286061d4b9e4026607613b95c06c06015ae8
0]
192 } {b534286061d4b9e4026607613b95c06c06015ae8 loaded
}
194 test
"In the context of Lua the output of random commands gets ordered" {
196 r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz
197 r
eval {return redis.call
('smembers'
,'myset'
)} 0
198 } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z
}
200 test
"SORT is normally not re-ordered by the scripting engine" {
202 r sadd myset
1 2 3 4 10
203 r
eval {return redis.call
('sort'
,'myset'
,'desc'
)} 0
206 test
"SORT BY <constant> output gets ordered by scripting" {
208 r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz
209 r
eval {return redis.call
('sort'
,'myset'
,'by'
,'_'
)} 0
210 } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z
}
212 test
"SORT output containing NULLs is well handled by scripting" {
215 r
eval {return redis.call
('sort'
,'myset'
,'by'
,'_'
,'get'
,'
#','get','_:*')} 0
218 test
"redis.sha1hex() implementation" {
219 list [r
eval {return redis.sha1hex
(''
)} 0] \
220 [r
eval {return redis.sha1hex
('Pizza
& Mandolino'
)} 0]
221 } {da39a3ee5e6b4b0d3255bfef95601890afd80709
74822d82031af7493c20eefa13bd07ec4fada82f
}
223 test
{Globals protection reading an undeclared
global variable} {
224 catch {r
eval {return a
} 0} e
226 } {*ERR
*attempted to access unexisting
global*}
228 test
{Globals protection setting an undeclared
global*} {
229 catch {r
eval {a
=10} 0} e
231 } {*ERR
*attempted to create
global*}
233 test
{Test an example script DECR_IF_GT
} {
237 current
= redis.call
('get'
,KEYS
[1])
238 if not current then
return nil end
239 if current
> ARGV
[1] then
240 return redis.call
('decr'
,KEYS
[1])
242 return redis.call
('get'
,KEYS
[1])
247 lappend res
[r
eval $decr_if_gt 1 foo
2]
248 lappend res
[r
eval $decr_if_gt 1 foo
2]
249 lappend res
[r
eval $decr_if_gt 1 foo
2]
250 lappend res
[r
eval $decr_if_gt 1 foo
2]
251 lappend res
[r
eval $decr_if_gt 1 foo
2]
255 test
{Scripting engine resets PRNG at every script execution
} {
256 set rand1
[r
eval {return tostring
(math.random
())} 0]
257 set rand2
[r
eval {return tostring
(math.random
())} 0]
258 assert_equal
$rand1 $rand2
261 test
{Scripting engine PRNG can be seeded correctly
} {
263 math.randomseed
(ARGV
[1]); return tostring
(math.random
())
266 math.randomseed
(ARGV
[1]); return tostring
(math.random
())
269 math.randomseed
(ARGV
[1]); return tostring
(math.random
())
271 assert_equal
$rand1 $rand2
272 assert
{$rand2 ne
$rand3}
276 # Start a new server since the last test in this stanza will kill the
278 start_server
{tags
{"scripting"}} {
279 test
{Timedout read-only scripts can be killed by SCRIPT KILL
} {
280 set rd
[redis_deferring_client
]
281 r config
set lua-time-limit
10
282 $rd eval {while true do end
} 0
285 assert_match
{BUSY
*} $e
287 assert_equal
[r ping
] "PONG"
290 test
{Timedout scripts that modified data can't be killed by SCRIPT KILL
} {
291 set rd
[redis_deferring_client
]
292 r config
set lua-time-limit
10
293 $rd eval {redis.call
('
set'
,'x'
,'y'
); while true do end
} 0
296 assert_match
{BUSY
*} $e
297 catch {r script kill
} e
298 assert_match
{ERR
*} $e
300 assert_match
{BUSY
*} $e
303 test
{SHUTDOWN NOSAVE can kill a timedout script anyway
} {
304 # The server sould be still unresponding to normal commands.
306 assert_match
{BUSY
*} $e
307 catch {r shutdown nosave
}
308 # Make sure the server was killed
309 catch {set rd
[redis_deferring_client
]} e
310 assert_match
{*connection refused
*} $e
314 start_server
{tags
{"scripting repl"}} {
316 test
{Before the slave connects we issue an EVAL command
} {
317 r
eval {return redis.call
('
incr'
,'x'
)} 0
320 test
{Connect a slave to the main instance
} {
321 r
-1 slaveof
[srv
0 host
] [srv
0 port
]
326 test
{Now use EVALSHA against the master
} {
327 r evalsha ae3477e27be955de7e1bc9adfdca626b478d3cb2
0
330 test
{If EVALSHA was replicated as EVAL the slave should be ok
} {
331 wait_for_condition
50 100 {
334 fail
"Expected 2 in x, but value is '[r -1 get x]'"