1 # BEGIN BPS TAGGED BLOCK {{{
5 # This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC
6 # <sales@bestpractical.com>
8 # (Except where explicitly superseded by other copyright notices)
13 # This work is made available to you under the terms of Version 2 of
14 # the GNU General Public License. A copy of that license should have
15 # been provided with this software, but in any event can be snarfed
18 # This work is distributed in the hope that it will be useful, but
19 # WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 # 02110-1301 or visit their web page on the internet at
27 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
30 # CONTRIBUTION SUBMISSION POLICY:
32 # (The following paragraph is not intended to limit the rights granted
33 # to you to modify and distribute this software under the terms of
34 # the GNU General Public License and is only of importance to you if
35 # you choose to contribute your changes and enhancements to the
36 # community by submitting them to Best Practical Solutions, LLC.)
38 # By intentionally submitting any modifications, corrections or
39 # derivatives to this work, or any other work intended for use with
40 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
41 # you are the copyright holder for those contributions and you grant
42 # Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43 # royalty-free, perpetual, license to use, copy, create derivative
44 # works based on those contributions, and sublicense and distribute
45 # those contributions and any derivatives thereof.
47 # END BPS TAGGED BLOCK }}}
49 package RT::Test::Apache;
55 "mod_perl" => [qw(authz_host env alias perl)],
56 "fastcgi" => [qw(authz_host env alias mime fastcgi)],
59 "mod_perl" => [qw(mpm_worker authz_core authn_core authz_host env alias perl)],
60 "fastcgi" => [qw(mpm_worker authz_core authn_core authz_host env alias mime fastcgi)],
64 my $apache_module_prefix = $ENV{RT_TEST_APACHE_MODULES};
67 || RT::Test->find_executable('apxs')
68 || RT::Test->find_executable('apxs2');
70 if ($apxs and not $apache_module_prefix) {
71 $apache_module_prefix = `$apxs -q LIBEXECDIR`;
72 chomp $apache_module_prefix;
75 $apache_module_prefix ||= 'modules';
79 my $passwd = File::Spec->rel2abs( File::Spec->catfile(
80 't', 'data', 'configs', 'passwords' ) );
84 AuthName "restricted area"
95 AuthName "restricted area"
96 AuthBasicProvider anon
100 Anonymous_MustGiveEmail Off
101 Anonymous_VerifyEmail Off
108 my ($self, %config) = @_;
109 my %tmp = %{$config{tmp}};
110 my %info = $self->apache_server_info( %config );
113 open( my $fh, '<', $tmp{'config'}{'RT'} ) or die $!;
118 my $tmpl = File::Spec->rel2abs( File::Spec->catfile(
119 't', 'data', 'configs',
120 'apache'. $info{'version'} .'+'. $config{variant} .'.conf'
123 listen => $config{port},
124 server_root => $info{'HTTPD_ROOT'} || $ENV{'HTTPD_ROOT'}
125 || Test::More::BAIL_OUT("Couldn't figure out server root"),
126 document_root => $RT::MasonComponentRoot,
127 tmp_dir => "$tmp{'directory'}",
128 rt_bin_path => $RT::BinPath,
129 rt_sbin_path => $RT::SbinPath,
130 rt_site_config => $ENV{'RT_SITE_CONFIG'},
131 load_modules => $info{load_modules},
133 if (not $config{basic_auth}) {
134 $opt{basic_auth} = "";
135 } elsif ($config{basic_auth} eq 'anon') {
136 $opt{basic_auth} = $self->basic_auth_anon;
138 $opt{basic_auth} = $self->basic_auth;
140 foreach (qw(log pid lock)) {
141 $opt{$_ .'_file'} = File::Spec->catfile(
142 "$tmp{'directory'}", "apache.$_"
146 $tmp{'config'}{'apache'} = File::Spec->catfile(
147 "$tmp{'directory'}", "apache.conf"
149 $self->process_in_file(
151 out => $tmp{'config'}{'apache'},
155 $self->fork_exec($info{'executable'}, '-f', $tmp{'config'}{'apache'});
158 while ( !-s $opt{'pid_file'} ) {
164 unless (-e $opt{'pid_file'} and open($pid_fh, '<', $opt{'pid_file'})) {
165 Test::More::BAIL_OUT("Couldn't start apache server, no pid file (unknown error)")
166 unless -e $opt{log_file};
168 open my $log, "<", $opt{log_file};
169 my $error = do {local $/; <$log>};
171 $RT::Logger->error($error) if $error;
172 Test::More::BAIL_OUT("Couldn't start apache server!");
180 Test::More::ok($pid, "Started apache server #$pid");
184 sub apache_server_info {
188 my $bin = $res{'executable'} = $ENV{'RT_TEST_APACHE'}
189 || $self->find_apache_server
190 || Test::More::BAIL_OUT("Couldn't find apache server, use RT_TEST_APACHE");
192 Test::More::BAIL_OUT(
193 "Couldn't find apache modules directory (set APXS= or RT_TEST_APACHE_MODULES=)"
194 ) unless -d $apache_module_prefix;
197 RT::Test::diag("Using '$bin' apache executable for testing");
199 my $info = `$bin -v`;
200 ($res{'version'}) = ($info =~ m{Server\s+version:\s+Apache/(\d+\.\d+)\.});
201 Test::More::BAIL_OUT(
202 "Couldn't figure out version of the server"
203 ) unless $res{'version'};
206 map {s/^\s+//; s/\s+$//; $_}
207 grep $_ !~ /Compiled in modules/i,
208 split /\r*\n/, `$bin -l`
211 Test::More::BAIL_OUT(
212 "Unsupported apache version $res{version}"
213 ) unless exists $MODULES{$res{version}};
215 Test::More::BAIL_OUT(
216 "Unsupported apache variant $res{variant}"
217 ) unless exists $MODULES{$res{version}}{$res{variant}};
219 my @mlist = @{$MODULES{$res{version}}{$res{variant}}};
220 if ($res{basic_auth}) {
221 push @mlist, "auth_basic", "authz_user";
222 push @mlist, $res{basic_auth} eq 'anon' ? "authn_anon" : "authn_file";
225 $res{'load_modules'} = '';
226 foreach my $mod ( @mlist ) {
227 next if grep $_ =~ /^(mod_|)$mod\.c$/, @{ $res{'modules'} };
229 my $so_file = $apache_module_prefix."/mod_".$mod.".so";
230 Test::More::BAIL_OUT( "Couldn't load $mod module (expected in $so_file)" )
232 $res{'load_modules'} .=
233 "LoadModule ${mod}_module $so_file\n";
236 # Apache 2.4 wants to fully-parse a config file when running -V,
237 # because the MPM is no longer compiled-in. Provide a trivial one.
239 my $tmp = File::Temp->new;
240 my ($mpm) = grep {/^mpm_/} @{$MODULES{$res{version}}{$res{variant}}};
241 print $tmp "LoadModule ${mpm}_module $apache_module_prefix/mod_${mpm}.so\n"
243 print $tmp "ErrorLog /dev/null\n";
244 print $tmp "TransferLog /dev/null\n";
246 $info = `$res{executable} -V -f $tmp`;
247 my %opts = ($info =~ m/^\s*-D\s+([A-Z_]+?)(?:="(.*)")$/mg);
248 %res = (%res, %opts);
252 sub find_apache_server {
254 return $_ foreach grep defined,
255 map RT::Test->find_executable($_),
256 qw(httpd apache apache2 apache1);
260 sub apache_mpm_type {
262 my $apache = $self->find_apache_server;
263 my $out = `$apache -l`;
264 if ( $out =~ /^\s*(worker|prefork|event|itk)\.c\s*$/m ) {
273 RT::Test::__disconnect_rt();
275 unless ( defined $pid ) {
276 die "cannot fork: $!";
279 die "can't exec `". join(' ', @_) ."` program: $!";
281 RT::Test::__reconnect_rt();
286 sub process_in_file {
288 my %args = ( in => undef, options => undef, @_ );
290 my $text = RT::Test->file_content( $args{'in'} );
291 while ( my ($opt) = ($text =~ /\%\%(.+?)\%\%/) ) {
292 my $value = $args{'options'}{ lc $opt };
293 die "no value for $opt" unless defined $value;
295 $text =~ s/\%\%\Q$opt\E\%\%/$value/g;
298 my ($out_fh, $out_conf);
299 unless ( $args{'out'} ) {
300 ($out_fh, $out_conf) = tempfile();
302 $out_conf = $args{'out'};
303 open( $out_fh, '>', $out_conf )
304 or die "couldn't open '$out_conf': $!";
309 return ($out_fh, $out_conf);