Mercurial > hg > nginx-tests
annotate spdy.t @ 431:05c46688b54b
Tests: ssl_password_file.t fixes.
Make sure to always specify listen socket in all servers as the
default vary (under root, nginx will try to listen on 80). Make sure
to detect if an https request was processed by http.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 09 Jul 2014 05:19:51 +0400 |
parents | 89f7a882d692 |
children | cc4697d6bd16 |
rev | line source |
---|---|
374 | 1 #!/usr/bin/perl |
2 | |
3 # (C) Sergey Kandaurov | |
4 # (C) Nginx, Inc. | |
5 | |
6 # Tests for SPDY protocol version 3.1. | |
7 | |
8 ############################################################################### | |
9 | |
10 use warnings; | |
11 use strict; | |
12 | |
13 use Test::More; | |
14 | |
15 use IO::Select; | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
16 use Socket qw/ CRLF /; |
374 | 17 |
18 BEGIN { use FindBin; chdir($FindBin::Bin); } | |
19 | |
20 use lib 'lib'; | |
21 use Test::Nginx; | |
22 | |
23 ############################################################################### | |
24 | |
25 select STDERR; $| = 1; | |
26 select STDOUT; $| = 1; | |
27 | |
28 eval { | |
29 require Compress::Raw::Zlib; | |
30 Compress::Raw::Zlib->Z_OK; | |
31 Compress::Raw::Zlib->Z_SYNC_FLUSH; | |
32 Compress::Raw::Zlib->Z_NO_COMPRESSION; | |
33 Compress::Raw::Zlib->WANT_GZIP_OR_ZLIB; | |
34 }; | |
35 plan(skip_all => 'Compress::Raw::Zlib not installed') if $@; | |
36 plan(skip_all => 'win32') if $^O eq 'MSWin32'; | |
37 | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
38 my $t = Test::Nginx->new() |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
39 ->has(qw/http proxy cache limit_conn rewrite spdy realip/); |
374 | 40 |
428
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
41 $t->plan(76)->write_file_expand('nginx.conf', <<'EOF'); |
374 | 42 |
43 %%TEST_GLOBALS%% | |
44 | |
45 daemon off; | |
46 | |
47 events { | |
48 } | |
49 | |
50 http { | |
51 %%TEST_GLOBALS_HTTP%% | |
52 | |
53 proxy_cache_path %%TESTDIR%%/cache keys_zone=NAME:10m; | |
54 limit_conn_zone $binary_remote_addr zone=conn:1m; | |
55 | |
56 server { | |
57 listen 127.0.0.1:8080 spdy; | |
58 listen 127.0.0.1:8081; | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
59 listen 127.0.0.1:8082 proxy_protocol spdy; |
374 | 60 server_name localhost; |
61 | |
62 location /s { | |
63 add_header X-Header X-Foo; | |
64 return 200 'body'; | |
65 } | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
66 location /pp { |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
67 set_real_ip_from 127.0.0.1/32; |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
68 real_ip_header proxy_protocol; |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
69 alias %%TESTDIR%%/t2.html; |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
70 add_header X-PP $remote_addr; |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
71 } |
374 | 72 location /spdy { |
73 return 200 $spdy; | |
74 } | |
75 location /prio { | |
76 return 200 $spdy_request_priority; | |
77 } | |
78 location /chunk_size { | |
79 spdy_chunk_size 1; | |
80 return 200 'body'; | |
81 } | |
82 location /redirect { | |
83 error_page 405 /s; | |
84 return 405; | |
85 } | |
86 location /proxy { | |
87 add_header X-Body "$request_body"; | |
88 proxy_pass http://127.0.0.1:8081/; | |
89 proxy_cache NAME; | |
90 proxy_cache_valid 1m; | |
91 } | |
428
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
92 location /proxy_buffering_off { |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
93 proxy_pass http://127.0.0.1:8081/; |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
94 proxy_cache NAME; |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
95 proxy_cache_valid 1m; |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
96 proxy_buffering off; |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
97 } |
374 | 98 location /t3.html { |
99 limit_conn conn 1; | |
100 } | |
101 } | |
102 } | |
103 | |
104 EOF | |
105 | |
106 $t->run(); | |
107 | |
108 # file size is slightly beyond initial window size: 2**16 + 80 bytes | |
109 | |
110 $t->write_file('t1.html', | |
111 join('', map { sprintf "X%04dXXX", $_ } (1 .. 8202))); | |
112 | |
113 $t->write_file('t2.html', 'SEE-THIS'); | |
114 $t->write_file('t3.html', 'SEE-THIS'); | |
115 | |
116 my %cframe = ( | |
117 2 => \&syn_reply, | |
118 3 => \&rst_stream, | |
119 4 => \&settings, | |
120 6 => \&ping, | |
121 7 => \&goaway, | |
122 9 => \&window_update | |
123 ); | |
124 | |
125 ############################################################################### | |
126 | |
127 # PING | |
128 | |
129 my $sess = new_session(); | |
130 spdy_ping($sess, 0x12345678); | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
131 my $frames = spdy_read($sess, all => [{ type => 'PING' }]); |
374 | 132 |
133 my ($frame) = grep { $_->{type} eq "PING" } @$frames; | |
134 ok($frame, 'PING frame'); | |
135 is($frame->{value}, 0x12345678, 'PING payload'); | |
136 | |
137 # GET | |
138 | |
139 $sess = new_session(); | |
140 my $sid1 = spdy_stream($sess, { path => '/s' }); | |
141 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
142 | |
143 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
144 ok($frame, 'SYN_REPLAY frame'); | |
145 is($frame->{sid}, $sid1, 'SYN_REPLAY stream'); | |
146 is($frame->{headers}->{':status'}, 200, 'SYN_REPLAY status'); | |
147 is($frame->{headers}->{'x-header'}, 'X-Foo', 'SYN_REPLAY header'); | |
148 | |
149 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
150 ok($frame, 'DATA frame'); | |
151 is($frame->{length}, length 'body', 'DATA length'); | |
152 is($frame->{data}, 'body', 'DATA payload'); | |
153 | |
154 # GET in new SPDY stream in same session | |
155 | |
156 my $sid2 = spdy_stream($sess, { path => '/s' }); | |
157 $frames = spdy_read($sess, all => [{ sid => $sid2, fin => 1 }]); | |
158 | |
159 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
160 is($frame->{sid}, $sid2, 'SYN_REPLAY stream 2'); | |
161 is($frame->{headers}->{':status'}, 200, 'SYN_REPLAY status 2'); | |
162 is($frame->{headers}->{'x-header'}, 'X-Foo', 'SYN_REPLAY header 2'); | |
163 | |
164 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
165 ok($frame, 'DATA frame 2'); | |
166 is($frame->{sid}, $sid2, 'SYN_REPLAY stream 2'); | |
167 is($frame->{length}, length 'body', 'DATA length 2'); | |
168 is($frame->{data}, 'body', 'DATA payload 2'); | |
169 | |
170 # HEAD | |
171 | |
172 $sess = new_session(); | |
173 $sid1 = spdy_stream($sess, { path => '/s', method => 'HEAD' }); | |
174 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
175 | |
176 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
177 is($frame->{sid}, $sid1, 'SYN_REPLAY stream HEAD'); | |
178 is($frame->{headers}->{':status'}, 200, 'SYN_REPLAY status HEAD'); | |
179 is($frame->{headers}->{'x-header'}, 'X-Foo', 'SYN_REPLAY header HEAD'); | |
180 | |
181 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
182 is($frame, undef, 'HEAD no body'); | |
183 | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
184 # GET with PROXY protocol |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
185 |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
186 my $proxy = 'PROXY TCP4 192.0.2.1 192.0.2.2 1234 5678' . CRLF; |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
187 $sess = new_session(8082, proxy => $proxy); |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
188 $sid1 = spdy_stream($sess, { path => '/pp' }); |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
189 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
190 |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
191 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
192 ok($frame, 'PROXY SYN_REPLAY frame'); |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
193 is($frame->{headers}->{'x-pp'}, '192.0.2.1', 'PROXY remote addr'); |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
194 |
374 | 195 # request header |
196 | |
197 $sess = new_session(); | |
198 $sid1 = spdy_stream($sess, { path => '/t1.html', | |
199 headers => { "range" => "bytes=10-19" } | |
200 }); | |
201 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
202 | |
203 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
204 is($frame->{headers}->{':status'}, 206, 'SYN_REPLAY status range'); | |
205 | |
206 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
207 is($frame->{length}, 10, 'DATA length range'); | |
208 is($frame->{data}, '002XXXX000', 'DATA payload range'); | |
209 | |
210 # $spdy | |
211 | |
212 $sess = new_session(); | |
213 $sid1 = spdy_stream($sess, { path => '/spdy' }); | |
214 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
215 | |
216 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
217 is($frame->{data}, '3.1', 'spdy variable'); | |
218 | |
219 # spdy_chunk_size=1 | |
220 | |
221 $sess = new_session(); | |
222 $sid1 = spdy_stream($sess, { path => '/chunk_size' }); | |
223 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
224 | |
225 my @data = grep { $_->{type} eq "DATA" } @$frames; | |
226 is(@data, 4, 'chunk_size body chunks'); | |
227 is($data[0]->{data}, 'b', 'chunk_size body 1'); | |
228 is($data[1]->{data}, 'o', 'chunk_size body 2'); | |
229 is($data[2]->{data}, 'd', 'chunk_size body 3'); | |
230 is($data[3]->{data}, 'y', 'chunk_size body 4'); | |
231 | |
232 # redirect | |
233 | |
234 $sess = new_session(); | |
235 $sid1 = spdy_stream($sess, { path => '/redirect' }); | |
236 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
237 | |
238 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
239 is($frame->{headers}->{':status'}, 405, 'SYN_REPLAY status with redirect'); | |
240 | |
241 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
242 ok($frame, 'DATA frame with redirect'); | |
243 is($frame->{data}, 'body', 'DATA payload with redirect'); | |
244 | |
428
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
245 # SYN_REPLY could be received with fin, followed by DATA |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
246 |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
247 $sess = new_session(); |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
248 $sid1 = spdy_stream($sess, { path => '/proxy/t2.html', method => 'HEAD' }); |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
249 |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
250 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
251 push @$frames, $_ for @{spdy_read($sess, all => [{ sid => $sid1 }])}; |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
252 ok(!grep ({ $_->{type} eq "DATA" } @$frames), 'proxy cache HEAD - no body'); |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
253 |
374 | 254 # ensure that HEAD-like requests, i.e., without response body, do not lead to |
255 # client connection close due to cache filling up with upstream response body | |
256 | |
257 TODO: { | |
429
89f7a882d692
Tests: spdy.t TODO updated.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
258 local $TODO = 'premature client connection close' |
89f7a882d692
Tests: spdy.t TODO updated.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
259 unless $t->has_version('1.7.3'); |
374 | 260 |
261 $sid2 = spdy_stream($sess, { path => '/' }); | |
262 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
263 ok(grep ({ $_->{type} eq "SYN_REPLY" } @$frames), 'proxy cache headers only'); | |
264 | |
265 } | |
266 | |
428
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
267 # HEAD on empty cache with proxy_buffering off |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
268 |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
269 $sess = new_session(); |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
270 $sid1 = spdy_stream($sess, |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
271 { path => '/proxy_buffering_off/t2.html?1', method => 'HEAD' }); |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
272 |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
273 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
274 push @$frames, $_ for @{spdy_read($sess, all => [{ sid => $sid1 }])}; |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
275 ok(!grep ({ $_->{type} eq "DATA" } @$frames), |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
276 'proxy cache HEAD buffering off - no body'); |
e95c3340d94a
Tests: more SPDY tests for caching HEAD requests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
427
diff
changeset
|
277 |
374 | 278 # simple proxy cache test |
279 | |
280 $sess = new_session(); | |
281 $sid1 = spdy_stream($sess, { path => '/proxy/t2.html' }); | |
282 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
283 | |
284 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
285 is($frame->{headers}->{':status'}, '200 OK', 'proxy cache unconditional'); | |
286 | |
287 $sid2 = spdy_stream($sess, { path => '/proxy/t2.html', | |
416
5c25acbc870a
Tests: etags support is present in all supported branches.
Maxim Dounin <mdounin@mdounin.ru>
parents:
397
diff
changeset
|
288 headers => { "if-none-match" => $frame->{headers}->{'etag'} } |
374 | 289 }); |
290 $frames = spdy_read($sess, all => [{ sid => $sid2, fin => 1 }]); | |
291 | |
292 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
293 is($frame->{headers}->{':status'}, 304, 'proxy cache conditional'); | |
294 | |
295 # request body (uses proxied response) | |
296 | |
297 $sess = new_session(); | |
298 $sid1 = spdy_stream($sess, { path => '/proxy/t2.html', body => 'TEST' }); | |
299 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
300 | |
301 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
302 is($frame->{headers}->{'x-body'}, 'TEST', 'request body'); | |
303 | |
304 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
305 is($frame->{length}, length 'SEE-THIS', 'proxied response length'); | |
306 is($frame->{data}, 'SEE-THIS', 'proxied response'); | |
307 | |
308 # WINDOW_UPDATE (client side) | |
309 | |
310 $sess = new_session(); | |
311 $sid1 = spdy_stream($sess, { path => '/t1.html' }); | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
312 $frames = spdy_read($sess, all => [{ sid => $sid1, length => 2**16 }]); |
374 | 313 |
314 @data = grep { $_->{type} eq "DATA" } @$frames; | |
315 my $sum = eval join '+', map { $_->{length} } @data; | |
316 is($sum, 2**16, 'iws - stream blocked on initial window size'); | |
317 | |
318 spdy_ping($sess, 0xf00ff00f); | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
319 $frames = spdy_read($sess, all => [{ type => 'PING' }]); |
374 | 320 |
321 ($frame) = grep { $_->{type} eq "PING" } @$frames; | |
322 ok($frame, 'iws - PING not blocked'); | |
323 | |
324 spdy_window($sess, 2**16, $sid1); | |
325 $frames = spdy_read($sess); | |
326 is(@$frames, 0, 'iws - updated stream window'); | |
327 | |
328 spdy_window($sess, 2**16); | |
329 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
330 | |
331 @data = grep { $_->{type} eq "DATA" } @$frames; | |
332 $sum = eval join '+', map { $_->{length} } @data; | |
333 is($sum, 80, 'iws - updated connection window'); | |
334 | |
335 # SETTINGS (initial window size, client side) | |
336 | |
337 $sess = new_session(); | |
338 spdy_settings($sess, 7 => 2**17); | |
339 spdy_window($sess, 2**17); | |
340 | |
341 $sid1 = spdy_stream($sess, { path => '/t1.html' }); | |
342 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
343 | |
344 @data = grep { $_->{type} eq "DATA" } @$frames; | |
345 $sum = eval join '+', map { $_->{length} } @data; | |
346 is($sum, 2**16 + 80, 'increased initial window size'); | |
347 | |
348 # probe for negative available space in a flow control window | |
349 | |
350 $sess = new_session(); | |
351 $sid1 = spdy_stream($sess, { path => '/t1.html' }); | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
352 spdy_read($sess, all => [{ sid => $sid1, length => 2**16 }]); |
374 | 353 |
354 spdy_window($sess, 1); | |
355 spdy_settings($sess, 7 => 42); | |
356 spdy_window($sess, 1024, $sid1); | |
357 | |
358 $frames = spdy_read($sess); | |
359 is(@$frames, 0, 'negative window - no data'); | |
360 | |
361 spdy_window($sess, 2**16 - 42 - 1024, $sid1); | |
362 $frames = spdy_read($sess); | |
363 is(@$frames, 0, 'zero window - no data'); | |
364 | |
365 spdy_window($sess, 1, $sid1); | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
366 $frames = spdy_read($sess, all => [{ sid => $sid1, length => 1 }]); |
374 | 367 is(@$frames, 1, 'positive window - data'); |
368 is(@$frames[0]->{length}, 1, 'positive window - data length'); | |
369 | |
370 # stream multiplexing | |
371 | |
372 $sess = new_session(); | |
373 $sid1 = spdy_stream($sess, { path => '/t1.html' }); | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
374 $frames = spdy_read($sess, all => [{ sid => $sid1, length => 2**16 }]); |
374 | 375 |
376 @data = grep { $_->{type} eq "DATA" } @$frames; | |
377 $sum = eval join '+', map { $_->{length} } @data; | |
378 is($sum, 2**16, 'multiple - stream1 data'); | |
379 | |
380 $sid2 = spdy_stream($sess, { path => '/t1.html' }); | |
381 $frames = spdy_read($sess, all => [{ sid => $sid2, fin => 0 }]); | |
382 | |
383 @data = grep { $_->{type} eq "DATA" } @$frames; | |
384 is(@data, 0, 'multiple - stream2 no data'); | |
385 | |
386 spdy_window($sess, 2**17, $sid1); | |
387 spdy_window($sess, 2**17, $sid2); | |
388 spdy_window($sess, 2**17); | |
389 | |
390 $frames = spdy_read($sess, all => [ | |
391 { sid => $sid1, fin => 1 }, | |
392 { sid => $sid2, fin => 1 } | |
393 ]); | |
394 | |
395 @data = grep { $_->{type} eq "DATA" && $_->{sid} == $sid1 } @$frames; | |
396 $sum = eval join '+', map { $_->{length} } @data; | |
397 is($sum, 80, 'multiple - stream1 remain data'); | |
398 | |
399 @data = grep { $_->{type} eq "DATA" && $_->{sid} == $sid2 } @$frames; | |
400 $sum = eval join '+', map { $_->{length} } @data; | |
401 is($sum, 2**16 + 80, 'multiple - stream2 full data'); | |
402 | |
403 # request priority parsing in $spdy_request_priority | |
404 | |
405 $sess = new_session(); | |
406 $sid1 = spdy_stream($sess, { path => '/prio', prio => 0 }); | |
407 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
408 | |
409 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
410 is($frame->{data}, 0, 'priority 0'); | |
411 | |
412 $sid1 = spdy_stream($sess, { path => '/prio', prio => 1 }); | |
413 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
414 | |
415 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
416 is($frame->{data}, 1, 'priority 1'); | |
417 | |
418 $sid1 = spdy_stream($sess, { path => '/prio', prio => 7 }); | |
419 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
420 | |
421 ($frame) = grep { $_->{type} eq "DATA" } @$frames; | |
422 is($frame->{data}, 7, 'priority 7'); | |
423 | |
424 # stream muliplexing + priority | |
425 | |
426 $sess = new_session(); | |
427 $sid1 = spdy_stream($sess, { path => '/t1.html', prio => 7 }); | |
428 $sid2 = spdy_stream($sess, { path => '/t2.html', prio => 0 }); | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
429 spdy_read($sess, all => [ |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
430 { sid => $sid1, length => 2**16 }, |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
431 { sid => $sid2, fin => 0 } |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
432 ]); |
374 | 433 |
434 spdy_window($sess, 2**17, $sid1); | |
435 spdy_window($sess, 2**17, $sid2); | |
436 spdy_window($sess, 2**17); | |
437 | |
438 $frames = spdy_read($sess, all => [ | |
439 { sid => $sid1, fin => 1 }, | |
440 { sid => $sid2, fin => 1 } | |
441 ]); | |
442 | |
443 @data = grep { $_->{type} eq "DATA" } @$frames; | |
444 is(join (' ', map { $_->{sid} } @data), "$sid2 $sid1", 'multiple priority 1'); | |
445 | |
446 # and vice versa | |
447 | |
448 $sess = new_session(); | |
449 $sid1 = spdy_stream($sess, { path => '/t1.html', prio => 0 }); | |
450 $sid2 = spdy_stream($sess, { path => '/t2.html', prio => 7 }); | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
451 spdy_read($sess, all => [ |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
452 { sid => $sid1, length => 2**16 }, |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
453 { sid => $sid2, fin => 0 } |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
454 ]); |
374 | 455 |
456 spdy_window($sess, 2**17, $sid1); | |
457 spdy_window($sess, 2**17, $sid2); | |
458 spdy_window($sess, 2**17); | |
459 | |
460 $frames = spdy_read($sess, all => [ | |
461 { sid => $sid1, fin => 1 }, | |
462 { sid => $sid2, fin => 1 } | |
463 ]); | |
464 | |
465 @data = grep { $_->{type} eq "DATA" } @$frames; | |
466 is(join (' ', map { $_->{sid} } @data), "$sid1 $sid2", 'multiple priority 2'); | |
467 | |
468 # limit_conn | |
469 | |
470 $sess = new_session(); | |
471 spdy_settings($sess, 7 => 1); | |
472 $sid1 = spdy_stream($sess, { path => '/t3.html' }); | |
473 $sid2 = spdy_stream($sess, { path => '/t3.html' }); | |
474 $frames = spdy_read($sess, all => [ | |
475 { sid => $sid1, fin => 0 }, | |
476 { sid => $sid2, fin => 0 } | |
477 ]); | |
478 | |
479 ($frame) = grep { $_->{type} eq "SYN_REPLY" && $_->{sid} == $sid1 } @$frames; | |
480 is($frame->{headers}->{':status'}, 200, 'conn_limit 1'); | |
481 | |
482 ($frame) = grep { $_->{type} eq "SYN_REPLY" && $_->{sid} == $sid2 } @$frames; | |
483 is($frame->{headers}->{':status'}, 503, 'conn_limit 2'); | |
484 | |
485 # limit_conn + client's RST_STREAM | |
486 | |
487 $sess = new_session(); | |
488 spdy_settings($sess, 7 => 1); | |
489 $sid1 = spdy_stream($sess, { path => '/t3.html' }); | |
490 spdy_rst($sess, $sid1, 5); | |
491 $sid2 = spdy_stream($sess, { path => '/t3.html' }); | |
492 $frames = spdy_read($sess, all => [ | |
493 { sid => $sid1, fin => 0 }, | |
494 { sid => $sid2, fin => 0 } | |
495 ]); | |
496 | |
497 ($frame) = grep { $_->{type} eq "SYN_REPLY" && $_->{sid} == $sid1 } @$frames; | |
498 is($frame->{headers}->{':status'}, 200, 'RST_STREAM 1'); | |
499 | |
500 ($frame) = grep { $_->{type} eq "SYN_REPLY" && $_->{sid} == $sid2 } @$frames; | |
501 is($frame->{headers}->{':status'}, 200, 'RST_STREAM 2'); | |
502 | |
503 # GOAWAY on SYN_STREAM with even StreamID | |
504 | |
505 TODO: { | |
506 local $TODO = 'not yet'; | |
507 | |
508 $sess = new_session(); | |
509 spdy_stream($sess, { path => '/s' }, 2); | |
510 $frames = spdy_read($sess); | |
511 | |
512 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; | |
513 ok($frame, 'even stream - GOAWAY frame'); | |
514 is($frame->{code}, 1, 'even stream - error code'); | |
515 is($frame->{sid}, 0, 'even stream - last used stream'); | |
516 | |
517 } | |
518 | |
519 # GOAWAY on SYN_STREAM with backward StreamID | |
520 | |
521 TODO: { | |
522 local $TODO = 'not yet'; | |
523 | |
524 $sess = new_session(); | |
525 $sid1 = spdy_stream($sess, { path => '/s' }, 3); | |
526 spdy_read($sess); | |
527 | |
528 $sid2 = spdy_stream($sess, { path => '/s' }, 1); | |
529 $frames = spdy_read($sess); | |
530 | |
531 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; | |
532 ok($frame, 'backward stream - GOAWAY frame'); | |
533 is($frame->{code}, 1, 'backward stream - error code'); | |
534 is($frame->{sid}, $sid1, 'backward stream - last used stream'); | |
535 | |
536 } | |
537 | |
538 # RST_STREAM on the second SYN_STREAM with same StreamID | |
539 | |
540 TODO: { | |
541 local $TODO = 'not yet'; | |
542 | |
543 $sess = new_session(); | |
544 $sid1 = spdy_stream($sess, { path => '/s' }, 3); | |
545 spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
546 $sid2 = spdy_stream($sess, { path => '/s' }, 3); | |
547 $frames = spdy_read($sess); | |
548 | |
549 ($frame) = grep { $_->{type} eq "RST_STREAM" } @$frames; | |
550 ok($frame, 'dup stream - RST_STREAM frame'); | |
551 is($frame->{code}, 1, 'dup stream - error code'); | |
552 is($frame->{sid}, $sid1, 'dup stream - stream'); | |
553 | |
554 } | |
555 | |
556 # awkward protocol version | |
557 | |
558 $sess = new_session(); | |
559 $sid1 = spdy_stream($sess, { path => '/s', version => 'HTTP/1.10' }); | |
560 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
561 | |
562 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
563 is($frame->{headers}->{':status'}, 200, 'awkward version'); | |
564 | |
565 # missing mandatory request header | |
566 | |
567 $sess = new_session(); | |
568 $sid1 = spdy_stream($sess, { path => '/s', version => '' }); | |
569 $frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]); | |
570 | |
571 ($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames; | |
572 is($frame->{headers}->{':status'}, 400, 'incomplete headers'); | |
573 | |
574 # GOAWAY before closing a connection by server | |
575 | |
576 $t->stop(); | |
577 | |
578 TODO: { | |
579 local $TODO = 'not yet'; | |
580 | |
581 $frames = spdy_read($sess); | |
582 | |
583 ($frame) = grep { $_->{type} eq "GOAWAY" } @$frames; | |
584 ok($frame, 'GOAWAY on connection close'); | |
585 | |
586 } | |
587 | |
588 ############################################################################### | |
589 | |
590 sub spdy_ping { | |
591 my ($sess, $payload) = @_; | |
592 | |
593 raw_write($sess->{socket}, pack("N3", 0x80030006, 0x4, $payload)); | |
594 } | |
595 | |
596 sub spdy_rst { | |
597 my ($sess, $sid, $error) = @_; | |
598 | |
599 raw_write($sess->{socket}, pack("N4", 0x80030003, 0x8, $sid, $error)); | |
600 } | |
601 | |
602 sub spdy_window { | |
603 my ($sess, $win, $stream) = @_; | |
604 | |
605 $stream = 0 unless defined $stream; | |
606 raw_write($sess->{socket}, pack("N4", 0x80030009, 8, $stream, $win)); | |
607 } | |
608 | |
609 sub spdy_settings { | |
610 my ($sess, %extra) = @_; | |
611 | |
612 my $cnt = keys %extra; | |
613 my $len = 4 + 8 * $cnt; | |
614 | |
615 my $buf = pack "N3", 0x80030004, $len, $cnt; | |
616 $buf .= join '', map { pack "N2", $_, $extra{$_} } keys %extra; | |
617 raw_write($sess->{socket}, $buf); | |
618 } | |
619 | |
620 sub spdy_read { | |
621 my ($sess, %extra) = @_; | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
622 my ($length, @got); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
623 my $s = $sess->{socket}; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
624 my $buf = ''; |
374 | 625 |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
626 eval { |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
627 local $SIG{ALRM} = sub { die "timeout\n" }; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
628 local $SIG{PIPE} = sub { die "sigpipe\n" }; |
374 | 629 again: |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
630 alarm(1); |
374 | 631 |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
632 $buf = raw_read($s, $buf, 8); |
379
f42de3a9fd74
Tests: avoid uninitialized warnings in spdy.t.
Maxim Dounin <mdounin@mdounin.ru>
parents:
377
diff
changeset
|
633 |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
634 my $type = unpack("B", $buf); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
635 $length = 8 + hex unpack("x5 H6", $buf); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
636 $buf = raw_read($s, $buf, $length); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
637 |
374 | 638 if ($type == 0) { |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
639 push @got, dframe($buf); |
374 | 640 |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
641 } else { |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
642 my $ctype = unpack("x2 n", $buf); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
643 push @got, $cframe{$ctype}($sess, $buf); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
644 } |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
645 $buf = substr($buf, $length); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
646 |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
647 goto again if test_fin($got[-1], $extra{all}); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
648 alarm(0); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
649 }; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
650 alarm(0); |
374 | 651 return \@got; |
652 } | |
653 | |
654 sub test_fin { | |
655 my ($frame, $all) = @_; | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
656 my @test = @{$all}; |
374 | 657 |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
658 # wait for the specified DATA length |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
659 |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
660 for (@test) { |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
661 if ($_->{length} && $frame->{type} eq 'DATA') { |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
662 # check also for StreamID if needed |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
663 |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
664 if (!$_->{sid} || $_->{sid} == $frame->{sid}) { |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
665 $_->{length} -= $frame->{length}; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
666 } |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
667 } |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
668 } |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
669 @test = grep { !(defined $_->{length} && $_->{length} == 0) } @test; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
670 |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
671 # wait for the fin flag |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
672 |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
673 @test = grep { !(defined $_->{fin} |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
674 && $_->{sid} == $frame->{sid} && $_->{fin} == $frame->{fin}) |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
675 } @test if defined $frame->{fin}; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
676 |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
677 # wait for the specified frame |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
678 |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
679 @test = grep { !($_->{type} && $_->{type} eq $frame->{type}) } @test; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
680 |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
681 @{$all} = @test; |
374 | 682 } |
683 | |
684 sub dframe { | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
685 my ($buf) = @_; |
374 | 686 my %frame; |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
687 my $skip = 0; |
374 | 688 |
689 my $stream = unpack "\@$skip B32", $buf; $skip += 4; | |
690 substr($stream, 0, 1) = 0; | |
691 $stream = unpack("N", pack("B32", $stream)); | |
692 $frame{sid} = $stream; | |
693 | |
694 my $flags = unpack "\@$skip B8", $buf; $skip += 1; | |
695 $frame{fin} = substr($flags, 7, 1); | |
696 | |
697 my $length = hex (unpack "\@$skip H6", $buf); $skip += 3; | |
698 $frame{length} = $length; | |
699 | |
700 $frame{data} = substr($buf, $skip, $length); | |
701 $frame{type} = "DATA"; | |
702 return \%frame; | |
703 } | |
704 | |
705 sub spdy_stream { | |
706 my ($ctx, $uri, $stream) = @_; | |
707 my ($input, $output, $buf); | |
708 my ($d, $status); | |
709 | |
710 my $host = $uri->{host} || '127.0.0.1:8080'; | |
711 my $method = $uri->{method} || 'GET'; | |
712 my $headers = $uri->{headers} || {}; | |
713 my $body = $uri->{body}; | |
714 my $prio = defined $uri->{prio} ? $uri->{prio} : 4; | |
715 my $version = defined $uri->{version} ? $uri->{version} : "HTTP/1.1"; | |
716 | |
717 if ($stream) { | |
718 $ctx->{last_stream} = $stream; | |
719 } else { | |
720 $ctx->{last_stream} += 2; | |
721 } | |
722 | |
723 $buf = pack("NC", 0x80030001, not $body); | |
724 $buf .= pack("xxx"); # Length stub | |
725 $buf .= pack("N", $ctx->{last_stream}); # Stream-ID | |
726 $buf .= pack("N", 0); # Assoc. Stream-ID | |
727 $buf .= pack("n", $prio << 13); | |
728 | |
729 my $ent = 4 + keys %{$headers}; | |
730 $ent++ if $body; | |
731 $ent++ if $version; | |
732 | |
733 $input = pack("N", $ent); | |
734 $input .= hpack(":host", $host); | |
735 $input .= hpack(":method", $method); | |
736 $input .= hpack(":path", $uri->{path}); | |
737 $input .= hpack(":scheme", "http"); | |
738 if ($version) { | |
739 $input .= hpack(":version", $version); | |
740 } | |
741 if ($body) { | |
742 $input .= hpack("content-length", length $body); | |
743 } | |
744 $input .= join '', map { hpack($_, $headers->{$_}) } keys %{$headers}; | |
745 | |
746 $d = $ctx->{zlib}->{d}; | |
747 $status = $d->deflate($input => \my $start); | |
748 $status == Compress::Raw::Zlib->Z_OK or fail "deflate failed"; | |
749 $status = $d->flush(\my $tail => Compress::Raw::Zlib->Z_SYNC_FLUSH); | |
750 $status == Compress::Raw::Zlib->Z_OK or fail "flush failed"; | |
751 $output = $start . $tail; | |
752 | |
426
7cb6af00afdd
Tests: fixed SPDY tests with large header length.
Sergey Kandaurov <pluknet@nginx.com>
parents:
425
diff
changeset
|
753 # set length, attach headers and optional body |
7cb6af00afdd
Tests: fixed SPDY tests with large header length.
Sergey Kandaurov <pluknet@nginx.com>
parents:
425
diff
changeset
|
754 |
7cb6af00afdd
Tests: fixed SPDY tests with large header length.
Sergey Kandaurov <pluknet@nginx.com>
parents:
425
diff
changeset
|
755 $buf |= pack "x4N", length($output) + 10; |
374 | 756 $buf .= $output; |
757 | |
758 if (defined $body) { | |
759 $buf .= pack "NCxn", $ctx->{last_stream}, 0x01, length $body; | |
760 $buf .= $body; | |
761 } | |
762 | |
763 raw_write($ctx->{socket}, $buf); | |
764 return $ctx->{last_stream}; | |
765 } | |
766 | |
767 sub syn_reply { | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
768 my ($ctx, $buf) = @_; |
374 | 769 my ($i, $status); |
770 my %payload; | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
771 my $skip = 4; |
374 | 772 |
773 my $flags = unpack "\@$skip B8", $buf; $skip += 1; | |
774 $payload{fin} = substr($flags, 7, 1); | |
775 | |
776 my $length = hex unpack "\@$skip H6", $buf; $skip += 3; | |
777 $payload{length} = $length; | |
778 $payload{type} = 'SYN_REPLY'; | |
779 | |
780 my $stream = unpack "\@$skip B32", $buf; $skip += 4; | |
781 substr($stream, 0, 1) = 0; | |
782 $stream = unpack("N", pack("B32", $stream)); | |
783 $payload{sid} = $stream; | |
784 | |
785 my $input = substr($buf, $skip, $length - 4); | |
786 $i = $ctx->{zlib}->{i}; | |
787 | |
788 $status = $i->inflate($input => \my $out); | |
789 fail "Failed: $status" unless $status == Compress::Raw::Zlib->Z_OK; | |
790 $payload{headers} = hunpack($out); | |
791 return \%payload; | |
792 } | |
793 | |
794 sub rst_stream { | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
795 my ($ctx, $buf) = @_; |
374 | 796 my %payload; |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
797 my $skip = 5; |
374 | 798 |
799 $payload{length} = hex(unpack "\@$skip H6", $buf); $skip += 3; | |
800 $payload{type} = 'RST_STREAM'; | |
801 $payload{sid} = unpack "\@$skip N", $buf; $skip += 4; | |
802 $payload{code} = unpack "\@$skip N", $buf; | |
803 return \%payload; | |
804 } | |
805 | |
806 sub settings { | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
807 my ($ctx, $buf) = @_; |
374 | 808 my %payload; |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
809 my $skip = 4; |
374 | 810 |
811 $payload{flags} = unpack "\@$skip H", $buf; $skip += 1; | |
812 $payload{length} = hex(unpack "\@$skip H6", $buf); $skip += 3; | |
813 $payload{type} = 'SETTINGS'; | |
814 | |
815 my $nent = unpack "\@$skip N", $buf; $skip += 4; | |
816 for (1 .. $nent) { | |
817 my $flags = hex unpack "\@$skip H2", $buf; $skip += 1; | |
818 my $id = hex unpack "\@$skip H6", $buf; $skip += 3; | |
819 $payload{$id}{flags} = $flags; | |
820 $payload{$id}{value} = unpack "\@$skip N", $buf; $skip += 4; | |
821 } | |
822 return \%payload; | |
823 } | |
824 | |
825 sub ping { | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
826 my ($ctx, $buf) = @_; |
374 | 827 my %payload; |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
828 my $skip = 5; |
374 | 829 |
830 $payload{length} = hex(unpack "\@$skip H6", $buf); $skip += 3; | |
831 $payload{type} = 'PING'; | |
832 $payload{value} = unpack "\@$skip N", $buf; | |
833 return \%payload; | |
834 } | |
835 | |
836 sub goaway { | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
837 my ($ctx, $buf) = @_; |
374 | 838 my %payload; |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
839 my $skip = 5; |
374 | 840 |
841 $payload{length} = hex unpack "\@$skip H6", $buf; $skip += 3; | |
842 $payload{type} = 'GOAWAY'; | |
843 $payload{sid} = unpack "\@$skip N", $buf; $skip += 4; | |
844 $payload{code} = unpack "\@$skip N", $buf; | |
845 return \%payload; | |
846 } | |
847 | |
848 sub window_update { | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
849 my ($ctx, $buf) = @_; |
374 | 850 my %payload; |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
851 my $skip = 5; |
374 | 852 |
853 $payload{length} = hex(unpack "\@$skip H6", $buf); $skip += 3; | |
854 $payload{type} = 'WINDOW_UPDATE'; | |
855 | |
856 my $stream = unpack "\@$skip B32", $buf; $skip += 4; | |
857 substr($stream, 0, 1) = 0; | |
858 $stream = unpack("N", pack("B32", $stream)); | |
859 $payload{sid} = $stream; | |
860 | |
861 my $value = unpack "\@$skip B32", $buf; | |
862 substr($value, 0, 1) = 0; | |
863 $payload{wdelta} = unpack("N", pack("B32", $value)); | |
864 return \%payload; | |
865 } | |
866 | |
867 sub hpack { | |
868 my ($name, $value) = @_; | |
869 | |
870 pack("N", length($name)) . $name . pack("N", length($value)) . $value; | |
871 } | |
872 | |
873 sub hunpack { | |
874 my ($data) = @_; | |
875 my %headers; | |
876 my $skip = 0; | |
877 | |
878 my $nent = unpack "\@$skip N", $data; $skip += 4; | |
879 for (1 .. $nent) { | |
880 my $len = unpack("\@$skip N", $data); $skip += 4; | |
881 my $name = unpack("\@$skip A$len", $data); $skip += $len; | |
882 | |
883 $len = unpack("\@$skip N", $data); $skip += 4; | |
884 my $value = unpack("\@$skip A$len", $data); $skip += $len; | |
885 | |
886 $headers{$name} = $value; | |
887 } | |
888 return \%headers; | |
889 } | |
890 | |
891 sub raw_read { | |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
892 my ($s, $buf, $len) = @_; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
893 my $got = ''; |
374 | 894 |
425
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
895 while (length($buf) < $len) { |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
896 $s->sysread($got, $len - length($buf)) or die; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
897 log_in($got); |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
898 $buf .= $got; |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
899 } |
cc7da696a330
Tests: reduced execution time of SPDY tests.
Sergey Kandaurov <pluknet@nginx.com>
parents:
416
diff
changeset
|
900 return $buf; |
374 | 901 } |
902 | |
903 sub raw_write { | |
904 my ($s, $message) = @_; | |
905 | |
906 local $SIG{PIPE} = 'IGNORE'; | |
907 | |
908 while (IO::Select->new($s)->can_write(0.4)) { | |
909 log_out($message); | |
910 my $n = $s->syswrite($message); | |
911 last unless $n; | |
912 $message = substr($message, $n); | |
913 last unless length $message; | |
914 } | |
915 } | |
916 | |
917 sub new_session { | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
918 my ($port, %extra) = @_; |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
919 my ($d, $i, $status, $s); |
374 | 920 |
921 ($d, $status) = Compress::Raw::Zlib::Deflate->new( | |
922 -WindowBits => 12, | |
923 -Dictionary => dictionary(), | |
924 -Level => Compress::Raw::Zlib->Z_NO_COMPRESSION | |
925 ); | |
926 fail "Zlib failure: $status" unless $d; | |
927 | |
928 ($i, $status) = Compress::Raw::Zlib::Inflate->new( | |
929 -WindowBits => Compress::Raw::Zlib->WANT_GZIP_OR_ZLIB, | |
930 -Dictionary => dictionary() | |
931 ); | |
932 fail "Zlib failure: $status" unless $i; | |
933 | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
934 $s = new_socket($port); |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
935 |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
936 if ($extra{proxy}) { |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
937 raw_write($s, $extra{proxy}); |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
938 } |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
939 |
374 | 940 return { zlib => { i => $i, d => $d }, |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
941 socket => $s, last_stream => -1 }; |
374 | 942 } |
943 | |
944 sub new_socket { | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
945 my ($port) = @_; |
374 | 946 my $s; |
947 | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
948 $port = 8080 unless defined $port; |
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
949 |
374 | 950 eval { |
951 local $SIG{ALRM} = sub { die "timeout\n" }; | |
952 local $SIG{PIPE} = sub { die "sigpipe\n" }; | |
953 alarm(2); | |
954 $s = IO::Socket::INET->new( | |
955 Proto => 'tcp', | |
427
daea9cf92c14
Tests: added proxy protocol tests over SPDY.
Sergey Kandaurov <pluknet@nginx.com>
parents:
426
diff
changeset
|
956 PeerAddr => "127.0.0.1:$port", |
374 | 957 ); |
958 alarm(0); | |
959 }; | |
960 alarm(0); | |
961 | |
962 if ($@) { | |
963 log_in("died: $@"); | |
964 return undef; | |
965 } | |
966 | |
967 return $s; | |
968 } | |
969 | |
970 sub dictionary { | |
971 join('', (map pack('N/a*', $_), qw( | |
972 options | |
973 head | |
974 post | |
975 put | |
976 delete | |
977 trace | |
978 accept | |
979 accept-charset | |
980 accept-encoding | |
981 accept-language | |
982 accept-ranges | |
983 age | |
984 allow | |
985 authorization | |
986 cache-control | |
987 connection | |
988 content-base | |
989 content-encoding | |
990 content-language | |
991 content-length | |
992 content-location | |
993 content-md5 | |
994 content-range | |
995 content-type | |
996 date | |
997 etag | |
998 expect | |
999 expires | |
1000 from | |
1001 host | |
1002 if-match | |
1003 if-modified-since | |
1004 if-none-match | |
1005 if-range | |
1006 if-unmodified-since | |
1007 last-modified | |
1008 location | |
1009 max-forwards | |
1010 pragma | |
1011 proxy-authenticate | |
1012 proxy-authorization | |
1013 range | |
1014 referer | |
1015 retry-after | |
1016 server | |
1017 te | |
1018 trailer | |
1019 transfer-encoding | |
1020 upgrade | |
1021 user-agent | |
1022 vary | |
1023 via | |
1024 warning | |
1025 www-authenticate | |
1026 method | |
1027 get | |
1028 status), "200 OK", | |
1029 qw(version HTTP/1.1 url public set-cookie keep-alive origin)), | |
1030 "100101201202205206300302303304305306307402405406407408409410", | |
1031 "411412413414415416417502504505", | |
1032 "203 Non-Authoritative Information", | |
1033 "204 No Content", | |
1034 "301 Moved Permanently", | |
1035 "400 Bad Request", | |
1036 "401 Unauthorized", | |
1037 "403 Forbidden", | |
1038 "404 Not Found", | |
1039 "500 Internal Server Error", | |
1040 "501 Not Implemented", | |
1041 "503 Service Unavailable", | |
1042 "Jan Feb Mar Apr May Jun Jul Aug Sept Oct Nov Dec", | |
1043 " 00:00:00", | |
1044 " Mon, Tue, Wed, Thu, Fri, Sat, Sun, GMT", | |
1045 "chunked,text/html,image/png,image/jpg,image/gif,", | |
1046 "application/xml,application/xhtml+xml,text/plain,", | |
1047 "text/javascript,public", "privatemax-age=gzip,deflate,", | |
1048 "sdchcharset=utf-8charset=iso-8859-1,utf-,*,enq=0." | |
1049 ); | |
1050 } | |
1051 | |
1052 ############################################################################### |