| 1 | start_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 | |
| 195 | start_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 | } |