summaryrefslogtreecommitdiff
path: root/examples/redis-unstable/tests/unit/pubsub.tcl
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-01-21 22:52:54 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-01-21 22:52:54 +0100
commitdcacc00e3750300617ba6e16eb346713f91a783a (patch)
tree38e2d4fb5ed9d119711d4295c6eda4b014af73fd /examples/redis-unstable/tests/unit/pubsub.tcl
parent58dac10aeb8f5a041c46bddbeaf4c7966a99b998 (diff)
downloadcrep-dcacc00e3750300617ba6e16eb346713f91a783a.tar.gz
Remove testing data
Diffstat (limited to 'examples/redis-unstable/tests/unit/pubsub.tcl')
-rw-r--r--examples/redis-unstable/tests/unit/pubsub.tcl1016
1 files changed, 0 insertions, 1016 deletions
diff --git a/examples/redis-unstable/tests/unit/pubsub.tcl b/examples/redis-unstable/tests/unit/pubsub.tcl
deleted file mode 100644
index 24f779f..0000000
--- a/examples/redis-unstable/tests/unit/pubsub.tcl
+++ /dev/null
@@ -1,1016 +0,0 @@
-start_server {tags {"pubsub network"}} {
- if {$::singledb} {
- set db 0
- } else {
- set db 9
- }
-
- foreach resp {2 3} {
- set rd1 [redis_deferring_client]
- if {[lsearch $::denytags "resp3"] >= 0} {
- if {$resp == 3} {continue}
- } elseif {$::force_resp3} {
- if {$resp == 2} {continue}
- }
-
- $rd1 hello $resp
- $rd1 read
-
- test "Pub/Sub PING on RESP$resp" {
- subscribe $rd1 somechannel
- # While subscribed to non-zero channels PING works in Pub/Sub mode.
- $rd1 ping
- $rd1 ping "foo"
- # In RESP3, the SUBSCRIBEd client can issue any command and get a reply, so the PINGs are standard
- # In RESP2, only a handful of commands are allowed after a client is SUBSCRIBED (PING is one of them).
- # For some reason, the reply in that case is an array with two elements: "pong" and argv[1] or an empty string
- # God knows why. Done in commit 2264b981
- if {$resp == 3} {
- assert_equal {PONG} [$rd1 read]
- assert_equal {foo} [$rd1 read]
- } else {
- assert_equal {pong {}} [$rd1 read]
- assert_equal {pong foo} [$rd1 read]
- }
- unsubscribe $rd1 somechannel
- # Now we are unsubscribed, PING should just return PONG.
- $rd1 ping
- assert_equal {PONG} [$rd1 read]
-
- }
- $rd1 close
- }
-
- test "PUBLISH/SUBSCRIBE basics" {
- set rd1 [redis_deferring_client]
-
- # 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]
-
- # 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]
-
- # 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]
-
- # clean up clients
- $rd1 close
- $rd2 close
- }
-
- test "PUBLISH/SUBSCRIBE after UNSUBSCRIBE without arguments" {
- set rd1 [redis_deferring_client]
- assert_equal {1 2 3} [subscribe $rd1 {chan1 chan2 chan3}]
- unsubscribe $rd1
- wait_for_condition 100 10 {
- [regexp {cmd=unsubscribe} [r client list]] eq 1
- } else {
- fail "unsubscribe did not arrive"
- }
- 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} [$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
- wait_for_condition 100 10 {
- [regexp {cmd=punsubscribe} [r client list]] eq 1
- } else {
- fail "punsubscribe did not arrive"
- }
- 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 "PubSub messages with CLIENT REPLY OFF" {
- set rd [redis_deferring_client]
- $rd hello 3
- $rd read ;# Discard the hello reply
-
- # Test that the subscribe/psubscribe notification is ok
- $rd client reply off
- assert_equal {1} [subscribe $rd channel]
- assert_equal {2} [psubscribe $rd ch*]
-
- # Test that the publish notification is ok
- $rd client reply off
- assert_equal 2 [r publish channel hello]
- assert_equal {message channel hello} [$rd read]
- assert_equal {pmessage ch* channel hello} [$rd read]
-
- # Test that the unsubscribe/punsubscribe notification is ok
- $rd client reply off
- assert_equal {1} [unsubscribe $rd channel]
- assert_equal {0} [punsubscribe $rd ch*]
-
- $rd close
- } {0} {resp3}
-
- 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 "NUMSUB returns numbers, not strings (#1561)" {
- r pubsub numsub abc def
- } {abc 0 def 0}
-
- test "NUMPATs returns the number of unique patterns" {
- set rd1 [redis_deferring_client]
- set rd2 [redis_deferring_client]
-
- # Three unique patterns and one that overlaps
- psubscribe $rd1 "foo*"
- psubscribe $rd2 "foo*"
- psubscribe $rd1 "bar*"
- psubscribe $rd2 "baz*"
-
- set patterns [r pubsub numpat]
-
- # clean up clients
- punsubscribe $rd1
- punsubscribe $rd2
- assert_equal 3 $patterns
- $rd1 close
- $rd2 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
- }
-
- test "PUNSUBSCRIBE and UNSUBSCRIBE should always reply" {
- # Make sure we are not subscribed to any channel at all.
- r punsubscribe
- r unsubscribe
- # Now check if the commands still reply correctly.
- set reply1 [r punsubscribe]
- set reply2 [r unsubscribe]
- concat $reply1 $reply2
- } {punsubscribe {} 0 unsubscribe {} 0}
-
- ### Keyspace events notification tests
-
- test "Keyspace notifications: we receive keyspace notifications" {
- r config set notify-keyspace-events KA
- set rd1 [redis_deferring_client]
- $rd1 CLIENT REPLY OFF ;# Make sure it works even if replies are silenced
- assert_equal {1} [psubscribe $rd1 *]
- r set foo bar
- assert_equal "pmessage * __keyspace@${db}__:foo set" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: we receive keyevent notifications" {
- r config set notify-keyspace-events EA
- r del foo
- set rd1 [redis_deferring_client]
- $rd1 CLIENT REPLY SKIP ;# Make sure it works even if replies are silenced
- assert_equal {1} [psubscribe $rd1 *]
- r set foo bar
- assert_equal "pmessage * __keyevent@${db}__:set foo" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: we can receive both kind of events" {
- r config set notify-keyspace-events KEA
- r del foo
- set rd1 [redis_deferring_client]
- $rd1 CLIENT REPLY ON ;# Just coverage
- assert_equal {OK} [$rd1 read]
- assert_equal {1} [psubscribe $rd1 *]
- r set foo bar
- assert_equal "pmessage * __keyspace@${db}__:foo set" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:set foo" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: we are able to mask events" {
- r config set notify-keyspace-events KEl
- r del mylist
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r set foo bar
- r lpush mylist a
- # No notification for set, because only list commands are enabled.
- assert_equal "pmessage * __keyspace@${db}__:mylist lpush" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:lpush mylist" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: general events test" {
- r config set notify-keyspace-events KEg
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r set foo bar
- r expire foo 1
- r del foo
- assert_equal "pmessage * __keyspace@${db}__:foo expire" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:expire foo" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:foo del" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:del foo" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: list events test" {
- r config set notify-keyspace-events KEl
- r del mylist
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r lpush mylist a
- r rpush mylist a
- r rpop mylist
- assert_equal "pmessage * __keyspace@${db}__:mylist lpush" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:lpush mylist" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:mylist rpush" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:rpush mylist" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:mylist rpop" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:rpop mylist" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: set events test" {
- r config set notify-keyspace-events Ks
- r del myset
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r sadd myset a b c d
- r srem myset x
- r sadd myset x y z
- r srem myset x
- assert_equal "pmessage * __keyspace@${db}__:myset sadd" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myset sadd" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myset srem" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: zset events test" {
- r config set notify-keyspace-events Kz
- r del myzset
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r zadd myzset 1 a 2 b
- r zrem myzset x
- r zadd myzset 3 x 4 y 5 z
- r zrem myzset x
- assert_equal "pmessage * __keyspace@${db}__:myzset zadd" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myzset zadd" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myzset zrem" [$rd1 read]
- $rd1 close
- }
-
- foreach {type max_lp_entries} {listpackex 512 hashtable 0} {
- test "Keyspace notifications: hash events test ($type)" {
- r config set hash-max-listpack-entries $max_lp_entries
- r config set notify-keyspace-events Khg
- r del myhash
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r hmset myhash yes 1 no 0 f1 1 f2 2 f3_hdel 3
- r hincrby myhash yes 10
- r hexpire myhash 999999 FIELDS 1 yes
- r hexpireat myhash [expr {[clock seconds] + 999999}] NX FIELDS 1 no
- r hpexpire myhash 999999 FIELDS 1 yes
- r hpersist myhash FIELDS 1 yes
- r hpexpire myhash 0 FIELDS 1 yes
- assert_encoding $type myhash
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hincrby" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hpersist" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
-
- # Test that we will get `hexpired` notification when
- # a hash field is removed by active expire.
- r hpexpire myhash 10 FIELDS 1 no
- after 100 ;# Wait for active expire
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
-
- # Test that when a field with TTL is deleted by commands like hdel without
- # updating the global DS, active expire will not send a notification.
- r hpexpire myhash 100 FIELDS 1 f3_hdel
- r hdel myhash f3_hdel
- after 200 ;# Wait for active expire
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
-
- # Test that we will get `hexpired` notification when
- # a hash field is removed by lazy expire.
- r debug set-active-expire 0
- r hpexpire myhash 10 FIELDS 2 f1 f2
- after 20
- r hmget myhash f1 f2 ;# Trigger lazy expire
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- # We should get only one `hexpired` notification even two fields was expired.
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- # We should get a `del` notification after all fields were expired.
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
- r debug set-active-expire 1
-
-
- # Test HSETEX, HGETEX and HGETDEL notifications
- r hsetex myhash FIELDS 3 f4 v4 f5 v5 f6 v6
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
-
- # hgetex sets ttl in past
- r hgetex myhash PX 0 FIELDS 1 f4
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
-
- # hgetex sets ttl
- r hgetex myhash EXAT [expr {[clock seconds] + 999999}] FIELDS 1 f5
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
-
- # hgetex persists field
- r hgetex myhash PERSIST FIELDS 1 f5
- assert_equal "pmessage * __keyspace@${db}__:myhash hpersist" [$rd1 read]
-
- # hgetex sets expiry for one field and lazy expiry deletes another field
- # (KSN should be 1-hexpired 2-hexpire)
- r debug set-active-expire 0
- r hsetex myhash PX 1 FIELDS 1 f5 v5
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- after 10
- r hgetex myhash EX 100 FIELDS 2 f5 f6
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
-
- # hgetex lazy expiry deletes the only field and the key
- # (KSN should be 1-hexpired 2-del)
- r hsetex myhash PX 1 FIELDS 2 f5 v5 f6 v6
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- after 10
- r hgetex myhash FIELDS 2 f5 f6
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
- r debug set-active-expire 1
-
- # hgetex sets an expired ttl for the only field and deletes the key
- # (KSN should be 1-hdel 2-del)
- r hsetex myhash EX 100 FIELDS 1 f5 v5
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- after 10
- r hgetex myhash PX 0 FIELDS 1 f5
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
-
- r hsetex myhash FIELDS 2 f5 v5 f6 v6
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
-
- # hgetdel deletes a field
- r hgetdel myhash FIELDS 1 f5
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
-
- # hsetex sets field and expiry time
- r hsetex myhash EXAT [expr {[clock seconds] + 999999}] FIELDS 1 f6 v6
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
-
- # hsetex sets field and ttl in the past
- r hsetex myhash PX 0 FIELDS 1 f6 v6
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
-
- # Test that we will get `hexpired` notification when a hash field is
- # removed by lazy expire using hgetdel command
- r debug set-active-expire 0
- r hsetex myhash PX 10 FIELDS 1 f1 v1
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
-
- # Set another field
- r hsetex myhash FIELDS 1 f2 v2
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- # Wait until field expires
- after 20
- r hgetdel myhash FIELDS 1 f1
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- # Get and delete the only field
- r hgetdel myhash FIELDS 1 f2
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
-
- # HGETDEL deletes one field and the other field is lazily expired
- # (KSN should be 1-hexpired 2-hdel)
- r hsetex myhash FIELDS 2 f1 v1 f2 v2
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- r hsetex myhash PX 1 FIELDS 1 f3 v3
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- after 10
- r hgetdel myhash FIELDS 2 f1 f3
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
-
- # HGETDEL, deletes one field and the last field lazily expires
- # (KSN should be 1-hexpired 2-hdel 3-del)
- r hsetex myhash FIELDS 1 f1 v1
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- r hsetex myhash PX 1 FIELDS 1 f2 v2
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- after 10
- r hgetdel myhash FIELDS 2 f1 f2
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
- r debug set-active-expire 1
-
- $rd1 close
- } {0} {needs:debug}
- } ;# foreach
-
- test "Keyspace notifications: stream events test" {
- r config set notify-keyspace-events Kt
- r del mystream
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r xgroup create mystream mygroup $ mkstream
- r xgroup createconsumer mystream mygroup Bob
- set id [r xadd mystream 1 field1 A]
- r xreadgroup group mygroup Alice STREAMS mystream >
- r xclaim mystream mygroup Mike 0 $id force
- # Not notify because of "Lee" not exists.
- r xgroup delconsumer mystream mygroup Lee
- # Not notify because of "Bob" exists.
- r xautoclaim mystream mygroup Bob 0 $id
- r xgroup delconsumer mystream mygroup Bob
- assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-create" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-createconsumer" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:mystream xadd" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-createconsumer" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-createconsumer" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:mystream xgroup-delconsumer" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications:FXX/FNX with HSETEX cmd" {
- r config set notify-keyspace-events Khxg
- r del myhash
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r debug set-active-expire 0
-
- # FXX on logically expired field
- r hset myhash f v
- r hset myhash f2 v
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- r hpexpire myhash 10 FIELDS 1 f
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- after 15
- assert_equal [r HSETEX myhash FXX PX 10 FIELDS 1 f v] 0
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- r hdel myhash f2
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
- assert_equal 0 [r exists myhash]
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
-
- # FXX with past expiry
- r HSET myhash f1 v1
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- set past [expr {[clock seconds] - 2}]
- assert_equal [r hsetex myhash FXX EXAT $past FIELDS 1 f1 v1] 1
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
-
- # FXX overwrite + full key expiry
- r hset myhash f v
- r hset myhash f2 v
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- r hpexpire myhash 10 FIELDS 1 f
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- after 15
- set past [expr {[clock milliseconds] - 5000}]
- assert_equal [r hsetex myhash FXX PXAT $past FIELDS 1 f v] 0
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- r hpexpire myhash 10 FIELDS 1 f2
- after 15
- r hget myhash f2
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
-
- # FNX on logically expired field
- r del myhash
- r hset myhash f v
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- r hpexpire myhash 10 FIELDS 1 f
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
- after 15
- assert_equal [r HSETEX myhash FNX PX 1000 FIELDS 1 f v] 1
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpired" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hexpire" [$rd1 read]
-
- # FNX with past expiry
- r del myhash
- r hset myhash f v
- assert_equal "pmessage * __keyspace@${db}__:myhash del" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- set past [expr {[clock seconds] - 2}]
- assert_equal [r hsetex myhash FNX EXAT $past FIELDS 1 f1 v1] 1
- # f1 is created and immediately expired
- assert_equal "pmessage * __keyspace@${db}__:myhash hset" [$rd1 read]
- assert_equal "pmessage * __keyspace@${db}__:myhash hdel" [$rd1 read]
-
- r debug set-active-expire 1
- $rd1 close
- } {0} {needs:debug}
-
- test "Keyspace notifications: expired events (triggered expire)" {
- r config set notify-keyspace-events Ex
- r del foo
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r psetex foo 100 1
- wait_for_condition 50 100 {
- [r exists foo] == 0
- } else {
- fail "Key does not expire?!"
- }
- assert_equal "pmessage * __keyevent@${db}__:expired foo" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: expired events (background expire)" {
- r config set notify-keyspace-events Ex
- r del foo
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r psetex foo 100 1
- assert_equal "pmessage * __keyevent@${db}__:expired foo" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: evicted events" {
- r config set notify-keyspace-events Ee
- r config set maxmemory-policy allkeys-lru
- r flushdb
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r set foo bar
- r config set maxmemory 1
- assert_equal "pmessage * __keyevent@${db}__:evicted foo" [$rd1 read]
- r config set maxmemory 0
- $rd1 close
- r config set maxmemory-policy noeviction
- } {OK} {needs:config-maxmemory}
-
- test "Keyspace notifications: test CONFIG GET/SET of event flags" {
- r config set notify-keyspace-events gKE
- assert_equal {gKE} [lindex [r config get notify-keyspace-events] 1]
- r config set notify-keyspace-events {$lshzxeKE}
- assert_equal {$lshzxeKE} [lindex [r config get notify-keyspace-events] 1]
- r config set notify-keyspace-events KA
- assert_equal {AK} [lindex [r config get notify-keyspace-events] 1]
- r config set notify-keyspace-events EA
- assert_equal {AE} [lindex [r config get notify-keyspace-events] 1]
- }
-
- test "Keyspace notifications: new key test" {
- r config set notify-keyspace-events En
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
- r set foo bar
- # second set of foo should not cause a 'new' event
- r set foo baz
- r set bar bar
- assert_equal "pmessage * __keyevent@${db}__:new foo" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:new bar" [$rd1 read]
- $rd1 close
- }
-
- ### overwritten and type_changed events
-
- test "Keyspace notifications: overwritten events - string to string" {
- r config set notify-keyspace-events Eo
- r del foo
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
-
- # First set - should not trigger overwritten (new key)
- r set foo bar
-
- # Second set - should trigger overwritten (same type)
- r set foo baz
-
- assert_equal "pmessage * __keyevent@${db}__:overwritten foo" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: type_changed events - hash to string" {
- r config set notify-keyspace-events Ec
- r del testkey
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
-
- # Set as hash first
- r hset testkey field "hash_value"
-
- # Change to string - should trigger type_changed
- r set testkey "string_value"
-
- assert_equal "pmessage * __keyevent@${db}__:type_changed testkey" [$rd1 read]
- $rd1 close
- }
-
- test "Keyspace notifications: both overwritten and type_changed events" {
- r config set notify-keyspace-events Eoc
- r del testkey3
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
-
- # Set as hash first
- r hset testkey3 field "hash_value"
-
- # Change to string - should trigger both overwritten and type_changed
- r set testkey3 "string_value"
-
- assert_equal "pmessage * __keyevent@${db}__:overwritten testkey3" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed testkey3" [$rd1 read]
-
- $rd1 close
- }
-
- test "Keyspace notifications: configuration flags work correctly" {
- # Test that 'o' flag enables override notifications
- r config set notify-keyspace-events o
- set config [r config get notify-keyspace-events]
- assert {[lindex $config 1] eq "o"}
-
- # Test that 'c' flag enables type_changed notifications
- r config set notify-keyspace-events c
- set config [r config get notify-keyspace-events]
- assert {[lindex $config 1] eq "c"}
-
- # Test that both flags can be combined
- r config set notify-keyspace-events oc
- set config [r config get notify-keyspace-events]
- assert {[lindex $config 1] eq "oc"}
- }
-
- ### RESTORE command tests for type_changed KSN types
-
- test "Keyspace notifications: RESTORE REPLACE different type - restore, overwritten and type_changed events" {
- r config set notify-keyspace-events Egoc
- r del restore_test_key3
-
- # Create a string value and dump it (do this before subscribing)
- r set temp_key "string_value"
- set dump_data [r dump temp_key]
- r del temp_key
-
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
-
- # Create initial hash key
- r hset restore_test_key3 field "hash_value"
-
- # Restore with REPLACE - should emit restore, overwritten and type_changed events
- r restore restore_test_key3 0 $dump_data REPLACE
-
- assert_equal "pmessage * __keyevent@${db}__:restore restore_test_key3" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:overwritten restore_test_key3" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed restore_test_key3" [$rd1 read]
-
- $rd1 close
- }
-
- ### SET command tests for overwritten and type_changed KSN types
-
- test "Keyspace notifications: SET on existing string key - overwritten event" {
- r config set notify-keyspace-events EAo
- r del set_test_key1
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
-
- # Create initial string key
- r set set_test_key1 "initial_value"
- assert_equal "pmessage * __keyevent@${db}__:set set_test_key1" [$rd1 read]
-
- # Set new value on existing string key - should emit overwritten event
- r set set_test_key1 "new_value"
-
- assert_equal "pmessage * __keyevent@${db}__:overwritten set_test_key1" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:set set_test_key1" [$rd1 read]
-
- $rd1 close
- }
-
- test "Keyspace notifications: setKey on existing different type key - overwritten and type_changed events" {
- r config set notify-keyspace-events Eoc
-
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
-
- r flushdb
- r hset set_test_key2 field "hash_value"
- r set set_test_key2 "string_value"
- assert_equal "pmessage * __keyevent@${db}__:overwritten set_test_key2" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed set_test_key2" [$rd1 read]
-
- # overwritten and type_changed events should be emitted for any->any
- # type conversion that uses the setKey command
- r flushdb
- r lpush l{t} 1 2 3
- r sadd s1{t} "A"
- r sadd s2{t} "B"
- r sunionstore l{t} s1{t} s2{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten l{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed l{t}" [$rd1 read]
-
- r flushdb
- r sadd s1{t} "A"
- r set x{t} "\x0f"
- r set y{t} "\xff"
- r bitop and s1{t} x{t} y{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten s1{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed s1{t}" [$rd1 read]
-
- $rd1 close
- }
-
- test "Keyspace notifications: overwritten and type_changed events for RENAME and COPY commands" {
- r config set notify-keyspace-events Eoc
-
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
-
- # test COPY events
- r flushdb
- r hset hs{t} 1 2 3 4
- r lpush l{t} 1 2 3 4
- r copy hs{t} l{t} replace
-
- assert_equal "pmessage * __keyevent@${db}__:overwritten l{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed l{t}" [$rd1 read]
-
- # test rename RENAME events
- r flushdb
- r hset hs{t} field "hash_value"
- r sadd x{t} 1 2 3
- r rename x{t} hs{t}
-
- assert_equal "pmessage * __keyevent@${db}__:overwritten hs{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed hs{t}" [$rd1 read]
-
- $rd1 close
- }
-
- test "Keyspace notifications: overwritten and type_changed for *STORE* commands" {
- r config set notify-keyspace-events Eoc
-
- set rd1 [redis_deferring_client]
- assert_equal {1} [psubscribe $rd1 *]
-
- r flushdb
- r set x{t} x
-
- # SORT
- r lpush l{t} 4 3 2 1
- r sort l{t} store x{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten x{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed x{t}" [$rd1 read]
-
- # SDIFFSTORE
- r sadd s1{t} a b c d
- r sadd s2{t} b e f
- r sdiffstore x{t} s1{t} s2{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten x{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed x{t}" [$rd1 read]
-
- # SINTERSTORE
- r set d1{t} x
- r sinterstore d1{t} s1{t} s2{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten d1{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d1{t}" [$rd1 read]
-
- # SUNIONSTORE
- r set d2{t} x
- r sunionstore d2{t} s1{t} s2{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten d2{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d2{t}" [$rd1 read]
-
- # ZUNIONSTORE
- r set d3{t} x
- r zadd z1{t} 1 a 2 b
- r zadd z2{t} 3 c 4 d
- r zunionstore d3{t} 2 z1{t} z2{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten d3{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d3{t}" [$rd1 read]
-
- # ZINTERSTORE
- r set d4{t} x
- r zadd z2{t} 2 a
- r zinterstore d4{t} 2 z1{t} z2{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten d4{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d4{t}" [$rd1 read]
-
- # ZDIFFSTORE
- r set d5{t} x
- r zdiffstore d5{t} 2 z1{t} z2{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten d5{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d5{t}" [$rd1 read]
-
- # ZRANGESTORE
- r set d6{t} x
- r zadd zsrc{t} 1 a 2 b 3 c 4 d
- r zrangestore d6{t} zsrc{t} 1 2
- assert_equal "pmessage * __keyevent@${db}__:overwritten d6{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d6{t}" [$rd1 read]
-
- # GEORADIUS with STORE
- r set d7{t} x
- r geoadd geo{t} 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
- r georadius geo{t} 15 37 200 km store d7{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten d7{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d7{t}" [$rd1 read]
-
- # GEORADIUS with STOREDIST
- r set d8{t} x
- r georadius geo{t} 15 37 200 km storedist d8{t}
- assert_equal "pmessage * __keyevent@${db}__:overwritten d8{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d8{t}" [$rd1 read]
-
- # GEOSEARCHSTORE
- r set d9{t} x
- r geosearchstore d9{t} geo{t} fromlonlat 15 37 byradius 200 km
- assert_equal "pmessage * __keyevent@${db}__:overwritten d9{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d9{t}" [$rd1 read]
-
- # GEOSEARCHSTORE with STOREDIST
- r set d10{t} x
- r geosearchstore d10{t} geo{t} fromlonlat 15 37 byradius 200 km storedist
- assert_equal "pmessage * __keyevent@${db}__:overwritten d10{t}" [$rd1 read]
- assert_equal "pmessage * __keyevent@${db}__:type_changed d10{t}" [$rd1 read]
-
- $rd1 close
- }
-
- test "publish to self inside multi" {
- r hello 3
- r subscribe foo
- r multi
- r ping abc
- r publish foo bar
- r publish foo vaz
- r ping def
- assert_equal [r exec] {abc 1 1 def}
- assert_equal [r read] {message foo bar}
- assert_equal [r read] {message foo vaz}
- } {} {resp3}
-
- test "publish to self inside script" {
- r hello 3
- r subscribe foo
- set res [r eval {
- redis.call("ping","abc")
- redis.call("publish","foo","bar")
- redis.call("publish","foo","vaz")
- redis.call("ping","def")
- return "bla"} 0]
- assert_equal $res {bla}
- assert_equal [r read] {message foo bar}
- assert_equal [r read] {message foo vaz}
- } {} {resp3}
-
- test "unsubscribe inside multi, and publish to self" {
- r hello 3
-
- # Note: SUBSCRIBE and UNSUBSCRIBE with multiple channels in the same command,
- # breaks the multi response, see https://github.com/redis/redis/issues/12207
- # this is just a temporary sanity test to detect unintended breakage.
-
- # subscribe for 3 channels actually emits 3 "responses"
- assert_equal "subscribe foo 1" [r subscribe foo bar baz]
- assert_equal "subscribe bar 2" [r read]
- assert_equal "subscribe baz 3" [r read]
-
- r multi
- r ping abc
- r unsubscribe bar
- r unsubscribe baz
- r ping def
- assert_equal [r exec] {abc {unsubscribe bar 2} {unsubscribe baz 1} def}
-
- # published message comes after the publish command's response.
- assert_equal [r publish foo vaz] {1}
- assert_equal [r read] {message foo vaz}
- } {} {resp3}
-
-}