1start_server {tags {"multi"}} { 2 test {MUTLI / EXEC basics} { 3 r del mylist 4 r rpush mylist a 5 r rpush mylist b 6 r rpush mylist c 7 r multi 8 set v1 [r lrange mylist 0 -1] 9 set v2 [r ping] 10 set v3 [r exec] 11 list $v1 $v2 $v3 12 } {QUEUED QUEUED {{a b c} PONG}} 13 14 test {DISCARD} { 15 r del mylist 16 r rpush mylist a 17 r rpush mylist b 18 r rpush mylist c 19 r multi 20 set v1 [r del mylist] 21 set v2 [r discard] 22 set v3 [r lrange mylist 0 -1] 23 list $v1 $v2 $v3 24 } {QUEUED OK {a b c}} 25 26 test {Nested MULTI are not allowed} { 27 set err {} 28 r multi 29 catch {[r multi]} err 30 r exec 31 set _ $err 32 } {*ERR MULTI*} 33 34 test {MULTI where commands alter argc/argv} { 35 r sadd myset a 36 r multi 37 r spop myset 38 list [r exec] [r exists myset] 39 } {a 0} 40 41 test {WATCH inside MULTI is not allowed} { 42 set err {} 43 r multi 44 catch {[r watch x]} err 45 r exec 46 set _ $err 47 } {*ERR WATCH*} 48 49 test {EXEC fails if there are errors while queueing commands #1} { 50 r del foo1 foo2 51 r multi 52 r set foo1 bar1 53 catch {r non-existing-command} 54 r set foo2 bar2 55 catch {r exec} e 56 assert_match {EXECABORT*} $e 57 list [r exists foo1] [r exists foo2] 58 } {0 0} 59 60 test {EXEC fails if there are errors while queueing commands #2} { 61 set rd [redis_deferring_client] 62 r del foo1 foo2 63 r multi 64 r set foo1 bar1 65 $rd config set maxmemory 1 66 assert {[$rd read] eq {OK}} 67 catch {r lpush mylist myvalue} 68 $rd config set maxmemory 0 69 assert {[$rd read] eq {OK}} 70 r set foo2 bar2 71 catch {r exec} e 72 assert_match {EXECABORT*} $e 73 $rd close 74 list [r exists foo1] [r exists foo2] 75 } {0 0} 76 77 test {If EXEC aborts, the client MULTI state is cleared} { 78 r del foo1 foo2 79 r multi 80 r set foo1 bar1 81 catch {r non-existing-command} 82 r set foo2 bar2 83 catch {r exec} e 84 assert_match {EXECABORT*} $e 85 r ping 86 } {PONG} 87 88 test {EXEC works on WATCHed key not modified} { 89 r watch x y z 90 r watch k 91 r multi 92 r ping 93 r exec 94 } {PONG} 95 96 test {EXEC fail on WATCHed key modified (1 key of 1 watched)} { 97 r set x 30 98 r watch x 99 r set x 40 100 r multi 101 r ping 102 r exec 103 } {} 104 105 test {EXEC fail on WATCHed key modified (1 key of 5 watched)} { 106 r set x 30 107 r watch a b x k z 108 r set x 40 109 r multi 110 r ping 111 r exec 112 } {} 113 114 test {EXEC fail on WATCHed key modified by SORT with STORE even if the result is empty} { 115 r flushdb 116 r lpush foo bar 117 r watch foo 118 r sort emptylist store foo 119 r multi 120 r ping 121 r exec 122 } {} 123 124 test {After successful EXEC key is no longer watched} { 125 r set x 30 126 r watch x 127 r multi 128 r ping 129 r exec 130 r set x 40 131 r multi 132 r ping 133 r exec 134 } {PONG} 135 136 test {After failed EXEC key is no longer watched} { 137 r set x 30 138 r watch x 139 r set x 40 140 r multi 141 r ping 142 r exec 143 r set x 40 144 r multi 145 r ping 146 r exec 147 } {PONG} 148 149 test {It is possible to UNWATCH} { 150 r set x 30 151 r watch x 152 r set x 40 153 r unwatch 154 r multi 155 r ping 156 r exec 157 } {PONG} 158 159 test {UNWATCH when there is nothing watched works as expected} { 160 r unwatch 161 } {OK} 162 163 test {FLUSHALL is able to touch the watched keys} { 164 r set x 30 165 r watch x 166 r flushall 167 r multi 168 r ping 169 r exec 170 } {} 171 172 test {FLUSHALL does not touch non affected keys} { 173 r del x 174 r watch x 175 r flushall 176 r multi 177 r ping 178 r exec 179 } {PONG} 180 181 test {FLUSHDB is able to touch the watched keys} { 182 r set x 30 183 r watch x 184 r flushdb 185 r multi 186 r ping 187 r exec 188 } {} 189 190 test {FLUSHDB does not touch non affected keys} { 191 r del x 192 r watch x 193 r flushdb 194 r multi 195 r ping 196 r exec 197 } {PONG} 198 199 test {WATCH is able to remember the DB a key belongs to} { 200 r select 5 201 r set x 30 202 r watch x 203 r select 1 204 r set x 10 205 r select 5 206 r multi 207 r ping 208 set res [r exec] 209 # Restore original DB 210 r select 9 211 set res 212 } {PONG} 213 214 test {WATCH will consider touched keys target of EXPIRE} { 215 r del x 216 r set x foo 217 r watch x 218 r expire x 10 219 r multi 220 r ping 221 r exec 222 } {} 223 224 test {WATCH will not consider touched expired keys} { 225 r del x 226 r set x foo 227 r expire x 1 228 r watch x 229 after 1100 230 r multi 231 r ping 232 r exec 233 } {PONG} 234 235 test {DISCARD should clear the WATCH dirty flag on the client} { 236 r watch x 237 r set x 10 238 r multi 239 r discard 240 r multi 241 r incr x 242 r exec 243 } {11} 244 245 test {DISCARD should UNWATCH all the keys} { 246 r watch x 247 r set x 10 248 r multi 249 r discard 250 r set x 10 251 r multi 252 r incr x 253 r exec 254 } {11} 255 256 test {MULTI / EXEC is propagated correctly (single write command)} { 257 set repl [attach_to_replication_stream] 258 r multi 259 r set foo bar 260 r exec 261 assert_replication_stream $repl { 262 {select *} 263 {multi} 264 {set foo bar} 265 {exec} 266 } 267 close_replication_stream $repl 268 } 269 270 test {MULTI / EXEC is propagated correctly (empty transaction)} { 271 set repl [attach_to_replication_stream] 272 r multi 273 r exec 274 r set foo bar 275 assert_replication_stream $repl { 276 {select *} 277 {set foo bar} 278 } 279 close_replication_stream $repl 280 } 281 282 test {MULTI / EXEC is propagated correctly (read-only commands)} { 283 r set foo value1 284 set repl [attach_to_replication_stream] 285 r multi 286 r get foo 287 r exec 288 r set foo value2 289 assert_replication_stream $repl { 290 {select *} 291 {set foo value2} 292 } 293 close_replication_stream $repl 294 } 295 296 test {MULTI / EXEC is propagated correctly (write command, no effect)} { 297 r del bar foo bar 298 set repl [attach_to_replication_stream] 299 r multi 300 r del foo 301 r exec 302 assert_replication_stream $repl { 303 {select *} 304 {multi} 305 {exec} 306 } 307 close_replication_stream $repl 308 } 309} 310