aboutsummaryrefslogtreecommitdiff
path: root/examples/redis-unstable/tests/unit/obuf-limits.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'examples/redis-unstable/tests/unit/obuf-limits.tcl')
-rw-r--r--examples/redis-unstable/tests/unit/obuf-limits.tcl240
1 files changed, 0 insertions, 240 deletions
diff --git a/examples/redis-unstable/tests/unit/obuf-limits.tcl b/examples/redis-unstable/tests/unit/obuf-limits.tcl
deleted file mode 100644
index 148187b..0000000
--- a/examples/redis-unstable/tests/unit/obuf-limits.tcl
+++ /dev/null
@@ -1,240 +0,0 @@
1start_server {tags {"obuf-limits external:skip logreqres:skip"}} {
2 r debug reply-copy-avoidance 0 ;# Disable copy avoidance because it affects memory usage
3
4 test {CONFIG SET client-output-buffer-limit} {
5 set oldval [lindex [r config get client-output-buffer-limit] 1]
6
7 catch {r config set client-output-buffer-limit "wrong number"} e
8 assert_match {*Wrong*arguments*} $e
9
10 catch {r config set client-output-buffer-limit "invalid_class 10mb 10mb 60"} e
11 assert_match {*Invalid*client*class*} $e
12 catch {r config set client-output-buffer-limit "master 10mb 10mb 60"} e
13 assert_match {*Invalid*client*class*} $e
14
15 catch {r config set client-output-buffer-limit "normal 10mbs 10mb 60"} e
16 assert_match {*Error*hard*} $e
17
18 catch {r config set client-output-buffer-limit "replica 10mb 10mbs 60"} e
19 assert_match {*Error*soft*} $e
20
21 catch {r config set client-output-buffer-limit "pubsub 10mb 10mb 60s"} e
22 assert_match {*Error*soft_seconds*} $e
23
24 r config set client-output-buffer-limit "normal 1mb 2mb 60 replica 3mb 4mb 70 pubsub 5mb 6mb 80"
25 set res [lindex [r config get client-output-buffer-limit] 1]
26 assert_equal $res "normal 1048576 2097152 60 slave 3145728 4194304 70 pubsub 5242880 6291456 80"
27
28 # Set back to the original value.
29 r config set client-output-buffer-limit $oldval
30 }
31
32 test {Client output buffer hard limit is enforced} {
33 r config set client-output-buffer-limit {pubsub 100000 0 0}
34 set rd1 [redis_deferring_client]
35
36 $rd1 subscribe foo
37 set reply [$rd1 read]
38 assert {$reply eq "subscribe foo 1"}
39
40 set omem 0
41 while 1 {
42 # The larger content size ensures that client.buf gets filled more quickly,
43 # allowing us to correctly observe the gradual increase of `omem`
44 r publish foo [string repeat bar 50]
45 set clients [split [r client list] "\r\n"]
46 set c [split [lindex $clients 1] " "]
47 if {![regexp {omem=([0-9]+)} $c - omem]} break
48 if {$omem > 200000} break
49 }
50 assert {$omem >= 70000 && $omem < 200000}
51 $rd1 close
52 }
53
54 foreach {soft_limit_time wait_for_timeout} {3 yes
55 4 no } {
56 if $wait_for_timeout {
57 set test_name "Client output buffer soft limit is enforced if time is overreached"
58 } else {
59 set test_name "Client output buffer soft limit is not enforced too early and is enforced when no traffic"
60 }
61
62 test $test_name {
63 r config set client-output-buffer-limit "pubsub 0 100000 $soft_limit_time"
64 set soft_limit_time [expr $soft_limit_time*1000]
65 set rd1 [redis_deferring_client]
66
67 $rd1 client setname test_client
68 set reply [$rd1 read]
69 assert {$reply eq "OK"}
70
71 $rd1 subscribe foo
72 set reply [$rd1 read]
73 assert {$reply eq "subscribe foo 1"}
74
75 set omem 0
76 set start_time 0
77 set time_elapsed 0
78 set last_under_limit_time [clock milliseconds]
79 while 1 {
80 r publish foo [string repeat "x" 1000]
81 set clients [split [r client list] "\r\n"]
82 set c [lsearch -inline $clients *name=test_client*]
83 if {$start_time != 0} {
84 set time_elapsed [expr {[clock milliseconds]-$start_time}]
85 # Make sure test isn't taking too long
86 assert {$time_elapsed <= [expr $soft_limit_time+3000]}
87 }
88 if {$wait_for_timeout && $c == ""} {
89 # Make sure we're disconnected when we reach the soft limit
90 assert {$omem >= 100000 && $time_elapsed >= $soft_limit_time}
91 break
92 } else {
93 assert {[regexp {omem=([0-9]+)} $c - omem]}
94 }
95 if {$omem > 100000} {
96 if {$start_time == 0} {set start_time $last_under_limit_time}
97 if {!$wait_for_timeout && $time_elapsed >= [expr $soft_limit_time-1000]} break
98 # Slow down loop when omem has reached the limit.
99 after 10
100 } else {
101 # if the OS socket buffers swallowed what we previously filled, reset the start timer.
102 set start_time 0
103 set last_under_limit_time [clock milliseconds]
104 }
105 }
106
107 if {!$wait_for_timeout} {
108 # After we completely stopped the traffic, wait for soft limit to time out
109 set timeout [expr {$soft_limit_time+1500 - ([clock milliseconds]-$start_time)}]
110 wait_for_condition [expr $timeout/10] 10 {
111 [lsearch [split [r client list] "\r\n"] *name=test_client*] == -1
112 } else {
113 fail "Soft limit timed out but client still connected"
114 }
115 }
116
117 $rd1 close
118 }
119 }
120
121 test {No response for single command if client output buffer hard limit is enforced} {
122 r config set latency-tracking no
123 r config set client-output-buffer-limit {normal 100000 0 0}
124 # Total size of all items must be more than 100k
125 set item [string repeat "x" 1000]
126 for {set i 0} {$i < 150} {incr i} {
127 r lpush mylist $item
128 }
129 set orig_mem [s used_memory]
130 # Set client name and get all items
131 set rd [redis_deferring_client]
132 $rd client setname mybiglist
133 assert {[$rd read] eq "OK"}
134 $rd lrange mylist 0 -1
135 $rd flush
136 after 100
137
138 # Before we read reply, redis will close this client.
139 set clients [r client list]
140 assert_no_match "*name=mybiglist*" $clients
141 set cur_mem [s used_memory]
142 # 10k just is a deviation threshold
143 assert {$cur_mem < 10000 + $orig_mem}
144
145 # Read nothing
146 set fd [$rd channel]
147 assert_equal {} [$rd rawread]
148 }
149
150 # Note: This test assumes that what's written with one write, will be read by redis in one read.
151 # this assumption is wrong, but seem to work empirically (for now)
152 test {No response for multi commands in pipeline if client output buffer limit is enforced} {
153 r config set client-output-buffer-limit {normal 100000 0 0}
154 set value [string repeat "x" 10000]
155 r set bigkey $value
156 set rd [redis_deferring_client]
157 $rd client setname multicommands
158 assert_equal "OK" [$rd read]
159
160 set server_pid [s process_id]
161 # Pause the server, so that the client's write will be buffered
162 pause_process $server_pid
163
164 # Create a pipeline of commands that will be processed in one socket read.
165 # It is important to use one write, in TLS mode independent writes seem
166 # to wait for response from the server.
167 # Total size should be less than OS socket buffer, redis can
168 # execute all commands in this pipeline when it wakes up.
169 set buf ""
170 for {set i 0} {$i < 15} {incr i} {
171 append buf "set $i $i\r\n"
172 append buf "get $i\r\n"
173 append buf "del $i\r\n"
174 # One bigkey is 10k, total response size must be more than 100k
175 append buf "get bigkey\r\n"
176 }
177 $rd write $buf
178 $rd flush
179
180 # Resume the server to process the pipeline in one go
181 resume_process $server_pid
182 # Make sure the pipeline of commands is processed
183 wait_for_condition 100 10 {
184 [expr {[regexp {calls=(\d+)} [cmdrstat get r] -> calls] ? $calls : 0}] >= 5
185 } else {
186 fail "the pipeline of commands commands is not processed"
187 }
188
189 # Redis must wake up if it can send reply
190 assert_equal "PONG" [r ping]
191 set clients [r client list]
192 assert_no_match "*name=multicommands*" $clients
193 assert_equal {} [$rd rawread]
194 }
195
196 test {Execute transactions completely even if client output buffer limit is enforced} {
197 r config set client-output-buffer-limit {normal 100000 0 0}
198 # Total size of all items must be more than 100k
199 set item [string repeat "x" 1000]
200 for {set i 0} {$i < 150} {incr i} {
201 r lpush mylist2 $item
202 }
203
204 # Output buffer limit is enforced during executing transaction
205 r client setname transactionclient
206 r set k1 v1
207 r multi
208 r set k2 v2
209 r get k2
210 r lrange mylist2 0 -1
211 r set k3 v3
212 r del k1
213 catch {[r exec]} e
214 assert_match "*I/O error*" $e
215 reconnect
216 set clients [r client list]
217 assert_no_match "*name=transactionclient*" $clients
218
219 # Transactions should be executed completely
220 assert_equal {} [r get k1]
221 assert_equal "v2" [r get k2]
222 assert_equal "v3" [r get k3]
223 }
224
225 test "Obuf limit, HRANDFIELD with huge count stopped mid-run" {
226 r config set client-output-buffer-limit {normal 1000000 0 0}
227 r hset myhash a b
228 catch {r hrandfield myhash -999999999} e
229 assert_match "*I/O error*" $e
230 reconnect
231 }
232
233 test "Obuf limit, KEYS stopped mid-run" {
234 r config set client-output-buffer-limit {normal 100000 0 0}
235 populate 1000 "long-key-name-prefix-of-100-chars-------------------------------------------------------------------"
236 catch {r keys *} e
237 assert_match "*I/O error*" $e
238 reconnect
239 }
240}