comparison 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
comparison
equal deleted inserted replaced
46:92125e266aa4 47:5cab730994f3
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
80 $t->plan(50);
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
202 # closed connection tests
203
204 like(http_get('/buffered/closed1'), qr/200 OK/, 'buffered closed 1');
205 like(http_get('/buffered/closed2'), qr/200 OK/, 'buffered closed 2');
206 like(http_get('/unbuffered/closed1'), qr/200 OK/, 'unbuffered closed 1');
207 like(http_get('/unbuffered/closed2'), qr/200 OK/, 'unbuffered closed 2');
208 like(http_get('/inmemory/closed1'), qr/200 OK/, 'inmemory closed 1');
209 like(http_get('/inmemory/closed2'), qr/200 OK/, 'inmemory closed 2');
210
211 # check for errors, shouldn't be any
212
213 like(`grep -F '[alert]' ${\($t->testdir())}/error.log`, qr/^$/s, 'no alerts');
214 like(`grep -F '[error]' ${\($t->testdir())}/error.log`, qr/^$/s, 'no errors');
215
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
333 } elsif ($uri =~ m/closed/) {
334 print $client
335 "HTTP/1.1 200 OK" . CRLF .
336 "X-Request: $rcount" . CRLF .
337 "X-Connection: $ccount" . CRLF .
338 "Connection: close" . CRLF .
339 "Content-Length: 12" . CRLF . CRLF .
340 "0123456789" . CRLF;
341 last;
342
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 ###############################################################################