xref: /redis-3.2.3/tests/unit/multi.tcl (revision 252cf305)
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