Added support for Redis PubSub:
[perl-Redis.git] / t / 03-pubsub.t
1 #!perl
2
3 use strict;
4 use warnings;
5 use Test::More;
6 use Test::Deep;
7 use Test::Exception;
8 use Redis;
9
10 my %got;
11 my $pub = Redis->new();
12 my $sub = Redis->new();
13
14 is($pub->publish('aa', 'v1'), 0, "No subscribers to 'aa' topic");
15
16 ## Basic pubsub
17 my $sub_cb = sub { my ($v, $t, $s) = @_; $got{$s} = "$v:$t" };
18 $sub->subscribe('aa', 'bb', $sub_cb);
19 is($pub->publish('aa', 'v1'), 1, "Delivered to 1 subscriber of topic 'aa'");
20
21 is($sub->wait_for_messages(1), 1, '... yep, got the expected 1 message');
22 cmp_deeply(\%got, {'aa' => 'v1:aa'}, "... for the expected topic, 'aa'");
23
24 my $sub_cb2 = sub { my ($v, $t, $s) = @_; $got{"2$s"} = uc("$v:$t") };
25 $sub->subscribe('aa', $sub_cb2);
26 is($pub->publish('aa', 'v1'), 1, "Delivered to 1 subscriber of topic 'aa'");
27
28 is($sub->wait_for_messages(1), 1, '... yep, got the expected 1 message');
29 cmp_deeply(
30   \%got,
31   {'aa' => 'v1:aa', '2aa' => 'V1:AA'},
32   "... for the expected topic, 'aa', with two handlers"
33 );
34
35
36 ## Trick subscribe with other messages
37 my $psub_cb = sub { my ($v, $t, $s) = @_; $got{$s} = "$v:$t" };
38 %got = ();
39 is($pub->publish('aa', 'v2'), 1, "Delivered to 1 subscriber of topic 'aa'");
40 $sub->psubscribe('a*', 'c*', $psub_cb);
41 cmp_deeply(
42   \%got,
43   {'aa' => 'v2:aa', '2aa' => 'V2:AA'},
44   '... received message while processing psubscribe(), two handlers'
45 );
46
47 is($pub->publish('aa', 'v3'), 2, "Delivered to 2 subscriber of topic 'aa'");
48 is($sub->wait_for_messages(1), 2, '... yep, got the expected 2 messages');
49 cmp_deeply(
50   \%got,
51   {'aa' => 'v3:aa', 'a*' => 'v3:aa', '2aa' => 'V3:AA'},
52   "... for the expected subs, 'aa' and 'a*', three handlers total"
53 );
54
55 ## Test subscribe/psubscribe diffs
56 %got = ();
57 is($pub->publish('aaa', 'v4'), 1, "Delivered to 1 subscriber of topic 'aaa'");
58 is($sub->wait_for_messages(1), 1, '... yep, got the expected 1 message');
59 cmp_deeply(\%got, {'a*' => 'v4:aaa'}, "... for the expected sub, 'a*'");
60
61
62 ## Subscriber mode status
63 is($sub->is_subscriber, 4, 'Current subscriber has 4 subscriptions active');
64 is($pub->is_subscriber, 0, '... the publisher has none');
65
66
67 ## Unsubscribe
68 $sub->unsubscribe('xx', sub { });
69 is($sub->is_subscriber, 4,
70   "No match to our subscriptions, unsubscribe doesn't change active count");
71
72 $sub->unsubscribe('aa', $sub_cb);
73 is($sub->is_subscriber, 4,
74   "unsubscribe ok, active count is still 4, another handler is alive");
75
76 $sub->unsubscribe('aa', $sub_cb2);
77 is($sub->is_subscriber, 3,
78   "unsubscribe done, active count is now 3, both handlers are done");
79
80 $pub->publish('aa', 'v5');
81 %got = ();
82 is($sub->wait_for_messages(1), 1, '... yep, got the expected 1 message');
83 cmp_deeply(\%got, {'a*', 'v5:aa'}, "... for the expected key, 'a*'");
84
85 $sub->unsubscribe('a*', $psub_cb);
86 is($sub->is_subscriber, 3,
87   "unsubscribe with topic wildcard failed, active count is now 3");
88
89 $pub->publish('aa', 'v6');
90 %got = ();
91 is($sub->wait_for_messages(1), 1, '... yep, got the expected 1 message');
92 cmp_deeply(\%got, {'a*', 'v6:aa'}, "... for the expected key, 'a*'");
93
94 $sub->unsubscribe('bb', $sub_cb);
95 is($sub->is_subscriber, 2, "unsubscribe with 'bb' ok, active count is now 2");
96
97 $sub->punsubscribe('a*', $psub_cb);
98 is($sub->is_subscriber, 1,
99   "punsubscribe with 'a*' ok, active count is now 1");
100
101 is($pub->publish('aa', 'v6'), 0, "Publish to 'aa' now gives 0 deliveries");
102 %got = ();
103 is($sub->wait_for_messages(1), 0, '... yep, no messages delivered');
104 cmp_deeply(\%got, {}, '... and an empty messages recorded set');
105
106 is($sub->is_subscriber, 1, 'Still some pending subcriptions active');
107 throws_ok sub { $sub->info },
108   qr/Cannot use command 'INFO' while in SUBSCRIBE mode/,
109   '... still an error to try commands in subscribe mode';
110 $sub->punsubscribe('c*', $psub_cb);
111 is($sub->is_subscriber, 0, '... but none anymore');
112
113 lives_ok sub { $sub->info },
114   'Other commands ok after we leave subscriber_mode';
115
116
117 ## And we are done
118 done_testing();