Tests: grpc request buffering and next upstream tests.
diff --git a/grpc_next_upstream.t b/grpc_next_upstream.t
new file mode 100644
index 0000000..635466f
--- /dev/null
+++ b/grpc_next_upstream.t
@@ -0,0 +1,146 @@
+#!/usr/bin/perl
+
+# (C) Maxim Dounin
+# (C) Sergey Kandaurov
+# (C) Nginx, Inc.
+
+# Tests for grpc module, grpc_next_upstream directive.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+my $t = Test::Nginx->new()->has(qw/http http_v2 grpc rewrite/);
+
+$t->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+}
+
+http {
+    %%TEST_GLOBALS_HTTP%%
+
+    upstream u {
+        server 127.0.0.1:8081 max_fails=2;
+        server 127.0.0.1:8082;
+    }
+
+    upstream u2 {
+        server 127.0.0.1:8081;
+        server 127.0.0.1:8082;
+    }
+
+    server {
+        listen       127.0.0.1:8080;
+        server_name  localhost;
+
+        location / {
+            grpc_pass u;
+            grpc_next_upstream http_500 http_404 invalid_header;
+        }
+
+        location /all/ {
+            grpc_pass u2;
+            grpc_next_upstream http_500 http_404;
+            error_page 404 /all/404;
+            grpc_intercept_errors on;
+        }
+
+        location /all/404 {
+            return 200 "$upstream_addr\n";
+        }
+    }
+
+    server {
+        listen       127.0.0.1:8081 http2;
+        server_name  localhost;
+
+        location / {
+            return 404;
+        }
+        location /ok {
+            return 200 "AND-THIS\n";
+        }
+        location /500 {
+            return 500;
+        }
+        location /444 {
+            return 444;
+        }
+
+        location /all/ {
+            return 404;
+        }
+    }
+
+    server {
+        listen       127.0.0.1:8082 http2;
+        server_name  localhost;
+
+        location / {
+            return 200 "TEST-OK-IF-YOU-SEE-THIS\n";
+        }
+
+        location /all/ {
+            return 404;
+        }
+    }
+}
+
+EOF
+
+$t->try_run('no grpc')->plan(9);
+
+###############################################################################
+
+my ($p1, $p2) = (port(8081), port(8082));
+
+# check if both request fallback to a backend
+# which returns valid response
+
+like(http_get('/'), qr/SEE-THIS/, 'grpc request');
+like(http_get('/'), qr/SEE-THIS/, 'second request');
+
+# make sure backend isn't switched off after
+# grpc_next_upstream http_404
+
+like(http_get('/ok') . http_get('/ok'), qr/AND-THIS/, 'not down');
+
+# next upstream on invalid_header
+
+like(http_get('/444'), qr/SEE-THIS/, 'request 444');
+like(http_get('/444'), qr/SEE-THIS/, 'request 444 second');
+
+# next upstream on http_500
+
+like(http_get('/500'), qr/SEE-THIS/, 'request 500');
+like(http_get('/500'), qr/SEE-THIS/, 'request 500 second');
+
+# make sure backend switched off with http_500
+
+unlike(http_get('/ok') . http_get('/ok'), qr/AND-THIS/, 'down after 500');
+
+# make sure all backends are tried once
+
+like(http_get('/all/rr'),
+	qr/^127.0.0.1:($p1, 127.0.0.1:$p2|$p2, 127.0.0.1:$p1)$/mi,
+	'all tried once');
+
+###############################################################################
diff --git a/grpc_request_buffering.t b/grpc_request_buffering.t
new file mode 100644
index 0000000..f290e8e
--- /dev/null
+++ b/grpc_request_buffering.t
@@ -0,0 +1,143 @@
+#!/usr/bin/perl
+
+# (C) Sergey Kandaurov
+# (C) Nginx, Inc.
+
+# Tests for grpc module, request body buffered.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+use Test::Nginx::HTTP2;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+my $t = Test::Nginx->new()->has(qw/http http_v2 grpc mirror/);
+
+$t->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+}
+
+http {
+    %%TEST_GLOBALS_HTTP%%
+
+    server {
+        listen       127.0.0.1:8080 http2;
+        server_name  localhost;
+
+        location /mirror { }
+
+        location / {
+            grpc_pass 127.0.0.1:8081;
+            add_header X-Body $request_body;
+            mirror /mirror;
+        }
+    }
+}
+
+EOF
+
+$t->try_run('no grpc')->plan(9);
+
+###############################################################################
+
+my $p = port(8081);
+my $f = grpc();
+
+my $frames = $f->{http_start}('/SayHello');
+my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
+is($frame->{flags}, 4, 'request - HEADERS flags');
+is($frame->{headers}{':method'}, 'POST', 'request - method');
+is($frame->{headers}{':scheme'}, 'http', 'request - scheme');
+is($frame->{headers}{':path'}, '/SayHello', 'request - path');
+is($frame->{headers}{':authority'}, "127.0.0.1:$p", 'request - authority');
+
+($frame) = grep { $_->{type} eq "DATA" } @$frames;
+is($frame->{data}, 'Hello', 'request - DATA');
+is($frame->{length}, 5, 'request - DATA length');
+is($frame->{flags}, 1, 'request - DATA flags');
+
+$frames = $f->{http_end}();
+($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
+is($frame->{headers}{'x-body'}, 'Hello', 'request body in memory');
+
+###############################################################################
+
+sub grpc {
+	my ($server, $client, $f, $s, $c, $sid, $uri);
+
+	$server = IO::Socket::INET->new(
+		Proto => 'tcp',
+		LocalHost => '127.0.0.1',
+		LocalPort => $p,
+		Listen => 5,
+		Reuse => 1
+	)
+		or die "Can't create listening socket: $!\n";
+
+	$f->{http_start} = sub {
+		($uri, my %extra) = @_;
+		$s = Test::Nginx::HTTP2->new() if !defined $s;
+		$s->new_stream({ body => 'Hello', headers => [
+			{ name => ':method', value => 'POST', mode => 0 },
+			{ name => ':scheme', value => 'http', mode => 0 },
+			{ name => ':path', value => $uri },
+			{ name => ':authority', value => 'localhost' },
+			{ name => 'content-length', value => '5' }]});
+
+		if (!$extra{reuse}) {
+			$client = $server->accept() or return;
+			log2c("(new connection $client)");
+
+			$client->sysread(my $buf, 24) == 24 or return; # preface
+
+			$c = Test::Nginx::HTTP2->new(1, socket => $client,
+				pure => 1, preface => "") or return;
+		}
+
+		my $frames = $c->read(all => [{ fin => 1 }]);
+
+		if (!$extra{reuse}) {
+			$c->h2_settings(0);
+			$c->h2_settings(1);
+		}
+
+		my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
+		$sid = $frame->{sid};
+		return $frames;
+	};
+	$f->{http_end} = sub {
+		$c->new_stream({ body_more => 1, headers => [
+			{ name => ':status', value => '200', mode => 0 },
+			{ name => 'content-type', value => 'application/grpc' },
+		]}, $sid);
+		$c->h2_body('Hello world', { body_more => 1 });
+		$c->new_stream({ headers => [
+			{ name => 'grpc-status', value => '0', mode => 2 },
+			{ name => 'grpc-message', value => '', mode => 2 },
+		]}, $sid);
+
+		return $s->read(all => [{ fin => 1 }]);
+	};
+	return $f;
+}
+
+sub log2c { Test::Nginx::log_core('||', @_); }
+
+###############################################################################