xref: /redis-3.2.3/tests/unit/scripting.tcl (revision 414c3dea)
1start_server {tags {"scripting"}} {
2    test {EVAL - Does Lua interpreter replies to our requests?} {
3        r eval {return 'hello'} 0
4    } {hello}
5
6    test {EVAL - Lua integer -> Redis protocol type conversion} {
7        r eval {return 100.5} 0
8    } {100}
9
10    test {EVAL - Lua string -> Redis protocol type conversion} {
11        r eval {return 'hello world'} 0
12    } {hello world}
13
14    test {EVAL - Lua true boolean -> Redis protocol type conversion} {
15        r eval {return true} 0
16    } {1}
17
18    test {EVAL - Lua false boolean -> Redis protocol type conversion} {
19        r eval {return false} 0
20    } {}
21
22    test {EVAL - Lua status code reply -> Redis protocol type conversion} {
23        r eval {return {ok='fine'}} 0
24    } {fine}
25
26    test {EVAL - Lua error reply -> Redis protocol type conversion} {
27        catch {
28            r eval {return {err='this is an error'}} 0
29        } e
30        set _ $e
31    } {this is an error}
32
33    test {EVAL - Lua table -> Redis protocol type conversion} {
34        r eval {return {1,2,3,'ciao',{1,2}}} 0
35    } {1 2 3 ciao {1 2}}
36
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
39    } {a b c d}
40
41    test {EVAL - is Lua able to call Redis API?} {
42        r set mykey myval
43        r eval {return redis.call('get','mykey')} 0
44    } {myval}
45
46    test {EVALSHA - Can we call a SHA1 if already defined?} {
47        r evalsha 9bd632c7d33e571e9f24556ebed26c3479a87129 0
48    } {myval}
49
50    test {EVALSHA - Do we get an error on invalid SHA1?} {
51        catch {r evalsha NotValidShaSUM 0} e
52        set _ $e
53    } {NOSCRIPT*}
54
55    test {EVALSHA - Do we get an error on non defined SHA1?} {
56        catch {r evalsha ffd632c7d33e571e9f24556ebed26c3479a87130 0} e
57        set _ $e
58    } {NOSCRIPT*}
59
60    test {EVAL - Redis integer -> Lua type conversion} {
61        r eval {
62            local foo = redis.pcall('incr','x')
63            return {type(foo),foo}
64        } 0
65    } {number 1}
66
67    test {EVAL - Redis bulk -> Lua type conversion} {
68        r set mykey myval
69        r eval {
70            local foo = redis.pcall('get','mykey')
71            return {type(foo),foo}
72        } 0
73    } {string myval}
74
75    test {EVAL - Redis multi bulk -> Lua type conversion} {
76        r del mylist
77        r rpush mylist a
78        r rpush mylist b
79        r rpush mylist c
80        r eval {
81            local foo = redis.pcall('lrange','mylist',0,-1)
82            return {type(foo),foo[1],foo[2],foo[3],# foo}
83        } 0
84    } {table a b c 3}
85
86    test {EVAL - Redis status reply -> Lua type conversion} {
87        r eval {
88            local foo = redis.pcall('set','mykey','myval')
89            return {type(foo),foo['ok']}
90        } 0
91    } {table OK}
92
93    test {EVAL - Redis error reply -> Lua type conversion} {
94        r set mykey myval
95        r eval {
96            local foo = redis.pcall('incr','mykey')
97            return {type(foo),foo['err']}
98        } 0
99    } {table {ERR value is not an integer or out of range}}
100
101    test {EVAL - Redis nil bulk reply -> Lua type conversion} {
102        r del mykey
103        r eval {
104            local foo = redis.pcall('get','mykey')
105            return {type(foo),foo == false}
106        } 0
107    } {boolean 1}
108
109    test {EVAL - Is Lua affecting the currently selected DB?} {
110        r set mykey "this is DB 9"
111        r select 10
112        r set mykey "this is DB 10"
113        r eval {return redis.pcall('get','mykey')} 0
114    } {this is DB 10}
115
116    test {EVAL - Is Lua seleced DB retained?} {
117        r eval {return redis.pcall('select','9')} 0
118        r get mykey
119    } {this is DB 9}
120
121    if 0 {
122        test {EVAL - Script can't run more than configured time limit} {
123            r config set lua-time-limit 1
124            catch {
125                r eval {
126                    local i = 0
127                    while true do i=i+1 end
128                } 0
129            } e
130            set _ $e
131        } {*execution time*}
132    }
133
134    test {EVAL - Scripts can't run certain commands} {
135        set e {}
136        catch {r eval {return redis.pcall('spop','x')} 0} e
137        set e
138    } {*not allowed*}
139
140    test {EVAL - Scripts can't run certain commands} {
141        set e {}
142        catch {
143            r eval "redis.pcall('randomkey'); return redis.pcall('set','x','ciao')" 0
144        } e
145        set e
146    } {*not allowed after*}
147
148    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {
149        set e {}
150        catch {
151            r eval "redis.call('nosuchcommand')" 0
152        } e
153        set e
154    } {*Unknown Redis*}
155
156    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {
157        set e {}
158        catch {
159            r eval "redis.call('get','a','b','c')" 0
160        } e
161        set e
162    } {*number of args*}
163
164    test {EVAL - redis.call variant raises a Lua error on Redis cmd error (1)} {
165        set e {}
166        r set foo bar
167        catch {
168            r eval "redis.call('lpush','foo','val')" 0
169        } e
170        set e
171    } {*against a key*}
172
173    test {SCRIPTING FLUSH - is able to clear the scripts cache?} {
174        r set mykey myval
175        set v [r evalsha 9bd632c7d33e571e9f24556ebed26c3479a87129 0]
176        assert_equal $v myval
177        set e ""
178        r script flush
179        catch {r evalsha 9bd632c7d33e571e9f24556ebed26c3479a87129 0} e
180        set e
181    } {NOSCRIPT*}
182
183    test {SCRIPT EXISTS - can detect already defined scripts?} {
184        r eval "return 1+1" 0
185        r script exists a27e7e8a43702b7046d4f6a7ccf5b60cef6b9bd9 a27e7e8a43702b7046d4f6a7ccf5b60cef6b9bda
186    } {1 0}
187
188    test {SCRIPT LOAD - is able to register scripts in the scripting cache} {
189        list \
190            [r script load "return 'loaded'"] \
191            [r evalsha b534286061d4b9e4026607613b95c06c06015ae8 0]
192    } {b534286061d4b9e4026607613b95c06c06015ae8 loaded}
193}
194
195start_server {tags {"scripting repl"}} {
196    start_server {} {
197        test {Before the slave connects we issue an EVAL command} {
198            r eval {return redis.call('incr','x')} 0
199        } {1}
200
201        test {Connect a slave to the main instance} {
202            r -1 slaveof [srv 0 host] [srv 0 port]
203            after 1000
204            s -1 role
205        } {slave}
206
207        test {Now use EVALSHA against the master} {
208            r evalsha ae3477e27be955de7e1bc9adfdca626b478d3cb2 0
209        } {2}
210
211        if {$::valgrind} {after 2000} else {after 100}
212
213        test {If EVALSHA was replicated as EVAL the slave should be ok} {
214            r -1 get x
215        } {2}
216    }
217}
218