1start_server {tags {"pubsub network"}} {
2    if {$::singledb} {
3        set db 0
4    } else {
5        set db 9
6    }
7
8    test "Pub/Sub PING" {
9        set rd1 [redis_deferring_client]
10        subscribe $rd1 somechannel
11        # While subscribed to non-zero channels PING works in Pub/Sub mode.
12        $rd1 ping
13        $rd1 ping "foo"
14        set reply1 [$rd1 read]
15        set reply2 [$rd1 read]
16        unsubscribe $rd1 somechannel
17        # Now we are unsubscribed, PING should just return PONG.
18        $rd1 ping
19        set reply3 [$rd1 read]
20        $rd1 close
21        list $reply1 $reply2 $reply3
22    } {{pong {}} {pong foo} PONG}
23
24    test "PUBLISH/SUBSCRIBE basics" {
25        set rd1 [redis_deferring_client]
26
27        # subscribe to two channels
28        assert_equal {1 2} [subscribe $rd1 {chan1 chan2}]
29        assert_equal 1 [r publish chan1 hello]
30        assert_equal 1 [r publish chan2 world]
31        assert_equal {message chan1 hello} [$rd1 read]
32        assert_equal {message chan2 world} [$rd1 read]
33
34        # unsubscribe from one of the channels
35        unsubscribe $rd1 {chan1}
36        assert_equal 0 [r publish chan1 hello]
37        assert_equal 1 [r publish chan2 world]
38        assert_equal {message chan2 world} [$rd1 read]
39
40        # unsubscribe from the remaining channel
41        unsubscribe $rd1 {chan2}
42        assert_equal 0 [r publish chan1 hello]
43        assert_equal 0 [r publish chan2 world]
44
45        # clean up clients
46        $rd1 close
47    }
48
49    test "PUBLISH/SUBSCRIBE with two clients" {
50        set rd1 [redis_deferring_client]
51        set rd2 [redis_deferring_client]
52
53        assert_equal {1} [subscribe $rd1 {chan1}]
54        assert_equal {1} [subscribe $rd2 {chan1}]
55        assert_equal 2 [r publish chan1 hello]
56        assert_equal {message chan1 hello} [$rd1 read]
57        assert_equal {message chan1 hello} [$rd2 read]
58
59        # clean up clients
60        $rd1 close
61        $rd2 close
62    }
63
64    test "PUBLISH/SUBSCRIBE after UNSUBSCRIBE without arguments" {
65        set rd1 [redis_deferring_client]
66        assert_equal {1 2 3} [subscribe $rd1 {chan1 chan2 chan3}]
67        unsubscribe $rd1
68        assert_equal 0 [r publish chan1 hello]
69        assert_equal 0 [r publish chan2 hello]
70        assert_equal 0 [r publish chan3 hello]
71
72        # clean up clients
73        $rd1 close
74    }
75
76    test "SUBSCRIBE to one channel more than once" {
77        set rd1 [redis_deferring_client]
78        assert_equal {1 1 1} [subscribe $rd1 {chan1 chan1 chan1}]
79        assert_equal 1 [r publish chan1 hello]
80        assert_equal {message chan1 hello} [$rd1 read]
81
82        # clean up clients
83        $rd1 close
84    }
85
86    test "UNSUBSCRIBE from non-subscribed channels" {
87        set rd1 [redis_deferring_client]
88        assert_equal {0 0 0} [unsubscribe $rd1 {foo bar quux}]
89
90        # clean up clients
91        $rd1 close
92    }
93
94    test "PUBLISH/PSUBSCRIBE basics" {
95        set rd1 [redis_deferring_client]
96
97        # subscribe to two patterns
98        assert_equal {1 2} [psubscribe $rd1 {foo.* bar.*}]
99        assert_equal 1 [r publish foo.1 hello]
100        assert_equal 1 [r publish bar.1 hello]
101        assert_equal 0 [r publish foo1 hello]
102        assert_equal 0 [r publish barfoo.1 hello]
103        assert_equal 0 [r publish qux.1 hello]
104        assert_equal {pmessage foo.* foo.1 hello} [$rd1 read]
105        assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]
106
107        # unsubscribe from one of the patterns
108        assert_equal {1} [punsubscribe $rd1 {foo.*}]
109        assert_equal 0 [r publish foo.1 hello]
110        assert_equal 1 [r publish bar.1 hello]
111        assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]
112
113        # unsubscribe from the remaining pattern
114        assert_equal {0} [punsubscribe $rd1 {bar.*}]
115        assert_equal 0 [r publish foo.1 hello]
116        assert_equal 0 [r publish bar.1 hello]
117
118        # clean up clients
119        $rd1 close
120    }
121
122    test "PUBLISH/PSUBSCRIBE with two clients" {
123        set rd1 [redis_deferring_client]
124        set rd2 [redis_deferring_client]
125
126        assert_equal {1} [psubscribe $rd1 {chan.*}]
127        assert_equal {1} [psubscribe $rd2 {chan.*}]
128        assert_equal 2 [r publish chan.foo hello]
129        assert_equal {pmessage chan.* chan.foo hello} [$rd1 read]
130        assert_equal {pmessage chan.* chan.foo hello} [$rd2 read]
131
132        # clean up clients
133        $rd1 close
134        $rd2 close
135    }
136
137    test "PUBLISH/PSUBSCRIBE after PUNSUBSCRIBE without arguments" {
138        set rd1 [redis_deferring_client]
139        assert_equal {1 2 3} [psubscribe $rd1 {chan1.* chan2.* chan3.*}]
140        punsubscribe $rd1
141        assert_equal 0 [r publish chan1.hi hello]
142        assert_equal 0 [r publish chan2.hi hello]
143        assert_equal 0 [r publish chan3.hi hello]
144
145        # clean up clients
146        $rd1 close
147    }
148
149    test "PUNSUBSCRIBE from non-subscribed channels" {
150        set rd1 [redis_deferring_client]
151        assert_equal {0 0 0} [punsubscribe $rd1 {foo.* bar.* quux.*}]
152
153        # clean up clients
154        $rd1 close
155    }
156
157    test "NUMSUB returns numbers, not strings (#1561)" {
158        r pubsub numsub abc def
159    } {abc 0 def 0}
160
161    test "NUMPATs returns the number of unique patterns" {
162        set rd1 [redis_deferring_client]
163        set rd2 [redis_deferring_client]
164
165        # Three unique patterns and one that overlaps
166        psubscribe $rd1 "foo*"
167        psubscribe $rd2 "foo*"
168        psubscribe $rd1 "bar*"
169        psubscribe $rd2 "baz*"
170
171        set patterns [r pubsub numpat]
172
173        # clean up clients
174        punsubscribe $rd1
175        punsubscribe $rd2
176        assert_equal 3 $patterns
177        $rd1 close
178        $rd2 close
179    }
180
181    test "Mix SUBSCRIBE and PSUBSCRIBE" {
182        set rd1 [redis_deferring_client]
183        assert_equal {1} [subscribe $rd1 {foo.bar}]
184        assert_equal {2} [psubscribe $rd1 {foo.*}]
185
186        assert_equal 2 [r publish foo.bar hello]
187        assert_equal {message foo.bar hello} [$rd1 read]
188        assert_equal {pmessage foo.* foo.bar hello} [$rd1 read]
189
190        # clean up clients
191        $rd1 close
192    }
193
194    test "PUNSUBSCRIBE and UNSUBSCRIBE should always reply" {
195        # Make sure we are not subscribed to any channel at all.
196        r punsubscribe
197        r unsubscribe
198        # Now check if the commands still reply correctly.
199        set reply1 [r punsubscribe]
200        set reply2 [r unsubscribe]
201        concat $reply1 $reply2
202    } {punsubscribe {} 0 unsubscribe {} 0}
203
204    ### Keyspace events notification tests
205
206    test "Keyspace notifications: we receive keyspace notifications" {
207        r config set notify-keyspace-events KA
208        set rd1 [redis_deferring_client]
209        assert_equal {1} [psubscribe $rd1 *]
210        r set foo bar
211        assert_equal "pmessage * __keyspace@${db}__:foo set" [$rd1 read]
212        $rd1 close
213    }
214
215    test "Keyspace notifications: we receive keyevent notifications" {
216        r config set notify-keyspace-events EA
217        set rd1 [redis_deferring_client]
218        assert_equal {1} [psubscribe $rd1 *]
219        r set foo bar
220        assert_equal "pmessage * __keyevent@${db}__:set foo" [$rd1 read]
221        $rd1 close
222    }
223
224    test "Keyspace notifications: we can receive both kind of events" {
225        r config set notify-keyspace-events KEA
226        set rd1 [redis_deferring_client]
227        assert_equal {1} [psubscribe $rd1 *]
228        r set foo bar
229        assert_equal "pmessage * __keyspace@${db}__:foo set" [$rd1 read]
230        assert_equal "pmessage * __keyevent@${db}__:set foo" [$rd1 read]
231        $rd1 close
232    }
233
234    test "Keyspace notifications: we are able to mask events" {
235        r config set notify-keyspace-events KEl
236        r del mylist
237        set rd1 [redis_deferring_client]
238        assert_equal {1} [psubscribe $rd1 *]
239        r set foo bar
240        r lpush mylist a
241        # No notification for set, because only list commands are enabled.
242        assert_equal "pmessage * __keyspace@${db}__:mylist lpush" [$rd1 read]
243        assert_equal "pmessage * __keyevent@${db}__:lpush mylist" [$rd1 read]
244        $rd1 close
245    }
246
247    test "Keyspace notifications: general events test" {
248        r config set notify-keyspace-events KEg
249        set rd1 [redis_deferring_client]
250        assert_equal {1} [psubscribe $rd1 *]
251        r set foo bar
252        r expire foo 1
253        r del foo
254        assert_equal "pmessage * __keyspace@${db}__:foo expire" [$rd1 read]
255        assert_equal "pmessage * __keyevent@${db}__:expire foo" [$rd1 read]
256        assert_equal "pmessage * __keyspace@${db}__:foo del" [$rd1 read]
257        assert_equal "pmessage * __keyevent@${db}__:del foo" [$rd1 read]
258        $rd1 close
259    }
260
261    test "Keyspace notifications: list events test" {
262        r config set notify-keyspace-events KEl
263        r del mylist
264        set rd1 [redis_deferring_client]
265        assert_equal {1} [psubscribe $rd1 *]
266        r lpush mylist a
267        r rpush mylist a
268        r rpop mylist
269        assert_equal "pmessage * __keyspace@${db}__:mylist lpush" [$rd1 read]
270        assert_equal "pmessage * __keyevent@${db}__:lpush mylist" [$rd1 read]
271        assert_equal "pmessage * __keyspace@${db}__:mylist rpush" [$rd1 read]
272        assert_equal "pmessage * __keyevent@${db}__:rpush mylist" [$rd1 read]
273        assert_equal "pmessage * __keyspace@${db}__:mylist rpop" [$rd1 read]
274        assert_equal "pmessage * __keyevent@${db}__:rpop mylist" [$rd1 read]
275        $rd1 close
276    }
277
278    test "Keyspace notifications: set events test" {
279        r config set notify-keyspace-events Ks
280        r del myset
281        set rd1 [redis_deferring_client]
282        assert_equal {1} [psubscribe $rd1 *]
283        r sadd myset a b c d
284        r srem myset x
285        r sadd myset x y z
286        r srem myset x
287        assert_equal "pmessage * __keyspace@${db}__:myset sadd" [$rd1 read]
288        assert_equal "pmessage * __keyspace@${db}__:myset sadd" [$rd1 read]
289        assert_equal "pmessage * __keyspace@${db}__:myset srem" [$rd1 read]
290        $rd1 close
291    }
292
293    test "Keyspace notifications: zset events test" {
294        r config set notify-keyspace-events Kz
295        r del myzset
296        set rd1 [redis_deferring_client]
297        assert_equal {1} [psubscribe $rd1 *]
298        r zadd myzset 1 a 2 b
299        r zrem myzset x
300        r zadd myzset 3 x 4 y 5 z
301        r zrem myzset x
302        assert_equal "pmessage * __keyspace@${db}__:myzset zadd" [$rd1 read]
303        assert_equal "pmessage * __keyspace@${db}__:myzset zadd" [$rd1 read]
304        assert_equal "pmessage * __keyspace@${db}__:myzset zrem" [$rd1 read]
305        $rd1 close
306    }
307
308    test "Keyspace notifications: hash events test" {
309        r config set notify-keyspace-events Kh
310        r del myhash
311        set rd1 [redis_deferring_client]
312        assert_equal {1} [psubscribe $rd1 *]
313        r hmset myhash yes 1 no 0
314        r hincrby myhash yes 10
315        assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
316        assert_equal "pmessage * __keyspace@${db}__:myhash hincrby" [$rd1 read]
317        $rd1 close
318    }
319
320    test "Keyspace notifications: stream events test" {
321        r config set notify-keyspace-events Kt
322        r del mystream
323        set rd1 [redis_deferring_client]
324        assert_equal {1} [psubscribe $rd1 *]
325        r xgroup create mystream mygroup $ mkstream
326        r xgroup createconsumer mystream mygroup Bob
327        set id [r xadd mystream 1 field1 A]
328        r xreadgroup group mygroup Alice STREAMS mystream >
329        r xclaim mystream mygroup Mike 0 $id force
330        # Not notify because of "Lee" not exists.
331        r xgroup delconsumer mystream mygroup Lee
332        # Not notify because of "Bob" exists.
333        r xautoclaim mystream mygroup Bob 0 $id
334        r xgroup delconsumer mystream mygroup Bob
335        assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-create" [$rd1 read]
336        assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-createconsumer" [$rd1 read]
337        assert_equal "pmessage * __keyspace@${db}__:mystream xadd" [$rd1 read]
338        assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-createconsumer" [$rd1 read]
339        assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-createconsumer" [$rd1 read]
340        assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-delconsumer" [$rd1 read]
341        $rd1 close
342    }
343
344    test "Keyspace notifications: expired events (triggered expire)" {
345        r config set notify-keyspace-events Ex
346        r del foo
347        set rd1 [redis_deferring_client]
348        assert_equal {1} [psubscribe $rd1 *]
349        r psetex foo 100 1
350        wait_for_condition 50 100 {
351            [r exists foo] == 0
352        } else {
353            fail "Key does not expire?!"
354        }
355        assert_equal "pmessage * __keyevent@${db}__:expired foo" [$rd1 read]
356        $rd1 close
357    }
358
359    test "Keyspace notifications: expired events (background expire)" {
360        r config set notify-keyspace-events Ex
361        r del foo
362        set rd1 [redis_deferring_client]
363        assert_equal {1} [psubscribe $rd1 *]
364        r psetex foo 100 1
365        assert_equal "pmessage * __keyevent@${db}__:expired foo" [$rd1 read]
366        $rd1 close
367    }
368
369    test "Keyspace notifications: evicted events" {
370        r config set notify-keyspace-events Ee
371        r config set maxmemory-policy allkeys-lru
372        r flushdb
373        set rd1 [redis_deferring_client]
374        assert_equal {1} [psubscribe $rd1 *]
375        r set foo bar
376        r config set maxmemory 1
377        assert_equal "pmessage * __keyevent@${db}__:evicted foo" [$rd1 read]
378        r config set maxmemory 0
379        $rd1 close
380        r config set maxmemory-policy noeviction
381    } {OK} {needs:config-maxmemory}
382
383    test "Keyspace notifications: test CONFIG GET/SET of event flags" {
384        r config set notify-keyspace-events gKE
385        assert_equal {gKE} [lindex [r config get notify-keyspace-events] 1]
386        r config set notify-keyspace-events {$lshzxeKE}
387        assert_equal {$lshzxeKE} [lindex [r config get notify-keyspace-events] 1]
388        r config set notify-keyspace-events KA
389        assert_equal {AK} [lindex [r config get notify-keyspace-events] 1]
390        r config set notify-keyspace-events EA
391        assert_equal {AE} [lindex [r config get notify-keyspace-events] 1]
392    }
393}
394