| # 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 ? "" : <<EOF; |
| PASSENV = $env |
| EOF |
| |
| my $cover; |
| |
| if (eval { require Devel::Cover }) { |
| my $atdir = File::Spec->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<Apache::TestMM> provides wrappers for the C<ExtUtils::MakeMaker> |
| craft, making it easier to extend the autogenerated F<Makefile> with |
| C<Apache::Test>. |
| |
| =head1 FUNCTIONS |
| |
| =head2 C<import> |
| |
| use Apache::TestMM qw(test clean); |
| |
| or: |
| |
| Apache::TestMM->import(qw(test clean)); |
| |
| Imports C<MY::> overrides for the default C<ExtUtils::MakeMaker> |
| I<test> and I<clean> targets, as if you have defined: |
| |
| sub MY::test {...} |
| sub MY::clean {...} |
| |
| in F<Makefile.PL>. C<Apache::TestMM> 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<filter_args> |
| |
| push @ARGV, '-apxs', $apxs_path; |
| Apache::TestMM::filter_args(); |
| WriteMakefile(...); |
| |
| When C<WriteMakefile()> is called it parses C<@ARGV>, hoping to find |
| special options like C<PREFIX=/home/stas/perl>. C<Apache::Test> |
| accepts a lot of configuration options of its own. When |
| C<Apache::TestMM::filter_args()> is called, it removes any |
| C<Apache::Test>-specific options from C<@ARGV> and stores them |
| internally, so when C<WriteMakefile()> is called they aren't in |
| C<@ARGV> and thus won't be processed by C<WriteMakefile()>. |
| |
| The options can be set when F<Makefile.PL> 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<Apache::Test>-specific options extracted by |
| C<Apache::TestMM::filter_args()> are written to the autogenerated |
| file. In our example, the autogenerated F<t/TEST> will include: |
| |
| %Apache::TestConfig::Argv = qw(apxs /path/to/apxs); |
| |
| which is going to be used by the C<Apache::Test> 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<MaxClients> 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<README> |
| file, especially the C<-apxs> and C<-httpd> options. |
| |
| |
| =head2 C<generate_script> |
| |
| Apache::TestMM::generate_script('t/TEST'); |
| |
| C<generate_script()> 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<t/TEST.PL>. The autogenerated script |
| F<t/TEST> will include the contents of F<t/TEST.PL>, and special |
| directives, including any configuration options passed via |
| C<L<filter_args()|/C_filter_args_>> called from F<Makefile.PL>, special |
| fixup code, etc. |
| |
| =cut |