Apache-Test
view release on metacpan or search on metacpan
lib/Apache/TestUtil.pm view on Meta::CPAN
# 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::TestUtil;
use strict;
use warnings FATAL => 'all';
use File::Find ();
use File::Path ();
use Exporter ();
use Carp ();
use Config;
use File::Basename qw(dirname);
use File::Spec::Functions qw(catfile catdir file_name_is_absolute tmpdir);
use Symbol ();
use Fcntl qw(SEEK_END);
use Apache::Test ();
use Apache::TestConfig ();
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %CLEAN);
$VERSION = '0.02';
@ISA = qw(Exporter);
@EXPORT = qw(t_cmp t_debug t_append_file t_write_file t_open_file
t_mkdir t_rmtree t_is_equal t_filepath_cmp t_write_test_lib
t_server_log_error_is_expected t_server_log_warn_is_expected
t_client_log_error_is_expected t_client_log_warn_is_expected
);
@EXPORT_OK = qw(t_write_perl_script t_write_shell_script t_chown
t_catfile_apache t_catfile t_file_watch_for
t_start_error_log_watch t_finish_error_log_watch
t_start_file_watch t_read_file_watch t_finish_file_watch);
%CLEAN = ();
$Apache::TestUtil::DEBUG_OUTPUT = \*STDOUT;
# 5.005's Data::Dumper has problems to dump certain datastructures
use constant HAS_DUMPER => eval { $] >= 5.006 && require Data::Dumper; };
use constant INDENT => 4;
{
my %files;
sub t_start_file_watch (;$) {
my $name = defined $_[0] ? $_[0] : 'error_log';
$name = File::Spec->catfile(Apache::Test::vars->{t_logs}, $name)
unless (File::Spec->file_name_is_absolute($name));
if (open my $fh, '<', $name) {
seek $fh, 0, SEEK_END;
$files{$name} = $fh;
}
else {
delete $files{$name};
}
return;
}
sub t_finish_file_watch (;$) {
my $name = defined $_[0] ? $_[0] : 'error_log';
$name = File::Spec->catfile(Apache::Test::vars->{t_logs}, $name)
unless (File::Spec->file_name_is_absolute($name));
my $fh = delete $files{$name};
unless (defined $fh) {
open $fh, '<', $name or return;
return readline $fh;
}
return readline $fh;
}
sub t_read_file_watch (;$) {
my $name = defined $_[0] ? $_[0] : 'error_log';
$name = File::Spec->catfile(Apache::Test::vars->{t_logs}, $name)
unless (File::Spec->file_name_is_absolute($name));
my $fh = $files{$name};
unless (defined $fh) {
open $fh, '<', $name or return;
$files{$name} = $fh;
}
return readline $fh;
}
sub t_file_watch_for ($$$) {
my ($name, $re, $timeout) = @_;
lib/Apache/TestUtil.pm view on Meta::CPAN
}
sub t_write_shell_script {
my $file = shift;
my $code = join '', @_;
my($ext, $shebang);
if (Apache::TestConfig::WIN32()) {
$code =~ s/echo$/echo./mg; #required to echo newline
$ext = 'bat';
$shebang = "\@echo off\nREM this is a bat";
}
else {
$ext = 'sh';
$shebang = '#!/bin/sh';
}
$file .= ".$ext";
t_write_file($file, "$shebang\n", $code);
$ext;
}
sub t_write_perl_script {
my $file = shift;
my $shebang = "#!$Config{perlpath}\n";
my $warning = Apache::TestConfig->thaw->genwarning($file);
t_write_file($file, $shebang, $warning, @_);
chmod 0755, $file;
}
sub t_mkdir {
my $dir = shift;
makepath($dir);
}
# returns a list of dirs successfully created
sub makepath {
my($path) = @_;
return if !defined($path) || -e $path;
my $full_path = $path;
# remember which dirs were created and should be cleaned up
while (1) {
$CLEAN{dirs}{$path} = 1;
$path = dirname $path;
last if -e $path;
}
return File::Path::mkpath($full_path, 0, 0755);
}
sub t_rmtree {
die "must pass a dirname" unless defined $_[0];
File::Path::rmtree((@_ > 1 ? \@_ : $_[0]), 0, 1);
}
#chown a file or directory to the test User/Group
#noop if chown is unsupported
sub t_chown {
my $file = shift;
my $config = Apache::Test::config();
my($uid, $gid);
eval {
#XXX cache this lookup
($uid, $gid) = (getpwnam($config->{vars}->{user}))[2,3];
};
if ($@) {
if ($@ =~ /^The getpwnam function is unimplemented/) {
#ok if unsupported, e.g. win32
return 1;
}
else {
die $@;
}
}
CORE::chown($uid, $gid, $file) || die "chown $file: $!";
}
# $string = struct_as_string($indent_level, $var);
#
# return any nested datastructure via Data::Dumper or ala Data::Dumper
# as a string. undef() is a valid arg.
#
# $indent_level should be 0 (used for nice indentation during
# recursive datastructure traversal)
sub struct_as_string{
return "???" unless @_ == 2;
my $level = shift;
return "undef" unless defined $_[0];
my $pad = ' ' x (($level + 1) * INDENT);
my $spad = ' ' x ($level * INDENT);
if (HAS_DUMPER) {
local $Data::Dumper::Terse = 1;
$Data::Dumper::Terse = $Data::Dumper::Terse; # warn
my $data = Data::Dumper::Dumper(@_);
$data =~ s/\n$//; # \n is handled by the caller
return $data;
}
else {
if (ref($_[0]) eq 'ARRAY') {
my @data = ();
for my $i (0..$#{ $_[0] }) {
push @data,
struct_as_string($level+1, $_[0]->[$i]);
}
return join "\n", "[", map({"$pad$_,"} @data), "$spad\]";
} elsif ( ref($_[0])eq 'HASH') {
my @data = ();
for my $key (keys %{ $_[0] }) {
push @data,
"$key => " .
struct_as_string($level+1, $_[0]->{$key});
}
return join "\n", "{", map({"$pad$_,"} @data), "$spad\}";
} else {
return $_[0];
}
}
}
my $banner_format =
"\n*** The following %s expected and harmless ***\n";
sub is_expected_banner {
my $type = shift;
my $count = @_ ? shift : 1;
sprintf $banner_format, $count == 1
? "$type entry is"
: "$count $type entries are";
}
sub t_server_log_is_expected {
print STDERR is_expected_banner(@_);
}
lib/Apache/TestUtil.pm view on Meta::CPAN
t_append_file().
This function is exported by default.
=item t_write_shell_script()
Apache::TestUtil::t_write_shell_script($filename, @lines);
Similar to t_write_file() but creates a portable shell/batch
script. The created filename is constructed from C<$filename> and an
appropriate extension automatically selected according to the platform
the code is running under.
It returns the extension of the created file.
=item t_write_perl_script()
Apache::TestUtil::t_write_perl_script($filename, @lines);
Similar to t_write_file() but creates a executable Perl script with
correctly set shebang line.
=item t_open_file()
my $fh = t_open_file($filename);
t_open_file() opens a file I<$filename> for writing and returns the
file handle to the opened file.
If parent directories of C<$filename> don't exist they will be
automagically created.
The generated file will be automatically deleted at the end of the
program's execution.
This function is exported by default.
=item t_mkdir()
t_mkdir($dirname);
t_mkdir() creates a directory I<$dirname>. The operation will fail if
the parent directory doesn't exist.
If parent directories of C<$dirname> don't exist they will be
automagically created.
The generated directory will be automatically deleted at the end of
the program's execution.
This function is exported by default.
=item t_rmtree()
t_rmtree(@dirs);
t_rmtree() deletes the whole directories trees passed in I<@dirs>.
This function is exported by default.
=item t_chown()
Apache::TestUtil::t_chown($file);
Change ownership of $file to the test's I<User>/I<Group>. This
function is noop on platforms where chown(2) is unsupported
(e.g. Win32).
=item t_is_equal()
t_is_equal($a, $b);
t_is_equal() compares any two datastructures and returns 1 if they are
exactly the same, otherwise 0. The datastructures can be nested
hashes, arrays, scalars, undefs or a combination of any of these. See
t_cmp() for an example.
If C<$b> is a regex reference, the regex comparison C<$a =~ $b> is
performed. For example:
t_is_equal($server_version, qr{^Apache});
If comparing non-scalars make sure to pass the references to the
datastructures.
This function is exported by default.
=item t_server_log_error_is_expected()
If the handler's execution results in an error or a warning logged to
the I<error_log> file which is expected, it's a good idea to have a
disclaimer printed before the error itself, so one can tell real
problems with tests from expected errors. For example when testing how
the package behaves under error conditions the I<error_log> file might
be loaded with errors, most of which are expected.
For example if a handler is about to generate a run-time error, this
function can be used as:
use Apache::TestUtil;
...
sub handler {
my $r = shift;
...
t_server_log_error_is_expected();
die "failed because ...";
}
After running this handler the I<error_log> file will include:
*** The following error entry is expected and harmless ***
[Tue Apr 01 14:00:21 2003] [error] failed because ...
When more than one entry is expected, an optional numerical argument,
indicating how many entries to expect, can be passed. For example:
t_server_log_error_is_expected(2);
will generate:
*** The following 2 error entries are expected and harmless ***
If the error is generated at compile time, the logging must be done in
the BEGIN block at the very beginning of the file:
BEGIN {
( run in 0.656 second using v1.01-cache-2.11-cpan-71847e10f99 )