#!/usr/bin/perl
use strict;
use warnings;
no warnings 'uninitialized';
use bytes;
use Test::More;
use Nginx::Test;
use constant { CRLF => "\x0d\x0a" };
my $prefix = make_path 'objs/t20'
or diag ("make_path failed: $!"),
plan ('skip_all', "Cannot create test directory: $!");
my $port1 = get_unused_port or plan ('skip_all', 'get_unused_port failed');
my $peer1 = "127.0.0.1:$port1";
my $nginx = find_nginx_perl
or diag ("find_nginx_perl failed: $!"),
plan ('skip_all', "Cannot find nginx-perl");
{
my $peer = $peer1; # for easier copy-paste
my $pkg = "package NginxTst;\n".
"# line ". (__LINE__+1) ." ". __FILE__ ."\n". <<' ENDPKG';
use Nginx;
sub ok ($$);
sub diag;
my @tests = (
14, # plan
sub {
foreach my $i (
[ NGX_ESCAPE_URI, 'a', 'a' ],
[ NGX_ESCAPE_URI, 'aaaa', 'aaaa' ],
[ NGX_ESCAPE_URI, '', '' ],
[ NGX_ESCAPE_URI, ' ', '%20' ],
[ NGX_ESCAPE_URI, 'aa%20aa', 'aa%2520aa' ],
[ NGX_ESCAPE_URI, 'foo&bar', 'foo&bar' ],
[ NGX_ESCAPE_ARGS, 'foo&bar', 'foo%26bar' ],
[ NGX_ESCAPE_URI, ' ' x 10, '%20' x 10 ],
[ NGX_ESCAPE_URI, ' ' x 100, '%20' x 100 ],
[ NGX_ESCAPE_URI, ' ' x 1000, '%20' x 1000 ],
[ NGX_ESCAPE_URI, ' ' x 10000, '%20' x 10000 ],
) {
my $str = ngx_escape_uri $i->[1], $i->[0];
ok $str eq $i->[2],
"ngx_escape_uri: ".substr($i->[2], 0, 20)
or diag "got = '$str', expected = '$i->[2]'";
}
},
sub {
my $str;
$str = ngx_escape_uri 0;
ok $str eq '0', "ngx_escape_uri: zero"
or diag "str = '$str'";
my $un;
$str = ngx_escape_uri $un;
ok !defined $str, "ngx_escape_uri: uninitialized"
or diag "str = '$str'";
$str = ngx_escape_uri undef;
ok !defined $str, "ngx_escape_uri: undef"
or diag "str = '$str'";
},
);
our $OUT;
sub diag { $OUT .= join '', map { "# $_" } split(/^/, "$_[0]\n") }
sub ok ($$) {
my (undef, $f, $l) = caller;
if ($_[0]) {
$OUT .= "1 - $_[1]\n";
return 1;
} else {
$OUT .= "0 - $_[1]\n";
$OUT .= "# Subtest '$_[1]'\n".
"# at $f line $l\n";
return undef;
}
}
sub handler {
use bytes;
my ($r) = @_;
$r->main_count_inc;
my $buf = '';
if ($r->uri eq '/') {
$buf = (@tests - 1)." ".$tests[0];
} elsif ($r->uri =~ m!^/(\d+)$!) {
my $sub = $tests[$1];
$OUT = '';
&$sub();
$buf = $OUT;
} else {
$r->finalize_request(404);
return NGX_DONE;
}
$r->header_out("Content-Length", length($buf));
$r->send_http_header("text/plain");
$r->print($buf)
unless $r->header_only;
$r->send_special(NGX_HTTP_LAST);
$r->finalize_request(NGX_OK);
return NGX_DONE;
}
1;
ENDPKG
prepare_nginx_dir_die $prefix, <<" ENDCONF", $pkg;
worker_processes 1;
daemon off;
master_process off;
error_log logs/error.log debug;
events {
worker_connections 128;
}
http {
default_type text/plain;
perl_inc lib;
perl_require NginxTst.pm;
server {
listen $peer;
location / { perl_handler NginxTst::handler; }
}
}
ENDCONF
my $child = fork_nginx_die $nginx, $prefix;
wait_for_peer $peer, 5
or diag ("wait_for_peer '$peer' failed"),
diag (cat_logs "$prefix/logs");
my ($sock, $remote_buf, $remote);
my $request = "GET / HTTP/1.0" .CRLF.
"Host: $peer" .CRLF.
"" .CRLF;
REQ: {
$sock = connect_peer $peer, 5
or diag ("connect_peer '$peer' failed"),
diag (cat_logs "$prefix/logs"),
last REQ;
send_data $sock, $request, 5
or diag ("send_data to '$peer' failed"),
diag (cat_logs "$prefix/logs"),
last REQ;
read_http_response $sock, $remote_buf, $remote, 5
or diag ("read_http_response failed: $@"),
diag (cat_logs "$prefix/logs"),
last REQ;
}
my ($requests, $tests) = split ' ', $remote_buf;
if ($requests =~ /^\d+$/ && $tests =~ /^\d+$/) {
plan 'tests', $tests;
my $failed = 0;
LOOP:
for my $i (1 .. $requests) {
my ($sock, $test);
my $request = "GET /$i HTTP/1.0" .CRLF.
"Host: $peer" .CRLF.
"" .CRLF;
$test = "$i";
$sock = connect_peer $peer, 5
or fail ($test), diag ("connect_peer '$peer' failed"),
diag (cat_logs "$prefix/logs"),
last LOOP;
send_data $sock, $request, 5
or fail ($test), diag ("send_data to '$peer' failed"),
diag ("Request: \n$request\n"),
diag (cat_logs "$prefix/logs"),
last LOOP;
my ($remote_buf, $remote);
read_http_response $sock, $remote_buf, $remote, 5
or fail ($test), diag ("read_http_response failed: $@"),
diag ("Request: \n$request\n"),
diag (cat_logs "$prefix/logs"),
last LOOP;
if ($remote->{_status} ne '200') {
fail ($test), diag ("non-200 response status"),
diag (cat_logs "$prefix/logs"),
last LOOP;
}
my @out = split /^/, $remote_buf;
foreach my $line (@out) {
chomp $line;
if ($line !~ /^#/) {
my ($rv, $name) = split ' - ', $line, 2;
if ($rv eq '1') {
pass "$i: $name";
} else {
fail "$i: $name";
$failed++;
}
} else {
$line =~ s/^# //;
diag $line;
}
}
$sock->close;
}
if ($failed) {
diag (cat_logs "$prefix/logs")
}
} else {
plan 'no_plan';
fail "all";
diag "no tests recv'd";
use Data::Dumper;
local $Data::Dumper::Terse = 1;
diag "remote = \n". Dumper ($remote);
diag "remote_buf = '$remote_buf'";
diag cat_logs "$prefix/logs";
}
}