comparison stream_resolver.t @ 988:64505109060c

Tests: simple stream proxy tests with resolver.
author Sergey Kandaurov <pluknet@nginx.com>
date Thu, 21 Jul 2016 14:00:58 +0300
parents
children 1beb641e21c9
comparison
equal deleted inserted replaced
987:d6a2c7bcdc4c 988:64505109060c
1 #!/usr/bin/perl
2
3 # (C) Sergey Kandaurov
4 # (C) Nginx, Inc.
5
6 # Tests for stream upstream name resolved, proxy_next_upstream_tries.
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::Stream qw/ stream /;
20
21 ###############################################################################
22
23 select STDERR; $| = 1;
24 select STDOUT; $| = 1;
25
26 my $t = Test::Nginx->new()->has(qw/stream stream_map stream_return/)
27 ->write_file_expand('nginx.conf', <<'EOF');
28
29 %%TEST_GLOBALS%%
30
31 daemon off;
32
33 events {
34 }
35
36 stream {
37 map $server_port $upstream {
38 %%PORT_8081%% a.example.com:%%PORT_8090%%;
39 %%PORT_8082%% a.example.com;
40 %%PORT_8083%% nx.example.com:%%PORT_8082%%;
41 }
42
43 map $server_port $many {
44 default $server_port.many.example.com;
45 }
46
47 resolver 127.0.0.1:%%PORT_8080_UDP%%;
48
49 server {
50 listen 127.0.0.1:8081;
51 listen 127.0.0.1:8082;
52 listen 127.0.0.1:8083;
53 proxy_pass $upstream;
54 }
55
56 server {
57 listen 127.0.0.1:8084;
58 proxy_pass $many:%%PORT_8090%%;
59
60 proxy_next_upstream_tries 3;
61 proxy_connect_timeout 1s;
62 }
63
64 server {
65 listen 127.0.0.1:8085;
66 proxy_pass $many:%%PORT_8090%%;
67
68 proxy_next_upstream_tries 2;
69 proxy_connect_timeout 1s;
70 }
71
72 server {
73 listen 127.0.0.1:8086;
74 proxy_pass $many:%%PORT_8090%%;
75
76 proxy_next_upstream_tries 0;
77 proxy_connect_timeout 1s;
78 }
79
80 server {
81 listen 127.0.0.1:8090;
82 return SEE-THIS;
83 }
84 }
85
86 EOF
87
88 $t->run_daemon(\&dns_daemon, port(8080), $t);
89 $t->try_run('no stream resolver')->plan(8);
90
91 $t->waitforfile($t->testdir . '/' . port(8080));
92
93 ###############################################################################
94
95 ok(stream('127.0.0.1:' . port(8081))->io('.'), 'resolver');
96 ok(!stream('127.0.0.1:' . port(8082))->io('.'), 'upstream no port');
97 ok(!stream('127.0.0.1:' . port(8083))->io('.'), 'name not found');
98
99 ok(stream('127.0.0.1:' . port(8084))->io('.'), 'resolved tries');
100 ok(!stream('127.0.0.1:' . port(8085))->io('.'), 'resolved tries limited');
101 ok(stream('127.0.0.1:' . port(8086))->io('.'), 'resolved tries zero');
102
103 $t->stop();
104
105 SKIP: {
106 skip "relies on error log contents", 2 unless $ENV{TEST_NGINX_UNSAFE};
107
108 my $log = `grep -F '[error]' ${\($t->testdir())}/error.log`;
109 like($log, qr/no port in upstream "a.example.com"/, 'log - no port');
110 like($log, qr/nx.example.com could not be resolved/, 'log - not found');
111
112 }
113
114 ###############################################################################
115
116 sub reply_handler {
117 my ($recv_data, $port) = @_;
118
119 my (@name, @rdata);
120
121 use constant NOERROR => 0;
122 use constant A => 1;
123 use constant IN => 1;
124
125 # default values
126
127 my ($hdr, $rcode, $ttl) = (0x8180, NOERROR, 3600);
128
129 # decode name
130
131 my ($len, $offset) = (undef, 12);
132 while (1) {
133 $len = unpack("\@$offset C", $recv_data);
134 last if $len == 0;
135 $offset++;
136 push @name, unpack("\@$offset A$len", $recv_data);
137 $offset += $len;
138 }
139
140 $offset -= 1;
141 my ($id, $type, $class) = unpack("n x$offset n2", $recv_data);
142
143 my $name = join('.', @name);
144 if ($name eq 'a.example.com' && $type == A) {
145 push @rdata, rd_addr($ttl, '127.0.0.1');
146
147 } elsif ($name =~ qr/many.example.com/ && $type == A) {
148 push @rdata, rd_addr($ttl, '127.0.0.2');
149 push @rdata, rd_addr($ttl, '127.0.0.2');
150 push @rdata, rd_addr($ttl, '127.0.0.1');
151 }
152
153 $len = @name;
154 pack("n6 (C/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata,
155 0, 0, @name, $type, $class) . join('', @rdata);
156 }
157
158 sub rd_addr {
159 my ($ttl, $addr) = @_;
160
161 my $code = 'split(/\./, $addr)';
162
163 return pack 'n3N', 0xc00c, A, IN, $ttl if $addr eq '';
164
165 pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code);
166 }
167
168 sub dns_daemon {
169 my ($port, $t) = @_;
170
171 my ($data, $recv_data);
172 my $socket = IO::Socket::INET->new(
173 LocalAddr => '127.0.0.1',
174 LocalPort => $port,
175 Proto => 'udp',
176 )
177 or die "Can't create listening socket: $!\n";
178
179 local $SIG{PIPE} = 'IGNORE';
180
181 # signal we are ready
182
183 open my $fh, '>', $t->testdir() . '/' . $port;
184 close $fh;
185
186 while (1) {
187 $socket->recv($recv_data, 65536);
188 $data = reply_handler($recv_data, $port);
189 $socket->send($data);
190 }
191 }
192
193 ###############################################################################