1start_server {tags {"pubsub"}} { 2 proc __consume_subscribe_messages {client type channels} { 3 set numsub -1 4 set counts {} 5 6 for {set i [llength $channels]} {$i > 0} {incr i -1} { 7 set msg [$client read] 8 assert_equal $type [lindex $msg 0] 9 10 # when receiving subscribe messages the channels names 11 # are ordered. when receiving unsubscribe messages 12 # they are unordered 13 set idx [lsearch -exact $channels [lindex $msg 1]] 14 if {[string match "*unsubscribe" $type]} { 15 assert {$idx >= 0} 16 } else { 17 assert {$idx == 0} 18 } 19 set channels [lreplace $channels $idx $idx] 20 21 # aggregate the subscription count to return to the caller 22 lappend counts [lindex $msg 2] 23 } 24 25 # we should have received messages for channels 26 assert {[llength $channels] == 0} 27 return $counts 28 } 29 30 proc subscribe {client channels} { 31 $client subscribe {*}$channels 32 __consume_subscribe_messages $client subscribe $channels 33 } 34 35 proc unsubscribe {client {channels {}}} { 36 $client unsubscribe {*}$channels 37 __consume_subscribe_messages $client unsubscribe $channels 38 } 39 40 proc psubscribe {client channels} { 41 $client psubscribe {*}$channels 42 __consume_subscribe_messages $client psubscribe $channels 43 } 44 45 proc punsubscribe {client {channels {}}} { 46 $client punsubscribe {*}$channels 47 __consume_subscribe_messages $client punsubscribe $channels 48 } 49 50 test "PUBLISH/SUBSCRIBE basics" { 51 set rd1 [redis_deferring_client] 52 53 # subscribe to two channels 54 assert_equal {1 2} [subscribe $rd1 {chan1 chan2}] 55 assert_equal 1 [r publish chan1 hello] 56 assert_equal 1 [r publish chan2 world] 57 assert_equal {message chan1 hello} [$rd1 read] 58 assert_equal {message chan2 world} [$rd1 read] 59 60 # unsubscribe from one of the channels 61 unsubscribe $rd1 {chan1} 62 assert_equal 0 [r publish chan1 hello] 63 assert_equal 1 [r publish chan2 world] 64 assert_equal {message chan2 world} [$rd1 read] 65 66 # unsubscribe from the remaining channel 67 unsubscribe $rd1 {chan2} 68 assert_equal 0 [r publish chan1 hello] 69 assert_equal 0 [r publish chan2 world] 70 71 # clean up clients 72 $rd1 close 73 } 74 75 test "PUBLISH/SUBSCRIBE with two clients" { 76 set rd1 [redis_deferring_client] 77 set rd2 [redis_deferring_client] 78 79 assert_equal {1} [subscribe $rd1 {chan1}] 80 assert_equal {1} [subscribe $rd2 {chan1}] 81 assert_equal 2 [r publish chan1 hello] 82 assert_equal {message chan1 hello} [$rd1 read] 83 assert_equal {message chan1 hello} [$rd2 read] 84 85 # clean up clients 86 $rd1 close 87 $rd2 close 88 } 89 90 test "PUBLISH/SUBSCRIBE after UNSUBSCRIBE without arguments" { 91 set rd1 [redis_deferring_client] 92 assert_equal {1 2 3} [subscribe $rd1 {chan1 chan2 chan3}] 93 unsubscribe $rd1 94 assert_equal 0 [r publish chan1 hello] 95 assert_equal 0 [r publish chan2 hello] 96 assert_equal 0 [r publish chan3 hello] 97 98 # clean up clients 99 $rd1 close 100 } 101 102 test "SUBSCRIBE to one channel more than once" { 103 set rd1 [redis_deferring_client] 104 assert_equal {1 1 1} [subscribe $rd1 {chan1 chan1 chan1}] 105 assert_equal 1 [r publish chan1 hello] 106 assert_equal {message chan1 hello} [$rd1 read] 107 108 # clean up clients 109 $rd1 close 110 } 111 112 test "UNSUBSCRIBE from non-subscribed channels" { 113 set rd1 [redis_deferring_client] 114 assert_equal {0 0 0} [unsubscribe $rd1 {foo bar quux}] 115 116 # clean up clients 117 $rd1 close 118 } 119 120 test "PUBLISH/PSUBSCRIBE basics" { 121 set rd1 [redis_deferring_client] 122 123 # subscribe to two patterns 124 assert_equal {1 2} [psubscribe $rd1 {foo.* bar.*}] 125 assert_equal 1 [r publish foo.1 hello] 126 assert_equal 1 [r publish bar.1 hello] 127 assert_equal 0 [r publish foo1 hello] 128 assert_equal 0 [r publish barfoo.1 hello] 129 assert_equal 0 [r publish qux.1 hello] 130 assert_equal {pmessage foo.* foo.1 hello} [$rd1 read] 131 assert_equal {pmessage bar.* bar.1 hello} [$rd1 read] 132 133 # unsubscribe from one of the patterns 134 assert_equal {1} [punsubscribe $rd1 {foo.*}] 135 assert_equal 0 [r publish foo.1 hello] 136 assert_equal 1 [r publish bar.1 hello] 137 assert_equal {pmessage bar.* bar.1 hello} [$rd1 read] 138 139 # unsubscribe from the remaining pattern 140 assert_equal {0} [punsubscribe $rd1 {bar.*}] 141 assert_equal 0 [r publish foo.1 hello] 142 assert_equal 0 [r publish bar.1 hello] 143 144 # clean up clients 145 $rd1 close 146 } 147 148 test "PUBLISH/PSUBSCRIBE with two clients" { 149 set rd1 [redis_deferring_client] 150 set rd2 [redis_deferring_client] 151 152 assert_equal {1} [psubscribe $rd1 {chan.*}] 153 assert_equal {1} [psubscribe $rd2 {chan.*}] 154 assert_equal 2 [r publish chan.foo hello] 155 assert_equal {pmessage chan.* chan.foo hello} [$rd1 read] 156 assert_equal {pmessage chan.* chan.foo hello} [$rd2 read] 157 158 # clean up clients 159 $rd1 close 160 $rd2 close 161 } 162 163 test "PUBLISH/PSUBSCRIBE after PUNSUBSCRIBE without arguments" { 164 set rd1 [redis_deferring_client] 165 assert_equal {1 2 3} [psubscribe $rd1 {chan1.* chan2.* chan3.*}] 166 punsubscribe $rd1 167 assert_equal 0 [r publish chan1.hi hello] 168 assert_equal 0 [r publish chan2.hi hello] 169 assert_equal 0 [r publish chan3.hi hello] 170 171 # clean up clients 172 $rd1 close 173 } 174 175 test "PUNSUBSCRIBE from non-subscribed channels" { 176 set rd1 [redis_deferring_client] 177 assert_equal {0 0 0} [punsubscribe $rd1 {foo.* bar.* quux.*}] 178 179 # clean up clients 180 $rd1 close 181 } 182 183 test "Mix SUBSCRIBE and PSUBSCRIBE" { 184 set rd1 [redis_deferring_client] 185 assert_equal {1} [subscribe $rd1 {foo.bar}] 186 assert_equal {2} [psubscribe $rd1 {foo.*}] 187 188 assert_equal 2 [r publish foo.bar hello] 189 assert_equal {message foo.bar hello} [$rd1 read] 190 assert_equal {pmessage foo.* foo.bar hello} [$rd1 read] 191 192 # clean up clients 193 $rd1 close 194 } 195 196 test "PUNSUBSCRIBE and UNSUBSCRIBE should always reply." { 197 # Make sure we are not subscribed to any channel at all. 198 r punsubscribe 199 r unsubscribe 200 # Now check if the commands still reply correctly. 201 set reply1 [r punsubscribe] 202 set reply2 [r unsubscribe] 203 concat $reply1 $reply2 204 } {punsubscribe {} 0 unsubscribe {} 0} 205} 206