Unverified Commit 2dba1e39 authored by Oran Agra's avatar Oran Agra Committed by GitHub
Browse files

Merge 6.2 RC3

parents ec2d1807 95338f9c
# Check the basic monitoring and failover capabilities.
source "../tests/includes/start-init-tests.tcl"
source "../tests/includes/init-tests.tcl"
if {$::simulate_error} {
......
proc set_redis_announce_ip {addr} {
foreach_redis_id id {
R $id config set replica-announce-ip $addr
}
}
proc set_sentinel_config {keyword value} {
foreach_sentinel_id id {
S $id sentinel config set $keyword $value
}
}
proc set_all_instances_hostname {hostname} {
foreach_sentinel_id id {
set_instance_attrib sentinel $id host $hostname
}
foreach_redis_id id {
set_instance_attrib redis $id host $hostname
}
}
test "(pre-init) Configure instances and sentinel for hostname use" {
set ::host "localhost"
restart_killed_instances
set_all_instances_hostname $::host
set_redis_announce_ip $::host
set_sentinel_config resolve-hostnames yes
set_sentinel_config announce-hostnames yes
}
source "../tests/includes/init-tests.tcl"
proc verify_hostname_announced {hostname} {
foreach_sentinel_id id {
# Master is reported with its hostname
if {![string equal [lindex [S $id SENTINEL GET-MASTER-ADDR-BY-NAME mymaster] 0] $hostname]} {
return 0
}
# Replicas are reported with their hostnames
foreach replica [S $id SENTINEL REPLICAS mymaster] {
if {![string equal [dict get $replica ip] $hostname]} {
return 0
}
}
}
return 1
}
test "Sentinel announces hostnames" {
# Check initial state
verify_hostname_announced $::host
# Disable announce-hostnames and confirm IPs are used
set_sentinel_config announce-hostnames no
assert {[verify_hostname_announced "127.0.0.1"] || [verify_hostname_announced "::1"]}
}
# We need to revert any special configuration because all tests currently
# share the same instances.
test "(post-cleanup) Configure instances and sentinel for IPs" {
set ::host "127.0.0.1"
set_all_instances_hostname $::host
set_redis_announce_ip $::host
set_sentinel_config resolve-hostnames no
set_sentinel_config announce-hostnames no
}
\ No newline at end of file
source "../tests/includes/init-tests.tcl"
set ::user "testuser"
set ::password "secret"
proc setup_acl {} {
foreach_sentinel_id id {
assert_equal {OK} [S $id ACL SETUSER $::user >$::password +@all on]
assert_equal {OK} [S $id ACL SETUSER default off]
S $id CLIENT KILL USER default SKIPME no
assert_equal {OK} [S $id AUTH $::user $::password]
}
}
proc teardown_acl {} {
foreach_sentinel_id id {
assert_equal {OK} [S $id ACL SETUSER default on]
assert_equal {1} [S $id ACL DELUSER $::user]
S $id SENTINEL CONFIG SET sentinel-user ""
S $id SENTINEL CONFIG SET sentinel-pass ""
}
}
test "(post-init) Set up ACL configuration" {
setup_acl
assert_equal $::user [S 1 ACL WHOAMI]
}
test "SENTINEL CONFIG SET handles on-the-fly credentials reconfiguration" {
# Make sure we're starting with a broken state...
after 5000
catch {S 1 SENTINEL CKQUORUM mymaster} err
assert_match {*NOQUORUM*} $err
foreach_sentinel_id id {
assert_equal {OK} [S $id SENTINEL CONFIG SET sentinel-user $::user]
assert_equal {OK} [S $id SENTINEL CONFIG SET sentinel-pass $::password]
}
after 5000
assert_match {*OK*} [S 1 SENTINEL CKQUORUM mymaster]
}
test "(post-cleanup) Tear down ACL configuration" {
teardown_acl
}
# Initialization tests -- most units will start including this.
test "(init) Restart killed instances" {
proc restart_killed_instances {} {
foreach type {redis sentinel} {
foreach_${type}_id id {
if {[get_instance_attrib $type $id pid] == -1} {
......@@ -12,6 +12,10 @@ test "(init) Restart killed instances" {
}
}
test "(init) Restart killed instances" {
restart_killed_instances
}
test "(init) Remove old master entry from sentinels" {
foreach_sentinel_id id {
catch {S $id SENTINEL REMOVE mymaster}
......@@ -37,6 +41,8 @@ test "(init) Sentinels can start monitoring a master" {
S $id SENTINEL SET mymaster down-after-milliseconds 2000
S $id SENTINEL SET mymaster failover-timeout 20000
S $id SENTINEL SET mymaster parallel-syncs 10
S $id SENTINEL SET mymaster notification-script ../../tests/includes/notify.sh
S $id SENTINEL SET mymaster client-reconfig-script ../../tests/includes/notify.sh
}
}
......
#!/usr/bin/env bash
OS=`uname -s`
if [ ${OS} != "Linux" ]
then
exit 0
fi
# fd 3 is meant to catch the actual access to /proc/pid/fd,
# in case there's an fd leak by the sentinel,
# it can take 3, but then the access to /proc will take another fd, and we'll catch that.
leaked_fd_count=`ls /proc/self/fd | grep -vE '^[0|1|2|3]$' | wc -l`
if [ $leaked_fd_count -gt 0 ]
then
sentinel_fd_leaks_file="../sentinel_fd_leaks"
if [ ! -f $sentinel_fd_leaks_file ]
then
ls -l /proc/self/fd | cat >> $sentinel_fd_leaks_file
lsof -p $$ | cat >> $sentinel_fd_leaks_file
fi
fi
# assume master is down after being unresponsive for 20s
sentinel down-after-milliseconds setmaster 20000
# reconfigure one slave at a time
sentinel parallel-syncs setmaster 2
# wait for 4m before assuming failover went wrong
sentinel failover-timeout setmaster 240000
# monitoring set
sentinel monitor setmaster 10.0.0.1 30000 2
test "(start-init) Flush config and compare rewrite config file lines" {
foreach_sentinel_id id {
assert_match "OK" [S $id SENTINEL FLUSHCONFIG]
set file1 ../tests/includes/sentinel.conf
set file2 [file join "sentinel_${id}" "sentinel.conf"]
set fh1 [open $file1 r]
set fh2 [open $file2 r]
while {[gets $fh1 line1]} {
if {[gets $fh2 line2]} {
assert [string equal $line1 $line2]
} else {
fail "sentinel config file rewrite sequence changed"
}
}
close $fh1
close $fh2
}
}
\ No newline at end of file
......@@ -244,6 +244,7 @@ proc ::redis::redis_read_reply {id fd} {
_ {redis_read_null $fd}
: -
+ {redis_read_line $fd}
, {expr {double([redis_read_line $fd])}}
- {return -code error [redis_read_line $fd]}
$ {redis_bulk_read $fd}
> -
......
......@@ -152,21 +152,49 @@ proc server_is_up {host port retrynum} {
return 0
}
# Check if current ::tags match requested tags. If ::allowtags are used,
# there must be some intersection. If ::denytags are used, no intersection
# is allowed. Returns 1 if tags are acceptable or 0 otherwise, in which
# case err_return names a return variable for the message to be logged.
proc tags_acceptable {err_return} {
upvar $err_return err
# If tags are whitelisted, make sure there's match
if {[llength $::allowtags] > 0} {
set matched 0
foreach tag $::allowtags {
if {[lsearch $::tags $tag] >= 0} {
incr matched
}
}
if {$matched < 1} {
set err "Tag: none of the tags allowed"
return 0
}
}
foreach tag $::denytags {
if {[lsearch $::tags $tag] >= 0} {
set err "Tag: $tag denied"
return 0
}
}
return 1
}
# doesn't really belong here, but highly coupled to code in start_server
proc tags {tags code} {
# If we 'tags' contain multiple tags, quoted and seperated by spaces,
# we want to get rid of the quotes in order to have a proper list
set tags [string map { \" "" } $tags]
set ::tags [concat $::tags $tags]
# We skip unwanted tags
foreach tag $::denytags {
if {[lsearch $::tags $tag] >= 0} {
if {![tags_acceptable err]} {
incr ::num_aborted
send_data_packet $::test_server_fd ignore "Tag: $tag"
send_data_packet $::test_server_fd ignore $err
set ::tags [lrange $::tags 0 end-[llength $tags]]
return
}
}
uplevel 1 $code
set ::tags [lrange $::tags 0 end-[llength $tags]]
}
......@@ -267,14 +295,12 @@ proc start_server {options {code undefined}} {
}
# We skip unwanted tags
foreach tag $::denytags {
if {[lsearch $::tags $tag] >= 0} {
if {![tags_acceptable err]} {
incr ::num_aborted
send_data_packet $::test_server_fd ignore "Tag: $tag"
send_data_packet $::test_server_fd ignore $err
set ::tags [lrange $::tags 0 end-[llength $tags]]
return
}
}
# If we are running against an external server, we just push the
# host/port pair in the stack the first time
......
......@@ -12,7 +12,11 @@ proc randstring {min max {type binary}} {
set maxval 52
}
while {$len} {
append output [format "%c" [expr {$minval+int(rand()*($maxval-$minval+1))}]]
set rr [expr {$minval+int(rand()*($maxval-$minval+1))}]
if {$type eq {alpha} && $rr eq 92} {
set rr 90; # avoid putting '\' char in the string, it can mess up TCL processing
}
append output [format "%c" $rr]
incr len -1
}
return $output
......@@ -86,12 +90,10 @@ proc waitForBgrewriteaof r {
}
proc wait_for_sync r {
while 1 {
if {[status $r master_link_status] eq "down"} {
after 10
wait_for_condition 50 100 {
[status $r master_link_status] eq "up"
} else {
break
}
fail "replica didn't sync in time"
}
}
......@@ -571,8 +573,8 @@ proc generate_fuzzy_traffic_on_key {key duration} {
# Commands per type, blocking commands removed
# TODO: extract these from help.h or elsewhere, and improve to include other types
set string_commands {APPEND BITCOUNT BITFIELD BITOP BITPOS DECR DECRBY GET GETBIT GETRANGE GETSET INCR INCRBY INCRBYFLOAT MGET MSET MSETNX PSETEX SET SETBIT SETEX SETNX SETRANGE STRALGO STRLEN}
set hash_commands {HDEL HEXISTS HGET HGETALL HINCRBY HINCRBYFLOAT HKEYS HLEN HMGET HMSET HSCAN HSET HSETNX HSTRLEN HVALS}
set zset_commands {ZADD ZCARD ZCOUNT ZINCRBY ZINTERSTORE ZLEXCOUNT ZPOPMAX ZPOPMIN ZRANGE ZRANGEBYLEX ZRANGEBYSCORE ZRANK ZREM ZREMRANGEBYLEX ZREMRANGEBYRANK ZREMRANGEBYSCORE ZREVRANGE ZREVRANGEBYLEX ZREVRANGEBYSCORE ZREVRANK ZSCAN ZSCORE ZUNIONSTORE}
set hash_commands {HDEL HEXISTS HGET HGETALL HINCRBY HINCRBYFLOAT HKEYS HLEN HMGET HMSET HSCAN HSET HSETNX HSTRLEN HVALS HRANDFIELD}
set zset_commands {ZADD ZCARD ZCOUNT ZINCRBY ZINTERSTORE ZLEXCOUNT ZPOPMAX ZPOPMIN ZRANGE ZRANGEBYLEX ZRANGEBYSCORE ZRANK ZREM ZREMRANGEBYLEX ZREMRANGEBYRANK ZREMRANGEBYSCORE ZREVRANGE ZREVRANGEBYLEX ZREVRANGEBYSCORE ZREVRANK ZSCAN ZSCORE ZUNIONSTORE ZRANDMEMBER}
set list_commands {LINDEX LINSERT LLEN LPOP LPOS LPUSH LPUSHX LRANGE LREM LSET LTRIM RPOP RPOPLPUSH RPUSH RPUSHX}
set set_commands {SADD SCARD SDIFF SDIFFSTORE SINTER SINTERSTORE SISMEMBER SMEMBERS SMOVE SPOP SRANDMEMBER SREM SSCAN SUNION SUNIONSTORE}
set stream_commands {XACK XADD XCLAIM XDEL XGROUP XINFO XLEN XPENDING XRANGE XREAD XREADGROUP XREVRANGE XTRIM}
......
......@@ -52,6 +52,7 @@ set ::all_tests {
integration/psync2
integration/psync2-reg
integration/psync2-pingoff
integration/failover
integration/redis-cli
integration/redis-benchmark
unit/pubsub
......@@ -717,6 +718,7 @@ if {[llength $filtered_tests] < [llength $::all_tests]} {
}
proc attach_to_replication_stream {} {
r config set repl-ping-replica-period 3600
if {$::tls} {
set s [::tls::socket [srv 0 "host"] [srv 0 "port"]]
} else {
......@@ -774,6 +776,7 @@ proc assert_replication_stream {s patterns} {
proc close_replication_stream {s} {
close $s
r config set repl-ping-replica-period 10
}
# With the parallel test running multiple Redis instances at the same time
......
......@@ -12,7 +12,7 @@ start_server {tags {"dump"}} {
r del foo
r restore foo 5000 $encoded
set ttl [r pttl foo]
assert {$ttl >= 3000 && $ttl <= 5000}
assert_range $ttl 3000 5000
r get foo
} {bar}
......@@ -22,7 +22,7 @@ start_server {tags {"dump"}} {
r del foo
r restore foo 2569591501 $encoded
set ttl [r pttl foo]
assert {$ttl >= (2569591501-3000) && $ttl <= 2569591501}
assert_range $ttl (2569591501-3000) 2569591501
r get foo
} {bar}
......@@ -33,7 +33,7 @@ start_server {tags {"dump"}} {
set now [clock milliseconds]
r restore foo [expr $now+3000] $encoded absttl
set ttl [r pttl foo]
assert {$ttl >= 2900 && $ttl <= 3100}
assert_range $ttl 2000 3100
r get foo
} {bar}
......
......@@ -209,19 +209,101 @@ start_server {tags {"expire"}} {
set e
} {*not an integer*}
test {SET - use EX/PX option, TTL should not be reseted after loadaof} {
test {EXPIRE and SET/GETEX EX/PX/EXAT/PXAT option, TTL should not be reset after loadaof} {
# This test makes sure that expire times are propagated as absolute
# times to the AOF file and not as relative time, so that when the AOF
# is reloaded the TTLs are not being shifted forward to the future.
# We want the time to logically pass when the server is restarted!
r config set appendonly yes
r set foo bar EX 100
after 2000
r debug loadaof
set ttl [r ttl foo]
assert {$ttl <= 98 && $ttl > 90}
r set foo1 bar EX 100
r set foo2 bar PX 100000
r set foo3 bar
r set foo4 bar
r expire foo3 100
r pexpire foo4 100000
r setex foo5 100 bar
r psetex foo6 100000 bar
r set foo7 bar EXAT [expr [clock seconds] + 100]
r set foo8 bar PXAT [expr [clock milliseconds] + 100000]
r set foo9 bar
r getex foo9 EX 100
r set foo10 bar
r getex foo10 PX 100000
r set foo11 bar
r getex foo11 EXAT [expr [clock seconds] + 100]
r set foo12 bar
r getex foo12 PXAT [expr [clock milliseconds] + 100000]
r set foo bar PX 100000
after 2000
r debug loadaof
set ttl [r ttl foo]
assert {$ttl <= 98 && $ttl > 90}
assert_range [r ttl foo1] 90 98
assert_range [r ttl foo2] 90 98
assert_range [r ttl foo3] 90 98
assert_range [r ttl foo4] 90 98
assert_range [r ttl foo5] 90 98
assert_range [r ttl foo6] 90 98
assert_range [r ttl foo7] 90 98
assert_range [r ttl foo8] 90 98
assert_range [r ttl foo9] 90 98
assert_range [r ttl foo10] 90 98
assert_range [r ttl foo11] 90 98
assert_range [r ttl foo12] 90 98
}
test {EXPIRE relative and absolute propagation to replicas} {
# Make sure that relative and absolute expire commands are propagated
# "as is" to replicas.
# We want replicas to honor the same high level contract of expires that
# the master has, that is, we want the time to be counted logically
# starting from the moment the write was received. This usually provides
# the most coherent behavior from the point of view of the external
# users, with TTLs that are similar from the POV of the external observer.
#
# This test is here to stop some innocent / eager optimization or cleanup
# from doing the wrong thing without proper discussion, see:
# https://github.com/redis/redis/pull/5171#issuecomment-409553266
set repl [attach_to_replication_stream]
r set foo1 bar ex 200
r set foo1 bar px 100000
r set foo1 bar exat [expr [clock seconds]+100]
r set foo1 bar pxat [expr [clock milliseconds]+10000]
r setex foo1 100 bar
r psetex foo1 100000 bar
r set foo2 bar
r expire foo2 100
r pexpire foo2 100000
r set foo3 bar
r expireat foo3 [expr [clock seconds]+100]
r pexpireat foo3 [expr [clock seconds]*1000+100000]
r expireat foo3 [expr [clock seconds]-100]
r set foo4 bar
r getex foo4 ex 200
r getex foo4 px 200000
r getex foo4 exat [expr [clock seconds]+100]
r getex foo4 pxat [expr [clock milliseconds]+10000]
assert_replication_stream $repl {
{select *}
{set foo1 bar PX 200000}
{set foo1 bar PX 100000}
{set foo1 bar PXAT *}
{set foo1 bar PXAT *}
{set foo1 bar PX 100000}
{set foo1 bar PX 100000}
{set foo2 bar}
{expire foo2 100}
{pexpire foo2 100000}
{set foo3 bar}
{expireat foo3 *}
{pexpireat foo3 *}
{del foo3}
{set foo4 bar}
{pexpire foo4 200000}
{pexpire foo4 200000}
{pexpireat foo4 *}
{pexpireat foo4 *}
}
}
test {SET command will remove expire} {
......@@ -246,4 +328,32 @@ start_server {tags {"expire"}} {
set ttl [r ttl foo]
assert {$ttl <= 98 && $ttl > 90}
}
test {GETEX use of PERSIST option should remove TTL} {
r set foo bar EX 100
r getex foo PERSIST
r ttl foo
} {-1}
test {GETEX use of PERSIST option should remove TTL after loadaof} {
r set foo bar EX 100
r getex foo PERSIST
after 2000
r debug loadaof
r ttl foo
} {-1}
test {GETEX propagate as to replica as PERSIST, DEL, or nothing} {
set repl [attach_to_replication_stream]
r set foo bar EX 100
r getex foo PERSIST
r getex foo
r getex foo exat [expr [clock seconds]-100]
assert_replication_stream $repl {
{select *}
{set foo bar PX 100000}
{persist foo}
{del foo}
}
}
}
......@@ -112,6 +112,7 @@ start_server {tags {"introspection"}} {
bio_cpulist
aof_rewrite_cpulist
bgsave_cpulist
set-proc-title
}
if {!$::tls} {
......
start_server {tags {"limits"} overrides {maxclients 10}} {
start_server {tags {"limits network"} overrides {maxclients 10}} {
if {$::tls} {
set expected_code "*I/O error*"
} else {
......
set testmodule [file normalize tests/modules/blockonbackground.so]
source tests/support/util.tcl
start_server {tags {"modules"}} {
r module load $testmodule
test { blocked clients time tracking - check blocked command that uses RedisModule_BlockedClientMeasureTimeStart() is tracking background time} {
r slowlog reset
r config set slowlog-log-slower-than 200000
assert_equal [r slowlog len] 0
r block.debug 0 10000
assert_equal [r slowlog len] 0
r config resetstat
r block.debug 200 10000
assert_equal [r slowlog len] 1
set cmdstatline [cmdrstat block.debug r]
regexp "calls=1,usec=(.*?),usec_per_call=(.*?),rejected_calls=0,failed_calls=0" $cmdstatline usec usec_per_call
assert {$usec >= 100000}
assert {$usec_per_call >= 100000}
}
test { blocked clients time tracking - check blocked command that uses RedisModule_BlockedClientMeasureTimeStart() is tracking background time even in timeout } {
r slowlog reset
r config set slowlog-log-slower-than 200000
assert_equal [r slowlog len] 0
r block.debug 0 20000
assert_equal [r slowlog len] 0
r config resetstat
r block.debug 20000 200
assert_equal [r slowlog len] 1
set cmdstatline [cmdrstat block.debug r]
regexp "calls=1,usec=(.*?),usec_per_call=(.*?),rejected_calls=0,failed_calls=0" $cmdstatline usec usec_per_call
assert {$usec >= 100000}
assert {$usec_per_call >= 100000}
}
test { blocked clients time tracking - check blocked command with multiple calls RedisModule_BlockedClientMeasureTimeStart() is tracking the total background time } {
r slowlog reset
r config set slowlog-log-slower-than 200000
assert_equal [r slowlog len] 0
r block.double_debug 0
assert_equal [r slowlog len] 0
r config resetstat
r block.double_debug 100
assert_equal [r slowlog len] 1
set cmdstatline [cmdrstat block.double_debug r]
regexp "calls=1,usec=(.*?),usec_per_call=(.*?),rejected_calls=0,failed_calls=0" $cmdstatline usec usec_per_call
assert {$usec >= 60000}
assert {$usec_per_call >= 60000}
}
test { blocked clients time tracking - check blocked command without calling RedisModule_BlockedClientMeasureTimeStart() is not reporting background time } {
r slowlog reset
r config set slowlog-log-slower-than 200000
assert_equal [r slowlog len] 0
r block.debug_no_track 200 1000
# ensure slowlog is still empty
assert_equal [r slowlog len] 0
}
}
......@@ -168,7 +168,7 @@ start_server {tags {"modules"}} {
assert_error "*unblocked*" {$rd read}
}
test {Module client blocked on keys does not wake up on wrong type} {
test {Module client re-blocked on keys after woke up on wrong type} {
r del k
set rd [redis_deferring_client]
$rd fsl.bpop k 0
......@@ -184,5 +184,56 @@ start_server {tags {"modules"}} {
r del k
r fsl.push k 34
assert_equal {34} [$rd read]
assert_equal {1} [r get fsl_wrong_type] ;# first lpush caused one wrong-type wake-up
}
test {Module client blocked on keys woken up by LPUSH} {
r del k
set rd [redis_deferring_client]
$rd blockonkeys.popall k
# wait until client is actually blocked
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Client is not blocked"
}
r lpush k 42 squirrel banana
assert_equal {banana squirrel 42} [$rd read]
$rd close
}
test {Module client unblocks BLPOP} {
r del k
set rd [redis_deferring_client]
$rd blpop k 3
# wait until client is actually blocked
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Client is not blocked"
}
r blockonkeys.lpush k 42
assert_equal {k 42} [$rd read]
$rd close
}
test {Module unblocks module blocked on non-empty list} {
r del k
r lpush k aa
# Module client blocks to pop 5 elements from list
set rd [redis_deferring_client]
$rd blockonkeys.blpopn k 5
# Wait until client is actually blocked
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Client is not blocked"
}
# Check that RM_SignalKeyAsReady() can wake up BLPOPN
r blockonkeys.lpush_unblock k bb cc ;# Not enough elements for BLPOPN
r lpush k dd ee ff ;# Doesn't unblock module
r blockonkeys.lpush_unblock k gg ;# Unblocks module
assert_equal {gg ff ee dd cc} [$rd read]
$rd close
}
}
set testmodule [file normalize tests/modules/stream.so]
start_server {tags {"modules"}} {
r module load $testmodule
test {Module stream add and delete} {
r del mystream
# add to empty key
set streamid1 [r stream.add mystream item 1 value a]
# add to existing stream
set streamid2 [r stream.add mystream item 2 value b]
# check result
assert { [string match "*-*" $streamid1] }
set items [r XRANGE mystream - +]
assert_equal $items \
"{$streamid1 {item 1 value a}} {$streamid2 {item 2 value b}}"
# delete one of them and try deleting non-existing ID
assert_equal OK [r stream.delete mystream $streamid1]
assert_error "ERR StreamDelete*" {r stream.delete mystream 123-456}
assert_error "Invalid stream ID*" {r stream.delete mystream foo}
assert_equal "{$streamid2 {item 2 value b}}" [r XRANGE mystream - +]
# check error condition: wrong type
r del mystream
r set mystream mystring
assert_error "ERR StreamAdd*" {r stream.add mystream item 1 value a}
assert_error "ERR StreamDelete*" {r stream.delete mystream 123-456}
}
test {Module stream add unblocks blocking xread} {
r del mystream
# Blocking XREAD on an empty key
set rd1 [redis_deferring_client]
$rd1 XREAD BLOCK 3000 STREAMS mystream $
# wait until client is actually blocked
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Client is not blocked"
}
set id [r stream.add mystream field 1 value a]
assert_equal "{mystream {{$id {field 1 value a}}}}" [$rd1 read]
# Blocking XREAD on an existing stream
set rd2 [redis_deferring_client]
$rd2 XREAD BLOCK 3000 STREAMS mystream $
# wait until client is actually blocked
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Client is not blocked"
}
set id [r stream.add mystream field 2 value b]
assert_equal "{mystream {{$id {field 2 value b}}}}" [$rd2 read]
}
test {Module stream add benchmark (1M stream add)} {
set n 1000000
r del mystream
set result [r stream.addn mystream $n field value]
assert_equal $result $n
}
test {Module stream iterator} {
r del mystream
set streamid1 [r xadd mystream * item 1 value a]
set streamid2 [r xadd mystream * item 2 value b]
# range result
set result1 [r stream.range mystream "-" "+"]
set expect1 [r xrange mystream "-" "+"]
assert_equal $result1 $expect1
# reverse range
set result_rev [r stream.range mystream "+" "-"]
set expect_rev [r xrevrange mystream "+" "-"]
assert_equal $result_rev $expect_rev
# only one item: range with startid = endid
set result2 [r stream.range mystream "-" $streamid1]
assert_equal $result2 "{$streamid1 {item 1 value a}}"
assert_equal $result2 [list [list $streamid1 {item 1 value a}]]
# only one item: range with startid = endid
set result3 [r stream.range mystream $streamid2 $streamid2]
assert_equal $result3 "{$streamid2 {item 2 value b}}"
assert_equal $result3 [list [list $streamid2 {item 2 value b}]]
}
test {Module stream iterator delete} {
r del mystream
set id1 [r xadd mystream * normal item]
set id2 [r xadd mystream * selfdestruct yes]
set id3 [r xadd mystream * another item]
# stream.range deletes the "selfdestruct" item after returning it
assert_equal \
"{$id1 {normal item}} {$id2 {selfdestruct yes}} {$id3 {another item}}" \
[r stream.range mystream - +]
# now, the "selfdestruct" item is gone
assert_equal \
"{$id1 {normal item}} {$id3 {another item}}" \
[r stream.range mystream - +]
}
test {Module stream trim by length} {
r del mystream
# exact maxlen
r xadd mystream * item 1 value a
r xadd mystream * item 2 value b
r xadd mystream * item 3 value c
assert_equal 3 [r xlen mystream]
assert_equal 0 [r stream.trim mystream maxlen = 5]
assert_equal 3 [r xlen mystream]
assert_equal 2 [r stream.trim mystream maxlen = 1]
assert_equal 1 [r xlen mystream]
assert_equal 1 [r stream.trim mystream maxlen = 0]
# check that there is no limit for exact maxlen
r stream.addn mystream 20000 item x value y
assert_equal 20000 [r stream.trim mystream maxlen = 0]
# approx maxlen (100 items per node implies default limit 10K items)
r stream.addn mystream 20000 item x value y
assert_equal 20000 [r xlen mystream]
assert_equal 10000 [r stream.trim mystream maxlen ~ 2]
assert_equal 9900 [r stream.trim mystream maxlen ~ 2]
assert_equal 0 [r stream.trim mystream maxlen ~ 2]
assert_equal 100 [r xlen mystream]
assert_equal 100 [r stream.trim mystream maxlen ~ 0]
assert_equal 0 [r xlen mystream]
}
test {Module stream trim by ID} {
r del mystream
# exact minid
r xadd mystream * item 1 value a
r xadd mystream * item 2 value b
set minid [r xadd mystream * item 3 value c]
assert_equal 3 [r xlen mystream]
assert_equal 0 [r stream.trim mystream minid = -]
assert_equal 3 [r xlen mystream]
assert_equal 2 [r stream.trim mystream minid = $minid]
assert_equal 1 [r xlen mystream]
assert_equal 1 [r stream.trim mystream minid = +]
# check that there is no limit for exact minid
r stream.addn mystream 20000 item x value y
assert_equal 20000 [r stream.trim mystream minid = +]
# approx minid (100 items per node implies default limit 10K items)
r stream.addn mystream 19980 item x value y
set minid [r xadd mystream * item x value y]
r stream.addn mystream 19 item x value y
assert_equal 20000 [r xlen mystream]
assert_equal 10000 [r stream.trim mystream minid ~ $minid]
assert_equal 9900 [r stream.trim mystream minid ~ $minid]
assert_equal 0 [r stream.trim mystream minid ~ $minid]
assert_equal 100 [r xlen mystream]
assert_equal 100 [r stream.trim mystream minid ~ +]
assert_equal 0 [r xlen mystream]
}
}
......@@ -39,7 +39,7 @@ if {$system_name eq {linux}} {
r bgsave
set child_pid [get_child_pid 0]
assert {[get_oom_score_adj $child_pid] == [expr $base + 30]}
assert_equal [get_oom_score_adj $child_pid] [expr $base + 30]
}
# Failed oom-score-adj tests can only run unprivileged
......
......@@ -321,3 +321,47 @@ start_server {tags {"other"}} {
assert_match "*table size: 8192*" [r debug HTSTATS 9]
}
}
proc read_proc_title {pid} {
set fd [open "/proc/$pid/cmdline" "r"]
set cmdline [read $fd 1024]
close $fd
return $cmdline
}
start_server {tags {"other"}} {
test {Process title set as expected} {
# Test only on Linux where it's easy to get cmdline without relying on tools.
# Skip valgrind as it messes up the arguments.
set os [exec uname]
if {$os == "Linux" && !$::valgrind} {
# Set a custom template
r config set "proc-title-template" "TEST {title} {listen-addr} {port} {tls-port} {unixsocket} {config-file}"
set cmdline [read_proc_title [srv 0 pid]]
assert_equal "TEST" [lindex $cmdline 0]
assert_match "*/redis-server" [lindex $cmdline 1]
if {$::tls} {
set expect_port 0
set expect_tls_port [srv 0 port]
} else {
set expect_port [srv 0 port]
set expect_tls_port 0
}
set port [srv 0 port]
assert_equal "$::host:$port" [lindex $cmdline 2]
assert_equal $expect_port [lindex $cmdline 3]
assert_equal $expect_tls_port [lindex $cmdline 4]
assert_match "*/tests/tmp/server.*/socket" [lindex $cmdline 5]
assert_match "*/tests/tmp/redis.conf.*" [lindex $cmdline 6]
# Try setting a bad template
catch {r config set "proc-title-template" "{invalid-var}"} err
assert_match {*template format is invalid*} $err
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment