use strict;
use warnings FATAL => 'all';
use Apache::Test;
use Apache::TestRequest;
use Apache::TestUtil;
use File::stat;
my $have_apache_2 = have_apache 2;
my $have_apache_2050 = have_min_apache_version "2.0.50";
my $script_log_length = 8192;
if (have_module 'mod_cgi') {
$script_log_length = 40960;
}
## mod_cgi test
##
## extra.conf.in:
##
## AddHandler cgi-script .sh
## AddHandler cgi-script .pl
## ScriptLog logs/mod_cgi.log
##
## ScriptLogLength 40960
##
##
## ScriptLogLength 8192
##
## ScriptLogBuffer 256
##
## Options +ExecCGI
## [some AcceptPathInfo stuff]
##
##
##
my @post_content = (10, 99, 250, 255, 256, 257, 258, 1024);
my %test = (
'perl.pl' => {
'rc' => 200,
'expect' => 'perl cgi'
},
'bogus-perl.pl' => {
'rc' => 500,
'expect' => 'none'
},
'nph-test.pl' => {
'rc' => 200,
'expect' => 'ok'
},
'sh.sh' => {
'rc' => 200,
'expect' => 'sh cgi'
},
'bogus-sh.sh' => {
'rc' => 500,
'expect' => 'none'
},
'acceptpathinfoon.sh' => {
'rc' => 200,
'expect' => ''
},
'acceptpathinfoon.sh/foo' => {
'rc' => 200,
'expect' => '/foo'
},
'acceptpathinfooff.sh' => {
'rc' => 200,
'expect' => ''
},
'acceptpathinfooff.sh/foo' => {
'rc' => 404,
'expect' => 'none'
},
'acceptpathinfodefault.sh' => {
'rc' => 200,
'expect' => ''
},
'acceptpathinfodefault.sh/foo' => {
'rc' => 200,
'expect' => '/foo'
},
'stderr1.pl' => {
'rc' => 200,
'expect' => 'this is stdout'
},
'stderr2.pl' => {
'rc' => 200,
'expect' => 'this is also stdout'
},
'stderr3.pl' => {
'rc' => 200,
'expect' => 'this is more stdout'
},
'nph-stderr.pl' => {
'rc' => 200,
'expect' => 'this is nph-stdout'
},
);
#XXX: find something that'll on other platforms (/bin/sh aint it)
if (Apache::TestConfig::WINFU()) {
delete @test{qw(sh.sh bogus-sh.sh)};
}
if (Apache::TestConfig::WINFU() || !$have_apache_2) {
delete @test{qw(acceptpathinfoon.sh acceptpathinfoon.sh/foo)};
delete @test{qw(acceptpathinfooff.sh acceptpathinfooff.sh/foo)};
delete @test{qw(acceptpathinfodefault.sh acceptpathinfodefault.sh/foo)};
}
# CGI stderr handling works in 2.0.50 and later only on Unixes.
if (!$have_apache_2050 || Apache::TestConfig::WINFU()) {
delete @test{qw(stderr1.pl stderr2.pl stderr3.pl nph-stderr.pl)};
}
my $tests = ((keys %test) * 2) + (@post_content * 3) + 4;
plan tests => $tests, \&need_cgi;
my ($expected, $actual);
my $path = "/modules/cgi";
my $vars = Apache::Test::vars();
my $t_logs = $vars->{t_logs};
my $cgi_log = "$t_logs/mod_cgi.log";
my ($bogus,$log_size,$stat) = (0,0,0);
unlink $cgi_log if -e $cgi_log;
foreach (sort keys %test) {
$expected = $test{$_}{rc};
$actual = GET_RC "$path/$_";
ok t_cmp($actual,
$expected,
"return code for $_"
);
if ($test{$_}{expect} ne 'none') {
$expected = $test{$_}{expect};
$actual = GET_BODY "$path/$_";
chomp $actual if $actual =~ /\n$/;
ok t_cmp($actual,
$expected,
"body for $_"
);
}
elsif ($_ !~ /^bogus/) {
print "# no body test for this one\n";
ok 1;
}
## verify bogus cgi's get handled correctly
## logging to the cgi log
if ($_ =~ /^bogus/) {
$bogus++;
if ($bogus == 1) {
## make sure cgi log got created, get size.
if (-e $cgi_log) {
print "# cgi log created ok.\n";
ok 1;
$stat = stat($cgi_log);
$log_size = $$stat[7];
} else {
print "# error: cgi log not created!\n";
ok 0;
}
} else {
## make sure log got bigger.
if (-e $cgi_log) {
$stat = stat($cgi_log);
print "# checking that log size ($$stat[7]) is bigger than it used to be ($log_size)\n";
ok ($$stat[7] > $log_size);
$log_size = $$stat[7];
} else {
print "# error: cgi log does not exist!\n";
ok 0;
}
}
}
}
## post lots of content to a bad cgi, so we can verify
## ScriptLogBuffer is working.
my $content = 0;
foreach my $length (@post_content) {
$content++;
$expected = '500';
$actual = POST_RC "$path/bogus-perl.pl", content => "$content"x$length;
print "# posted content (length $length) to bogus-perl.pl\n";
print "# got return code of: $actual, expecting: $expected\n";
## should get rc 500
ok ($actual eq $expected);
if (-e $cgi_log) {
## cgi log should be bigger.
## as long as it's under ScriptLogLength
$stat = stat($cgi_log);
if ($log_size < $script_log_length) {
print "# checking that log size ($$stat[7]) is greater than $log_size\n";
ok ($$stat[7] > $log_size);
} else {
## should not fall in here at this point,
## but just in case...
print "# verifying log did not increase in size...\n";
ok ($$stat[7] eq $log_size);
}
$log_size = $$stat[7];
## there should be less than ScriptLogBuffer (256)
## characters logged from the post content
open (LOG, $cgi_log) or die "died opening cgi log: $!";
my $multiplier = 256;
my $log;
{
local $/;
$log = ;
}
close (LOG);
$multiplier = $length unless $length > $multiplier;
print "# verifying that logged content is $multiplier characters\n";
if ($log =~ /^(?:$content){$multiplier}\n?$/m) {
ok 1;
}
else {
$log =~ s{^}{# }m;
print "# no log line found with $multiplier '$content' characters\n";
print "# log is:\n'$log'\n";
ok 0;
}
} else {
## log does not exist ##
print "# cgi log does not exist, test fails.\n";
ok 0;
}
}
## make sure cgi log does not
## keep logging after it is bigger
## than ScriptLogLength
for (my $i=1 ; $i<=40 ; $i++) {
## get out if log does not exist ##
last unless -e $cgi_log;
## request the 1k bad cgi
## (1k of data logged per request)
GET_RC "$path/bogus1k.pl";
## when log goes over max size stop making requests
$stat = stat($cgi_log);
$log_size = $$stat[7];
last if ($log_size > $script_log_length);
}
## make sure its over (or equal) our ScriptLogLength
print "# verifying log is greater than $script_log_length bytes.\n";
ok ($log_size >= $script_log_length);
## make sure it does not grow now.
GET_RC "$path/bogus1k.pl";
print "# verifying log did not grow after making bogus request.\n";
if (-e $cgi_log) {
$stat = stat($cgi_log);
ok ($log_size eq $$stat[7]);
} else {
print "# log does not exist!\n";
ok 0;
}
GET_RC "$path/bogus-perl.pl";
print "# verifying log did not grow after making another bogus request.\n";
if (-e $cgi_log) {
$stat = stat($cgi_log);
ok ($log_size eq $$stat[7]);
} else {
print "# log does not exist!\n";
ok 0;
}
print "# checking that HEAD $path/perl.pl returns 200.\n";
ok HEAD_RC("$path/perl.pl") == 200;
## clean up
unlink $cgi_log;