Mercurial > hg > ngx_http_upstream_keepalive
annotate t/proxy_keepalive.t @ 47:5cab730994f3 draft
Keepalive: rename tests.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 22 Jan 2013 19:05:49 +0400 |
parents | t/proxy.t@52ca695446d3 |
children | 450ad1052368 |
rev | line source |
---|---|
27 | 1 #!/usr/bin/perl |
2 | |
3 # (C) Maxim Dounin | |
4 | |
5 # Tests for proxy with keepalive. | |
6 | |
7 ############################################################################### | |
8 | |
9 use warnings; | |
10 use strict; | |
11 | |
12 use Test::More; | |
13 use IO::Socket::INET; | |
14 use Socket qw/ CRLF /; | |
15 | |
16 use Test::Nginx; | |
17 | |
18 ############################################################################### | |
19 | |
20 select STDERR; $| = 1; | |
21 select STDOUT; $| = 1; | |
22 | |
23 my $t = Test::Nginx->new()->has(qw/http proxy ssi rewrite/) | |
24 ->write_file_expand('nginx.conf', <<'EOF'); | |
25 | |
26 %%TEST_GLOBALS%% | |
27 | |
28 daemon off; | |
29 | |
30 events { | |
31 } | |
32 | |
33 http { | |
34 %%TEST_GLOBALS_HTTP%% | |
35 | |
36 upstream backend { | |
37 server 127.0.0.1:8081; | |
38 keepalive 1; | |
39 } | |
40 | |
41 server { | |
42 listen 127.0.0.1:8080; | |
43 server_name localhost; | |
44 | |
45 proxy_read_timeout 2s; | |
46 proxy_http_version 1.1; | |
47 proxy_set_header Connection ""; | |
48 | |
49 location / { | |
50 proxy_pass http://backend; | |
51 } | |
52 | |
53 location /unbuffered/ { | |
54 proxy_pass http://backend; | |
55 proxy_buffering off; | |
56 } | |
57 | |
58 location /inmemory/ { | |
59 ssi on; | |
60 rewrite ^ /ssi.html break; | |
61 } | |
62 } | |
63 } | |
64 | |
65 EOF | |
66 | |
67 $t->write_file('ssi.html', | |
68 '<!--#include virtual="/include$request_uri" set="x" -->' . | |
69 'set: <!--#echo var="x" -->'); | |
70 | |
71 $t->run_daemon(\&http_daemon); | |
72 | |
73 eval { | |
74 open OLDERR, ">&", \*STDERR; close STDERR; | |
75 $t->run(); | |
76 open STDERR, ">&", \*OLDERR; | |
77 }; | |
78 plan(skip_all => 'no keepalive patches') if $@; | |
79 | |
33
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
80 $t->plan(50); |
27 | 81 |
82 ############################################################################### | |
83 | |
84 # There are 3 mostly independend modes of upstream operation: | |
85 # | |
86 # 1. Buffered, i.e. normal mode with "proxy_buffering on;" | |
87 # 2. Unbuffered, i.e. "proxy_buffering off;". | |
88 # 3. In memory, i.e. ssi <!--#include ... set --> | |
89 # | |
90 # These all should be tested. | |
91 | |
92 my ($r, $n); | |
93 | |
94 # buffered | |
95 | |
96 like($r = http_get('/buffered/length1'), qr/SEE-THIS/, 'buffered'); | |
97 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
98 like(http_get('/buffered/length2'), qr/X-Connection: $n.*SEE/ms, 'buffered 2'); | |
99 | |
100 like($r = http_get('/buffered/chunked1'), qr/SEE-THIS/, 'buffered chunked'); | |
101 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
102 like(http_get('/buffered/chunked2'), qr/X-Connection: $n/, | |
103 'buffered chunked 2'); | |
104 | |
105 like($r = http_get('/buffered/complex1'), qr/(0123456789){100}/, | |
106 'buffered complex chunked'); | |
107 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
108 like(http_get('/buffered/complex2'), qr/X-Connection: $n/, | |
109 'buffered complex chunked 2'); | |
110 | |
111 like($r = http_get('/buffered/chunk01'), qr/200 OK/, 'buffered 0 chunk'); | |
112 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
113 like(http_get('/buffered/chunk02'), qr/X-Connection: $n/, 'buffered 0 chunk 2'); | |
114 | |
115 like($r = http_head('/buffered/length/head1'), qr/(?!SEE-THIS)/, | |
116 'buffered head'); | |
117 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
118 like(http_head('/buffered/length/head2'), qr/X-Connection: $n/, | |
119 'buffered head 2'); | |
120 | |
121 like($r = http_get('/buffered/empty1'), qr/200 OK/, 'buffered empty'); | |
122 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
123 like(http_get('/buffered/empty2'), qr/X-Connection: $n/, 'buffered empty 2'); | |
124 | |
125 like($r = http_get('/buffered/304nolen1'), qr/304 Not/, 'buffered 304'); | |
126 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
127 like(http_get('/buffered/304nolen2'), qr/X-Connection: $n/, 'buffered 304 2'); | |
128 | |
129 like($r = http_get('/buffered/304len1'), qr/304 Not/, | |
130 'buffered 304 with length'); | |
131 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
132 like(http_get('/buffered/304len2'), qr/X-Connection: $n/, | |
133 'buffered 304 with length 2'); | |
134 | |
135 # unbuffered | |
136 | |
137 like($r = http_get('/unbuffered/length1'), qr/SEE-THIS/, 'unbuffered'); | |
138 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
139 like(http_get('/unbuffered/length2'), qr/X-Connection: $n/, 'unbuffered 2'); | |
140 | |
141 like($r = http_get('/unbuffered/chunked1'), qr/SEE-THIS/, 'unbuffered chunked'); | |
142 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
143 like(http_get('/unbuffered/chunked2'), qr/X-Connection: $n/, | |
144 'unbuffered chunked 2'); | |
145 | |
146 like($r = http_get('/unbuffered/complex1'), qr/(0123456789){100}/, | |
147 'unbuffered complex chunked'); | |
148 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
149 like(http_get('/unbuffered/complex2'), qr/X-Connection: $n/, | |
150 'unbuffered complex chunked 2'); | |
151 | |
152 like($r = http_get('/unbuffered/chunk01'), qr/200 OK/, 'unbuffered 0 chunk'); | |
153 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
154 like(http_get('/unbuffered/chunk02'), qr/X-Connection: $n/, | |
155 'unbuffered 0 chunk 2'); | |
156 | |
157 like($r = http_get('/unbuffered/empty1'), qr/200 OK/, 'unbuffered empty'); | |
158 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
159 like(http_get('/unbuffered/empty2'), qr/X-Connection: $n/, | |
160 'unbuffered empty 2'); | |
161 | |
162 like($r = http_head('/unbuffered/length/head1'), qr/(?!SEE-THIS)/, | |
163 'unbuffered head'); | |
164 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
165 like(http_head('/unbuffered/length/head2'), qr/X-Connection: $n/, | |
166 'unbuffered head 2'); | |
167 | |
168 like($r = http_get('/unbuffered/304nolen1'), qr/304 Not/, 'unbuffered 304'); | |
169 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
170 like(http_get('/unbuffered/304nolen2'), qr/X-Connection: $n/, | |
171 'unbuffered 304 2'); | |
172 | |
173 like($r = http_get('/unbuffered/304len1'), qr/304 Not/, | |
174 'unbuffered 304 with length'); | |
175 $r =~ m/X-Connection: (\d+)/; $n = $1; | |
176 like(http_get('/unbuffered/304len2'), qr/X-Connection: $n/, | |
177 'unbuffered 304 with length 2'); | |
178 | |
179 # in memory | |
180 | |
181 like($r = http_get('/inmemory/length1'), qr/SEE-THIS/, 'inmemory'); | |
182 $r =~ m/SEE-THIS(\d+)/; $n = $1; | |
183 like(http_get('/inmemory/length2'), qr/SEE-THIS$n/, 'inmemory 2'); | |
184 | |
185 like($r = http_get('/inmemory/empty1'), qr/200 OK/, 'inmemory empty'); | |
186 $r =~ m/SEE-THIS(\d+)/; $n = $1; | |
187 like(http_get('/inmemory/empty2'), qr/200 OK/, 'inmemory empty 2'); | |
188 | |
189 like($r = http_get('/inmemory/chunked1'), qr/SEE-THIS/, 'inmemory chunked'); | |
190 $r =~ m/SEE-THIS(\d+)/; $n = $1; | |
191 like(http_get('/inmemory/chunked2'), qr/SEE-THIS$n/, 'inmemory chunked 2'); | |
192 | |
193 like($r = http_get('/inmemory/complex1'), qr/(0123456789){100}/, | |
194 'inmemory complex chunked'); | |
195 $r =~ m/SEE-THIS(\d+)/; $n = $1; | |
196 like(http_get('/inmemory/complex2'), qr/SEE-THIS$n/, | |
197 'inmemory complex chunked 2'); | |
198 | |
199 like(http_get('/inmemory/chunk01'), qr/set: $/, 'inmemory 0 chunk'); | |
200 like(http_get('/inmemory/chunk02'), qr/set: $/, 'inmemory 0 chunk 2'); | |
201 | |
33
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
202 # closed connection tests |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
203 |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
204 like(http_get('/buffered/closed1'), qr/200 OK/, 'buffered closed 1'); |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
205 like(http_get('/buffered/closed2'), qr/200 OK/, 'buffered closed 2'); |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
206 like(http_get('/unbuffered/closed1'), qr/200 OK/, 'unbuffered closed 1'); |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
207 like(http_get('/unbuffered/closed2'), qr/200 OK/, 'unbuffered closed 2'); |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
208 like(http_get('/inmemory/closed1'), qr/200 OK/, 'inmemory closed 1'); |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
209 like(http_get('/inmemory/closed2'), qr/200 OK/, 'inmemory closed 2'); |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
210 |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
211 # check for errors, shouldn't be any |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
212 |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
213 like(`grep -F '[alert]' ${\($t->testdir())}/error.log`, qr/^$/s, 'no alerts'); |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
214 like(`grep -F '[error]' ${\($t->testdir())}/error.log`, qr/^$/s, 'no errors'); |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
215 |
27 | 216 ############################################################################### |
217 | |
218 sub http_daemon { | |
219 my $server = IO::Socket::INET->new( | |
220 Proto => 'tcp', | |
221 LocalHost => '127.0.0.1:8081', | |
222 Listen => 5, | |
223 Reuse => 1 | |
224 ) | |
225 or die "Can't create listening socket: $!\n"; | |
226 | |
227 my $ccount = 0; | |
228 my $rcount = 0; | |
229 | |
230 # dumb server which is able to keep connections alive | |
231 | |
232 while (my $client = $server->accept()) { | |
233 Test::Nginx::log_core('||', "connection from " . $client->peerhost()); | |
234 $client->autoflush(1); | |
235 $ccount++; | |
236 | |
237 while (1) { | |
238 my $headers = ''; | |
239 my $uri = ''; | |
240 | |
241 while (<$client>) { | |
242 Test::Nginx::log_core('||', $_); | |
243 $headers .= $_; | |
244 last if (/^\x0d?\x0a?$/); | |
245 } | |
246 | |
247 last if $headers eq ''; | |
248 $rcount++; | |
249 | |
250 $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i; | |
251 | |
252 if ($uri =~ m/length/) { | |
253 print $client | |
254 "HTTP/1.1 200 OK" . CRLF . | |
255 "X-Request: $rcount" . CRLF . | |
256 "X-Connection: $ccount" . CRLF . | |
257 "Content-Length: 26" . CRLF . CRLF; | |
258 print $client "TEST-OK-IF-YOU-SEE-THIS" . | |
259 sprintf("%03d", $ccount) | |
260 unless $headers =~ /^HEAD/i; | |
261 | |
262 } elsif ($uri =~ m/empty/) { | |
263 print $client | |
264 "HTTP/1.1 200 OK" . CRLF . | |
265 "X-Request: $rcount" . CRLF . | |
266 "X-Connection: $ccount" . CRLF . | |
267 "Content-Length: 0" . CRLF . CRLF; | |
268 | |
269 } elsif ($uri =~ m/304nolen/) { | |
270 print $client | |
271 "HTTP/1.1 304 Not Modified" . CRLF . | |
272 "X-Request: $rcount" . CRLF . | |
273 "X-Connection: $ccount" . CRLF . CRLF; | |
274 | |
275 } elsif ($uri =~ m/304len/) { | |
276 print $client | |
277 "HTTP/1.1 304 Not Modified" . CRLF . | |
278 "X-Request: $rcount" . CRLF . | |
279 "X-Connection: $ccount" . CRLF . | |
280 "Content-Length: 100" . CRLF . CRLF; | |
281 | |
282 } elsif ($uri =~ m/chunked/) { | |
283 print $client | |
284 "HTTP/1.1 200 OK" . CRLF . | |
285 "X-Request: $rcount" . CRLF . | |
286 "X-Connection: $ccount" . CRLF . | |
287 "Transfer-Encoding: chunked" . CRLF . | |
288 CRLF; | |
289 print $client | |
290 "1a" . CRLF . | |
291 "TEST-OK-IF-YOU-SEE-THIS" . | |
292 sprintf("%03d", $ccount) . CRLF . | |
293 "0" . CRLF . CRLF | |
294 unless $headers =~ /^HEAD/i; | |
295 | |
296 } elsif ($uri =~ m/complex/) { | |
297 print $client | |
298 "HTTP/1.1 200 OK" . CRLF . | |
299 "X-Request: $rcount" . CRLF . | |
300 "X-Connection: $ccount" . CRLF . | |
301 "Transfer-Encoding: chunked" . CRLF . | |
302 CRLF; | |
303 | |
304 if ($headers !~ /^HEAD/i) { | |
305 for my $n (1..100) { | |
306 print $client | |
307 "a" . CRLF . | |
308 "0123456789" . CRLF; | |
309 select undef, undef, undef, 0.01 | |
310 if $n % 50 == 0; | |
311 } | |
312 print $client | |
313 "1a" . CRLF . | |
314 "TEST-OK-IF-YOU-SEE-THIS" . | |
315 sprintf("%03d", $ccount) . | |
316 CRLF . | |
317 "0" . CRLF; | |
318 select undef, undef, undef, 0.05; | |
319 print $client CRLF; | |
320 } | |
321 | |
322 } elsif ($uri =~ m/chunk0/) { | |
323 print $client | |
324 "HTTP/1.1 200 OK" . CRLF . | |
325 "X-Request: $rcount" . CRLF . | |
326 "X-Connection: $ccount" . CRLF . | |
327 "Transfer-Encoding: chunked" . CRLF . | |
328 CRLF; | |
329 print $client | |
330 "0" . CRLF . CRLF | |
331 unless $headers =~ /^HEAD/i; | |
332 | |
33
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
333 } elsif ($uri =~ m/closed/) { |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
334 print $client |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
335 "HTTP/1.1 200 OK" . CRLF . |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
336 "X-Request: $rcount" . CRLF . |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
337 "X-Connection: $ccount" . CRLF . |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
338 "Connection: close" . CRLF . |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
339 "Content-Length: 12" . CRLF . CRLF . |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
340 "0123456789" . CRLF; |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
341 last; |
52ca695446d3
Keepalive: more connection validity checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
27
diff
changeset
|
342 |
27 | 343 } else { |
344 print $client | |
345 "HTTP/1.1 404 Not Found" . CRLF . | |
346 "X-Request: $rcount" . CRLF . | |
347 "X-Connection: $ccount" . CRLF . | |
348 "Connection: close" . CRLF . CRLF . | |
349 "Oops, '$uri' not found" . CRLF; | |
350 last; | |
351 } | |
352 } | |
353 | |
354 close $client; | |
355 } | |
356 } | |
357 | |
358 ############################################################################### |