changeset 1020:196d33c2bb45

Tests: removed TODO and try_run() checks for legacy versions. Also removed now unused spdy.t and shmem prerequisite.
author Andrey Zelenkov <zelenkov@nginx.com>
date Wed, 31 Aug 2016 18:21:07 +0300
parents 41139d6f8b7b
children ebdf239722b9
files auth_request.t config_dump.t fastcgi_body.t fastcgi_cache.t fastcgi_merge_params.t fastcgi_merge_params2.t h2.t h2_headers.t h2_limit_req.t h2_proxy_ssl.t h2_request_body.t h2_request_body_preread.t h2_ssl_proxy_cache.t headers.t http_resolver.t image_filter_finalize.t lib/Test/Nginx.pm limit_conn.t limit_conn_complex.t limit_req.t mail_error_log.t mail_resolver.t not_modified_proxy.t proxy_cache.t proxy_cache_bypass.t proxy_cache_chunked.t proxy_cache_convert_head.t proxy_cache_lock.t proxy_cache_lock_age.t proxy_cache_lock_ssi.t proxy_cache_path.t proxy_cache_range.t proxy_cache_revalidate.t proxy_cache_variables.t proxy_cache_vary.t proxy_force_ranges.t proxy_merge_headers.t proxy_non_idempotent.t proxy_protocol_ipv6.t proxy_request_buffering_keepalive.t proxy_unfinished.t proxy_variables.t range_charset.t realip_remote_addr.t scgi_cache.t scgi_merge_params.t slice.t spdy.t ssi.t ssl_sni_reneg.t stream_limit_conn.t stream_limit_conn_complex.t stream_proxy_protocol.t stream_proxy_protocol_ipv6.t stream_proxy_protocol_ssl.t stream_tcp_nodelay.t stream_udp_limit_conn.t stream_udp_proxy.t stream_udp_upstream.t stream_udp_upstream_hash.t stream_udp_upstream_least_conn.t sub_filter.t sub_filter_merge.t sub_filter_multi.t sub_filter_multi2.t syslog.t upstream_hash_memcached.t upstream_zone_ssl.t
diffstat 68 files changed, 64 insertions(+), 1430 deletions(-) [+]
line wrap: on
line diff
--- a/auth_request.t
+++ b/auth_request.t
@@ -25,7 +25,6 @@ select STDOUT; $| = 1;
 
 my $t = Test::Nginx->new()
 	->has(qw/http rewrite proxy cache fastcgi auth_basic auth_request/)
-	->has(qw/shmem/)
 	->plan(19);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
--- a/config_dump.t
+++ b/config_dump.t
@@ -25,8 +25,6 @@ select STDOUT; $| = 1;
 
 my $t = Test::Nginx->new()->has(qw/http map/);
 
-plan(skip_all => 'no config dump') unless $t->has_version('1.9.2');
-
 $t->plan(10)->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/fastcgi_body.t
+++ b/fastcgi_body.t
@@ -59,9 +59,6 @@ like(http_get_length('/', ''), qr/X-Body
 like(http_get_length('/', 'foobar'), qr/X-Body: foobar_eos\x0d?$/ms,
 	'fastcgi body');
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.15');
-
 like(http(<<EOF), qr/X-Body: foobar_eos\x0d?$/ms, 'fastcgi chunked');
 GET / HTTP/1.1
 Host: localhost
@@ -84,8 +81,6 @@ 0
 
 EOF
 
-}
-
 ###############################################################################
 
 sub http_get_length {
--- a/fastcgi_cache.t
+++ b/fastcgi_cache.t
@@ -25,7 +25,7 @@ eval { require FCGI; };
 plan(skip_all => 'FCGI not installed') if $@;
 plan(skip_all => 'win32') if $^O eq 'MSWin32';
 
-my $t = Test::Nginx->new()->has(qw/http fastcgi cache shmem/)->plan(5)
+my $t = Test::Nginx->new()->has(qw/http fastcgi cache/)->plan(5)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/fastcgi_merge_params.t
+++ b/fastcgi_merge_params.t
@@ -25,7 +25,7 @@ eval { require FCGI; };
 plan(skip_all => 'FCGI not installed') if $@;
 plan(skip_all => 'win32') if $^O eq 'MSWin32';
 
-my $t = Test::Nginx->new()->has(qw/http fastcgi cache shmem/)->plan(9)
+my $t = Test::Nginx->new()->has(qw/http fastcgi cache/)->plan(9)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/fastcgi_merge_params2.t
+++ b/fastcgi_merge_params2.t
@@ -25,7 +25,7 @@ eval { require FCGI; };
 plan(skip_all => 'FCGI not installed') if $@;
 plan(skip_all => 'win32') if $^O eq 'MSWin32';
 
-my $t = Test::Nginx->new()->has(qw/http fastcgi cache shmem/)->plan(4)
+my $t = Test::Nginx->new()->has(qw/http fastcgi cache/)->plan(4)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/h2.t
+++ b/h2.t
@@ -451,9 +451,6 @@ is($frame->{headers}->{':status'}, 200, 
 
 # padding followed by CONTINUATION
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.11');
-
 $s = Test::Nginx::HTTP2->new();
 $sid = $s->new_stream({ padding => 42, continuation => [ 2, 4, 1, 5 ],
 	headers => [
@@ -466,8 +463,6 @@ local $TODO = 'not yet' unless $t->has_v
 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
 is($frame->{headers}->{':status'}, 200, 'padding - CONTINUATION');
 
-}
-
 # internal redirect
 
 $s = Test::Nginx::HTTP2->new();
@@ -625,9 +620,6 @@ is($frame->{headers}->{'content-type'}, 
 # partial request header frame received (field split),
 # the rest of frame is received after client header timeout
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.12');
-
 $s = Test::Nginx::HTTP2->new(port(8087));
 $sid = $s->new_stream({ path => '/t2.html', split => [35],
 	split_delay => 2.1 });
@@ -637,8 +629,6 @@ local $TODO = 'not yet' unless $t->has_v
 ok($frame, 'client header timeout');
 is($frame->{code}, 1, 'client header timeout - protocol error');
 
-}
-
 $s->h2_ping('SEE-THIS');
 $frames = $s->read(all => [{ type => 'PING' }]);
 
@@ -647,9 +637,6 @@ ok($frame, 'client header timeout - PING
 
 # partial request body data frame received, the rest is after body timeout
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.12');
-
 $s = Test::Nginx::HTTP2->new(port(8087));
 $sid = $s->new_stream({ path => '/proxy/t2.html', body_more => 1 });
 $s->h2_body('TEST', { split => [10], split_delay => 2.1 });
@@ -659,15 +646,12 @@ local $TODO = 'not yet' unless $t->has_v
 ok($frame, 'client body timeout');
 is($frame->{code}, 1, 'client body timeout - protocol error');
 
-}
-
 $s->h2_ping('SEE-THIS');
 $frames = $s->read(all => [{ type => 'PING' }]);
 
 ($frame) = grep { $_->{type} eq "PING" && $_->{flags} & 0x1 } @$frames;
 ok($frame, 'client body timeout - PING');
 
-
 # proxied request with logging pristine request header field (e.g., referer)
 
 $s = Test::Nginx::HTTP2->new();
--- a/h2_headers.t
+++ b/h2_headers.t
@@ -405,14 +405,8 @@ like($s->{headers}, qr/\Q{{{{{/, 'rare c
 
 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
 is($frame->{headers}->{'x-sent-foo'}, 'aaaaa', 'well known chars');
-
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.12');
-
 unlike($s->{headers}, qr/aaaaa/, 'well known chars - huffman encoding');
 
-}
-
 # response header field with huffman encoding - complete table mod \0, CR, LF
 # first saturate with short-encoded characters (NB: implementation detail)
 
@@ -429,14 +423,8 @@ my $field = pack "C*", ((map { 97 } (1 .
 
 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
 is($frame->{headers}->{'x-sent-foo'}, $field, 'all chars');
-
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.12');
-
 unlike($s->{headers}, qr/abcde/, 'all chars - huffman encoding');
 
-}
-
 # 6.3.  Dynamic Table Size Update
 
 # remove some indexed headers from the dynamic table
@@ -657,9 +645,6 @@ cmp_ok($data[-1], '<=', 2**14, 'response
 
 # response header frame sent in parts
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.7');
-
 $s = Test::Nginx::HTTP2->new(port(8082));
 $s->h2_settings(0, 0x5 => 2**17);
 
@@ -690,8 +675,6 @@ cmp_ok($lengths, '<=', 16384, 'response 
 is(length join('', @{@$frames[-1]->{headers}->{'x-longheader'}}), 98304,
 	'response header split - headers');
 
-}
-
 # max_field_size - header field name
 
 $s = Test::Nginx::HTTP2->new(port(8084));
@@ -951,9 +934,6 @@ is($frame->{code}, 1, 'newline in reques
 
 # invalid header name as seen with underscore should not lead to ignoring rest
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.7');
-
 $s = Test::Nginx::HTTP2->new();
 $sid = $s->new_stream({ headers => [
 	{ name => ':method', value => 'GET', mode => 0 },
@@ -967,8 +947,6 @@ local $TODO = 'not yet' unless $t->has_v
 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
 is($frame->{headers}->{'x-referer'}, 'see-this', 'after invalid header name');
 
-}
-
 # missing mandatory request header ':scheme'
 
 TODO: {
--- a/h2_limit_req.t
+++ b/h2_limit_req.t
@@ -26,8 +26,6 @@ select STDOUT; $| = 1;
 my $t = Test::Nginx->new()->has(qw/http http_v2 proxy rewrite limit_req/)
 	->plan(7);
 
-$t->todo_alerts() unless $t->has_version('1.9.14');
-
 $t->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -81,9 +79,6 @@ my ($frame) = grep { $_->{type} eq "HEAD
 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TEST',
 	'request body - limit req');
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.15');
-
 $s = Test::Nginx::HTTP2->new();
 $sid = $s->new_stream({ path => '/proxy_limit_req/', body_more => 1 });
 select undef, undef, undef, 1.1;
@@ -94,8 +89,6 @@ select undef, undef, undef, 1.1;
 is(read_body_file($frame->{headers}->{'x-body-file'}), 'TEST',
 	'request body - limit req - limited');
 
-}
-
 # request body delayed in limit_req - with an empty DATA frame
 # "zero size buf in output" alerts seen
 
@@ -114,7 +107,6 @@ is($frame->{headers}->{':status'}, 200, 
 my ($maxwin) = sort {$a <=> $b} $s->{streams}{$sid}, $s->{conn_window};
 
 SKIP: {
-skip 'leaves coredump', 1 unless $t->has_version('1.9.7');
 skip 'not enough window', 1 if $maxwin < 5;
 
 $s = Test::Nginx::HTTP2->new();
@@ -136,10 +128,6 @@ is(read_body_file($frame->{headers}->{'x
 SKIP: {
 skip 'not enough window', 1 if $maxwin < 4;
 
-TODO: {
-todo_skip 'use-after-free', 1 unless $ENV{TEST_NGINX_UNSAFE}
-	or $t->has_version('1.9.12');
-
 $sid = $s->new_stream({ path => '/limit_req', body => 'TEST', split => [61],
 	split_delay => 1.1 });
 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
@@ -149,8 +137,6 @@ is($frame->{headers}->{':status'}, '200'
 
 }
 
-}
-
 $sid = $s->new_stream({ path => '/' });
 $frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
 
@@ -163,10 +149,6 @@ is($frame->{headers}->{':status'}, '200'
 SKIP: {
 skip 'not enough window', 1 if $maxwin < 4;
 
-TODO: {
-todo_skip 'use-after-free', 1 unless $ENV{TEST_NGINX_UNSAFE}
-	or $t->has_version('1.9.12');
-
 $s = Test::Nginx::HTTP2->new();
 $sid = $s->new_stream({ path => '/limit_req', body => 'TEST', split => [61],
 	abort => 1 });
@@ -178,8 +160,6 @@ pass('discard body - limit req - eof');
 
 }
 
-}
-
 ###############################################################################
 
 sub read_body_file {
--- a/h2_proxy_ssl.t
+++ b/h2_proxy_ssl.t
@@ -26,8 +26,6 @@ select STDOUT; $| = 1;
 my $t = Test::Nginx->new()->has(qw/http http_ssl http_v2 proxy/)
 	->has_daemon('openssl')->plan(1);
 
-$t->todo_alerts() unless $t->has_version('1.9.14');
-
 $t->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -83,9 +81,6 @@ foreach my $name ('localhost') {
 # request body with an empty DATA frame proxied to ssl backend
 # "zero size buf in output" alerts seen
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.14');
-
 my $s = Test::Nginx::HTTP2->new();
 my $sid = $s->new_stream({ path => '/proxy_ssl/', body_more => 1 });
 $s->h2_body('');
@@ -94,6 +89,4 @@ my $frames = $s->read(all => [{ sid => $
 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
 is($frame->{headers}->{':status'}, 200, 'empty request body');
 
-}
-
 ###############################################################################
--- a/h2_request_body.t
+++ b/h2_request_body.t
@@ -25,8 +25,6 @@ select STDOUT; $| = 1;
 
 my $t = Test::Nginx->new()->has(qw/http http_v2 proxy/)->plan(42);
 
-$t->todo_alerts() unless $t->has_version('1.9.14');
-
 $t->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -141,22 +139,10 @@ is($frame->{headers}->{'x-length'}, 12,
 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
 is($frame->{headers}->{':status'}, 200, 'request body - empty');
 is($frame->{headers}->{'x-length'}, 0, 'request body - empty size');
-
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.14');
-
 ok($frame->{headers}{'x-body-file'}, 'request body - empty body file');
-
-}
-
-TODO: {
-todo_skip 'empty body file', 1 unless $frame->{headers}{'x-body-file'};
-
 is(read_body_file($frame->{headers}{'x-body-file'}), '',
 	'request body - empty content');
 
-}
-
 # it is expected to avoid adding Content-Length for requests without body
 
 $s = Test::Nginx::HTTP2->new();
--- a/h2_request_body_preread.t
+++ b/h2_request_body_preread.t
@@ -23,7 +23,7 @@ use Test::Nginx::HTTP2;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http http_v2 proxy limit_req shmem/);
+my $t = Test::Nginx->new()->has(qw/http http_v2 proxy limit_req/);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
 
--- a/h2_ssl_proxy_cache.t
+++ b/h2_ssl_proxy_cache.t
@@ -26,7 +26,7 @@ select STDOUT; $| = 1;
 eval { require IO::Socket::SSL; };
 plan(skip_all => 'IO::Socket::SSL not installed') if $@;
 
-my $t = Test::Nginx->new()->has(qw/http http_ssl http_v2 proxy cache shmem/)
+my $t = Test::Nginx->new()->has(qw/http http_ssl http_v2 proxy cache/)
 	->has_daemon('openssl');
 
 $t->todo_alerts() unless $t->has_version('1.11.3');
--- a/headers.t
+++ b/headers.t
@@ -131,14 +131,8 @@ unlike($r, qr/ETag/, 'good add_header al
 unlike($r, qr/Cache-Control/, 'bad expires');
 unlike($r, qr/X-URI/, 'bad add_header');
 like($r, qr/X-Always/, 'bad add_header always');
-
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.12');
-
 unlike($r, qr/ETag/, 'bad add_header always empty');
 
-}
-
 # various expires variants
 
 like(http_get('/epoch'), qr/Expires:.*1970/, 'expires epoch');
--- a/http_resolver.t
+++ b/http_resolver.t
@@ -282,16 +282,11 @@ like(http_end($s2), qr/502 Bad/, 'timeou
 
 # resend DNS query over TCP once UDP response came truncated
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.11');
-
 unlike(http_host_header('tcp.example.net', '/tcp'), qr/127.0.0.201/, 'tc');
 like(http_host_header('tcp.example.net', '/tcp'), qr/X-IP: 127.0.0.1/, 'tcp');
 like(http_host_header('tcp2.example.net', '/tcp2'), qr/X-IP: 127.0.0.1/,
 	'tcp with resend');
 
-}
-
 ###############################################################################
 
 sub http_host_header {
--- a/image_filter_finalize.t
+++ b/image_filter_finalize.t
@@ -22,7 +22,7 @@ select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
 my $t = Test::Nginx->new()->has(qw/http proxy cache image_filter limit_req/)
-	->has(qw/rewrite shmem/)->plan(3)
+	->has(qw/rewrite/)->plan(3)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/lib/Test/Nginx.pm
+++ b/lib/Test/Nginx.pm
@@ -200,10 +200,6 @@ sub has_feature($) {
 		return $^O ne 'MSWin32';
 	}
 
-	if ($feature eq 'shmem') {
-		return $^O ne 'MSWin32' || $self->has_version('1.9.0');
-	}
-
 	if ($feature eq 'unix') {
 		return $^O ne 'MSWin32';
 	}
--- a/limit_conn.t
+++ b/limit_conn.t
@@ -21,7 +21,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy limit_conn limit_req shmem/);
+my $t = Test::Nginx->new()->has(qw/http proxy limit_conn limit_req/);
 
 $t->write_file_expand('nginx.conf', <<'EOF')->plan(8);
 
--- a/limit_conn_complex.t
+++ b/limit_conn_complex.t
@@ -24,7 +24,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy limit_conn limit_req shmem/)
+my $t = Test::Nginx->new()->has(qw/http proxy limit_conn limit_req/)
 	->plan(4);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
--- a/limit_req.t
+++ b/limit_req.t
@@ -21,7 +21,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http limit_req shmem/)->plan(5);
+my $t = Test::Nginx->new()->has(qw/http limit_req/)->plan(5);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
 
--- a/mail_error_log.t
+++ b/mail_error_log.t
@@ -29,8 +29,6 @@ plan(skip_all => 'win32') if $^O eq 'MSW
 
 my $t = Test::Nginx->new()->has(qw/mail imap http rewrite/);
 
-plan(skip_all => 'no error_log') unless $t->has_version('1.9.0');
-
 $t->plan(30)->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/mail_resolver.t
+++ b/mail_resolver.t
@@ -206,10 +206,6 @@ local $TODO = 'support for CNAME RR';
 
 # uncompressed answer
 
-TODO: {
-local $TODO = 'support for uncompressed name in PTR'
-	unless $t->has_version('1.9.11');
-
 $s = Test::Nginx::SMTP->new(PeerAddr => '127.0.0.1:' . port(8030));
 $s->read();
 $s->send('EHLO example.com');
@@ -223,11 +219,6 @@ local $TODO = 'support for uncompressed 
 $s->send('QUIT');
 $s->read();
 
-}
-
-TODO: {
-local $TODO = 'PTR type checking' unless $t->has_version('1.9.11');
-
 $s = Test::Nginx::SMTP->new(PeerAddr => '127.0.0.1:' . port(8031));
 $s->read();
 $s->send('EHLO example.com');
@@ -241,13 +232,8 @@ local $TODO = 'PTR type checking' unless
 $s->send('QUIT');
 $s->read();
 
-}
-
 # CNAME and PTR in one answer section
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.11');
-
 $s = Test::Nginx::SMTP->new(PeerAddr => '127.0.0.1:' . port(8032));
 $s->read();
 $s->send('EHLO example.com');
@@ -261,8 +247,6 @@ local $TODO = 'not yet' unless $t->has_v
 $s->send('QUIT');
 $s->read();
 
-}
-
 ###############################################################################
 
 sub reply_handler {
--- a/not_modified_proxy.t
+++ b/not_modified_proxy.t
@@ -26,7 +26,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem/)->plan(12);
+my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(12);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
 
--- a/proxy_cache.t
+++ b/proxy_cache.t
@@ -21,7 +21,7 @@ use Test::Nginx qw/ :DEFAULT :gzip /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache gzip shmem/)->plan(15)
+my $t = Test::Nginx->new()->has(qw/http proxy cache gzip/)->plan(15)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -126,14 +126,8 @@ EOF
 my $r = http_get('/t.html', socket => $s);
 
 like($r, qr/Connection: keep-alive/, 'non-cacheable head - keepalive');
-
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.13');
-
 like($r, qr/SEE-THIS/, 'non-cacheable head - second');
 
-}
-
 ###############################################################################
 
 sub http_get_range {
--- a/proxy_cache_bypass.t
+++ b/proxy_cache_bypass.t
@@ -21,7 +21,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem rewrite/)->plan(8)
+my $t = Test::Nginx->new()->has(qw/http proxy cache rewrite/)->plan(8)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_cache_chunked.t
+++ b/proxy_cache_chunked.t
@@ -23,7 +23,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem/)->plan(2);
+my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(2);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
 
--- a/proxy_cache_convert_head.t
+++ b/proxy_cache_convert_head.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem/)
+my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(8)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -78,8 +78,7 @@ http {
 EOF
 
 $t->write_file('t.html', 'SEE-THIS');
-
-$t->try_run('no proxy_cache_convert_head')->plan(8);
+$t->run();
 
 ###############################################################################
 
--- a/proxy_cache_lock.t
+++ b/proxy_cache_lock.t
@@ -21,7 +21,7 @@ use Test::Nginx qw/ :DEFAULT http_end /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem/)->plan(17)
+my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(17)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_cache_lock_age.t
+++ b/proxy_cache_lock_age.t
@@ -24,7 +24,7 @@ use Test::Nginx qw/ :DEFAULT http_end /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem/)->plan(4)
+my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(4)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_cache_lock_ssi.t
+++ b/proxy_cache_lock_ssi.t
@@ -21,7 +21,7 @@ use Test::Nginx qw/ :DEFAULT http_end /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache ssi shmem/)
+my $t = Test::Nginx->new()->has(qw/http proxy cache ssi/)
 	->write_file_expand('nginx.conf', <<'EOF')->plan(2);
 
 %%TEST_GLOBALS%%
--- a/proxy_cache_path.t
+++ b/proxy_cache_path.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem/)->plan(6)
+my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(6)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_cache_range.t
+++ b/proxy_cache_range.t
@@ -21,7 +21,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem/)->plan(7)
+my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(7)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_cache_revalidate.t
+++ b/proxy_cache_revalidate.t
@@ -21,7 +21,7 @@ use Test::Nginx qw/ :DEFAULT :gzip /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache rewrite shmem/)->plan(23)
+my $t = Test::Nginx->new()->has(qw/http proxy cache rewrite/)->plan(23)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_cache_variables.t
+++ b/proxy_cache_variables.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem/)->plan(8)
+my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(8)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_cache_vary.t
+++ b/proxy_cache_vary.t
@@ -21,7 +21,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache gzip rewrite shmem/)
+my $t = Test::Nginx->new()->has(qw/http proxy cache gzip rewrite/)
 	->plan(42)->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_force_ranges.t
+++ b/proxy_force_ranges.t
@@ -23,7 +23,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache shmem/)->plan(4)
+my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(4)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_merge_headers.t
+++ b/proxy_merge_headers.t
@@ -21,7 +21,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache rewrite shmem/)->plan(7)
+my $t = Test::Nginx->new()->has(qw/http proxy cache rewrite/)->plan(7)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/proxy_non_idempotent.t
+++ b/proxy_non_idempotent.t
@@ -22,7 +22,8 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy rewrite upstream_keepalive/);
+my $t = Test::Nginx->new()->has(qw/http proxy rewrite upstream_keepalive/)
+	->plan(6);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
 
@@ -87,7 +88,7 @@ http {
 
 EOF
 
-$t->try_run('no proxy_next_upstream non_idempotent')->plan(6);
+$t->run();
 
 ###############################################################################
 
--- a/proxy_protocol_ipv6.t
+++ b/proxy_protocol_ipv6.t
@@ -68,9 +68,6 @@ EOF
 
 ###############################################################################
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.10');
-
 my $r = http_get('/t');
 like($r, qr/X-IP: ::1/, 'realip');
 like($r, qr/X-PP: 127.0.0.1/, 'proxy protocol');
@@ -78,6 +75,4 @@ like($r, qr/X-PP: 127.0.0.1/, 'proxy pro
 $r = http_get('/pp');
 like($r, qr/X-IP: 127.0.0.1/, 'proxy protocol realip');
 
-}
-
 ###############################################################################
--- a/proxy_request_buffering_keepalive.t
+++ b/proxy_request_buffering_keepalive.t
@@ -82,11 +82,6 @@ Content-Length: 10
 
 EOF
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.10');
-
 like(http_get('/t1'), qr/200 OK.*SEE/ms, 'keepalive after discarded');
 
-}
-
 ###############################################################################
--- a/proxy_unfinished.t
+++ b/proxy_unfinished.t
@@ -31,7 +31,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache sub shmem/)->plan(15);
+my $t = Test::Nginx->new()->has(qw/http proxy cache sub/)->plan(15);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
 
--- a/proxy_variables.t
+++ b/proxy_variables.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy/)
+my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(18)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -76,7 +76,7 @@ EOF
 
 $t->write_file('stub', '');
 $t->run_daemon(\&http_daemon, port(8081));
-$t->try_run('no upstream_connect_time')->plan(18);
+$t->run();
 
 $t->waitforsocket('127.0.0.1:' . port(8081));
 
--- a/range_charset.t
+++ b/range_charset.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache charset shmem/)->plan(10)
+my $t = Test::Nginx->new()->has(qw/http proxy cache charset/)->plan(10)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/realip_remote_addr.t
+++ b/realip_remote_addr.t
@@ -54,7 +54,7 @@ EOF
 
 $t->write_file('index.html', '');
 $t->write_file('1', '');
-$t->try_run('no realip_remote_addr');
+$t->run();
 
 plan(skip_all => 'no 127.0.0.1 on host')
 	if http_get('/') !~ /X-IP: 127.0.0.1/m;
--- a/scgi_cache.t
+++ b/scgi_cache.t
@@ -25,7 +25,7 @@ select STDOUT; $| = 1;
 eval { require SCGI; };
 plan(skip_all => 'SCGI not installed') if $@;
 
-my $t = Test::Nginx->new()->has(qw/http scgi cache shmem/)->plan(10)
+my $t = Test::Nginx->new()->has(qw/http scgi cache/)->plan(10)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/scgi_merge_params.t
+++ b/scgi_merge_params.t
@@ -24,7 +24,7 @@ select STDOUT; $| = 1;
 eval { require SCGI; };
 plan(skip_all => 'SCGI not installed') if $@;
 
-my $t = Test::Nginx->new()->has(qw/http scgi cache shmem/)->plan(9)
+my $t = Test::Nginx->new()->has(qw/http scgi cache/)->plan(9)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/slice.t
+++ b/slice.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http proxy cache fastcgi slice shmem/)
+my $t = Test::Nginx->new()->has(qw/http proxy cache fastcgi slice/)
 	->plan(72);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
deleted file mode 100644
--- a/spdy.t
+++ /dev/null
@@ -1,1204 +0,0 @@
-#!/usr/bin/perl
-
-# (C) Sergey Kandaurov
-# (C) Nginx, Inc.
-
-# Tests for SPDY protocol version 3.1.
-
-###############################################################################
-
-use warnings;
-use strict;
-
-use Test::More;
-
-use IO::Select;
-use Socket qw/ CRLF /;
-
-BEGIN { use FindBin; chdir($FindBin::Bin); }
-
-use lib 'lib';
-use Test::Nginx;
-
-###############################################################################
-
-select STDERR; $| = 1;
-select STDOUT; $| = 1;
-
-eval {
-	require Compress::Raw::Zlib;
-	Compress::Raw::Zlib->Z_OK;
-	Compress::Raw::Zlib->Z_SYNC_FLUSH;
-	Compress::Raw::Zlib->Z_NO_COMPRESSION;
-	Compress::Raw::Zlib->WANT_GZIP_OR_ZLIB;
-};
-plan(skip_all => 'Compress::Raw::Zlib not installed') if $@;
-
-my $t = Test::Nginx->new()
-	->has(qw/http proxy cache limit_conn rewrite spdy realip shmem/);
-
-# Some systems have a bug in not treating zero writev iovcnt as EINVAL
-
-$t->todo_alerts() if $^O eq 'darwin';
-
-$t->plan(84)->write_file_expand('nginx.conf', <<'EOF');
-
-%%TEST_GLOBALS%%
-
-daemon off;
-
-events {
-}
-
-http {
-    %%TEST_GLOBALS_HTTP%%
-
-    proxy_cache_path %%TESTDIR%%/cache    keys_zone=NAME:1m;
-    limit_conn_zone  $binary_remote_addr  zone=conn:1m;
-
-    server {
-        listen       127.0.0.1:8080 spdy;
-        listen       127.0.0.1:8081;
-        listen       127.0.0.1:8082 proxy_protocol spdy;
-        server_name  localhost;
-
-        location /s {
-            add_header X-Header X-Foo;
-            return 200 'body';
-        }
-        location /pp {
-            set_real_ip_from  127.0.0.1/32;
-            real_ip_header proxy_protocol;
-            alias %%TESTDIR%%/t2.html;
-            add_header X-PP $remote_addr;
-        }
-        location /spdy {
-            return 200 $spdy;
-        }
-        location /prio {
-            return 200 $spdy_request_priority;
-        }
-        location /chunk_size {
-            spdy_chunk_size 1;
-            return 200 'body';
-        }
-        location /redirect {
-            error_page 405 /s;
-            return 405;
-        }
-        location /proxy {
-            add_header X-Body "$request_body";
-            proxy_pass http://127.0.0.1:8081/;
-            proxy_cache NAME;
-            proxy_cache_valid 1m;
-        }
-        location /header/ {
-            proxy_pass http://127.0.0.1:8083/;
-        }
-        location /proxy_buffering_off {
-            proxy_pass http://127.0.0.1:8081/;
-            proxy_cache NAME;
-            proxy_cache_valid 1m;
-            proxy_buffering off;
-        }
-        location /t3.html {
-            limit_conn conn 1;
-        }
-        location /set-cookie {
-            add_header Set-Cookie val1;
-            add_header Set-Cookie val2;
-            return 200;
-        }
-        location /cookie {
-            add_header X-Cookie $http_cookie;
-            return 200;
-        }
-    }
-}
-
-EOF
-
-$t->run_daemon(\&http_daemon);
-$t->run()->waitforsocket('127.0.0.1:8083');
-
-# file size is slightly beyond initial window size: 2**16 + 80 bytes
-
-$t->write_file('t1.html',
-	join('', map { sprintf "X%04dXXX", $_ } (1 .. 8202)));
-$t->write_file('tbig.html',
-	join('', map { sprintf "XX%06dXX", $_ } (1 .. 100000)));
-
-$t->write_file('t2.html', 'SEE-THIS');
-$t->write_file('t3.html', 'SEE-THIS');
-
-my %cframe = (
-	2 => \&syn_reply,
-	3 => \&rst_stream,
-	4 => \&settings,
-	6 => \&ping,
-	7 => \&goaway,
-	9 => \&window_update
-);
-
-###############################################################################
-
-# PING
-
-my $sess = new_session();
-spdy_ping($sess, 0x12345678);
-my $frames = spdy_read($sess, all => [{ type => 'PING' }]);
-
-my ($frame) = grep { $_->{type} eq "PING" } @$frames;
-ok($frame, 'PING frame');
-is($frame->{value}, 0x12345678, 'PING payload');
-
-# GET
-
-$sess = new_session();
-my $sid1 = spdy_stream($sess, { path => '/s' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-ok($frame, 'SYN_REPLY frame');
-is($frame->{sid}, $sid1, 'SYN_REPLY stream');
-is($frame->{headers}->{':status'}, 200, 'SYN_REPLY status');
-is($frame->{headers}->{'x-header'}, 'X-Foo', 'SYN_REPLY header');
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-ok($frame, 'DATA frame');
-is($frame->{length}, length 'body', 'DATA length');
-is($frame->{data}, 'body', 'DATA payload');
-
-# GET in new SPDY stream in same session
-
-my $sid2 = spdy_stream($sess, { path => '/s' });
-$frames = spdy_read($sess, all => [{ sid => $sid2, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{sid}, $sid2, 'SYN_REPLY stream 2');
-is($frame->{headers}->{':status'}, 200, 'SYN_REPLY status 2');
-is($frame->{headers}->{'x-header'}, 'X-Foo', 'SYN_REPLY header 2');
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-ok($frame, 'DATA frame 2');
-is($frame->{sid}, $sid2, 'SYN_REPLY stream 2');
-is($frame->{length}, length 'body', 'DATA length 2');
-is($frame->{data}, 'body', 'DATA payload 2');
-
-# HEAD
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/s', method => 'HEAD' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{sid}, $sid1, 'SYN_REPLY stream HEAD');
-is($frame->{headers}->{':status'}, 200, 'SYN_REPLY status HEAD');
-is($frame->{headers}->{'x-header'}, 'X-Foo', 'SYN_REPLY header HEAD');
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-is($frame, undef, 'HEAD no body');
-
-# GET with PROXY protocol
-
-my $proxy = 'PROXY TCP4 192.0.2.1 192.0.2.2 1234 5678' . CRLF;
-$sess = new_session(8082, proxy => $proxy);
-$sid1 = spdy_stream($sess, { path => '/pp' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-ok($frame, 'PROXY SYN_REPLY frame');
-is($frame->{headers}->{'x-pp'}, '192.0.2.1', 'PROXY remote addr');
-
-# request header
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/t1.html',
-	headers => { "range" =>  "bytes=10-19" }
-});
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{':status'}, 206, 'SYN_REPLY status range');
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-is($frame->{length}, 10, 'DATA length range');
-is($frame->{data}, '002XXXX000', 'DATA payload range');
-
-# request header with multiple values
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/cookie',
-	headers => { "cookie" =>  "val1\0val2" }
-});
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-ok(grep ({ $_->{type} eq "SYN_REPLY" } @$frames),
-	'multiple request header values');
-
-# request header with multiple values proxied to http backend
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/proxy/cookie',
-	headers => { "cookie" =>  "val1\0val2" }
-});
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{'x-cookie'}, 'val1; val2',
-	'multiple request header values - proxied');
-
-# response header with multiple values
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/set-cookie' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{'set-cookie'}, "val1\0val2",
-	'response header with multiple values');
-
-# response header with multiple values - no empty values inside
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/header/inside' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{'x-foo'}, "val1\0val2", 'no empty header value inside');
-
-$sid1 = spdy_stream($sess, { path => '/header/first' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{'x-foo'}, "val1\0val2", 'no empty header value first');
-
-$sid1 = spdy_stream($sess, { path => '/header/last' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{'x-foo'}, "val1\0val2", 'no empty header value last');
-
-# $spdy
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/spdy' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-is($frame->{data}, '3.1', 'spdy variable');
-
-# spdy_chunk_size=1
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/chunk_size' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-my @data = grep { $_->{type} eq "DATA" } @$frames;
-is(@data, 4, 'chunk_size body chunks');
-is($data[0]->{data}, 'b', 'chunk_size body 1');
-is($data[1]->{data}, 'o', 'chunk_size body 2');
-is($data[2]->{data}, 'd', 'chunk_size body 3');
-is($data[3]->{data}, 'y', 'chunk_size body 4');
-
-# redirect
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/redirect' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{':status'}, 405, 'SYN_REPLY status with redirect');
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-ok($frame, 'DATA frame with redirect');
-is($frame->{data}, 'body', 'DATA payload with redirect');
-
-# SYN_REPLY could be received with fin, followed by DATA
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/proxy/t2.html', method => 'HEAD' });
-
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-push @$frames, $_ for @{spdy_read($sess, all => [{ sid => $sid1 }])};
-ok(!grep ({ $_->{type} eq "DATA" } @$frames), 'proxy cache HEAD - no body');
-
-# ensure that HEAD-like requests, i.e., without response body, do not lead to
-# client connection close due to cache filling up with upstream response body
-
-$sid2 = spdy_stream($sess, { path => '/' });
-$frames = spdy_read($sess, all => [{ sid => $sid2, fin => 1 }]);
-ok(grep ({ $_->{type} eq "SYN_REPLY" } @$frames), 'proxy cache headers only');
-
-# HEAD on empty cache with proxy_buffering off
-
-$sess = new_session();
-$sid1 = spdy_stream($sess,
-	{ path => '/proxy_buffering_off/t2.html?1', method => 'HEAD' });
-
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-push @$frames, $_ for @{spdy_read($sess, all => [{ sid => $sid1 }])};
-ok(!grep ({ $_->{type} eq "DATA" } @$frames),
-	'proxy cache HEAD buffering off - no body');
-
-# simple proxy cache test
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/proxy/t2.html' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{':status'}, '200 OK', 'proxy cache unconditional');
-
-$sid2 = spdy_stream($sess, { path => '/proxy/t2.html',
-	headers => { "if-none-match" => $frame->{headers}->{'etag'} }
-});
-$frames = spdy_read($sess, all => [{ sid => $sid2, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{':status'}, 304, 'proxy cache conditional');
-
-# request body (uses proxied response)
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/proxy/t2.html', body => 'TEST' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{'x-body'}, 'TEST', 'request body');
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-is($frame->{length}, length 'SEE-THIS', 'proxied response length');
-is($frame->{data}, 'SEE-THIS', 'proxied response');
-
-# WINDOW_UPDATE (client side)
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/t1.html' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, length => 2**16 }]);
-
-@data = grep { $_->{type} eq "DATA" } @$frames;
-my $sum = eval join '+', map { $_->{length} } @data;
-is($sum, 2**16, 'iws - stream blocked on initial window size');
-
-spdy_ping($sess, 0xf00ff00f);
-$frames = spdy_read($sess, all => [{ type => 'PING' }]);
-
-($frame) = grep { $_->{type} eq "PING" } @$frames;
-ok($frame, 'iws - PING not blocked');
-
-spdy_window($sess, 2**16, $sid1);
-$frames = spdy_read($sess);
-is(@$frames, 0, 'iws - updated stream window');
-
-spdy_window($sess, 2**16);
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-@data = grep { $_->{type} eq "DATA" } @$frames;
-$sum = eval join '+', map { $_->{length} } @data;
-is($sum, 80, 'iws - updated connection window');
-
-# SETTINGS (initial window size, client side)
-
-$sess = new_session();
-spdy_settings($sess, 7 => 2**17);
-spdy_window($sess, 2**17);
-
-$sid1 = spdy_stream($sess, { path => '/t1.html' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-@data = grep { $_->{type} eq "DATA" } @$frames;
-$sum = eval join '+', map { $_->{length} } @data;
-is($sum, 2**16 + 80, 'increased initial window size');
-
-# probe for negative available space in a flow control window
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/t1.html' });
-spdy_read($sess, all => [{ sid => $sid1, length => 2**16 }]);
-
-spdy_window($sess, 1);
-spdy_settings($sess, 7 => 42);
-spdy_window($sess, 1024, $sid1);
-
-$frames = spdy_read($sess);
-is(@$frames, 0, 'negative window - no data');
-
-spdy_window($sess, 2**16 - 42 - 1024, $sid1);
-$frames = spdy_read($sess);
-is(@$frames, 0, 'zero window - no data');
-
-spdy_window($sess, 1, $sid1);
-$frames = spdy_read($sess, all => [{ sid => $sid1, length => 1 }]);
-is(@$frames, 1, 'positive window - data');
-is(@$frames[0]->{length}, 1, 'positive window - data length');
-
-# ask write handler in sending large response
-
-$sid1 = spdy_stream($sess, { path => '/tbig.html' });
-
-spdy_window($sess, 2**30, $sid1);
-spdy_window($sess, 2**30);
-
-sleep 1;
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{':status'}, 200, 'large response - HEADERS');
-
-@data = grep { $_->{type} eq "DATA" } @$frames;
-$sum = eval join '+', map { $_->{length} } @data;
-is($sum, 1000000, 'large response - DATA');
-
-# stream multiplexing
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/t1.html' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, length => 2**16 }]);
-
-@data = grep { $_->{type} eq "DATA" } @$frames;
-$sum = eval join '+', map { $_->{length} } @data;
-is($sum, 2**16, 'multiple - stream1 data');
-
-$sid2 = spdy_stream($sess, { path => '/t1.html' });
-$frames = spdy_read($sess, all => [{ sid => $sid2, fin => 0 }]);
-
-@data = grep { $_->{type} eq "DATA" } @$frames;
-is(@data, 0, 'multiple - stream2 no data');
-
-spdy_window($sess, 2**17, $sid1);
-spdy_window($sess, 2**17, $sid2);
-spdy_window($sess, 2**17);
-
-$frames = spdy_read($sess, all => [
-	{ sid => $sid1, fin => 1 },
-	{ sid => $sid2, fin => 1 }
-]);
-
-@data = grep { $_->{type} eq "DATA" && $_->{sid} == $sid1 } @$frames;
-$sum = eval join '+', map { $_->{length} } @data;
-is($sum, 80, 'multiple - stream1 remain data');
-
-@data = grep { $_->{type} eq "DATA" && $_->{sid} == $sid2 } @$frames;
-$sum = eval join '+', map { $_->{length} } @data;
-is($sum, 2**16 + 80, 'multiple - stream2 full data');
-
-# request priority parsing in $spdy_request_priority
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/prio', prio => 0 });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-is($frame->{data}, 0, 'priority 0');
-
-$sid1 = spdy_stream($sess, { path => '/prio', prio => 1 });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-is($frame->{data}, 1, 'priority 1');
-
-$sid1 = spdy_stream($sess, { path => '/prio', prio => 7 });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "DATA" } @$frames;
-is($frame->{data}, 7, 'priority 7');
-
-# stream multiplexing + priority
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/t1.html', prio => 7 });
-spdy_read($sess, all => [{ sid => $sid1, length => 2**16 }]);
-
-$sid2 = spdy_stream($sess, { path => '/t2.html', prio => 0 });
-spdy_read($sess, all => [{ sid => $sid2, fin => 0 }]);
-
-spdy_window($sess, 2**17, $sid1);
-spdy_window($sess, 2**17, $sid2);
-spdy_window($sess, 2**17);
-
-$frames = spdy_read($sess, all => [
-	{ sid => $sid1, fin => 1 },
-	{ sid => $sid2, fin => 1 }
-]);
-
-@data = grep { $_->{type} eq "DATA" } @$frames;
-is(join (' ', map { $_->{sid} } @data), "$sid2 $sid1", 'multiple priority 1');
-
-# and vice versa
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/t1.html', prio => 0 });
-spdy_read($sess, all => [{ sid => $sid1, length => 2**16 }]);
-
-$sid2 = spdy_stream($sess, { path => '/t2.html', prio => 7 });
-spdy_read($sess, all => [{ sid => $sid2, fin => 0 }]);
-
-spdy_window($sess, 2**17, $sid1);
-spdy_window($sess, 2**17, $sid2);
-spdy_window($sess, 2**17);
-
-$frames = spdy_read($sess, all => [
-	{ sid => $sid1, fin => 1 },
-	{ sid => $sid2, fin => 1 }
-]);
-
-@data = grep { $_->{type} eq "DATA" } @$frames;
-is(join (' ', map { $_->{sid} } @data), "$sid1 $sid2", 'multiple priority 2');
-
-# limit_conn
-
-$sess = new_session();
-spdy_settings($sess, 7 => 1);
-
-$sid1 = spdy_stream($sess, { path => '/t3.html' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 0 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" && $_->{sid} == $sid1 } @$frames;
-is($frame->{headers}->{':status'}, 200, 'conn_limit 1');
-
-$sid2 = spdy_stream($sess, { path => '/t3.html' });
-$frames = spdy_read($sess, all => [{ sid => $sid2, fin => 0 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" && $_->{sid} == $sid2 } @$frames;
-is($frame->{headers}->{':status'}, 503, 'conn_limit 2');
-
-spdy_settings($sess, 7 => 2**16);
-
-spdy_read($sess, all => [
-	{ sid => $sid1, fin => 1 },
-	{ sid => $sid2, fin => 1 }
-]);
-
-# limit_conn + client's RST_STREAM
-
-$sess = new_session();
-spdy_settings($sess, 7 => 1);
-
-$sid1 = spdy_stream($sess, { path => '/t3.html' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 0 }]);
-spdy_rst($sess, $sid1, 5);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" && $_->{sid} == $sid1 } @$frames;
-is($frame->{headers}->{':status'}, 200, 'RST_STREAM 1');
-
-$sid2 = spdy_stream($sess, { path => '/t3.html' });
-$frames = spdy_read($sess, all => [{ sid => $sid2, fin => 0 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" && $_->{sid} == $sid2 } @$frames;
-is($frame->{headers}->{':status'}, 200, 'RST_STREAM 2');
-
-# GOAWAY on SYN_STREAM with even StreamID
-
-TODO: {
-local $TODO = 'not yet';
-
-$sess = new_session();
-spdy_stream($sess, { path => '/s' }, 2);
-$frames = spdy_read($sess, all => [{ type => 'GOAWAY' }]);
-
-($frame) = grep { $_->{type} eq "GOAWAY" } @$frames;
-ok($frame, 'even stream - GOAWAY frame');
-is($frame->{code}, 1, 'even stream - error code');
-is($frame->{sid}, 0, 'even stream - last used stream');
-
-}
-
-# GOAWAY on SYN_STREAM with backward StreamID
-
-TODO: {
-local $TODO = 'not yet';
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/s' }, 3);
-spdy_read($sess, all => [{ type => 'GOAWAY' }]);
-
-$sid2 = spdy_stream($sess, { path => '/s' }, 1);
-$frames = spdy_read($sess, all => [{ type => 'GOAWAY' }]);
-
-($frame) = grep { $_->{type} eq "GOAWAY" } @$frames;
-ok($frame, 'backward stream - GOAWAY frame');
-is($frame->{code}, 1, 'backward stream - error code');
-is($frame->{sid}, $sid1, 'backward stream - last used stream');
-
-}
-
-# RST_STREAM on the second SYN_STREAM with same StreamID
-
-TODO: {
-local $TODO = 'not yet';
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/s' }, 3);
-spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-$sid2 = spdy_stream($sess, { path => '/s' }, 3);
-$frames = spdy_read($sess, all => [{ type => 'RST_STREAM' }]);
-
-($frame) = grep { $_->{type} eq "RST_STREAM" } @$frames;
-ok($frame, 'dup stream - RST_STREAM frame');
-is($frame->{code}, 1, 'dup stream - error code');
-is($frame->{sid}, $sid1, 'dup stream - stream');
-
-}
-
-# awkward protocol version
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/s', version => 'HTTP/1.10' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{':status'}, 200, 'awkward version');
-
-# missing mandatory request header
-
-$sess = new_session();
-$sid1 = spdy_stream($sess, { path => '/s', version => '' });
-$frames = spdy_read($sess, all => [{ sid => $sid1, fin => 1 }]);
-
-($frame) = grep { $_->{type} eq "SYN_REPLY" } @$frames;
-is($frame->{headers}->{':status'}, 400, 'incomplete headers');
-
-# GOAWAY before closing a connection by server
-
-$t->stop();
-
-TODO: {
-local $TODO = 'not yet';
-
-$frames = spdy_read($sess, all => [{ type => 'RST_STREAM' }]);
-
-($frame) = grep { $_->{type} eq "GOAWAY" } @$frames;
-ok($frame, 'GOAWAY on connection close');
-
-}
-
-###############################################################################
-
-sub spdy_ping {
-	my ($sess, $payload) = @_;
-
-	raw_write($sess->{socket}, pack("N3", 0x80030006, 0x4, $payload));
-}
-
-sub spdy_rst {
-	my ($sess, $sid, $error) = @_;
-
-	raw_write($sess->{socket}, pack("N4", 0x80030003, 0x8, $sid, $error));
-}
-
-sub spdy_window {
-	my ($sess, $win, $stream) = @_;
-
-	$stream = 0 unless defined $stream;
-	raw_write($sess->{socket}, pack("N4", 0x80030009, 8, $stream, $win));
-}
-
-sub spdy_settings {
-	my ($sess, %extra) = @_;
-
-	my $cnt = keys %extra;
-	my $len = 4 + 8 * $cnt;
-
-	my $buf = pack "N3", 0x80030004, $len, $cnt;
-	$buf .= join '', map { pack "N2", $_, $extra{$_} } keys %extra;
-	raw_write($sess->{socket}, $buf);
-}
-
-sub spdy_read {
-	my ($sess, %extra) = @_;
-	my ($length, @got);
-	my $s = $sess->{socket};
-	my $buf = '';
-
-	while (1) {
-		$buf = raw_read($s, $buf, 8);
-		last unless length $buf;
-
-		my $type = unpack("B", $buf);
-		$length = 8 + hex unpack("x5 H6", $buf);
-		$buf = raw_read($s, $buf, $length);
-		last unless length $buf;
-
-		if ($type == 0) {
-			push @got, dframe($buf);
-
-		} else {
-			my $ctype = unpack("x2 n", $buf);
-			push @got, $cframe{$ctype}($sess, $buf);
-		}
-		$buf = substr($buf, $length);
-
-		last unless test_fin($got[-1], $extra{all});
-	};
-	return \@got;
-}
-
-sub test_fin {
-	my ($frame, $all) = @_;
-	my @test = @{$all};
-
-	# wait for the specified DATA length
-
-	for (@test) {
-		if ($_->{length} && $frame->{type} eq 'DATA') {
-			# check also for StreamID if needed
-
-			if (!$_->{sid} || $_->{sid} == $frame->{sid}) {
-				$_->{length} -= $frame->{length};
-			}
-		}
-	}
-	@test = grep { !(defined $_->{length} && $_->{length} == 0) } @test;
-
-	# wait for the fin flag
-
-	@test = grep { !(defined $_->{fin}
-		&& $_->{sid} == $frame->{sid} && $_->{fin} == $frame->{fin})
-	} @test if defined $frame->{fin};
-
-	# wait for the specified frame
-
-	@test = grep { !($_->{type} && $_->{type} eq $frame->{type}) } @test;
-
-	@{$all} = @test;
-}
-
-sub dframe {
-	my ($buf) = @_;
-	my %frame;
-	my $skip = 0;
-
-	my $stream = unpack "\@$skip B32", $buf; $skip += 4;
-	substr($stream, 0, 1) = 0;
-	$stream = unpack("N", pack("B32", $stream));
-	$frame{sid} = $stream;
-
-	my $flags = unpack "\@$skip B8", $buf; $skip += 1;
-	$frame{fin} = substr($flags, 7, 1);
-
-	my $length = hex (unpack "\@$skip H6", $buf); $skip += 3;
-	$frame{length} = $length;
-
-	$frame{data} = substr($buf, $skip, $length);
-	$frame{type} = "DATA";
-	return \%frame;
-}
-
-sub spdy_stream {
-	my ($ctx, $uri, $stream) = @_;
-	my ($input, $output, $buf);
-	my ($d, $status);
-
-	my $host = $uri->{host} || '127.0.0.1:8080';
-	my $method = $uri->{method} || 'GET';
-	my $headers = $uri->{headers} || {};
-	my $body = $uri->{body};
-	my $prio = defined $uri->{prio} ? $uri->{prio} : 4;
-	my $version = defined $uri->{version} ? $uri->{version} : "HTTP/1.1";
-
-	if ($stream) {
-		$ctx->{last_stream} = $stream;
-	} else {
-		$ctx->{last_stream} += 2;
-	}
-
-	$buf = pack("NC", 0x80030001, not $body);
-	$buf .= pack("xxx");			# Length stub
-	$buf .= pack("N", $ctx->{last_stream});	# Stream-ID
-	$buf .= pack("N", 0);			# Assoc. Stream-ID
-	$buf .= pack("n", $prio << 13);
-
-	my $ent = 4 + keys %{$headers};
-	$ent++ if $body;
-	$ent++ if $version;
-
-	$input = pack("N", $ent);
-	$input .= hpack(":host", $host);
-	$input .= hpack(":method", $method);
-	$input .= hpack(":path", $uri->{path});
-	$input .= hpack(":scheme", "http");
-	if ($version) {
-		$input .= hpack(":version", $version);
-	}
-	if ($body) {
-		$input .= hpack("content-length", length $body);
-	}
-	$input .= join '', map { hpack($_, $headers->{$_}) } keys %{$headers};
-
-	$d = $ctx->{zlib}->{d};
-	$status = $d->deflate($input => \my $start);
-	$status == Compress::Raw::Zlib->Z_OK or fail "deflate failed";
-	$status = $d->flush(\my $tail => Compress::Raw::Zlib->Z_SYNC_FLUSH);
-	$status == Compress::Raw::Zlib->Z_OK or fail "flush failed";
-	$output = $start . $tail;
-
-	# set length, attach headers and optional body
-
-	$buf |= pack "x4N", length($output) + 10;
-	$buf .= $output;
-
-	if (defined $body) {
-		$buf .= pack "NCxn", $ctx->{last_stream}, 0x01, length $body;
-		$buf .= $body;
-	}
-
-	raw_write($ctx->{socket}, $buf);
-	return $ctx->{last_stream};
-}
-
-sub syn_reply {
-	my ($ctx, $buf) = @_;
-	my ($i, $status);
-	my %payload;
-	my $skip = 4;
-
-	my $flags = unpack "\@$skip B8", $buf; $skip += 1;
-	$payload{fin} = substr($flags, 7, 1);
-
-	my $length = hex unpack "\@$skip H6", $buf; $skip += 3;
-	$payload{length} = $length;
-	$payload{type} = 'SYN_REPLY';
-
-	my $stream = unpack "\@$skip B32", $buf; $skip += 4;
-	substr($stream, 0, 1) = 0;
-	$stream = unpack("N", pack("B32", $stream));
-	$payload{sid} = $stream;
-
-	my $input = substr($buf, $skip, $length - 4);
-	$i = $ctx->{zlib}->{i};
-
-	$status = $i->inflate($input => \my $out);
-	fail "Failed: $status" unless $status == Compress::Raw::Zlib->Z_OK;
-	$payload{headers} = hunpack($out);
-	return \%payload;
-}
-
-sub rst_stream {
-	my ($ctx, $buf) = @_;
-	my %payload;
-	my $skip = 5;
-
-	$payload{length} = hex(unpack "\@$skip H6", $buf); $skip += 3;
-	$payload{type} = 'RST_STREAM';
-	$payload{sid} = unpack "\@$skip N", $buf; $skip += 4;
-	$payload{code} = unpack "\@$skip N", $buf;
-	return \%payload;
-}
-
-sub settings {
-	my ($ctx, $buf) = @_;
-	my %payload;
-	my $skip = 4;
-
-	$payload{flags} = unpack "\@$skip H", $buf; $skip += 1;
-	$payload{length} = hex(unpack "\@$skip H6", $buf); $skip += 3;
-	$payload{type} = 'SETTINGS';
-
-	my $nent = unpack "\@$skip N", $buf; $skip += 4;
-	for (1 .. $nent) {
-		my $flags = hex unpack "\@$skip H2", $buf; $skip += 1;
-		my $id = hex unpack "\@$skip H6", $buf; $skip += 3;
-		$payload{$id}{flags} = $flags;
-		$payload{$id}{value} = unpack "\@$skip N", $buf; $skip += 4;
-	}
-	return \%payload;
-}
-
-sub ping {
-	my ($ctx, $buf) = @_;
-	my %payload;
-	my $skip = 5;
-
-	$payload{length} = hex(unpack "\@$skip H6", $buf); $skip += 3;
-	$payload{type} = 'PING';
-	$payload{value} = unpack "\@$skip N", $buf;
-	return \%payload;
-}
-
-sub goaway {
-	my ($ctx, $buf) = @_;
-	my %payload;
-	my $skip = 5;
-
-	$payload{length} = hex unpack "\@$skip H6", $buf; $skip += 3;
-	$payload{type} = 'GOAWAY';
-	$payload{sid} = unpack "\@$skip N", $buf; $skip += 4;
-	$payload{code} = unpack "\@$skip N", $buf;
-	return \%payload;
-}
-
-sub window_update {
-	my ($ctx, $buf) = @_;
-	my %payload;
-	my $skip = 5;
-
-	$payload{length} = hex(unpack "\@$skip H6", $buf); $skip += 3;
-	$payload{type} = 'WINDOW_UPDATE';
-
-	my $stream = unpack "\@$skip B32", $buf; $skip += 4;
-	substr($stream, 0, 1) = 0;
-	$stream = unpack("N", pack("B32", $stream));
-	$payload{sid} = $stream;
-
-	my $value = unpack "\@$skip B32", $buf;
-	substr($value, 0, 1) = 0;
-	$payload{wdelta} = unpack("N", pack("B32", $value));
-	return \%payload;
-}
-
-sub hpack {
-	my ($name, $value) = @_;
-
-	pack("N", length($name)) . $name . pack("N", length($value)) . $value;
-}
-
-sub hunpack {
-	my ($data) = @_;
-	my %headers;
-	my $skip = 0;
-
-	my $nent = unpack "\@$skip N", $data; $skip += 4;
-	for (1 .. $nent) {
-		my $len = unpack("\@$skip N", $data); $skip += 4;
-		my $name = unpack("\@$skip A$len", $data); $skip += $len;
-
-		$len = unpack("\@$skip N", $data); $skip += 4;
-		my $value = unpack("\@$skip A$len", $data); $skip += $len;
-		$value .= "\0" x ($len - length $value);
-
-		$headers{$name} = $value;
-	}
-	return \%headers;
-}
-
-sub raw_read {
-	my ($s, $buf, $len) = @_;
-	my $got = '';
-
-	while (length($buf) < $len && IO::Select->new($s)->can_read(1)) {
-		$s->sysread($got, $len - length($buf)) or last;
-		log_in($got);
-		$buf .= $got;
-	}
-	return $buf;
-}
-
-sub raw_write {
-	my ($s, $message) = @_;
-
-	local $SIG{PIPE} = 'IGNORE';
-
-	while (IO::Select->new($s)->can_write(0.4)) {
-		log_out($message);
-		my $n = $s->syswrite($message);
-		last unless $n;
-		$message = substr($message, $n);
-		last unless length $message;
-	}
-}
-
-sub new_session {
-	my ($port, %extra) = @_;
-	my ($d, $i, $status, $s);
-
-	($d, $status) = Compress::Raw::Zlib::Deflate->new(
-		-WindowBits => 12,
-		-Dictionary => dictionary(),
-		-Level => Compress::Raw::Zlib->Z_NO_COMPRESSION
-	);
-	fail "Zlib failure: $status" unless $d;
-
-	($i, $status) = Compress::Raw::Zlib::Inflate->new(
-		-WindowBits => Compress::Raw::Zlib->WANT_GZIP_OR_ZLIB,
-		-Dictionary => dictionary()
-	);
-	fail "Zlib failure: $status" unless $i;
-
-	$s = new_socket($port);
-
-	if ($extra{proxy}) {
-		raw_write($s, $extra{proxy});
-	}
-
-	return { zlib => { i => $i, d => $d },
-		socket => $s, last_stream => -1 };
-}
-
-sub new_socket {
-	my ($port) = @_;
-	my $s;
-
-	$port = 8080 unless defined $port;
-
-	eval {
-		local $SIG{ALRM} = sub { die "timeout\n" };
-		local $SIG{PIPE} = sub { die "sigpipe\n" };
-		alarm(2);
-		$s = IO::Socket::INET->new(
-			Proto => 'tcp',
-			PeerAddr => "127.0.0.1:$port",
-		);
-		alarm(0);
-	};
-	alarm(0);
-
-	if ($@) {
-		log_in("died: $@");
-		return undef;
-	}
-
-	return $s;
-}
-
-sub dictionary {
-	join('', (map pack('N/a*', $_), qw(
-		options
-		head
-		post
-		put
-		delete
-		trace
-		accept
-		accept-charset
-		accept-encoding
-		accept-language
-		accept-ranges
-		age
-		allow
-		authorization
-		cache-control
-		connection
-		content-base
-		content-encoding
-		content-language
-		content-length
-		content-location
-		content-md5
-		content-range
-		content-type
-		date
-		etag
-		expect
-		expires
-		from
-		host
-		if-match
-		if-modified-since
-		if-none-match
-		if-range
-		if-unmodified-since
-		last-modified
-		location
-		max-forwards
-		pragma
-		proxy-authenticate
-		proxy-authorization
-		range
-		referer
-		retry-after
-		server
-		te
-		trailer
-		transfer-encoding
-		upgrade
-		user-agent
-		vary
-		via
-		warning
-		www-authenticate
-		method
-		get
-		status), "200 OK",
-		qw(version HTTP/1.1 url public set-cookie keep-alive origin)),
-		"100101201202205206300302303304305306307402405406407408409410",
-		"411412413414415416417502504505",
-		"203 Non-Authoritative Information",
-		"204 No Content",
-		"301 Moved Permanently",
-		"400 Bad Request",
-		"401 Unauthorized",
-		"403 Forbidden",
-		"404 Not Found",
-		"500 Internal Server Error",
-		"501 Not Implemented",
-		"503 Service Unavailable",
-		"Jan Feb Mar Apr May Jun Jul Aug Sept Oct Nov Dec",
-		" 00:00:00",
-		" Mon, Tue, Wed, Thu, Fri, Sat, Sun, GMT",
-		"chunked,text/html,image/png,image/jpg,image/gif,",
-		"application/xml,application/xhtml+xml,text/plain,",
-		"text/javascript,public", "privatemax-age=gzip,deflate,",
-		"sdchcharset=utf-8charset=iso-8859-1,utf-,*,enq=0."
-	);
-}
-
-###############################################################################
-
-# reply with multiple (also empty) header values
-
-sub http_daemon {
-	my $server = IO::Socket::INET->new(
-		Proto => 'tcp',
-		LocalHost => '127.0.0.1',
-		LocalPort => 8083,
-		Listen => 5,
-		Reuse => 1
-	)
-		or die "Can't create listening socket: $!\n";
-
-	local $SIG{PIPE} = 'IGNORE';
-
-	while (my $client = $server->accept()) {
-		$client->autoflush(1);
-
-		my $headers = '';
-		my $uri = '';
-
-		while (<$client>) {
-			$headers .= $_;
-			last if (/^\x0d?\x0a?$/);
-		}
-
-		next if $headers eq '';
-		$uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
-
-		if ($uri eq '/inside') {
-
-			print $client <<EOF;
-HTTP/1.1 200 OK
-Connection: close
-X-Foo: val1
-X-Foo:
-X-Foo: val2
-
-EOF
-
-		} elsif ($uri eq '/first') {
-
-			print $client <<EOF;
-HTTP/1.1 200 OK
-Connection: close
-X-Foo:
-X-Foo: val1
-X-Foo: val2
-
-EOF
-
-		} elsif ($uri eq '/last') {
-
-			print $client <<EOF;
-HTTP/1.1 200 OK
-Connection: close
-X-Foo: val1
-X-Foo: val2
-X-Foo:
-
-EOF
-		}
-
-	} continue {
-		close $client;
-	}
-}
-
-###############################################################################
--- a/ssi.t
+++ b/ssi.t
@@ -21,7 +21,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http ssi cache proxy rewrite shmem/)
+my $t = Test::Nginx->new()->has(qw/http ssi cache proxy rewrite/)
 	->plan(27);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
--- a/ssl_sni_reneg.t
+++ b/ssl_sni_reneg.t
@@ -100,18 +100,12 @@ Net::SSLeay::write($ssl, 'GET / HTTP/1.0
 ok(Net::SSLeay::renegotiate($ssl), 'renegotiation');
 ok(Net::SSLeay::set_tlsext_host_name($ssl, 'localhost'), 'SNI');
 
-SKIP: {
-skip 'leaves coredump', 1 unless $t->has_version('1.9.8')
-	or $ENV{TEST_NGINX_UNSAFE};
-
 Net::SSLeay::write($ssl, 'Host: localhost' . CRLF . CRLF);
 
 is(Net::SSLeay::read($ssl), undef, 'response');
 
 }
 
-}
-
 ###############################################################################
 
 sub get_ssl_socket {
--- a/stream_limit_conn.t
+++ b/stream_limit_conn.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http stream stream_limit_conn shmem/)
+my $t = Test::Nginx->new()->has(qw/http stream stream_limit_conn/)
 	->plan(8)->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/stream_limit_conn_complex.t
+++ b/stream_limit_conn_complex.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http stream stream_limit_conn shmem/)
+my $t = Test::Nginx->new()->has(qw/http stream stream_limit_conn/)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/stream_proxy_protocol.t
+++ b/stream_proxy_protocol.t
@@ -26,7 +26,7 @@ use Test::Nginx::Stream qw/ stream /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/stream/)
+my $t = Test::Nginx->new()->has(qw/stream/)->plan(2)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -54,7 +54,7 @@ stream {
 EOF
 
 $t->run_daemon(\&stream_daemon);
-$t->try_run('no stream proxy_protocol')->plan(2);
+$t->run();
 $t->waitforsocket('127.0.0.1:' . port(8081));
 
 ###############################################################################
--- a/stream_proxy_protocol_ipv6.t
+++ b/stream_proxy_protocol_ipv6.t
@@ -62,7 +62,7 @@ stream {
 EOF
 
 $t->run_daemon(\&stream_daemon);
-$t->try_run('no inet6 support or stream proxy_protocol')->plan(2);
+$t->try_run('no inet6 support')->plan(2);
 $t->waitforsocket('127.0.0.1:' . port(8082));
 
 ###############################################################################
--- a/stream_proxy_protocol_ssl.t
+++ b/stream_proxy_protocol_ssl.t
@@ -27,7 +27,8 @@ select STDOUT; $| = 1;
 eval { require IO::Socket::SSL; };
 plan(skip_all => 'IO::Socket::SSL not installed') if $@;
 
-my $t = Test::Nginx->new()->has(qw/stream stream_ssl/)->has_daemon('openssl');
+my $t = Test::Nginx->new()->has(qw/stream stream_ssl/)->has_daemon('openssl')
+	->plan(2);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
 
@@ -76,7 +77,7 @@ foreach my $name ('localhost') {
 
 $t->run_daemon(\&stream_daemon_ssl, port(8081), path => $d, pp => 1);
 $t->run_daemon(\&stream_daemon_ssl, port(8083), path => $d, pp => 0);
-$t->try_run('no stream proxy_protocol')->plan(2);
+$t->run();
 
 $t->waitforsocket('127.0.0.1:' . port(8081));
 $t->waitforsocket('127.0.0.1:' . port(8083));
--- a/stream_tcp_nodelay.t
+++ b/stream_tcp_nodelay.t
@@ -28,8 +28,6 @@ select STDOUT; $| = 1;
 
 my $t = Test::Nginx->new()->has(qw/stream/);
 
-plan(skip_all => 'no tcp_nodelay') unless $t->has_version('1.9.4');
-
 $t->plan(2)->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/stream_udp_limit_conn.t
+++ b/stream_udp_limit_conn.t
@@ -23,7 +23,7 @@ use Test::Nginx::Stream qw/ dgram /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/stream stream_limit_conn udp shmem/)
+my $t = Test::Nginx->new()->has(qw/stream stream_limit_conn udp/)->plan(9)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -75,7 +75,7 @@ stream {
 
 EOF
 
-$t->try_run('no stream udp')->plan(9);
+$t->run();
 $t->run_daemon(\&udp_daemon, $t);
 $t->waitforfile($t->testdir . '/' . port(8080));
 
--- a/stream_udp_proxy.t
+++ b/stream_udp_proxy.t
@@ -22,7 +22,7 @@ use Test::Nginx::Stream qw/ dgram /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/stream udp/)
+my $t = Test::Nginx->new()->has(qw/stream udp/)->plan(5)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -59,7 +59,7 @@ EOF
 
 
 $t->run_daemon(\&udp_daemon, port(8081), $t);
-$t->try_run('no stream udp')->plan(5);
+$t->run();
 $t->waitforfile($t->testdir . '/' . port(8081));
 
 ###############################################################################
--- a/stream_udp_upstream.t
+++ b/stream_udp_upstream.t
@@ -23,7 +23,7 @@ use Test::Nginx::Stream qw/ dgram /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/stream udp/)
+my $t = Test::Nginx->new()->has(qw/stream udp/)->plan(4)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -84,7 +84,7 @@ EOF
 
 $t->run_daemon(\&udp_daemon, port(8084), $t);
 $t->run_daemon(\&udp_daemon, port(8085), $t);
-$t->try_run('no stream udp')->plan(4);
+$t->run();
 
 $t->waitforfile($t->testdir . '/' . port(8084));
 $t->waitforfile($t->testdir . '/' . port(8085));
--- a/stream_udp_upstream_hash.t
+++ b/stream_udp_upstream_hash.t
@@ -23,7 +23,7 @@ use Test::Nginx::Stream qw/ dgram /;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/stream stream_upstream_hash udp/);
+my $t = Test::Nginx->new()->has(qw/stream stream_upstream_hash udp/)->plan(2);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
 
@@ -65,7 +65,7 @@ EOF
 
 $t->run_daemon(\&udp_daemon, port(8082), $t);
 $t->run_daemon(\&udp_daemon, port(8083), $t);
-$t->try_run('no stream udp')->plan(2);
+$t->run();
 
 $t->waitforfile($t->testdir . '/' . port(8082));
 $t->waitforfile($t->testdir . '/' . port(8083));
--- a/stream_udp_upstream_least_conn.t
+++ b/stream_udp_upstream_least_conn.t
@@ -24,7 +24,7 @@ select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
 my $t = Test::Nginx->new()->has(qw/stream stream_upstream_least_conn udp/)
-	->write_file_expand('nginx.conf', <<'EOF');
+	->plan(2)->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
 
@@ -53,7 +53,7 @@ EOF
 
 $t->run_daemon(\&udp_daemon, port(8081), $t);
 $t->run_daemon(\&udp_daemon, port(8082), $t);
-$t->try_run('no stream udp')->plan(2);
+$t->run();
 
 $t->waitforfile($t->testdir . '/' . port(8081));
 $t->waitforfile($t->testdir . '/' . port(8082));
--- a/sub_filter.t
+++ b/sub_filter.t
@@ -138,17 +138,12 @@ like(http_get('/single/many?b=AA'), qr/B
 like(http_get('/single/many?b=CAAC'), qr/CBBC/, 'single many middle');
 like(http_get('/single/many?b=CA'), qr/CB/, 'single many end');
 
-TODO: {
-local $TODO = 'not yet' unless $t->has_version('1.9.4');
-
 like(http_get('/var/string?a=foo&b=Xfoo'), qr/_replaced/, 'complex string');
 like(http_get('/var/string?a=foo&b=XFOO'), qr/_replaced/,
 	'complex string caseless');
 like(http_get('/var/string?a=abcdefghijklmnopq&b=Xabcdefghijklmnopq'),
 	qr/_replaced/, 'complex string long');
 
-}
-
 like(http_get('/var/replacement?a=ee&b=aaab'), qr/aee_replaced/,
 	'complex replacement');
 
--- a/sub_filter_merge.t
+++ b/sub_filter_merge.t
@@ -24,9 +24,6 @@ select STDOUT; $| = 1;
 
 my $t = Test::Nginx->new()->has(qw/http sub/);
 
-plan(skip_all => 'leaves coredump') unless $ENV{TEST_NGINX_UNSAFE}
-	or $t->has_version('1.9.5');
-
 $t->plan(1)->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
--- a/sub_filter_multi.t
+++ b/sub_filter_multi.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http rewrite sub proxy/);
+my $t = Test::Nginx->new()->has(qw/http rewrite sub proxy/)->plan(42);
 
 my $long_pattern = '0123456789abcdef' x 17;
 
@@ -281,7 +281,7 @@ EOF
 $t->write_file('huge10-02.html', scalar ('01efABC' . $long_pattern) x 1000);
 $t->write_file('huge11.html', scalar ('01efA_Z' . $long_pattern) x 1000);
 
-$t->try_run('no multiple sub_filter')->plan(42);
+$t->run();
 
 ###############################################################################
 
--- a/sub_filter_multi2.t
+++ b/sub_filter_multi2.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http rewrite sub/)
+my $t = Test::Nginx->new()->has(qw/http rewrite sub/)->plan(7)
 	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
@@ -60,7 +60,7 @@ http {
 
 EOF
 
-$t->try_run('no multiple sub_filter')->plan(7);
+$t->run();
 
 ###############################################################################
 
--- a/syslog.t
+++ b/syslog.t
@@ -24,7 +24,7 @@ select STDOUT; $| = 1;
 
 plan(skip_all => 'win32') if $^O eq 'MSWin32';
 
-my $t = Test::Nginx->new()->has(qw/http limit_req/);
+my $t = Test::Nginx->new()->has(qw/http limit_req/)->plan(59);
 
 $t->write_file_expand('nginx.conf', <<'EOF');
 
@@ -147,7 +147,7 @@ EOF
 $t->waitforfile($t->testdir . '/s_http.log');
 $t->waitforfile($t->testdir . '/s_if.log');
 
-$t->try_run('no syslog nohostname')->plan(59);
+$t->run();
 
 ###############################################################################
 
--- a/upstream_hash_memcached.t
+++ b/upstream_hash_memcached.t
@@ -144,14 +144,8 @@ is_deeply(ngx('/'), mem($memd), 'cache::
 	'127.0.0.1:' . port(8082),
 	'127.0.0.1:' . port(8083)] });
 
-TODO: {
-local $TODO = 'not yet' unless $Config{byteorder} =~ '1234'
-	or $t->has_version('1.9.1');
-
 is_deeply(ngx('/c'), mem($memd), 'cache::memcached::fast');
 
-}
-
 $memd = new Cache::Memcached(servers => [
 	[ '127.0.0.1:' . port(8081), 2 ],
 	[ '127.0.0.1:' . port(8082), 3 ],
@@ -164,14 +158,8 @@ is_deeply(ngx('/w'), mem($memd), 'cache:
 	{ address => '127.0.0.1:' . port(8082), weight => 3 },
 	{ address => '127.0.0.1:' . port(8083), weight => 1 }] });
 
-TODO: {
-local $TODO = 'not yet' unless $Config{byteorder} =~ '1234'
-	or $t->has_version('1.9.1');
-
 is_deeply(ngx('/cw'), mem($memd), 'cache::memcached::fast weight');
 
-}
-
 ###############################################################################
 
 sub ngx {
--- a/upstream_zone_ssl.t
+++ b/upstream_zone_ssl.t
@@ -23,7 +23,8 @@ select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
 my $t = Test::Nginx->new()->has(qw/http proxy http_ssl upstream_zone/)
-	->has_daemon('openssl')->write_file_expand('nginx.conf', <<'EOF');
+	->has_daemon('openssl')->plan(8)
+	->write_file_expand('nginx.conf', <<'EOF');
 
 %%TEST_GLOBALS%%
 
@@ -106,7 +107,7 @@ foreach my $name ('localhost') {
 		or die "Can't create certificate for $name: $!\n";
 }
 
-$t->try_run('no upstream zone')->plan(8);
+$t->run();
 
 ###############################################################################