# 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::TestMM; use strict; use warnings FATAL => 'all'; use Config; use Apache::TestConfig (); use Apache::TestTrace; use Apache::TestSmoke; sub import { my $class = shift; for my $section (@_) { unless (defined &$section) { die "unknown Apache::TestMM section: $section"; } no strict 'refs'; my $sub = "MY::$section"; # Force aliasing, since previous WriteMakefile might have # moved it undef &$sub if defined &$sub; *$sub = \&{$section}; } } sub add_dep { my($string, $targ, $add) = @_; $$string =~ s/($targ\s+::)/$1 $add /; } sub clean { my $self = shift; my $string = $self->MM::clean(@_); add_dep(\$string, clean => 'test_clean'); $string; } sub test { my $self = shift; my $env = Apache::TestConfig->passenv_makestr(); my $tests = "TEST_FILES =\n"; if (ref $self && exists $self->{'test'}) { $tests = 'TEST_FILES = ' . $self->{'test'}->{'TESTS'} . "\n"; } my $preamble = Apache::TestConfig::WIN32 ? "" : <catfile($ENV{HOME}, '.apache-test'); my $cover_exec = Apache::TestConfig::which("cover"); my @cover = ("", "testcover :", ); push @cover, "\t-\@$cover_exec -delete" if $cover_exec; push @cover, "\t-HARNESS_PERL_SWITCHES=-MDevel::Cover=+inc,$atdir \\", "\tAPACHE_TEST_EXTRA_ARGS=-one-process \$(MAKE) test"; push @cover, "\t-\@$cover_exec" if $cover_exec; $cover = join "\n", @cover, ""; } else { $cover = <<'EOF'; testcover : @echo "Cannot run testcover action unless Devel::Cover is installed" @echo "Don't forget to rebuild your Makefile after installing Devel::Cover" EOF } return $preamble . $tests . <<'EOF' . $cover; TEST_VERBOSE = 0 test_clean : $(FULLPERL) -I$(INST_ARCHLIB) -I$(INST_LIB) \ t/TEST $(APACHE_TEST_EXTRA_ARGS) -clean run_tests : $(PASSENV) \ $(FULLPERL) -I$(INST_ARCHLIB) -I$(INST_LIB) \ t/TEST $(APACHE_TEST_EXTRA_ARGS) -bugreport -verbose=$(TEST_VERBOSE) $(TEST_FILES) test :: pure_all test_clean run_tests test_config : $(PASSENV) \ $(FULLPERL) -I$(INST_ARCHLIB) -I$(INST_LIB) \ t/TEST $(APACHE_TEST_EXTRA_ARGS) -conf cmodules: test_config cd c-modules && $(MAKE) all cmodules_clean: test_config cd c-modules && $(MAKE) clean EOF } sub generate_script { my $file = shift; unlink $file if -e $file; my $body = "BEGIN { eval { require blib && blib->import; } }\n"; my %args = @Apache::TestMM::Argv; while (my($k, $v) = each %args) { $v =~ s/\|/\\|/g; $body .= "\n\$Apache::TestConfig::Argv{'$k'} = q|$v|;\n"; } my $in = Symbol::gensym(); open $in, "$file.PL" or die "Couldn't open $file.PL: $!"; { local $/; $body .= <$in>; } close $in; info "generating script $file"; Apache::Test::basic_config()->write_perlscript($file, $body); Apache::TestSmoke->generate_script; } sub filter_args { my($argv, $vars) = Apache::TestConfig::filter_args(\@ARGV, \%Apache::TestConfig::Usage); @ARGV = @$argv; @Apache::TestMM::Argv = %$vars; } 1; =head1 NAME Apache::TestMM - Provide MakeMaker Wrapper Methods =head1 SYNOPSIS require Apache::TestMM; # import MY::test and MY::clean overrides for MM Apache::TestMM->import(qw(test clean)); # parse command line args Apache::TestMM::filter_args(); # autogenerate the script Apache::TestMM::generate_script('t/TEST'); =head1 DESCRIPTION C provides wrappers for the C craft, making it easier to extend the autogenerated F with C. =head1 FUNCTIONS =head2 C use Apache::TestMM qw(test clean); or: Apache::TestMM->import(qw(test clean)); Imports C overrides for the default C I and I targets, as if you have defined: sub MY::test {...} sub MY::clean {...} in F. C does this for you so that these Makefile targets will run the Apache server and the tests for it, and clean up after its mess. =head2 C push @ARGV, '-apxs', $apxs_path; Apache::TestMM::filter_args(); WriteMakefile(...); When C is called it parses C<@ARGV>, hoping to find special options like C. C accepts a lot of configuration options of its own. When C is called, it removes any C-specific options from C<@ARGV> and stores them internally, so when C is called they aren't in C<@ARGV> and thus won't be processed by C. The options can be set when F is called: % perl Makefile.PL -apxs /path/to/apxs Or you can push them manually to C<@ARGV> from the code: push @ARGV, '-apxs', $apxs_path; When: Apache::TestMM::generate_script('t/TEST'); is called, C-specific options extracted by C are written to the autogenerated file. In our example, the autogenerated F will include: %Apache::TestConfig::Argv = qw(apxs /path/to/apxs); which is going to be used by the C runtime. The other frequently used options are: C<-httpd>, telling where to find the httpd (usually when the C<-apxs> option is not used), C<-libmodperl> to use a specific mod_perl shared object (if your mod_perl is built as DSO), C<-maxclients> to change the default number of the configured C directive, C<-port> to start the server on a specific port, etc. To get the complete list of available configuration options and their purpose and syntax, run: % perl -MApache::TestConfig -le 'Apache::TestConfig::usage()' You may wish to document some of these in your application's F file, especially the C<-apxs> and C<-httpd> options. =head2 C Apache::TestMM::generate_script('t/TEST'); C accepts the name of the script to generate and will look for a template with the same name and suffix I<.PL>. So in our example it'll look for F. The autogenerated script F will include the contents of F, and special directives, including any configuration options passed via C> called from F, special fixup code, etc. =cut