summaryrefslogtreecommitdiffstats
path: root/debian/perl-framework/Apache-Test/lib/Apache/Test.pm
diff options
context:
space:
mode:
Diffstat (limited to 'debian/perl-framework/Apache-Test/lib/Apache/Test.pm')
-rw-r--r--debian/perl-framework/Apache-Test/lib/Apache/Test.pm1214
1 files changed, 1214 insertions, 0 deletions
diff --git a/debian/perl-framework/Apache-Test/lib/Apache/Test.pm b/debian/perl-framework/Apache-Test/lib/Apache/Test.pm
new file mode 100644
index 0000000..b3263c6
--- /dev/null
+++ b/debian/perl-framework/Apache-Test/lib/Apache/Test.pm
@@ -0,0 +1,1214 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache::Test;
+
+use strict;
+use warnings FATAL => 'all';
+
+use Exporter ();
+use Config;
+use Apache::TestConfig ();
+use Test qw/ok skip/;
+
+BEGIN {
+ # Apache::Test loads a bunch of mp2 stuff while getting itself
+ # together. because we need to choose one of mp1 or mp2 to load
+ # check first (and we choose mp2) $mod_perl::VERSION == 2.0
+ # just because someone loaded Apache::Test. This Is Bad. so,
+ # let's try to correct for that here by removing mod_perl from
+ # %INC after the above use() statements settle in. nobody
+ # should be relying on us loading up mod_perl.pm anyway...
+
+ delete $INC{'mod_perl.pm'};
+}
+
+use vars qw(@ISA @EXPORT %EXPORT_TAGS $VERSION %SubTests @SkipReasons);
+
+$VERSION = '1.42';
+
+my @need = qw(need_lwp need_http11 need_cgi need_access need_auth
+ need_module need_apache need_min_apache_version need_min_apache_fix
+ need_apache_version need_perl need_min_perl_version
+ need_min_module_version need_threads need_fork need_apache_mpm
+ need_php need_php4 need_ssl need_imagemap need_cache_disk);
+
+my @have = map { (my $need = $_) =~ s/need/have/; $need } @need;
+
+@ISA = qw(Exporter);
+@EXPORT = (qw(sok plan skip_reason under_construction need),
+ @need, @have);
+
+%SubTests = ();
+@SkipReasons = ();
+
+sub cp {
+ my @l;
+ for( my $i=1; (@l=caller $i)[0] eq __PACKAGE__; $i++ ) {};
+ return wantarray ? @l : $l[0];
+}
+
+my $Config;
+my %wtm;
+sub import {
+ my $class=$_[0];
+ my $wtm=0;
+ my @base_exp;
+ my @exp;
+ my %my_exports;
+ undef @my_exports{@EXPORT};
+
+ my ($caller,$f,$l)=cp;
+
+ for( my $i=1; $i<@_; $i++ ) {
+ if( $_[$i] eq '-withtestmore' ) {
+ $wtm=1;
+ }
+ elsif( $_[$i] eq ':DEFAULT' ) {
+ push @exp, $_[$i];
+ push @base_exp, $_[$i];
+ }
+ elsif( $_[$i] eq '!:DEFAULT' ) {
+ push @exp, $_[$i];
+ push @base_exp, $_[$i];
+ }
+ elsif( $_[$i]=~m@^[:/!]@ ) {
+ warn("Ignoring import spec $_[$i] ".
+ "at $f line $l\n")
+ }
+ elsif( exists $my_exports{$_[$i]} ) {
+ push @exp, $_[$i];
+ }
+ else {
+ push @base_exp, $_[$i];
+ }
+ }
+ if (!@exp and @base_exp) {
+ @exp=('!:DEFAULT');
+ }
+ elsif (@exp and !@base_exp) {
+ @base_exp=('!:DEFAULT');
+ }
+
+ $wtm{$caller}=[$wtm,$f,$l] unless exists $wtm{$caller};
+
+ warn("Ignoring -withtestmore due to a previous call ".
+ "($wtm{$caller}->[1]:$wtm{$caller}->[2]) without it ".
+ "at $f line $l\n")
+ if $wtm{$caller}->[0]==0 and $wtm==1;
+
+ $class->export_to_level(1, $class, @exp);
+
+ push @base_exp, '!plan';
+ if( $wtm{$caller}->[0] ) { # -withtestmore
+ eval <<"EVAL"
+package $caller;
+#line $l $f
+use Test::More import=>\\\@base_exp;
+EVAL
+ }
+ else { # -withouttestmore
+ eval <<"EVAL";
+package $caller;
+#line $l $f
+use Test \@base_exp;
+EVAL
+ }
+ die $@ if $@;
+}
+
+sub config {
+ $Config ||= Apache::TestConfig->thaw->httpd_config;
+}
+
+my $Basic_config;
+
+# config bits which doesn't require httpd to be found
+sub basic_config {
+ $Basic_config ||= Apache::TestConfig->thaw();
+}
+
+sub vars {
+ @_ ? @{ config()->{vars} }{ @_ } : config()->{vars};
+}
+
+sub sok (&;$) {
+ my $sub = shift;
+ my $nok = shift || 1; #allow sok to have 'ok' within
+
+ my ($caller,$f,$l)=cp;
+
+ if (exists $wtm{$caller} and $wtm{$caller}->[0]==1) { # -withtestmore
+ require Test::Builder;
+ my $tb=Test::Builder->new;
+
+ if (%SubTests and not $SubTests{ 1+$tb->current_test }) {
+ $tb->skip("skipping this subtest") for (1..$nok);
+ return;
+ }
+
+ # trick ok() into reporting the caller filename/line when a
+ # sub-test fails in sok()
+ return eval <<EOE;
+#line $l $f
+ Test::More::ok(\$sub->());
+EOE
+ }
+ else {
+ if (%SubTests and not $SubTests{ $Test::ntest }) {
+ skip("skipping this subtest", 0) for (1..$nok);
+ return;
+ }
+
+ # trick ok() into reporting the caller filename/line when a
+ # sub-test fails in sok()
+ return eval <<EOE;
+#line $l $f
+ Test::ok(\$sub->());
+EOE
+ }
+}
+
+#so Perl's Test.pm can be run inside mod_perl
+sub test_pm_refresh {
+ my ($caller,$f,$l)=cp;
+
+ if (exists $wtm{$caller} and $wtm{$caller}->[0]==1) { # -withtestmore
+ require Test::Builder;
+ my $builder = Test::Builder->new;
+
+ $builder->reset;
+
+ $builder->output(\*STDOUT);
+ $builder->todo_output(\*STDOUT);
+
+ # this is STDOUT because Test::More seems to put
+ # most of the stuff we want on STDERR, so it ends
+ # up in the error_log instead of where the user can
+ # see it. consider leaving it alone based on
+ # later user reports.
+ $builder->failure_output(\*STDOUT);
+ }
+ else { # -withouttestmore
+ unless (exists $wtm{$caller}) {
+ warn "You forgot to 'use Apache::Test' in package $caller\n";
+ $wtm{$caller}=[0,$f,$l];
+ }
+ if (defined &Test::_reset_globals) {
+ Test::_reset_globals();
+ # Test.pm uses $TESTOUT=*STDOUT{IO}. We cannot do that
+ # due to the way SetupEnv works.
+ $Test::TESTOUT = \*STDOUT;
+ }
+ else {
+ $Test::TESTOUT = \*STDOUT;
+ $Test::planned = 0;
+ $Test::ntest = 1;
+ %Test::todo = ();
+ }
+ }
+}
+
+sub init_test_pm {
+ my $r = shift;
+
+ # needed to load Apache2::RequestRec::TIEHANDLE
+ eval {require Apache2::RequestIO};
+ if (defined &Apache2::RequestRec::TIEHANDLE) {
+ untie *STDOUT;
+ tie *STDOUT, $r;
+ require Apache2::RequestRec; # $r->pool
+ require APR::Pool;
+ $r->pool->cleanup_register(sub { untie *STDOUT });
+ }
+ else {
+ $r->send_http_header; #1.xx
+ }
+
+ $r->content_type('text/plain');
+}
+
+sub plan {
+ init_test_pm(shift) if ref $_[0];
+ test_pm_refresh();
+
+ # extending Test::plan's functionality, by using the optional
+ # single value in @_ coming after a ballanced %hash which
+ # Test::plan expects
+ if (@_ % 2) {
+ my $condition = pop @_;
+ my $ref = ref $condition;
+ my $meets_condition = 0;
+ if ($ref) {
+ if ($ref eq 'CODE') {
+ #plan tests $n, \&has_lwp
+ $meets_condition = $condition->();
+ }
+ elsif ($ref eq 'ARRAY') {
+ #plan tests $n, [qw(php4 rewrite)];
+ $meets_condition = need_module($condition);
+ }
+ else {
+ die "don't know how to handle a condition of type $ref";
+ }
+ }
+ else {
+ # we have the verdict already: true/false
+ $meets_condition = $condition ? 1 : 0;
+ }
+
+ # trying to emulate a dual variable (ala errno)
+ unless ($meets_condition) {
+ my $reason = join ', ',
+ @SkipReasons ? @SkipReasons : "no reason given";
+ print "1..0 # skipped: $reason\n";
+ @SkipReasons = (); # reset
+ exit; #XXX: Apache->exit
+ }
+ }
+ @SkipReasons = (); # reset
+
+ my ($caller,$f,$l)=cp;
+
+ %SubTests=();
+ if (my $subtests=$ENV{HTTPD_TEST_SUBTESTS}) {
+ %SubTests=map { $_, 1 } split /\s+/, $subtests;
+ }
+
+ if (exists $wtm{$caller} and $wtm{$caller}->[0]==1) { # -withtestmore
+ Test::More::plan(@_);
+ }
+ else { # -withouttestmore
+ unless (exists $wtm{$caller}) {
+ warn "You forgot to 'use Apache::Test' in package $caller\n";
+ $wtm{$caller}=[0,$f,$l];
+ }
+ Test::plan(@_);
+ }
+
+ # add to Test.pm verbose output
+ print "# Using Apache/Test.pm version $VERSION\n";
+}
+
+sub need_http11 {
+ require Apache::TestRequest;
+ if (Apache::TestRequest::install_http11()) {
+ return 1;
+ }
+ else {
+ push @SkipReasons,
+ "LWP version 5.60+ required for HTTP/1.1 support";
+ return 0;
+ }
+}
+
+sub need_ssl {
+ my $vars = vars();
+ need_module([$vars->{ssl_module_name}, 'IO::Socket::SSL']);
+}
+
+sub need_lwp {
+ require Apache::TestRequest;
+ if (Apache::TestRequest::has_lwp()) {
+ return 1;
+ }
+ else {
+ push @SkipReasons, "libwww-perl is not installed";
+ return 0;
+ }
+}
+
+sub need {
+ my $need_all = 1;
+ for my $cond (@_) {
+ if (ref $cond eq 'HASH') {
+ while (my($reason, $value) = each %$cond) {
+ $value = $value->() if ref $value eq 'CODE';
+ next if $value;
+ push @SkipReasons, $reason;
+ $need_all = 0;
+ }
+ }
+ elsif ($cond =~ /^(0|1)$/) {
+ $need_all = 0 if $cond == 0;
+ }
+ else {
+ $need_all = 0 unless need_module($cond);
+ }
+ }
+ return $need_all;
+
+}
+
+sub need_module {
+ my $cfg = config();
+
+ my @modules = grep defined $_,
+ ref($_[0]) eq 'ARRAY' ? @{ $_[0] } : @_;
+
+ my @reasons = ();
+ for (@modules) {
+ if (/^[a-z0-9_.]+$/) {
+ my $mod = $_;
+ $mod .= '.c' unless $mod =~ /\.c$/;
+ next if $cfg->{modules}->{$mod};
+ $mod = 'mod_' . $mod unless $mod =~ /^mod_/;
+ next if $cfg->{modules}->{$mod};
+ if (exists $cfg->{cmodules_disabled}->{$mod}) {
+ push @reasons, $cfg->{cmodules_disabled}->{$mod};
+ next;
+ }
+ }
+ die "bogus module name $_" unless /^[\w:.]+$/;
+
+ # if the module was explicitly passed with a .c extension,
+ # do not try to eval it as a Perl module
+ my $not_found = 1;
+ unless (/\.c$/) {
+ eval "require $_";
+ $not_found = 0 unless $@;
+ #print $@ if $@;
+ }
+ push @reasons, "cannot find module '$_'" if $not_found;
+
+ }
+ if (@reasons) {
+ push @SkipReasons, @reasons;
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+sub need_min_perl_version {
+ my $version = shift;
+
+ return 1 if $] >= $version;
+
+ push @SkipReasons, "perl >= $version is required";
+ return 0;
+}
+
+# currently supports only perl modules
+sub need_min_module_version {
+ my($module, $version) = @_;
+
+ # need_module requires the perl module
+ return 0 unless need_module($module);
+
+ # support dev versions like 0.18_01
+ return 1
+ if eval { no warnings qw(numeric); $module->VERSION($version) };
+
+ push @SkipReasons, "$module version $version or higher is required";
+ return 0;
+}
+
+sub need_cgi {
+ return _need_multi(qw(cgi.c cgid.c));
+}
+
+sub need_cache_disk {
+ return _need_multi(qw(cache_disk.c disk_cache.c));
+}
+
+
+sub need_php {
+ return _need_multi(qw(php4 php5 sapi_apache2.c));
+}
+
+sub need_php4 {
+ return _need_multi(qw(php4 sapi_apache2.c));
+}
+
+sub need_access {
+ return _need_multi(qw(access authz_host));
+}
+
+sub need_auth {
+ return _need_multi(qw(auth auth_basic));
+}
+
+sub need_imagemap {
+ return need_module("imagemap") || need_module("imap");
+}
+
+sub _need_multi {
+
+ my @check = @_;
+
+ my $rc = 0;
+
+ {
+ local @SkipReasons;
+
+ foreach my $module (@check) {
+ $rc ||= need_module($module);
+ }
+ }
+
+ my $reason = join ' or ', @check;
+
+ push @SkipReasons, "cannot find one of $reason"
+ unless $rc;
+
+ return $rc;
+}
+
+sub need_apache {
+ my $version = shift;
+ my $cfg = Apache::Test::config();
+ my $rev = $cfg->{server}->{rev};
+
+ if ($rev == $version) {
+ return 1;
+ }
+ else {
+ push @SkipReasons,
+ "apache version $version required, this is version $rev";
+ return 0;
+ }
+}
+
+sub need_min_apache_version {
+ my $wanted = shift;
+ my $cfg = Apache::Test::config();
+ (my $current) = $cfg->{server}->{version} =~ m:^Apache/(\d\.\d+\.\d+):;
+
+ if (normalize_vstring($current) < normalize_vstring($wanted)) {
+ push @SkipReasons,
+ "apache version $wanted or higher is required," .
+ " this is version $current";
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+sub need_min_apache_fix {
+ my @wantlevels = @_;
+ my $cfg = Apache::Test::config();
+ (my $current) = $cfg->{server}->{version} =~ m:^Apache/((\d)\.(\d+)\.(\d+)):;
+ my $current_major = $2;
+ my $current_minor = $3;
+ my $current_micro = $4;
+
+ foreach(@wantlevels) {
+ if ($_ =~ m/(\d)\.(\d+)\.(\d+)/) {
+ my $wanted_major = $1;
+ my $wanted_minor = $2;
+ my $wanted_micro = $3;
+ if ($wanted_major eq $current_major && $wanted_minor eq $current_minor) {
+ if ($wanted_micro > $current_micro) {
+ push @SkipReasons,
+ "apache version $_ or higher is required," .
+ " this is version $current";
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ }
+ }
+ }
+
+ # We didn't match major+minor, run the test and let the author sort it out
+ return 1;
+}
+
+sub need_apache_version {
+ my $wanted = shift;
+ my $cfg = Apache::Test::config();
+ (my $current) = $cfg->{server}->{version} =~ m:^Apache/(\d\.\d+\.\d+):;
+
+ if (normalize_vstring($current) != normalize_vstring($wanted)) {
+ push @SkipReasons,
+ "apache version $wanted or higher is required," .
+ " this is version $current";
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+sub need_apache_mpm {
+ my $wanted = shift;
+ my $cfg = Apache::Test::config();
+ my $current = $cfg->{server}->{mpm};
+
+ if ($current ne $wanted) {
+ push @SkipReasons,
+ "apache $wanted mpm is required," .
+ " this is the $current mpm";
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+sub config_enabled {
+ my $key = shift;
+ defined $Config{$key} and $Config{$key} eq 'define';
+}
+
+sub need_perl_iolayers {
+ if (my $ext = $Config{extensions}) {
+ #XXX: better test? might need to test patchlevel
+ #if support depends bugs fixed in bleedperl
+ return $ext =~ m:PerlIO/scalar:;
+ }
+ 0;
+}
+
+sub need_perl {
+ my $thing = shift;
+ #XXX: $thing could be a version
+ my $config;
+
+ my $have = \&{"need_perl_$thing"};
+ if (defined &$have) {
+ return 1 if $have->();
+ }
+ else {
+ for my $key ($thing, "use$thing") {
+ if (exists $Config{$key}) {
+ $config = $key;
+ return 1 if config_enabled($key);
+ }
+ }
+ }
+
+ push @SkipReasons, $config ?
+ "Perl was not built with $config enabled" :
+ "$thing is not available with this version of Perl";
+
+ return 0;
+}
+
+sub need_threads {
+ my $status = 1;
+
+ # check APR support
+ my $build_config = Apache::TestConfig->modperl_build_config;
+
+ if ($build_config) {
+ my $apr_config = $build_config->get_apr_config();
+ unless ($apr_config->{HAS_THREADS}) {
+ $status = 0;
+ push @SkipReasons, "Apache/APR was built without threads support";
+ }
+ }
+
+ # check Perl's useithreads
+ my $key = 'useithreads';
+ unless (exists $Config{$key} and config_enabled($key)) {
+ $status = 0;
+ push @SkipReasons, "Perl was not built with 'ithreads' enabled";
+ }
+
+ return $status;
+}
+
+sub need_fork {
+ my $have_fork = $Config{d_fork} ||
+ $Config{d_pseudofork} ||
+ (($^O eq 'MSWin32' || $^O eq 'NetWare') &&
+ $Config{useithreads} &&
+ $Config{ccflags} =~ /-DPERL_IMPLICIT_SYS/);
+
+ if (!$have_fork) {
+ push @SkipReasons, 'The fork function is unimplemented';
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+sub under_construction {
+ push @SkipReasons, "This test is under construction";
+ return 0;
+}
+
+sub skip_reason {
+ my $reason = shift || 'no reason specified';
+ push @SkipReasons, $reason;
+ return 0;
+}
+
+# normalize Apache-style version strings (2.0.48, 0.9.4)
+# for easy numeric comparison. note that 2.1 and 2.1.0
+# are considered equivalent.
+sub normalize_vstring {
+
+ my @digits = shift =~ m/(\d+)\.?(\d*)\.?(\d*)/;
+
+ return join '', map { sprintf("%03d", $_ || 0) } @digits;
+}
+
+# have_ functions are the same as need_ but they don't populate
+# @SkipReasons
+for my $func (@have) {
+ no strict 'refs';
+ (my $real_func = $func) =~ s/^have_/need_/;
+ *$func = sub {
+ # be nice to poor souls calling functions with $_ argument in
+ # the foreach loop, etc.!
+ local $_;
+ local @SkipReasons;
+ return $real_func->(@_);
+ };
+}
+
+package Apache::TestToString;
+
+Apache::Test->import('!:DEFAULT');
+
+sub TIEHANDLE {
+ my $string = "";
+ bless \$string;
+}
+
+sub PRINT {
+ my $string = shift;
+ $$string .= join '', @_;
+}
+
+sub start {
+ tie *STDOUT, __PACKAGE__;
+ Apache::Test::test_pm_refresh();
+}
+
+sub finish {
+ my $s;
+ {
+ my $o = tied *STDOUT;
+ $s = $$o;
+ }
+ untie *STDOUT;
+ $s;
+}
+
+1;
+__END__
+
+
+=head1 NAME
+
+Apache::Test - Test.pm wrapper with helpers for testing Apache
+
+=head1 SYNOPSIS
+
+ use Apache::Test;
+
+=head1 DESCRIPTION
+
+B<Apache::Test> is a wrapper around the standard C<Test.pm> with
+helpers for testing an Apache server.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item plan
+
+This function is a wrapper around C<Test::plan>:
+
+ plan tests => 3;
+
+just like using Test.pm, plan 3 tests.
+
+If the first argument is an object, such as an C<Apache::RequestRec>
+object, C<STDOUT> will be tied to it. The C<Test.pm> global state will
+also be refreshed by calling C<Apache::Test::test_pm_refresh>. For
+example:
+
+ plan $r, tests => 7;
+
+ties STDOUT to the request object C<$r>.
+
+If there is a last argument that doesn't belong to C<Test::plan>
+(which expects a balanced hash), it's used to decide whether to
+continue with the test or to skip it all-together. This last argument
+can be:
+
+=over
+
+=item * a C<SCALAR>
+
+the test is skipped if the scalar has a false value. For example:
+
+ plan tests => 5, 0;
+
+But this won't hint the reason for skipping therefore it's better to
+use need():
+
+ plan tests => 5,
+ need 'LWP',
+ { "not Win32" => sub { $^O eq 'MSWin32'} };
+
+see C<need()> for more info.
+
+=item * an C<ARRAY> reference
+
+need_module() is called for each value in this array. The test is
+skipped if need_module() returns false (which happens when at least
+one C or Perl module from the list cannot be found).
+
+Watch out for case insensitive file systems or duplicate modules
+with the same name. I.E. If you mean mod_env.c
+ need_module('mod_env.c')
+Not
+ need_module('env')
+
+=item * a C<CODE> reference
+
+the tests will be skipped if the function returns a false value. For
+example:
+
+ plan tests => 5, need_lwp;
+
+the test will be skipped if LWP is not available
+
+=back
+
+All other arguments are passed through to I<Test::plan> as is.
+
+=item ok
+
+Same as I<Test::ok>, see I<Test.pm> documentation.
+
+=item sok
+
+Allows to skip a sub-test, controlled from the command line. The
+argument to sok() is a CODE reference or a BLOCK whose return value
+will be passed to ok(). By default behaves like ok(). If all sub-tests
+of the same test are written using sok(), and a test is executed as:
+
+ % ./t/TEST -v skip_subtest 1 3
+
+only sub-tests 1 and 3 will be run, the rest will be skipped.
+
+=item skip
+
+Same as I<Test::skip>, see I<Test.pm> documentation.
+
+=item test_pm_refresh
+
+Normally called by I<Apache::Test::plan>, this function will refresh
+the global state maintained by I<Test.pm>, allowing C<plan> and
+friends to be called more than once per-process. This function is not
+exported.
+
+=back
+
+Functions that can be used as a last argument to the extended plan().
+Note that for each C<need_*> function there is a C<have_*> equivalent
+that performs the exact same function except that it is designed to
+be used outside of C<plan()>. C<need_*> functions have the side effect
+of generating skip messages, if the test is skipped. C<have_*> functions
+don't have this side effect. In other words, use C<need_apache()>
+with C<plan()> to decide whether a test will run, but C<have_apache()>
+within test logic to adjust expectations based on older or newer
+server versions.
+
+=over
+
+=item need_http11
+
+ plan tests => 5, need_http11;
+
+Require HTTP/1.1 support.
+
+=item need_ssl
+
+ plan tests => 5, need_ssl;
+
+Require SSL support.
+
+Not exported by default.
+
+=item need_lwp
+
+ plan tests => 5, need_lwp;
+
+Require LWP support.
+
+=item need_cgi
+
+ plan tests => 5, need_cgi;
+
+Requires mod_cgi or mod_cgid to be installed.
+
+=item need_cache_disk
+
+ plan tests => 5, need_cache_disk
+
+Requires mod_cache_disk or mod_disk_cache to be installed.
+
+
+=item need_php
+
+ plan tests => 5, need_php;
+
+Requires a PHP module to be installed (version 4 or 5).
+
+=item need_php4
+
+ plan tests => 5, need_php4;
+
+Requires a PHP version 4 module to be installed.
+
+=item need_imagemap
+
+ plan tests => 5, need_imagemap;
+
+Requires a mod_imagemap or mod_imap be installed
+
+=item need_apache
+
+ plan tests => 5, need_apache 2;
+
+Requires Apache 2nd generation httpd-2.x.xx
+
+ plan tests => 5, need_apache 1;
+
+Requires Apache 1st generation (apache-1.3.xx)
+
+See also C<need_min_apache_version()>.
+
+=item need_min_apache_version
+
+Used to require a minimum version of Apache.
+
+For example:
+
+ plan tests => 5, need_min_apache_version("2.0.40");
+
+requires Apache 2.0.40 or higher.
+
+=item need_apache_version
+
+Used to require a specific version of Apache.
+
+For example:
+
+ plan tests => 5, need_apache_version("2.0.40");
+
+requires Apache 2.0.40.
+
+=item need_min_apache_fix
+
+Used to require a particular micro version from corresponding minor release
+
+For example:
+
+ plan tests => 5, need_min_apache_fix("2.0.40", "2.2.30", "2.4.18");
+
+requires Apache 2.0.40 or higher.
+
+=item need_apache_mpm
+
+Used to require a specific Apache Multi-Processing Module.
+
+For example:
+
+ plan tests => 5, need_apache_mpm('prefork');
+
+requires the prefork MPM.
+
+=item need_perl
+
+ plan tests => 5, need_perl 'iolayers';
+ plan tests => 5, need_perl 'ithreads';
+
+Requires a perl extension to be present, or perl compiled with certain
+capabilities.
+
+The first example tests whether C<PerlIO> is available, the second
+whether:
+
+ $Config{useithread} eq 'define';
+
+=item need_min_perl_version
+
+Used to require a minimum version of Perl.
+
+For example:
+
+ plan tests => 5, need_min_perl_version("5.008001");
+
+requires Perl 5.8.1 or higher.
+
+=item need_fork
+
+Requires the perl built-in function C<fork> to be implemented.
+
+=item need_module
+
+ plan tests => 5, need_module 'CGI';
+ plan tests => 5, need_module qw(CGI Find::File);
+ plan tests => 5, need_module ['CGI', 'Find::File', 'cgid'];
+
+Requires Apache C and Perl modules. The function accept a list of
+arguments or a reference to a list.
+
+In case of C modules, depending on how the module name was passed it
+may pass through the following completions:
+
+=over
+
+=item 1 need_module 'proxy_http.c'
+
+If there is the I<.c> extension, the module name will be looked up as
+is, i.e. I<'proxy_http.c'>.
+
+=item 2 need_module 'mod_cgi'
+
+The I<.c> extension will be appended before the lookup, turning it into
+I<'mod_cgi.c'>.
+
+=item 3 need_module 'cgi'
+
+The I<.c> extension and I<mod_> prefix will be added before the
+lookup, turning it into I<'mod_cgi.c'>.
+
+=back
+
+=item need_min_module_version
+
+Used to require a minimum version of a module
+
+For example:
+
+ plan tests => 5, need_min_module_version(CGI => 2.81);
+
+requires C<CGI.pm> version 2.81 or higher.
+
+Currently works only for perl modules.
+
+=item need
+
+ plan tests => 5,
+ need 'LWP',
+ { "perl >= 5.8.0 and w/ithreads is required" =>
+ ($Config{useperlio} && $] >= 5.008) },
+ { "not Win32" => sub { $^O eq 'MSWin32' },
+ "foo is disabled" => \&is_foo_enabled,
+ },
+ 'cgid';
+
+need() is more generic function which can impose multiple requirements
+at once. All requirements must be satisfied.
+
+need()'s argument is a list of things to test. The list can include
+scalars, which are passed to need_module(), and hash references. If
+hash references are used, the keys, are strings, containing a reason
+for a failure to satisfy this particular entry, the values are the
+condition, which are satisfaction if they return true. If the value is
+0 or 1, it used to decide whether the requirements very satisfied, so
+you can mix special C<need_*()> functions that return 0 or 1. For
+example:
+
+ plan tests => 1, need 'Compress::Zlib', 'deflate',
+ need_min_apache_version("2.0.49");
+
+If the scalar value is a string, different from 0 or 1, it's passed to
+I<need_module()>. If the value is a code reference, it gets executed
+at the time of check and its return value is used to check the
+condition. If the condition check fails, the provided (in a key)
+reason is used to tell user why the test was skipped.
+
+In the presented example, we require the presence of the C<LWP> Perl
+module, C<mod_cgid>, that we run under perl E<gt>= 5.7.3 on Win32.
+
+It's possible to put more than one requirement into a single hash
+reference, but be careful that the keys will be different.
+
+It's also important to mention to avoid using:
+
+ plan tests => 1, requirement1 && requirement2;
+
+technique. While test-wise that technique is equivalent to:
+
+ plan tests => 1, need requirement1, requirement2;
+
+since the test will be skipped, unless all the rules are satisfied,
+it's not equivalent for the end users. The second technique, deploying
+C<need()> and a list of requirements, always runs all the requirement
+checks and reports all the missing requirements. In the case of the
+first technique, if the first requirement fails, the second is not
+run, and the missing requirement is not reported. So let's say all the
+requirements are missing Apache modules, and a user wants to satisfy
+all of these and run the test suite again. If all the unsatisfied
+requirements are reported at once, she will need to rebuild Apache
+once. If only one requirement is reported at a time, she will have to
+rebuild Apache as many times as there are elements in the C<&&>
+statement.
+
+Also see plan().
+
+=item under_construction
+
+ plan tests => 5, under_construction;
+
+skip all tests, noting that the tests are under construction
+
+=item skip_reason
+
+ plan tests => 5, skip_reason('my custom reason');
+
+skip all tests. the reason you specify will be given at runtime.
+if no reason is given a default reason will be used.
+
+=back
+
+=head1 Additional Configuration Variables
+
+=over 4
+
+=item basic_config
+
+ my $basic_cfg = Apache::Test::basic_config();
+ $basic_cfg->write_perlscript($file, $content);
+
+C<basic_config()> is similar to C<config()>, but doesn't contain any
+httpd-specific information and should be used for operations that
+don't require any httpd-specific knowledge.
+
+=item config
+
+ my $cfg = Apache::Test::config();
+ my $server_rev = $cfg->{server}->{rev};
+ ...
+
+C<config()> gives an access to the configuration object.
+
+=item vars
+
+ my $serverroot = Apache::Test::vars->{serverroot};
+ my $serverroot = Apache::Test::vars('serverroot');
+ my($top_dir, $t_dir) = Apache::Test::vars(qw(top_dir t_dir));
+
+C<vars()> gives an access to the configuration variables, otherwise
+accessible as:
+
+ $vars = Apache::Test::config()->{vars};
+
+If no arguments are passed, the reference to the variables hash is
+returned. If one or more arguments are passed the corresponding values
+are returned.
+
+=back
+
+=head1 Test::More Integration
+
+There are a few caveats if you want to use I<Apache::Test> with
+I<Test::More> instead of the default I<Test> backend. The first is
+that I<Test::More> requires you to use its own C<plan()> function
+and not the one that ships with I<Apache::Test>. I<Test::More> also
+defines C<ok()> and C<skip()> functions that are different, and
+simply C<use>ing both modules in your test script will lead to redefined
+warnings for these subroutines.
+
+To assist I<Test::More> users we have created a special I<Apache::Test>
+import tag, C<:withtestmore>, which will export all of the standard
+I<Apache::Test> symbols into your namespace except the ones that collide
+with I<Test::More>.
+
+ use Apache::Test qw(:withtestmore);
+ use Test::More;
+
+ plan tests => 1; # Test::More::plan()
+
+ ok ('yes', 'testing ok'); # Test::More::ok()
+
+Now, while this works fine for standard client-side tests
+(such as C<t/basic.t>), the more advanced features of I<Apache::Test>
+require using I<Test::More> as the sole driver behind the scenes.
+
+Should you choose to use I<Test::More> as the backend for
+server-based tests (such as C<t/response/TestMe/basic.pm>) you will
+need to use the C<-withtestmore> action tag:
+
+ use Apache::Test qw(-withtestmore);
+
+ sub handler {
+
+ my $r = shift;
+
+ plan $r, tests => 1; # Test::More::plan() with
+ # Apache::Test features
+
+ ok ('yes', 'testing ok'); # Test::More::ok()
+ }
+
+C<-withtestmore> tells I<Apache::Test> to use I<Test::More>
+instead of I<Test.pm> behind the scenes. Note that you are not
+required to C<use Test::More> yourself with the C<-withtestmore>
+option and that the C<use Test::More tests =E<gt> 1> syntax
+may have unexpected results.
+
+Note that I<Test::More> version 0.49, available within the
+I<Test::Simple> 0.49 distribution on CPAN, or greater is required
+to use this feature.
+
+Because I<Apache:Test> was initially developed using I<Test> as
+the framework driver, complete I<Test::More> integration is
+considered experimental at this time - it is supported as best as
+possible but is not guaranteed to be as stable as the default I<Test>
+interface at this time.
+
+=head1 Apache::TestToString Class
+
+The I<Apache::TestToString> class is used to capture I<Test.pm> output
+into a string. Example:
+
+ Apache::TestToString->start;
+
+ plan tests => 4;
+
+ ok $data eq 'foo';
+
+ ...
+
+ # $tests will contain the Test.pm output: 1..4\nok 1\n...
+ my $tests = Apache::TestToString->finish;
+
+=head1 SEE ALSO
+
+The Apache-Test tutorial:
+L<http://perl.apache.org/docs/general/testing/testing.html>.
+
+L<Apache::TestRequest|Apache::TestRequest> subclasses LWP::UserAgent and
+exports a number of useful functions for sending request to the Apache test
+server. You can then test the results of those requests.
+
+Use L<Apache::TestMM|Apache::TestMM> in your F<Makefile.PL> to set up your
+distribution for testing.
+
+=head1 AUTHOR
+
+Doug MacEachern with contributions from Geoffrey Young, Philippe
+M. Chiasson, Stas Bekman and others.
+
+Questions can be asked at the test-dev <at> httpd.apache.org list
+For more information see: http://httpd.apache.org/test/.
+
+=cut