# 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::TestHarness; use strict; use warnings FATAL => 'all'; use Test::Harness (); use Apache::Test (); use Apache::TestSort (); use Apache::TestTrace; use File::Spec::Functions qw(catfile catdir); use File::Find qw(finddepth); use File::Basename qw(dirname); sub inc_fixup { # use blib unshift @INC, map "blib/$_", qw(lib arch); # fix all relative library locations for (@INC) { $_ = "../$_" unless m,^(/)|([a-f]:),i; } } #skip tests listed in t/SKIP sub skip { my($self, $file) = @_; $file ||= catfile Apache::Test::vars('serverroot'), 'SKIP'; return unless -e $file; my $fh = Symbol::gensym(); open $fh, $file or die "open $file: $!"; my @skip; local $_; while (<$fh>) { chomp; s/^\s+//; s/\s+$//; s/^\#.*//; next unless $_; s/\*/.*/g; push @skip, $_; } close $fh; return join '|', @skip; } #test if all.t would skip tests or not { my $source_lib = ''; sub run_t { my($self, $file) = @_; my $ran = 0; if (Apache::TestConfig::IS_APACHE_TEST_BUILD and !length $source_lib) { # so we can find Apache/Test.pm from both the perl-framework/ # and Apache-Test/ my $top_dir = Apache::Test::vars('top_dir'); foreach my $lib (catfile($top_dir, qw(Apache-Test lib)), catfile($top_dir, qw(.. Apache-Test lib)), catfile($top_dir, 'lib')) { if (-d $lib) { info "adding source lib $lib to \@INC"; $source_lib = qq[-Mlib="$lib"]; last; } } } my $cmd = qq[$^X $source_lib $file]; my $h = Symbol::gensym(); open $h, "$cmd|" or die "open $cmd: $!"; local $_; while (<$h>) { if (/^1\.\.(\d)/) { $ran = $1; last; } } close $h; $ran; } } #if a directory has an all.t test #skip all tests in that directory if all.t prints "1..0\n" sub prune { my($self, @tests) = @_; my(@new_tests, %skip_dirs); foreach my $test (@tests) { next if $test =~ /\.#/; # skip temp emacs files my $dir = dirname $test; if ($test =~ m:\Wall\.t$:) { unless (__PACKAGE__->run_t($test)) { $skip_dirs{$dir} = 1; @new_tests = grep { m:\Wall\.t$: || not $skip_dirs{dirname $_} } @new_tests; push @new_tests, $test; } } elsif (!$skip_dirs{$dir}) { push @new_tests, $test; } } @new_tests; } sub get_tests { my $self = shift; my $args = shift; my @tests = (); my $base = -d 't' ? catdir('t', '.') : '.'; my $ts = $args->{tests} || []; if (@$ts) { for (@$ts) { if (-d $_) { push(@tests, sort <$base/$_/*.t>); } else { $_ .= ".t" unless /\.t$/; push(@tests, $_); } } } else { if ($args->{tdirs}) { push @tests, map { sort <$base/$_/*.t> } @{ $args->{tdirs} }; } else { finddepth(sub { return unless /\.t$/; my $t = catfile $File::Find::dir, $_; my $dotslash = catfile '.', ""; $t =~ s:^\Q$dotslash::; push @tests, $t }, $base); @tests = sort @tests; } } @tests = $self->prune(@tests); if (my $skip = $self->skip) { # Allow / \ and \\ path delimiters in SKIP file $skip =~ s![/\\\\]+![/\\\\]!g; @tests = grep { not /(?:$skip)/ } @tests; } Apache::TestSort->run(\@tests, $args); #when running 't/TEST t/dir' shell tab completion adds a / #dir//foo output is annoying, fix that. s:/+:/:g for @tests; return @tests; } sub run { my $self = shift; my $args = shift || {}; $Test::Harness::verbose ||= $args->{verbose}; if (my(@subtests) = @{ $args->{subtests} || [] }) { $ENV{HTTPD_TEST_SUBTESTS} = "@subtests"; } Test::Harness::runtests($self->get_tests($args, @_)); } 1;