comparison grpc_ssl.t @ 1303:42577a840a7d

Tests: grpc module tests.
author Sergey Kandaurov <pluknet@nginx.com>
date Tue, 20 Mar 2018 18:56:33 +0300
parents
children 6f95c0ed2335
comparison
equal deleted inserted replaced
1302:beed8146d045 1303:42577a840a7d
1 #!/usr/bin/perl
2
3 # (C) Sergey Kandaurov
4 # (C) Nginx, Inc.
5
6 # Tests for grpc backend with ssl.
7
8 ###############################################################################
9
10 use warnings;
11 use strict;
12
13 use Test::More;
14
15 BEGIN { use FindBin; chdir($FindBin::Bin); }
16
17 use lib 'lib';
18 use Test::Nginx;
19 use Test::Nginx::HTTP2;
20
21 ###############################################################################
22
23 select STDERR; $| = 1;
24 select STDOUT; $| = 1;
25
26 my $t = Test::Nginx->new()->has(qw/http proxy rewrite http_v2 grpc/)
27 ->has(qw/upstream_keepalive http_ssl/);
28
29 $t->{_configure_args} =~ /OpenSSL ([\d\.]+)/;
30 plan(skip_all => 'OpenSSL too old') unless defined $1 and $1 ge '1.0.2';
31
32 $t->write_file_expand('nginx.conf', <<'EOF');
33
34 %%TEST_GLOBALS%%
35
36 daemon off;
37
38 events {
39 }
40
41 http {
42 %%TEST_GLOBALS_HTTP%%
43
44 upstream u {
45 server 127.0.0.1:8081;
46 keepalive 1;
47 }
48
49 server {
50 listen 127.0.0.1:8081 http2 ssl;
51 server_name localhost;
52
53 ssl_certificate_key localhost.key;
54 ssl_certificate localhost.crt;
55
56 http2_max_field_size 128k;
57 http2_max_header_size 128k;
58 http2_body_preread_size 128k;
59
60 location / {
61 grpc_pass 127.0.0.1:8082;
62 add_header X-Connection $connection;
63 }
64 }
65
66 server {
67 listen 127.0.0.1:8080 http2;
68 server_name localhost;
69
70 http2_max_field_size 128k;
71 http2_max_header_size 128k;
72 http2_body_preread_size 128k;
73
74 location / {
75 grpc_pass grpcs://127.0.0.1:8081;
76
77 if ($arg_if) {
78 # nothing
79 }
80
81 limit_except GET {
82 # nothing
83 }
84 }
85
86 location /KeepAlive {
87 grpc_pass grpcs://u;
88 }
89 }
90 }
91
92 EOF
93
94 $t->write_file('openssl.conf', <<EOF);
95 [ req ]
96 default_bits = 1024
97 encrypt_key = no
98 distinguished_name = req_distinguished_name
99 [ req_distinguished_name ]
100 EOF
101
102 my $d = $t->testdir();
103
104 foreach my $name ('localhost') {
105 system('openssl req -x509 -new '
106 . "-config $d/openssl.conf -subj /CN=$name/ "
107 . "-out $d/$name.crt -keyout $d/$name.key "
108 . ">>$d/openssl.out 2>&1") == 0
109 or die "Can't create certificate for $name: $!\n";
110 }
111
112 $t->try_run('no grpc')->plan(33);
113
114 ###############################################################################
115
116 my $p = port(8082);
117 my $f = grpc();
118
119 my $frames = $f->{http_start}('/SayHello');
120 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
121 is($frame->{flags}, 4, 'request - HEADERS flags');
122 ok((my $sid = $frame->{sid}) % 2, 'request - HEADERS sid odd');
123 is($frame->{headers}{':method'}, 'POST', 'request - method');
124 is($frame->{headers}{':scheme'}, 'http', 'request - scheme');
125 is($frame->{headers}{':path'}, '/SayHello', 'request - path');
126 is($frame->{headers}{':authority'}, "127.0.0.1:$p", 'request - authority');
127 is($frame->{headers}{'content-type'}, 'application/grpc',
128 'request - content type');
129 is($frame->{headers}{te}, 'trailers', 'request - te');
130
131 $frames = $f->{data}('Hello');
132 ($frame) = grep { $_->{type} eq "SETTINGS" } @$frames;
133 is($frame->{flags}, 1, 'request - SETTINGS ack');
134 is($frame->{sid}, 0, 'request - SETTINGS sid');
135 is($frame->{length}, 0, 'request - SETTINGS length');
136
137 ($frame) = grep { $_->{type} eq "DATA" } @$frames;
138 is($frame->{data}, 'Hello', 'request - DATA');
139 is($frame->{length}, 5, 'request - DATA length');
140 is($frame->{flags}, 1, 'request - DATA flags');
141 is($frame->{sid}, $sid, 'request - DATA sid match');
142
143 $frames = $f->{http_end}();
144 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
145 is($frame->{flags}, 4, 'response - HEADERS flags');
146 is($frame->{sid}, 1, 'response - HEADERS sid');
147 is($frame->{headers}{':status'}, '200', 'response - status');
148 is($frame->{headers}{'content-type'}, 'application/grpc',
149 'response - content type');
150 ok($frame->{headers}{server}, 'response - server');
151 ok($frame->{headers}{date}, 'response - date');
152 ok(my $c = $frame->{headers}{'x-connection'}, 'response - connection');
153
154 ($frame) = grep { $_->{type} eq "DATA" } @$frames;
155 is($frame->{data}, 'Hello world', 'response - DATA');
156 is($frame->{length}, 11, 'response - DATA length');
157 is($frame->{flags}, 0, 'response - DATA flags');
158 is($frame->{sid}, 1, 'response - DATA sid');
159
160 (undef, $frame) = grep { $_->{type} eq "HEADERS" } @$frames;
161 is($frame->{flags}, 5, 'response - trailers flags');
162 is($frame->{sid}, 1, 'response - trailers sid');
163 is($frame->{headers}{'grpc-message'}, '', 'response - trailers message');
164 is($frame->{headers}{'grpc-status'}, '0', 'response - trailers status');
165
166 # next request is on a new backend connection, no sid incremented
167
168 $f->{http_start}('/SayHello');
169 $f->{data}('Hello');
170 $frames = $f->{http_end}();
171 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
172 cmp_ok($frame->{headers}{'x-connection'}, '>', $c, 'response 2 - connection');
173
174 # upstream keepalive
175
176 $f->{http_start}('/KeepAlive');
177 $f->{data}('Hello');
178 $frames = $f->{http_end}();
179 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
180 ok($c = $frame->{headers}{'x-connection'}, 'keepalive - connection');
181
182 TODO: {
183 local $TODO = 'not yet' if $^O eq 'MSWin32';
184
185 $f->{http_start}('/KeepAlive');
186 $f->{data}('Hello');
187 $frames = $f->{http_end}();
188 ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
189 is($frame->{headers}{'x-connection'}, $c, 'keepalive - connection reuse');
190
191 }
192
193 ###############################################################################
194
195 sub grpc {
196 my ($server, $client, $f, $s, $c, $sid, $uri);
197
198 $server = IO::Socket::INET->new(
199 Proto => 'tcp',
200 LocalHost => '127.0.0.1',
201 LocalPort => $p,
202 Listen => 5,
203 Reuse => 1
204 )
205 or die "Can't create listening socket: $!\n";
206
207 $f->{http_start} = sub {
208 ($uri, my %extra) = @_;
209 my $body_more = 1 if $uri !~ /LongHeader/;
210 $s = Test::Nginx::HTTP2->new() if !defined $s;
211 $s->new_stream({ body_more => $body_more, headers => [
212 { name => ':method', value => 'POST', mode => 0 },
213 { name => ':scheme', value => 'http', mode => 0 },
214 { name => ':path', value => $uri, },
215 { name => ':authority', value => 'localhost' },
216 { name => 'content-type', value => 'application/grpc' },
217 { name => 'te', value => 'trailers', mode => 2 }]});
218
219 if (!$extra{reuse}) {
220 $client = $server->accept() or return;
221 log2c("(new connection $client)");
222
223 $client->sysread(my $buf, 24) == 24 or return; # preface
224
225 $c = Test::Nginx::HTTP2->new(1, socket => $client,
226 pure => 1, preface => "") or return;
227 }
228
229 my $frames = $c->read(all => [{ fin => 4 }]);
230
231 if (!$extra{reuse}) {
232 $c->h2_settings(0);
233 $c->h2_settings(1);
234 }
235
236 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
237 $sid = $frame->{sid};
238 return $frames;
239 };
240 $f->{data} = sub {
241 my ($body, %extra) = @_;
242 $s->h2_body($body, { %extra });
243 return $c->read(all => [{ sid => $sid,
244 length => length($body) }]);
245 };
246 $f->{http_end} = sub {
247 $c->new_stream({ body_more => 1, headers => [
248 { name => ':status', value => '200', mode => 0 },
249 { name => 'content-type', value => 'application/grpc',
250 mode => 1, huff => 1 },
251 ]}, $sid);
252 $c->h2_body('Hello world', { body_more => 1 });
253 $c->new_stream({ headers => [
254 { name => 'grpc-status', value => '0',
255 mode => 2, huff => 1 },
256 { name => 'grpc-message', value => '',
257 mode => 2, huff => 1 },
258 ]}, $sid);
259
260 return $s->read(all => [{ fin => 1 }]);
261 };
262 return $f;
263 }
264
265 sub log2i { Test::Nginx::log_core('|| <<', @_); }
266 sub log2o { Test::Nginx::log_core('|| >>', @_); }
267 sub log2c { Test::Nginx::log_core('||', @_); }
268
269 ###############################################################################