Mercurial > hg > nginx-tests
comparison stream_error_log.t @ 558:27740a2dd781
Tests: stream error_log tests.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Thu, 23 Apr 2015 14:01:20 +0300 |
parents | |
children | abf5f3197967 |
comparison
equal
deleted
inserted
replaced
557:05cbe9e2def8 | 558:27740a2dd781 |
---|---|
1 #!/usr/bin/perl | |
2 | |
3 # (C) Sergey Kandaurov | |
4 # (C) Nginx, Inc. | |
5 | |
6 # Stream tests for error_log. | |
7 | |
8 ############################################################################### | |
9 | |
10 use warnings; | |
11 use strict; | |
12 | |
13 use Test::More; | |
14 | |
15 use IO::Select; | |
16 | |
17 BEGIN { use FindBin; chdir($FindBin::Bin); } | |
18 | |
19 use lib 'lib'; | |
20 use Test::Nginx; | |
21 | |
22 ############################################################################### | |
23 | |
24 select STDERR; $| = 1; | |
25 select STDOUT; $| = 1; | |
26 | |
27 my $t = Test::Nginx->new()->has(qw/stream/)->plan(33); | |
28 | |
29 $t->write_file_expand('nginx.conf', <<'EOF'); | |
30 | |
31 %%TEST_GLOBALS%% | |
32 | |
33 error_log %%TESTDIR%%/e_glob.log info; | |
34 error_log %%TESTDIR%%/e_glob2.log info; | |
35 error_log syslog:server=127.0.0.1:8083 info; | |
36 | |
37 daemon off; | |
38 | |
39 events { | |
40 } | |
41 | |
42 stream { | |
43 upstream u { | |
44 server 127.0.0.1:8083 down; | |
45 } | |
46 | |
47 server { | |
48 listen 127.0.0.1:8080; | |
49 proxy_pass u; | |
50 | |
51 error_log %%TESTDIR%%/e_debug.log debug; | |
52 error_log %%TESTDIR%%/e_info.log info; | |
53 error_log %%TESTDIR%%/e_emerg.log emerg; | |
54 error_log stderr info; | |
55 } | |
56 | |
57 server { | |
58 listen 127.0.0.1:8082; | |
59 proxy_pass 127.0.0.1:8081; | |
60 | |
61 error_log %%TESTDIR%%/e_stream.log info; | |
62 error_log syslog:server=127.0.0.1:8084 info; | |
63 } | |
64 } | |
65 | |
66 EOF | |
67 | |
68 open OLDERR, ">&", \*STDERR; | |
69 open STDERR, '>', $t->testdir() . '/stderr' or die "Can't reopen STDERR: $!"; | |
70 open my $stderr, '<', $t->testdir() . '/stderr' | |
71 or die "Can't open stderr file: $!"; | |
72 | |
73 $t->run_daemon(\&stream_daemon); | |
74 $t->run_daemon(\&syslog_daemon, 8083, $t, 's_glob.log'); | |
75 $t->run_daemon(\&syslog_daemon, 8084, $t, 's_stream.log'); | |
76 | |
77 $t->waitforsocket('127.0.0.1:8081'); | |
78 $t->waitforfile($t->testdir . '/s_glob.log'); | |
79 $t->waitforfile($t->testdir . '/s_stream.log'); | |
80 | |
81 $t->run(); | |
82 | |
83 open STDERR, ">&", \*OLDERR; | |
84 | |
85 ############################################################################### | |
86 | |
87 stream_get('data'); | |
88 | |
89 # error_log levels | |
90 | |
91 SKIP: { | |
92 skip "no --with-debug", 1 unless $t->has_module('--with-debug'); | |
93 | |
94 isnt(lines($t, 'e_debug.log', '[debug]'), 0, 'file debug in debug'); | |
95 | |
96 } | |
97 | |
98 isnt(lines($t, 'e_info.log', '[info]'), 0, 'file info in info'); | |
99 is(lines($t, 'e_info.log', '[debug]'), 0, 'file debug in info'); | |
100 isnt(lines($t, 'stderr', '[info]'), 0, 'stderr info in info'); | |
101 is(lines($t, 'stderr', '[debug]'), 0, 'stderr debug in info'); | |
102 | |
103 # multiple error_log | |
104 | |
105 like($t->read_file('e_glob.log'), qr!nginx/[.0-9]+!, 'error global'); | |
106 like($t->read_file('e_glob2.log'), qr!nginx/[.0-9]+!, 'error global 2'); | |
107 is_deeply(levels($t, 'e_glob.log'), levels($t, 'e_glob2.log'), | |
108 'multiple error global'); | |
109 | |
110 # syslog | |
111 | |
112 stream_get('data2', '127.0.0.1:8082'); | |
113 | |
114 parse_syslog_message('syslog', $t->read_file('s_stream.log')); | |
115 | |
116 is_deeply(levels($t, 's_glob.log'), levels($t, 'e_glob.log'), | |
117 'global syslog messages'); | |
118 is_deeply(levels($t, 's_stream.log'), levels($t, 'e_stream.log'), | |
119 'stream syslog messages'); | |
120 | |
121 # error_log context | |
122 | |
123 SKIP: { | |
124 skip "relies on error log contents", 5 unless $ENV{TEST_NGINX_UNSAFE}; | |
125 | |
126 my $msg = 'no live upstreams while connecting to upstream, ' | |
127 . 'client: 127.0.0.1, server: 127.0.0.1:8080, upstream: "u"'; | |
128 | |
129 unlike($t->read_file('e_glob.log'), qr/$msg/ms, 'stream error in global'); | |
130 like($t->read_file('e_info.log'), qr/$msg/ms, 'stream error in info'); | |
131 like($t->read_file('stderr'), qr/$msg/ms, 'stream error in info stderr'); | |
132 unlike($t->read_file('e_emerg.log'), qr/$msg/ms, 'stream error in emerg'); | |
133 | |
134 $msg = "bytes from/to client:5/4, bytes from/to upstream:4/5"; | |
135 | |
136 like($t->read_file('e_stream.log'), qr/$msg/ms, 'stream byte counters'); | |
137 | |
138 } | |
139 | |
140 ############################################################################### | |
141 | |
142 sub lines { | |
143 my ($t, $file, $pattern) = @_; | |
144 | |
145 if ($file eq 'stderr') { | |
146 return map { $_ =~ /\Q$pattern\E/ } (<$stderr>); | |
147 } | |
148 | |
149 my $path = $t->testdir() . '/' . $file; | |
150 open my $fh, '<', $path or return "$!"; | |
151 my $value = map { $_ =~ /\Q$pattern\E/ } (<$fh>); | |
152 close $fh; | |
153 return $value; | |
154 } | |
155 | |
156 sub levels { | |
157 my ($t, $file) = @_; | |
158 my %levels_hash; | |
159 | |
160 map { $levels_hash{$_}++; } ($t->read_file($file) =~ /(\[\w+\])/g); | |
161 | |
162 return \%levels_hash; | |
163 } | |
164 | |
165 sub stream_get { | |
166 my ($data, $peer) = @_; | |
167 | |
168 $peer = '127.0.0.1:8080' unless defined $peer; | |
169 my $s = stream_connect($peer); | |
170 stream_write($s, $data); | |
171 my $r = stream_read($s); | |
172 | |
173 $s->close; | |
174 return $r; | |
175 } | |
176 | |
177 sub stream_connect { | |
178 my $peer = shift; | |
179 my $s = IO::Socket::INET->new( | |
180 Proto => 'tcp', | |
181 PeerAddr => $peer || '127.0.0.1:8080' | |
182 ) | |
183 or die "Can't connect to nginx: $!\n"; | |
184 | |
185 return $s; | |
186 } | |
187 | |
188 sub stream_write { | |
189 my ($s, $message) = @_; | |
190 | |
191 local $SIG{PIPE} = 'IGNORE'; | |
192 | |
193 $s->blocking(0); | |
194 while (IO::Select->new($s)->can_write(1.5)) { | |
195 my $n = $s->syswrite($message); | |
196 last unless $n; | |
197 $message = substr($message, $n); | |
198 last unless length $message; | |
199 } | |
200 | |
201 if (length $message) { | |
202 $s->close(); | |
203 } | |
204 } | |
205 | |
206 sub stream_read { | |
207 my ($s) = @_; | |
208 my ($buf); | |
209 | |
210 $s->blocking(0); | |
211 if (IO::Select->new($s)->can_read(5)) { | |
212 $s->sysread($buf, 1024); | |
213 }; | |
214 | |
215 log_in($buf); | |
216 return $buf; | |
217 } | |
218 | |
219 sub parse_syslog_message { | |
220 my ($desc, $line) = @_; | |
221 | |
222 my @months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', | |
223 'Sep', 'Oct', 'Nov', 'Dec'); | |
224 | |
225 my ($pri, $mon, $mday, $hour, $minute, $sec, $host, $tag, $msg) = | |
226 $line =~ /^<(\d{1,3})> # PRI | |
227 ([A-Z][a-z]{2})\s # mon | |
228 ([ \d]\d)\s(\d{2}):(\d{2}):(\d{2})\s # date | |
229 ([\S]*)\s # host | |
230 (\w{1,32}):\s # tag | |
231 (.*)/x; # MSG | |
232 | |
233 my $sev = $pri & 0x07; | |
234 my $fac = ($pri & 0x03f8) >> 3; | |
235 | |
236 ok(defined($pri), "$desc has PRI"); | |
237 ok($sev >= 0 && $sev <= 7, "$desc valid severity"); | |
238 ok($fac >= 0 && $fac < 24, "$desc valid facility"); | |
239 | |
240 ok(defined($mon), "$desc has month"); | |
241 ok((grep $mon, @months), "$desc valid month"); | |
242 | |
243 ok(defined($mday), "$desc has day"); | |
244 ok($mday <= 31, "$desc valid day"); | |
245 | |
246 ok(defined($hour), "$desc has hour"); | |
247 ok($hour < 24, "$desc valid hour"); | |
248 | |
249 ok(defined($minute), "$desc has minutes"); | |
250 ok($minute < 60, "$desc valid minutes"); | |
251 | |
252 ok(defined($sec), "$desc has seconds"); | |
253 ok($sec < 60, "$desc valid seconds"); | |
254 | |
255 ok(defined($host), "$desc has host"); | |
256 chomp(my $hostname = lc `hostname`); | |
257 is($host , $hostname, "$desc valid host"); | |
258 | |
259 ok(defined($tag), "$desc has tag"); | |
260 like($tag, qr'\w+', "$desc valid tag"); | |
261 | |
262 ok(length($msg) > 0, "$desc valid CONTENT"); | |
263 } | |
264 | |
265 ############################################################################### | |
266 | |
267 sub syslog_daemon { | |
268 my ($port, $t, $file) = @_; | |
269 | |
270 my $s = IO::Socket::INET->new( | |
271 Proto => 'udp', | |
272 LocalAddr => "127.0.0.1:$port" | |
273 ); | |
274 | |
275 open my $fh, '>', $t->testdir() . '/' . $file; | |
276 select $fh; $| = 1; | |
277 | |
278 while (1) { | |
279 my $buffer; | |
280 $s->recv($buffer, 4096); | |
281 print $fh $buffer . "\n"; | |
282 } | |
283 } | |
284 | |
285 sub stream_daemon { | |
286 my $server = IO::Socket::INET->new( | |
287 Proto => 'tcp', | |
288 LocalHost => '127.0.0.1', | |
289 LocalPort => 8081, | |
290 Listen => 5, | |
291 Reuse => 1 | |
292 ) | |
293 or die "Can't create listening socket: $!\n"; | |
294 | |
295 local $SIG{PIPE} = 'IGNORE'; | |
296 | |
297 while (my $client = $server->accept()) { | |
298 $client->autoflush(1); | |
299 | |
300 log2c("(new connection $client)"); | |
301 | |
302 $client->sysread(my $buffer, 65536) or next; | |
303 | |
304 log2i("$client $buffer"); | |
305 | |
306 $buffer = $client->sockport(); | |
307 | |
308 log2o("$client $buffer"); | |
309 | |
310 $client->syswrite($buffer); | |
311 | |
312 close $client; | |
313 } | |
314 } | |
315 | |
316 sub log2i { Test::Nginx::log_core('|| <<', @_); } | |
317 sub log2o { Test::Nginx::log_core('|| >>', @_); } | |
318 sub log2c { Test::Nginx::log_core('||', @_); } | |
319 | |
320 ############################################################################### |