httpd-test-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject cvs commit: httpd-test/perl-framework/Apache-Test/lib/Apache TestConfig.pm TestRun.pm
Date Wed, 07 Jan 2004 17:51:21 GMT
stas        2004/01/07 09:51:21

  Modified:    perl-framework/Apache-Test Changes Makefile.PL
               perl-framework/Apache-Test/lib/Apache TestConfig.pm
                        TestRun.pm
  Log:
  implementing custom interactive and non-interactive (with the -save
  option) reusable configuration for -httpd, -apxs, -user, -group, and
  -port
  
  Revision  Changes    Path
  1.76      +4 -0      httpd-test/perl-framework/Apache-Test/Changes
  
  Index: Changes
  ===================================================================
  RCS file: /home/cvs/httpd-test/perl-framework/Apache-Test/Changes,v
  retrieving revision 1.75
  retrieving revision 1.76
  diff -u -u -r1.75 -r1.76
  --- Changes	22 Dec 2003 19:51:02 -0000	1.75
  +++ Changes	7 Jan 2004 17:51:21 -0000	1.76
  @@ -8,6 +8,10 @@
   
   =item 1.08_dev
   
  +implementing custom interactive and non-interactive (with the -save
  +option) reusable configuration for -httpd, -apxs, -user, -group, and
  +-port [Randy Kobes, Stas]
  +
   =item 1.07 - Decemeber 22, 2003
   
   allow conditional C module compilation on a more granular level.
  
  
  
  1.16      +19 -1     httpd-test/perl-framework/Apache-Test/Makefile.PL
  
  Index: Makefile.PL
  ===================================================================
  RCS file: /home/cvs/httpd-test/perl-framework/Apache-Test/Makefile.PL,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -u -r1.15 -r1.16
  --- Makefile.PL	6 Jan 2004 19:17:59 -0000	1.15
  +++ Makefile.PL	7 Jan 2004 17:51:21 -0000	1.16
  @@ -12,12 +12,14 @@
   
   use ExtUtils::MakeMaker;
   use Symbol;
  +use File::Spec::Functions qw(catfile);
  +use FindBin;
   
   use Apache::TestMM qw(test); #enable 'make test'
  +use Apache::TestRun;
   
   my $VERSION;
   
  -
   Apache::TestMM::filter_args();
   
   my @scripts = qw(t/TEST);
  @@ -35,6 +37,8 @@
       add_Apache__test_target();
   }
   
  +write_custom_config_file_stub();
  +
   WriteMakefile(
       NAME      => 'Apache::Test',
       VERSION   => $VERSION,
  @@ -99,3 +103,17 @@
           $string;
       };
   }
  +
  +# write the custom test file so it'll be copied to blib if updated
  +# during 'make test' and then installed system-wide
  +sub write_custom_config_file_stub {
  +    # It doesn't matter whether it gets written under modperl-2.0/lib
  +    # or Apache-Test/lib root, since Apache::TestRun uses the same
  +    # logic and will update that file with real config data, which
  +    # 'make install' will then pick and install system-wide
  +    my $path = catfile $FindBin::Bin, "lib",
  +        Apache::TestRun::CUSTOM_CONFIG_FILE;
  +    # write an empty stub
  +    Apache::TestRun::custom_config_write($path, '');
  +}
  +
  
  
  
  1.193     +4 -15     httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfig.pm
  
  Index: TestConfig.pm
  ===================================================================
  RCS file: /home/cvs/httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfig.pm,v
  retrieving revision 1.192
  retrieving revision 1.193
  diff -u -u -r1.192 -r1.193
  --- TestConfig.pm	5 Jan 2004 23:40:53 -0000	1.192
  +++ TestConfig.pm	7 Jan 2004 17:51:21 -0000	1.193
  @@ -17,6 +17,9 @@
   use constant IS_MOD_PERL_2_BUILD => IS_MOD_PERL_2 &&
       require Apache::Build && Apache::Build::IS_MOD_PERL_BUILD();
   
  +use constant IS_APACHE_TEST_BUILD =>
  +    grep { -e "$_/lib/Apache/TestConfig.pm" } qw(. ..);
  +
   use Symbol ();
   use File::Copy ();
   use File::Find qw(finddepth);
  @@ -305,20 +308,6 @@
   
       $vars->{target} ||= (WIN32 ? 'Apache.exe' : 'httpd');
   
  -    unless ($vars->{httpd}) {
  -        #sbindir should be bin/ with the default layout
  -        #but its eaiser to workaround apxs than fix apxs
  -        for my $dir (map { $vars->{$_} } qw(sbindir bindir)) {
  -            next unless defined $dir;
  -            my $httpd = catfile $dir, $vars->{target};
  -            next unless -x $httpd;
  -            $vars->{httpd} = $httpd;
  -            last;
  -        }
  -
  -        $vars->{httpd} ||= $self->default_httpd;
  -    }
  -
       if ($vars->{httpd}) {
           my @chunks = splitdir $vars->{httpd};
           #handle both $prefix/bin/httpd and $prefix/Apache.exe
  @@ -1366,7 +1355,7 @@
           }
       }
   
  -    my $exe = $vars->{apxs} || $vars->{httpd};
  +    my $exe = $vars->{apxs} || $vars->{httpd} || '';
       # if httpd.conf is older than executable
       push @reasons,
           "$exe is newer than $vars->{t_conf_file}"
  
  
  
  1.132     +418 -14   httpd-test/perl-framework/Apache-Test/lib/Apache/TestRun.pm
  
  Index: TestRun.pm
  ===================================================================
  RCS file: /home/cvs/httpd-test/perl-framework/Apache-Test/lib/Apache/TestRun.pm,v
  retrieving revision 1.131
  retrieving revision 1.132
  diff -u -u -r1.131 -r1.132
  --- TestRun.pm	19 Dec 2003 09:16:14 -0000	1.131
  +++ TestRun.pm	7 Jan 2004 17:51:21 -0000	1.132
  @@ -11,20 +11,29 @@
   use Apache::TestHarness ();
   use Apache::TestTrace;
   
  +use Cwd;
   use File::Find qw(finddepth);
  -use File::Spec::Functions qw(catfile);
  +use File::Spec::Functions qw(catfile catdir);
   use File::Basename qw(basename dirname);
   use Getopt::Long qw(GetOptions);
   use Config;
   
  +use constant IS_APACHE_TEST_BUILD => Apache::TestConfig::IS_APACHE_TEST_BUILD;
  +
   use constant STARTUP_TIMEOUT => 300; # secs (good for extreme debug cases)
  +
  +use constant CUSTOM_CONFIG_FILE => 'Apache/TestConfigData.pm';
  +
   use subs qw(exit_shell exit_perl);
   
  +my $original_command;
  +my $orig_cwd;
  +
   my %core_files  = ();
   my %original_t_perms = ();
   
   my @std_run      = qw(start-httpd run-tests stop-httpd);
  -my @others       = qw(verbose configure clean help ssl http11 bugreport);
  +my @others       = qw(verbose configure clean help ssl http11 bugreport save);
   my @flag_opts    = (@std_run, @others);
   my @string_opts  = qw(order trace);
   my @ostring_opts = qw(proxy ping);
  @@ -57,9 +66,24 @@
      'ssl'             => 'run tests through ssl',
      'proxy'           => 'proxy requests (default proxy is localhost)',
      'trace=T'         => 'change tracing default to: warning, notice, info, debug, ...',
  +   'save'            => 'save test paramaters into Apache::TestConfigData',
      (map { $_, "\U$_\E url" } @request_opts),
   );
   
  +# variables stored in $Apache::TestConfigData::vars
  +my @data_vars_must = qw(httpd apxs);
  +my @data_vars_opt  = qw(user group port);
  +# mapping from $Apache::TestConfigData::vars to $ENV settings
  +my %vars_to_env = (
  +    httpd => 'APACHE',
  +    user  => 'APACHE_USER',
  +    group => 'APACHE_GROUP',
  +    apxs  => 'APXS',
  +    port  => 'APACHE_PORT',
  +);
  +
  +custom_config_load();
  +
   sub fixup {
       #make sure we use an absolute path to perl
       #else Test::Harness uses the perl in our PATH
  @@ -435,6 +459,19 @@
       $test_config->cmodules_configure;
       $test_config->generate_httpd_conf;
       $test_config->save;
  +
  +    # save if
  +    # 1) requested to save
  +    # 2) no saved config yet
  +    # 3) A-T build (since it'll override the global file)
  +    # the only side-effect of (3) is that if config is changed during
  +    # A-T build it'll change the global custom config if that exists,
  +    # but it shouldn't affect normal users who won't do it more than once
  +    if ($self->{opts}->{save} 
  +        or !$self->custom_config_exists()
  +        or IS_APACHE_TEST_BUILD) {
  +        $self->custom_config_save();
  +    }
   }
   
   sub try_exit_opts {
  @@ -470,12 +507,17 @@
       my $test_config = $self->{test_config};
   
       unless ($test_config->{vars}->{httpd}) {
  -        error "no test server configured, please specify an httpd or ".
  -              ($test_config->{APXS} ?
  -               "an apxs other than $test_config->{APXS}" : "apxs").
  -               " or put either in your PATH. For example:\n" .
  -               "$0 -httpd /path/to/bin/httpd";
  -        exit_perl 0;
  +        $self->opt_clean(1);
  +        # this method restarts the whole program via exec
  +        # so it never returns
  +        $self->custom_config_first_time;
  +    }
  +
  +    # if we have gotten that far we know at least about the location
  +    # of httpd, so let's save it if we haven't saved any custom
  +    # configs yet
  +    unless ($self->custom_config_exists()) {
  +        $self->custom_config_save();
       }
   
       my $opts = $self->{opts};
  @@ -541,6 +583,10 @@
   
   sub new_test_config {
       my $self = shift;
  +    for (@data_vars_must, @data_vars_opt) {
  +        next unless $Apache::TestConfigData::vars->{$_};
  +        $self->{conf_opts}->{$_} ||= $Apache::TestConfigData::vars->{$_};
  +    }
       Apache::TestConfig->new($self->{conf_opts});
   }
   
  @@ -563,12 +609,10 @@
       }
       close $sh;
   
  -    # reconstruct argv, preserve multiwords args, eg 'PerlTrace all'
  -    my $argv = join " ", map { /^-/ ? $_ : qq['$_'] } @ARGV;
  -    my $command = "ulimit -c unlimited; $0 $argv";
  -    warning "setting ulimit to allow core files\n$command";
  -    exec $command;
  -    die "exec $command has failed"; # shouldn't be reached
  +    $original_command = "ulimit -c unlimited; $original_command";
  +    warning "setting ulimit to allow core files\n$original_command";
  +    exec $original_command;
  +    die "exec $original_command has failed"; # shouldn't be reached
   }
   
   sub set_ulimit {
  @@ -587,6 +631,10 @@
   sub run {
       my $self = shift;
   
  +    # reconstruct argv, preserve multiwords args, eg 'PerlTrace all'
  +    my $argv = join " ", map { /^-/ ? $_ : qq['$_'] } @ARGV;
  +    $original_command = "$0 $argv";
  +    $orig_cwd = Cwd::cwd();
       $self->set_ulimit;
       $self->set_env; #make sure these are always set
   
  @@ -1087,6 +1135,324 @@
       CORE::exit $_[0];
   }
   
  +# determine where the configuration file Apache/TestConfigData.pm
  +# lives. The order searched is:
  +# 1) $ENV{HOME}/.apache-test/
  +# 2) in global @INC (if preconfigured already)
  +# 3) in local lib (for build times)
  +my $custom_config_path;
  +sub custom_config_path {
  +
  +    return $custom_config_path if $custom_config_path;
  +
  +    my @global_inc = ();
  +    my @build_inc  = ();
  +    for (@INC) {
  +        my $rel_dir = basename $_;
  +        $rel_dir eq 'lib' ? push(@build_inc, $_) : push(@global_inc, $_);
  +    }
  +
  +    # XXX $ENV{HOME} isn't propagated in mod_perl
  +    unshift @global_inc, catdir $ENV{HOME}, '.apache-test' if $ENV{HOME};
  +
  +    for (@global_inc, @build_inc) {
  +        my $candidate = File::Spec->rel2abs(catfile $_, CUSTOM_CONFIG_FILE);
  +        next unless -e $candidate;
  +        return $custom_config_path = $candidate;
  +    }
  +
  +    return '';
  +}
  +
  +sub custom_config_exists {
  +    my $self = shift;
  +    # custom config gets loaded via custom_config_load when this
  +    # package is loaded. it's enough to check whether we have a custom
  +    # config for 'httpd'.
  +    my $httpd = $Apache::TestConfigData::vars->{httpd} || '';
  +    return $httpd && -e $httpd ? 1 : 0;
  +}
  +
  +sub custom_config_save {
  +    my $self = shift;
  +    my $vars = $self->{test_config}->{vars};
  +    my $conf_opts = $self->{conf_opts};
  +    my $config_dump = '';
  +
  +    # minimum httpd needs to be set
  +    return 0 unless $vars->{httpd} or $Apache::TestConfigData::vars->{httpd};
  +
  +    # it doesn't matter how these vars were set (apxs may get set
  +    # using the path to httpd, or the other way around)
  +    for (@data_vars_must) {
  +        next unless my $var = $vars->{$_} || $conf_opts->{$_};
  +        $config_dump .= qq{    '$_' => '$var',\n};
  +    }
  +
  +    # save these vars only if they were explicitly set via command line
  +    # options. For example if someone builds A-T as user 'foo', then
  +    # installs it as root and we save it, all users will now try to 
  +    # configure under that user 'foo' which won't quite work.
  +    for (@data_vars_opt) {
  +        next unless my $var = $conf_opts->{$_};
  +        $config_dump .= qq{    '$_' => '$var',\n};
  +    }
  +
  +    my $path;
  +    # if A-T build always update the build file, regardless whether
  +    # the global file already exists, since 'make install' will
  +    # overwrite it
  +    if (IS_APACHE_TEST_BUILD) {
  +        $path = catfile $vars->{top_dir}, 'lib', CUSTOM_CONFIG_FILE;
  +    }
  +    elsif ($path = custom_config_path() ) {
  +        # do nothing, the config file already exists (global)
  +        debug "Found custom config '$path'";
  +    }
  +    else {
  +        # next try a global location, as if it was configured before
  +        # Apache::Test's 'make install'
  +        my $base = dirname dirname $INC{"Apache/TestRun.pm"};
  +        $path = catdir $base, CUSTOM_CONFIG_FILE;
  +    }
  +
  +    # check whether we can write to the directory of the chosen path
  +    if ($path) {
  +        # first make sure that the file is writable if it exists
  +        # already (it might be non-writable if installed via EU::MM)
  +        if (-e $path) {
  +            my $mode = (stat _)[2];
  +            $mode |= 0200;
  +            chmod $mode, $path; # it's ok if we fail
  +        }
  +
  +        # try to open for append
  +        my $fh = Symbol::gensym;
  +        if (open $fh, ">>$path") {
  +            close $fh;
  +        }
  +        else {
  +            $path = ''; # can't use that path to write custom config
  +        }
  +    }
  +
  +    # if we have no path yet, try to use ~
  +    if (!$path and $ENV{HOME}) {
  +        $path = catfile $ENV{HOME}, '.apache-test', CUSTOM_CONFIG_FILE;
  +    }
  +
  +    if ($path) {
  +        custom_config_write($path, $config_dump);
  +        return 1;
  +    }
  +
  +    return 0; # failed to write config XXX: should we croak?
  +}
  +
  +sub custom_config_write {
  +    my($path, $config_dump) = @_;
  +
  +    my $pkg = << "EOC";
  +package Apache::TestConfigData;
  +
  +use strict;
  +use warnings;
  +
  +\$Apache::TestConfigData::vars = {
  +$config_dump
  +};
  +
  +1;
  +
  +=head1 NAME
  +
  +Apache::TestConfigData - Configuration file for Apache::Test
  +
  +=cut
  +EOC
  +
  +    debug "Writing custom config $path";
  +    require File::Path;
  +    my $dir = dirname $path;
  +    File::Path::mkpath($dir, 0, 0755) unless -e $dir;
  +    my $fh = Symbol::gensym;
  +    open $fh, ">$path" or die "Cannot open $path: $!";
  +    print $fh $pkg;
  +    close $fh;
  +}
  +
  +sub custom_config_load {
  +    debug "trying to load custom config data";
  +
  +    if (my $custom_config_path = custom_config_path()) {
  +        debug "loading custom config path '$custom_config_path'";
  +
  +        require $custom_config_path;
  +
  +        # %ENV overloads any custom saved config (command-line option will
  +        # override any of these settings), though only if assigned
  +        # some value (this is because Makefile will pass empty env
  +        # vars if none were assigned)
  +        for (@data_vars_must, @data_vars_opt) {
  +            my $value = $ENV{ $vars_to_env{$_} };
  +            next unless defined $value and length $value;
  +            $Apache::TestConfigData::vars->{$_} = $value;
  +        }
  +    }
  +}
  +
  +sub custom_config_first_time {
  +    my $self = shift;
  +
  +    my $test_config = $self->{test_config};
  +    my $vars = $test_config->{vars};
  +
  +    require ExtUtils::MakeMaker;
  +    require File::Spec;
  +    local *which = \&Apache::TestConfig::which;
  +
  +    print qq[
  +
  +We are now going to configure the Apache-Test framework.
  +This configuration process needs to be done only once.
  +
  +];
  +
  +    print qq[
  +
  +First we need to know where the 'httpd' executable is located.
  +If you have more than one Apache server is installed, make sure
  +you supply the path to the one you are going to use for testing.
  +You can always override this setting at run time via the '-httpd'
  +option. For example:
  +
  +  % t/TEST -httpd /path/to/alternative/httpd
  +
  +or via the environment variable APACHE. For example:
  +
  +  % APACHE=/path/to/alternative/httpd t/TEST
  +
  +];
  +
  +    {
  +        my %choices = ();
  +        for (grep defined $_,
  +             map({ catfile $vars->{$_}, $vars->{target} } qw(sbindir bindir)),
  +             $test_config->default_httpd, which($vars->{target}),
  +             $ENV{APACHE},  which('apache'),  which('httpd'),
  +             $ENV{APACHE2}, which('apache2'), which('httpd2')) {
  +            $choices{$_}++ if -e $_ && -x _;
  +        }
  +        my $optional = 0;
  +        my $wanted = 'httpd';
  +        $test_config->{vars}->{$wanted} = 
  +            _custom_config_prompt_path($wanted, \%choices, $optional);
  +    }
  +
  +    print qq[
  +
  +Next we need to know where the 'apxs' script is located. This script
  +provides a lot of information about the apache installation, and makes
  +it easier to find things. However it's not available on all platforms,
  +therefore it's optional. If you don't have it installed it's not a
  +problem. Notice that if you have Apache 2.x installed that script
  +could be called as 'apxs2'.
  +
  +If you have more than one Apache server is installed, make sure you
  +supply the path to the apxs script you are going to use for testing.
  +You can always override this setting at run time via the '-apxs'
  +option. For example:
  +
  +  % t/TEST -apxs /path/to/alternative/apxs
  +
  +or via the environment variable APACHE. For example:
  +
  +  % APXS=/path/to/alternative/apxs t/TEST
  +
  +];
  +    {
  +        my %choices = ();
  +        for (grep defined $_,
  +             map({ catfile $vars->{$_}, 'apxs' } qw(sbindir bindir)),
  +             $test_config->default_apxs,
  +             $ENV{APXS},  which('apxs'),
  +             $ENV{APXS2}, which('apxs2')) {
  +            $choices{$_}++ if -e $_ && -x _;
  +        }
  +        my $optional = 1;
  +        my $wanted = 'apxs';
  +        $test_config->{vars}->{$wanted} = 
  +            _custom_config_prompt_path($wanted, \%choices, $optional);
  +    }
  +
  +    $self->custom_config_save();
  +
  +    # we probably could reconfigure on the fly ($self->configure), but
  +    # the problem is various cached data which won't be refreshed. so
  +    # the simplest is just to restart the run from scratch
  +    chdir $orig_cwd;
  +    warning "rerunning '$original_command' with new config opts";
  +    exec $original_command;
  +    die "exec $original_command has failed"; # shouldn't be reached
  +}
  +
  +sub _custom_config_prompt_path {
  +    my($wanted, $rh_choices, $optional) = @_;
  +
  +    my $ans;
  +    my $default = '';
  +    my $optional_str = $optional ? " (optional)" : '';
  +    my $prompt =
  +        "\nPlease provide a full path to$optional_str '$wanted' executable";
  +
  +    my @choices = ();
  +    if (%$rh_choices) {
  +        $prompt .= " or choose from the following options:\n\n";
  +        my $c = 0;
  +        for (sort keys %$rh_choices) {
  +            $c++;
  +            $prompt .= "    [$c] $_\n";
  +            push @choices, $_;
  +        }
  +        $prompt .= " \n";
  +        $default = 1; # a wild guess
  +    }
  +    else {
  +        $prompt .= ":\n\n";
  +    }
  +
  +    while (1) {
  +        $ans = ExtUtils::MakeMaker::prompt($prompt, $default);
  +
  +        # convert the item number to the path
  +        if ($ans =~ /^\s*(\d+)\s*$/) {
  +            if ($1 > 0 and $choices[$1-1]) {
  +                $ans = $choices[$1-1];
  +            }
  +            else {
  +                warn "The choice '$ans' doesn't exist\n";
  +                next;
  +            }
  +        }
  +
  +        if ($optional) {
  +            return '' unless $ans;
  +        }
  +
  +        unless (File::Spec->file_name_is_absolute($ans)) {
  +            my $cwd = Cwd::cwd();
  +            warn "The path '$ans' is not an absolute path. " .
  +                "Please specify an absolute path\n";
  +            next;
  +        }
  +
  +        warn("'$ans' doesn't exist\n"),     next unless -e $ans;
  +        warn("'$ans' is not executable\n"), next unless -x $ans;
  +
  +        return $ans;
  +    }
  +}
  +
   1;
   
   __END__
  @@ -1162,6 +1528,44 @@
     }
   
   Notice that the extension is I<.c>, and not I<.so>.
  +
  +=head1 Saving options
  +
  +When C<Apache::Test> is first installed, it will save the
  +values of C<httpd>, C<port>, C<apxs>, C<user>, and C<group>,
  +if set, to a configuration file C<Apache::TestConfigData>.
  +This information will then be used in setting these options
  +for subsequent uses.
  +
  +The values stored in C<Apache::TestConfigData> can be overriden
  +temporarily either by setting the appropriate environment
  +variable or by giving the relevant option when the C<TEST>
  +script is run. If you want to save these options to
  +C<Apache::TestConfigData>, use the C<-save> flag when
  +running C<TEST>.
  +
  +If you are running C<Apache::Test> as a
  +user who does not have permission to alter the system
  +C<Apache::TestConfigData>, you can place your
  +own private configuration file F<TestConfigData.pm>
  +under C<$ENV{HOME}/.apache-test/Apache/>,
  +which C<Apache::Test> will use, if present. An example
  +of such a configuration file is
  +
  +  # file $ENV{HOME}/.apache-test/Apache/TestConfigData.pm
  +  package Apache::TestConfigData;
  +  use strict;
  +  use warnings;
  +  use vars qw($vars);
  +
  +  $vars = {
  +      'group' => 'me',
  +      'user' => 'myself',
  +      'port' => '8529',
  +      'httpd' => '/usr/local/apache/bin/httpd',
  +
  +  };
  +  1;
   
   =head2 C<new_test_config>
   
  
  
  

Mime
View raw message