|
|
|
@ -6,6 +6,7 @@ use IO::Socket;
|
|
|
|
|
use Test::More;
|
|
|
|
|
use Socket;
|
|
|
|
|
use Cwd 'abs_path';
|
|
|
|
|
use POSIX ":sys_wait_h";
|
|
|
|
|
|
|
|
|
|
sub mtime {
|
|
|
|
|
my $file = shift;
|
|
|
|
@ -30,12 +31,17 @@ sub new {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mtime($self->{BASEDIR}.'/src/lighttpd') > mtime($self->{BASEDIR}.'/build/lighttpd')) {
|
|
|
|
|
$self->{LIGHTTPD_PATH} = $self->{BASEDIR}.'/src/lighttpd';
|
|
|
|
|
$self->{MODULES_PATH} = $self->{BASEDIR}.'/src/.libs';
|
|
|
|
|
$self->{BINDIR} = $self->{BASEDIR}.'/src';
|
|
|
|
|
if (mtime($self->{BASEDIR}.'/src/.libs')) {
|
|
|
|
|
$self->{MODULES_PATH} = $self->{BASEDIR}.'/src/.libs';
|
|
|
|
|
} else {
|
|
|
|
|
$self->{MODULES_PATH} = $self->{BASEDIR}.'/src';
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$self->{LIGHTTPD_PATH} = $self->{BASEDIR}.'/build/lighttpd';
|
|
|
|
|
$self->{BINDIR} = $self->{BASEDIR}.'/build';
|
|
|
|
|
$self->{MODULES_PATH} = $self->{BASEDIR}.'/build';
|
|
|
|
|
}
|
|
|
|
|
$self->{LIGHTTPD_PATH} = $self->{BINDIR}.'/lighttpd';
|
|
|
|
|
$self->{LIGHTTPD_PIDFILE} = $self->{TESTDIR}.'/tmp/lighttpd/lighttpd.pid';
|
|
|
|
|
$self->{PIDOF_PIDFILE} = $self->{TESTDIR}.'/tmp/lighttpd/pidof.pid';
|
|
|
|
|
$self->{PORT} = 2048;
|
|
|
|
@ -66,58 +72,84 @@ sub listening_on {
|
|
|
|
|
sub stop_proc {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
|
|
open F, $self->{LIGHTTPD_PIDFILE} or return -1;
|
|
|
|
|
my $pid = <F>;
|
|
|
|
|
close F;
|
|
|
|
|
# open F, $self->{LIGHTTPD_PIDFILE} or return -1;
|
|
|
|
|
# my $pid = <F>;
|
|
|
|
|
# close F;
|
|
|
|
|
|
|
|
|
|
# if (defined $pid) {
|
|
|
|
|
# kill('TERM',$pid) or return -1;
|
|
|
|
|
# select(undef, undef, undef, 0.5);
|
|
|
|
|
# }
|
|
|
|
|
|
|
|
|
|
my $pid = $self->{LIGHTTPD_PID};
|
|
|
|
|
if (defined $pid) {
|
|
|
|
|
kill('TERM',$pid) or return -1;
|
|
|
|
|
select(undef, undef, undef, 0.1);
|
|
|
|
|
kill('TERM', $pid) or return -1;
|
|
|
|
|
return -1 if ($pid != waitpid($pid, 0));
|
|
|
|
|
} else {
|
|
|
|
|
diag("Nothing to kill\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub wait_for_port_with_proc {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
my $port = shift;
|
|
|
|
|
my $child = shift;
|
|
|
|
|
|
|
|
|
|
while (0 == $self->listening_on($port)) {
|
|
|
|
|
select(undef, undef, undef, 0.1);
|
|
|
|
|
|
|
|
|
|
# the process is gone, we failed
|
|
|
|
|
if (0 != waitpid($child, WNOHANG)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub start_proc {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
# kill old proc if necessary
|
|
|
|
|
$self->stop_proc;
|
|
|
|
|
#$self->stop_proc;
|
|
|
|
|
|
|
|
|
|
# pre-process configfile if necessary
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
$ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
|
|
|
|
|
$ENV{'PORT'} = $self->{PORT};
|
|
|
|
|
|
|
|
|
|
unlink($self->{LIGHTTPD_PIDFILE});
|
|
|
|
|
my $cmdline = $self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH};
|
|
|
|
|
if (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'strace') {
|
|
|
|
|
system("strace -tt -s 512 -o strace ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
|
|
|
|
|
$cmdline = "strace -tt -s 512 -o strace ".$cmdline;
|
|
|
|
|
} elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'truss') {
|
|
|
|
|
system("/usr/dtrctkit/bin/dtruss -d -e ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." 2> strace &");
|
|
|
|
|
$cmdline = "truss -a -l -w all -v all -o strace ".$cmdline;
|
|
|
|
|
} elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'gdb') {
|
|
|
|
|
$cmdline = "gdb --batch --ex 'run' --ex 'bt' --args ".$cmdline." > gdb.out";
|
|
|
|
|
} elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'valgrind') {
|
|
|
|
|
system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --log-file=valgrind ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
|
|
|
|
|
} else {
|
|
|
|
|
system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH});
|
|
|
|
|
$cmdline = "valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --log-file=valgrind ".$cmdline;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
select(undef, undef, undef, 0.1);
|
|
|
|
|
if (not -e $self->{LIGHTTPD_PIDFILE} or 0 == kill 0, `cat $self->{LIGHTTPD_PIDFILE}`) {
|
|
|
|
|
select(undef, undef, undef, 2);
|
|
|
|
|
# diag("starting lighttpd at :".$self->{PORT}.", cmdline: ".$cmdline );
|
|
|
|
|
my $child = fork();
|
|
|
|
|
if (not defined $child) {
|
|
|
|
|
diag("Fork failed");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if ($child == 0) {
|
|
|
|
|
exec $cmdline or die($?);
|
|
|
|
|
}
|
|
|
|
|
# system($cmdline) == 0 or die($?);
|
|
|
|
|
|
|
|
|
|
unlink($self->{TESTDIR}."/tmp/cfg.file");
|
|
|
|
|
|
|
|
|
|
# no pidfile, we failed
|
|
|
|
|
if (not -e $self->{LIGHTTPD_PIDFILE}) {
|
|
|
|
|
diag(sprintf('Could not find pidfile: %s', $self->{LIGHTTPD_PIDFILE}));
|
|
|
|
|
if (0 != $self->wait_for_port_with_proc($self->{PORT}, $child)) {
|
|
|
|
|
diag(sprintf('The process %i is not up', $child));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# the process is gone, we failed
|
|
|
|
|
if (0 == kill 0, `cat $self->{LIGHTTPD_PIDFILE}`) {
|
|
|
|
|
diag(sprintf('the process referenced by %s is not up', $self->{LIGHTTPD_PIDFILE}));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
$self->{LIGHTTPD_PID} = $child;
|
|
|
|
|
|
|
|
|
|
0;
|
|
|
|
|
}
|
|
|
|
@ -131,6 +163,7 @@ sub handle_http {
|
|
|
|
|
|
|
|
|
|
my @request = $t->{REQUEST};
|
|
|
|
|
my @response = $t->{RESPONSE};
|
|
|
|
|
my $is_debug = $ENV{"TRACE_HTTP"};
|
|
|
|
|
|
|
|
|
|
my $remote =
|
|
|
|
|
IO::Socket::INET->new(Proto => "tcp",
|
|
|
|
@ -144,20 +177,27 @@ sub handle_http {
|
|
|
|
|
|
|
|
|
|
$remote->autoflush(1);
|
|
|
|
|
|
|
|
|
|
diag("sending request header to ".$host.":".$self->{PORT}) if $is_debug;
|
|
|
|
|
foreach(@request) {
|
|
|
|
|
# pipeline requests
|
|
|
|
|
s/\r//g;
|
|
|
|
|
s/\n/$EOL/g;
|
|
|
|
|
|
|
|
|
|
print $remote $_.$BLANK;
|
|
|
|
|
print $remote $_.$BLANK;
|
|
|
|
|
diag("<< ".$_) if $is_debug;
|
|
|
|
|
}
|
|
|
|
|
shutdown($remote, 1); # I've stopped writing data
|
|
|
|
|
diag("... done") if $is_debug;
|
|
|
|
|
|
|
|
|
|
my $lines = "";
|
|
|
|
|
|
|
|
|
|
diag("receiving response") if $is_debug;
|
|
|
|
|
# read everything
|
|
|
|
|
while(<$remote>) {
|
|
|
|
|
$lines .= $_;
|
|
|
|
|
diag(">> ".$_) if $is_debug;
|
|
|
|
|
}
|
|
|
|
|
diag("... done") if $is_debug;
|
|
|
|
|
|
|
|
|
|
close $remote;
|
|
|
|
|
|
|
|
|
@ -187,18 +227,23 @@ sub handle_http {
|
|
|
|
|
(my $h = $1) =~ tr/[A-Z]/[a-z]/;
|
|
|
|
|
|
|
|
|
|
if (defined $resp_hdr{$h}) {
|
|
|
|
|
diag(sprintf("header %s is duplicated: %s and %s\n",
|
|
|
|
|
diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
|
|
|
|
|
$h, $resp_hdr{$h}, $2));
|
|
|
|
|
} else {
|
|
|
|
|
$resp_hdr{$h} = $2;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
diag(sprintf("unexpected line '$line'\n"));
|
|
|
|
|
diag(sprintf("unexpected line '%s'\n", $line));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (not defined($resp_line)) {
|
|
|
|
|
diag(sprintf("empty response\n"));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$t->{etag} = $resp_hdr{'etag'};
|
|
|
|
|
$t->{date} = $resp_hdr{'date'};
|
|
|
|
|
|
|
|
|
@ -227,7 +272,7 @@ sub handle_http {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
diag(sprintf("unexpected resp_line '$resp_line'\n"));
|
|
|
|
|
diag(sprintf("unexpected resp_line '%s'\n", $resp_line));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -237,7 +282,9 @@ sub handle_http {
|
|
|
|
|
diag(sprintf("body failed: expected '%s', got '%s'\n", $href->{'HTTP-Content'}, $resp_body));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} elsif (defined $href->{'-HTTP-Content'}) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (defined $href->{'-HTTP-Content'}) {
|
|
|
|
|
if (defined $resp_body && $resp_body ne '') {
|
|
|
|
|
diag(sprintf("body failed: expected empty body, got '%s'\n", $resp_body));
|
|
|
|
|
return -1;
|
|
|
|
@ -245,7 +292,6 @@ sub handle_http {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (keys %{ $href }) {
|
|
|
|
|
## filter special keys
|
|
|
|
|
next if $_ eq 'HTTP-Protocol';
|
|
|
|
|
next if $_ eq 'HTTP-Status';
|
|
|
|
|
next if $_ eq 'HTTP-Content';
|
|
|
|
@ -257,7 +303,6 @@ sub handle_http {
|
|
|
|
|
my $key_inverted = 0;
|
|
|
|
|
|
|
|
|
|
if (substr($k, 0, 1) eq '+') {
|
|
|
|
|
## the key has to exist, but the value is ignored
|
|
|
|
|
$k = substr($k, 1);
|
|
|
|
|
$verify_value = 0;
|
|
|
|
|
} elsif (substr($k, 0, 1) eq '-') {
|
|
|
|
@ -265,11 +310,11 @@ sub handle_http {
|
|
|
|
|
$k = substr($k, 1);
|
|
|
|
|
$key_inverted = 1;
|
|
|
|
|
$verify_value = 0; ## skip the value check
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($key_inverted) {
|
|
|
|
|
if (defined $resp_hdr{$k}) {
|
|
|
|
|
diag(sprintf("required header '%s' is missing\n", $k));
|
|
|
|
|
diag(sprintf("header '%s' MUST not be set\n", $k));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -297,12 +342,38 @@ sub handle_http {
|
|
|
|
|
|
|
|
|
|
# we should have sucked up everything
|
|
|
|
|
if (defined $lines) {
|
|
|
|
|
diag(sprintf("unexpected lines '$lines'\n"));
|
|
|
|
|
diag(sprintf("unexpected lines '%s'\n", $lines));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
1;
|
|
|
|
|
|
|
|
|
|
sub spawnfcgi {
|
|
|
|
|
my ($self, $binary, $port) = @_;
|
|
|
|
|
my $child = fork();
|
|
|
|
|
if (not defined $child) {
|
|
|
|
|
diag("Couldn't fork\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if ($child == 0) {
|
|
|
|
|
my $cmd = $self->{BINDIR}.'/spawn-fcgi -n -p '.$port.' -f "'.$binary.'"';
|
|
|
|
|
exec $cmd or die($?);
|
|
|
|
|
} else {
|
|
|
|
|
if (0 != $self->wait_for_port_with_proc($port, $child)) {
|
|
|
|
|
diag(sprintf('The process %i is not up (port %i, %s)', $child, $port, $binary));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return $child;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub endspawnfcgi {
|
|
|
|
|
my ($self, $pid) = @_;
|
|
|
|
|
return -1 if (-1 == $pid);
|
|
|
|
|
kill(2, $pid);
|
|
|
|
|
waitpid($pid, 0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
1;
|
|
|
|
|