pubsub.tcl 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. start_server {tags {"pubsub"}} {
  2. proc __consume_subscribe_messages {client type channels} {
  3. set numsub -1
  4. set counts {}
  5. for {set i [llength $channels]} {$i > 0} {incr i -1} {
  6. set msg [$client read]
  7. assert_equal $type [lindex $msg 0]
  8. # when receiving subscribe messages the channels names
  9. # are ordered. when receiving unsubscribe messages
  10. # they are unordered
  11. set idx [lsearch -exact $channels [lindex $msg 1]]
  12. if {[string match "*unsubscribe" $type]} {
  13. assert {$idx >= 0}
  14. } else {
  15. assert {$idx == 0}
  16. }
  17. set channels [lreplace $channels $idx $idx]
  18. # aggregate the subscription count to return to the caller
  19. lappend counts [lindex $msg 2]
  20. }
  21. # we should have received messages for channels
  22. assert {[llength $channels] == 0}
  23. return $counts
  24. }
  25. proc subscribe {client channels} {
  26. $client subscribe {*}$channels
  27. __consume_subscribe_messages $client subscribe $channels
  28. }
  29. proc unsubscribe {client {channels {}}} {
  30. $client unsubscribe {*}$channels
  31. __consume_subscribe_messages $client unsubscribe $channels
  32. }
  33. proc psubscribe {client channels} {
  34. $client psubscribe {*}$channels
  35. __consume_subscribe_messages $client psubscribe $channels
  36. }
  37. proc punsubscribe {client {channels {}}} {
  38. $client punsubscribe {*}$channels
  39. __consume_subscribe_messages $client punsubscribe $channels
  40. }
  41. test "PUBLISH/SUBSCRIBE basics" {
  42. set rd1 [redis_deferring_client]
  43. # subscribe to two channels
  44. assert_equal {1 2} [subscribe $rd1 {chan1 chan2}]
  45. assert_equal 1 [r publish chan1 hello]
  46. assert_equal 1 [r publish chan2 world]
  47. assert_equal {message chan1 hello} [$rd1 read]
  48. assert_equal {message chan2 world} [$rd1 read]
  49. # unsubscribe from one of the channels
  50. unsubscribe $rd1 {chan1}
  51. assert_equal 0 [r publish chan1 hello]
  52. assert_equal 1 [r publish chan2 world]
  53. assert_equal {message chan2 world} [$rd1 read]
  54. # unsubscribe from the remaining channel
  55. unsubscribe $rd1 {chan2}
  56. assert_equal 0 [r publish chan1 hello]
  57. assert_equal 0 [r publish chan2 world]
  58. # clean up clients
  59. $rd1 close
  60. }
  61. test "PUBLISH/SUBSCRIBE with two clients" {
  62. set rd1 [redis_deferring_client]
  63. set rd2 [redis_deferring_client]
  64. assert_equal {1} [subscribe $rd1 {chan1}]
  65. assert_equal {1} [subscribe $rd2 {chan1}]
  66. assert_equal 2 [r publish chan1 hello]
  67. assert_equal {message chan1 hello} [$rd1 read]
  68. assert_equal {message chan1 hello} [$rd2 read]
  69. # clean up clients
  70. $rd1 close
  71. $rd2 close
  72. }
  73. test "PUBLISH/SUBSCRIBE after UNSUBSCRIBE without arguments" {
  74. set rd1 [redis_deferring_client]
  75. assert_equal {1 2 3} [subscribe $rd1 {chan1 chan2 chan3}]
  76. unsubscribe $rd1
  77. assert_equal 0 [r publish chan1 hello]
  78. assert_equal 0 [r publish chan2 hello]
  79. assert_equal 0 [r publish chan3 hello]
  80. # clean up clients
  81. $rd1 close
  82. }
  83. test "SUBSCRIBE to one channel more than once" {
  84. set rd1 [redis_deferring_client]
  85. assert_equal {1 1 1} [subscribe $rd1 {chan1 chan1 chan1}]
  86. assert_equal 1 [r publish chan1 hello]
  87. assert_equal {message chan1 hello} [$rd1 read]
  88. # clean up clients
  89. $rd1 close
  90. }
  91. test "UNSUBSCRIBE from non-subscribed channels" {
  92. set rd1 [redis_deferring_client]
  93. assert_equal {0 0 0} [unsubscribe $rd1 {foo bar quux}]
  94. # clean up clients
  95. $rd1 close
  96. }
  97. test "PUBLISH/PSUBSCRIBE basics" {
  98. set rd1 [redis_deferring_client]
  99. # subscribe to two patterns
  100. assert_equal {1 2} [psubscribe $rd1 {foo.* bar.*}]
  101. assert_equal 1 [r publish foo.1 hello]
  102. assert_equal 1 [r publish bar.1 hello]
  103. assert_equal 0 [r publish foo1 hello]
  104. assert_equal 0 [r publish barfoo.1 hello]
  105. assert_equal 0 [r publish qux.1 hello]
  106. assert_equal {pmessage foo.* foo.1 hello} [$rd1 read]
  107. assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]
  108. # unsubscribe from one of the patterns
  109. assert_equal {1} [punsubscribe $rd1 {foo.*}]
  110. assert_equal 0 [r publish foo.1 hello]
  111. assert_equal 1 [r publish bar.1 hello]
  112. assert_equal {pmessage bar.* bar.1 hello} [$rd1 read]
  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. # clean up clients
  118. $rd1 close
  119. }
  120. test "PUBLISH/PSUBSCRIBE with two clients" {
  121. set rd1 [redis_deferring_client]
  122. set rd2 [redis_deferring_client]
  123. assert_equal {1} [psubscribe $rd1 {chan.*}]
  124. assert_equal {1} [psubscribe $rd2 {chan.*}]
  125. assert_equal 2 [r publish chan.foo hello]
  126. assert_equal {pmessage chan.* chan.foo hello} [$rd1 read]
  127. assert_equal {pmessage chan.* chan.foo hello} [$rd2 read]
  128. # clean up clients
  129. $rd1 close
  130. $rd2 close
  131. }
  132. test "PUBLISH/PSUBSCRIBE after PUNSUBSCRIBE without arguments" {
  133. set rd1 [redis_deferring_client]
  134. assert_equal {1 2 3} [psubscribe $rd1 {chan1.* chan2.* chan3.*}]
  135. punsubscribe $rd1
  136. assert_equal 0 [r publish chan1.hi hello]
  137. assert_equal 0 [r publish chan2.hi hello]
  138. assert_equal 0 [r publish chan3.hi hello]
  139. # clean up clients
  140. $rd1 close
  141. }
  142. test "PUNSUBSCRIBE from non-subscribed channels" {
  143. set rd1 [redis_deferring_client]
  144. assert_equal {0 0 0} [punsubscribe $rd1 {foo.* bar.* quux.*}]
  145. # clean up clients
  146. $rd1 close
  147. }
  148. test "Mix SUBSCRIBE and PSUBSCRIBE" {
  149. set rd1 [redis_deferring_client]
  150. assert_equal {1} [subscribe $rd1 {foo.bar}]
  151. assert_equal {2} [psubscribe $rd1 {foo.*}]
  152. assert_equal 2 [r publish foo.bar hello]
  153. assert_equal {message foo.bar hello} [$rd1 read]
  154. assert_equal {pmessage foo.* foo.bar hello} [$rd1 read]
  155. # clean up clients
  156. $rd1 close
  157. }
  158. }