From c2ff0e90b8ce84d7b966622ffe0178303bb0a625 Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Wed, 16 Jun 2010 11:03:23 +0200 Subject: [PATCH] more pub/sub tests --- tests/support/test.tcl | 7 ++ tests/unit/pubsub.tcl | 202 +++++++++++++++++++++++++++++++++++------ 2 files changed, 183 insertions(+), 26 deletions(-) diff --git a/tests/support/test.tcl b/tests/support/test.tcl index 8849c9d6a..2c1fc164f 100644 --- a/tests/support/test.tcl +++ b/tests/support/test.tcl @@ -2,6 +2,13 @@ set ::passed 0 set ::failed 0 set ::testnum 0 +proc assert {condition} { + if {![uplevel 1 expr $condition]} { + puts "!! ERROR\nExpected '$value' to evaluate to true" + error "assertion" + } +} + proc assert_match {pattern value} { if {![string match $pattern $value]} { puts "!! ERROR\nExpected '$value' to match '$pattern'" diff --git a/tests/unit/pubsub.tcl b/tests/unit/pubsub.tcl index 10af85856..c8b547b4f 100644 --- a/tests/unit/pubsub.tcl +++ b/tests/unit/pubsub.tcl @@ -1,45 +1,195 @@ start_server {tags {"pubsub"}} { - test "PUBLISH when no one is listening" { - assert_equal 0 [r publish chan hello] + proc __consume_subscribe_messages {client type channels} { + set numsub -1 + set counts {} + + for {set i [llength $channels]} {$i > 0} {incr i -1} { + set msg [$client read] + assert_equal $type [lindex $msg 0] + + # when receiving subscribe messages the channels names + # are ordered. when receiving unsubscribe messages + # they are unordered + set idx [lsearch -exact $channels [lindex $msg 1]] + if {[string match "*unsubscribe" $type]} { + assert {$idx >= 0} + } else { + assert {$idx == 0} + } + set channels [lreplace $channels $idx $idx] + + # aggregate the subscription count to return to the caller + lappend counts [lindex $msg 2] + } + + # we should have received messages for channels + assert {[llength $channels] == 0} + return $counts } - test "SUBSCRIBE basics" { + proc subscribe {client channels} { + $client subscribe {*}$channels + __consume_subscribe_messages $client subscribe $channels + } + + proc unsubscribe {client {channels {}}} { + $client unsubscribe {*}$channels + __consume_subscribe_messages $client unsubscribe $channels + } + + proc psubscribe {client channels} { + $client psubscribe {*}$channels + __consume_subscribe_messages $client psubscribe $channels + } + + proc punsubscribe {client {channels {}}} { + $client punsubscribe {*}$channels + __consume_subscribe_messages $client punsubscribe $channels + } + + test "PUBLISH/SUBSCRIBE basics" { set rd1 [redis_deferring_client] - set rd2 [redis_deferring_client] - # subscribe first client to two channels - $rd1 subscribe chan1 chan2 - assert_equal {subscribe chan1 1} [$rd1 read] - assert_equal {subscribe chan2 2} [$rd1 read] - - # publish on both channels + # subscribe to two channels + assert_equal {1 2} [subscribe $rd1 {chan1 chan2}] assert_equal 1 [r publish chan1 hello] assert_equal 1 [r publish chan2 world] assert_equal {message chan1 hello} [$rd1 read] assert_equal {message chan2 world} [$rd1 read] - # subscribe second client to one channel - $rd2 subscribe chan1 - assert_equal {subscribe chan1 1} [$rd2 read] + # unsubscribe from one of the channels + unsubscribe $rd1 {chan1} + assert_equal 0 [r publish chan1 hello] + assert_equal 1 [r publish chan2 world] + assert_equal {message chan2 world} [$rd1 read] - # publish on channel with two subscribers + # unsubscribe from the remaining channel + unsubscribe $rd1 {chan2} + assert_equal 0 [r publish chan1 hello] + assert_equal 0 [r publish chan2 world] + + # clean up clients + $rd1 close + } + + test "PUBLISH/SUBSCRIBE with two clients" { + set rd1 [redis_deferring_client] + set rd2 [redis_deferring_client] + + assert_equal {1} [subscribe $rd1 {chan1}] + assert_equal {1} [subscribe $rd2 {chan1}] assert_equal 2 [r publish chan1 hello] assert_equal {message chan1 hello} [$rd1 read] assert_equal {message chan1 hello} [$rd2 read] - # unsubscribe first client from all channels - $rd1 unsubscribe - set msg [$rd1 read] - assert_equal "unsubscribe" [lindex $msg 0] - assert_match "chan*" [lindex $msg 1] - assert_match 1 [lindex $msg 2] - set msg [$rd1 read] - assert_equal "unsubscribe" [lindex $msg 0] - assert_match "chan*" [lindex $msg 1] - assert_match 0 [lindex $msg 2] + # clean up clients + $rd1 close + $rd2 close + } - # publish on channel with only remaining subscriber + test "PUBLISH/SUBSCRIBE after UNSUBSCRIBE without arguments" { + set rd1 [redis_deferring_client] + assert_equal {1 2 3} [subscribe $rd1 {chan1 chan2 chan3}] + unsubscribe $rd1 + assert_equal 0 [r publish chan1 hello] + assert_equal 0 [r publish chan2 hello] + assert_equal 0 [r publish chan3 hello] + + # clean up clients + $rd1 close + } + + test "SUBSCRIBE to one channel more than once" { + set rd1 [redis_deferring_client] + assert_equal {1 1 1} [subscribe $rd1 {chan1 chan1 chan1}] assert_equal 1 [r publish chan1 hello] - assert_equal {message chan1 hello} [$rd2 read] + assert_equal {message chan1 hello} [$rd1 read] + + # clean up clients + $rd1 close + } + + test "UNSUBSCRIBE from non-subscribed channels" { + set rd1 [redis_deferring_client] + assert_equal {0 0 0} [unsubscribe $rd1 {foo bar quux}] + + # clean up clients + $rd1 close + } + + test "PUBLISH/PSUBSCRIBE basics" { + set rd1 [redis_deferring_client] + + # subscribe to two patterns + assert_equal {1 2} [psubscribe $rd1 {foo.* bar.*}] + assert_equal 1 [r publish foo.1 hello] + assert_equal 1 [r publish bar.1 hello] + assert_equal 0 [r publish foo1 hello] + assert_equal 0 [r publish barfoo.1 hello] + assert_equal 0 [r publish qux.1 hello] + assert_equal {pmessage foo.* foo.1 hello} [$rd1 read] + assert_equal {pmessage bar.* bar.1 hello} [$rd1 read] + + # unsubscribe from one of the patterns + assert_equal {1} [punsubscribe $rd1 {foo.*}] + assert_equal 0 [r publish foo.1 hello] + assert_equal 1 [r publish bar.1 hello] + assert_equal {pmessage bar.* bar.1 hello} [$rd1 read] + + # unsubscribe from the remaining pattern + assert_equal {0} [punsubscribe $rd1 {bar.*}] + assert_equal 0 [r publish foo.1 hello] + assert_equal 0 [r publish bar.1 hello] + + # clean up clients + $rd1 close + } + + test "PUBLISH/PSUBSCRIBE with two clients" { + set rd1 [redis_deferring_client] + set rd2 [redis_deferring_client] + + assert_equal {1} [psubscribe $rd1 {chan.*}] + assert_equal {1} [psubscribe $rd2 {chan.*}] + assert_equal 2 [r publish chan.foo hello] + assert_equal {pmessage chan.* chan.foo hello} [$rd1 read] + assert_equal {pmessage chan.* chan.foo hello} [$rd2 read] + + # clean up clients + $rd1 close + $rd2 close + } + + test "PUBLISH/PSUBSCRIBE after PUNSUBSCRIBE without arguments" { + set rd1 [redis_deferring_client] + assert_equal {1 2 3} [psubscribe $rd1 {chan1.* chan2.* chan3.*}] + punsubscribe $rd1 + assert_equal 0 [r publish chan1.hi hello] + assert_equal 0 [r publish chan2.hi hello] + assert_equal 0 [r publish chan3.hi hello] + + # clean up clients + $rd1 close + } + + test "PUNSUBSCRIBE from non-subscribed channels" { + set rd1 [redis_deferring_client] + assert_equal {0 0 0} [punsubscribe $rd1 {foo.* bar.* quux.*}] + + # clean up clients + $rd1 close + } + + test "Mix SUBSCRIBE and PSUBSCRIBE" { + set rd1 [redis_deferring_client] + assert_equal {1} [subscribe $rd1 {foo.bar}] + assert_equal {2} [psubscribe $rd1 {foo.*}] + + assert_equal 2 [r publish foo.bar hello] + assert_equal {message foo.bar hello} [$rd1 read] + assert_equal {pmessage foo.* foo.bar hello} [$rd1 read] + + # clean up clients + $rd1 close } } \ No newline at end of file