App-Fetchware
view release on metacpan or search on metacpan
lib/Test/Fetchware.pm view on Meta::CPAN
# CPAN modules making Fetchwarefile better.
use File::Temp 'tempdir';
use File::Spec::Functions qw(catfile rel2abs updir tmpdir);
use Test::More 0.98; # some utility test subroutines need it.
use Cwd;
use Archive::Tar;
use Path::Class;
use Digest::MD5;
use Fcntl qw(:flock :mode);
use Perl::OSType 'is_os_type';
use File::Temp 'tempfile';
use File::Path 'remove_tree';
use App::Fetchware::Util ':UTIL';
use App::Fetchware::Config ':CONFIG';
# Enable Perl 6 knockoffs, and use 5.10.1, because smartmatching and other
# things in 5.10 were changed in 5.10.1+.
use 5.010001;
# Set up Exporter to bring App::Fetchware's API to everyone who use's it
# including fetchware's ability to let you rip into its guts, and customize it
# as you need.
use Exporter qw( import );
# By default fetchware exports its configuration file like subroutines and
# fetchware().
#
# These tags go with the override() subroutine, and together allow you to
# replace some or all of fetchware's default behavior to install unusual
# software.
our %EXPORT_TAGS = (
TESTING => [qw(
eval_ok
print_ok
fork_ok
fork_not_ok
skip_all_unless_release_testing
make_clean
make_test_dist
md5sum_file
expected_filename_listing
verbose_on
export_ok
end_ok
add_prefix_if_nonroot
create_test_fetchwarefile
rmdashr_ok
)],
);
# *All* entries in @EXPORT_TAGS must also be in @EXPORT_OK.
our @EXPORT_OK = map {@{$_}} values %EXPORT_TAGS;
sub eval_ok {
my ($code, $expected_exception_text_or_regex, $test_name) = @_;
eval {$code->()};
# Test if an exception was actually thrown.
if (not defined $@) {
BAIL_OUT("[$test_name]'s provided code did not actually throw an exception");
}
# Support regexing the thrown exception's test if needed.
if (ref $expected_exception_text_or_regex ne 'Regexp') {
is($@, $expected_exception_text_or_regex, $test_name);
} elsif (ref $expected_exception_text_or_regex eq 'Regexp') {
like($@, qr/$expected_exception_text_or_regex/, $test_name);
}
}
sub print_ok {
my ($printer, $expected, $test_name) = @_;
my $error;
my $stdout;
# Use eval to catch errors that $printer->() could possibly throw.
eval {
local *STDOUT;
# Turn on Autoflush mode, so each time print is called it causes perl to
# flush STDOUT's buffer. Otherwise a write could happen, that may not
# actually get written before this eval closes, causing $stdout to stay
# undef instead of getting whatever was written to STDOUT.
$| = 1;
open STDOUT, '>', \$stdout
or $error = 'Can\'t open STDOUT to test cmd_upgrade using cmd_list';
# Execute $printer
$printer->();
close STDOUT
or $error = 'WTF! closing STDOUT actually failed! Huh?';
} or do {
$error = $@ if $@;
fail($error) if defined $error;
};
# Since Test::More's testing subroutines return true or false if the test
# passes or fails, return this true or false value back to the caller.
if (ref($expected) eq '') {
return is($stdout, $expected,
$test_name);
} elsif (ref($expected) eq 'Regexp') {
return like($stdout, $expected,
$test_name);
} elsif (ref($expected) eq 'CODE') {
# Call the provided callback with what $printer->() printed.
return ok($expected->($stdout),
$test_name);
}
}
sub fork_ok {
my $coderef = shift;
my $test_name = shift;
my $kid = fork;
die "Couldn't fork: $!\n" if not defined $kid;
# ... parent code here ...
if ( $kid ) {
# Block waiting for the child process ($kid) to exit.
waitpid($kid, 0);
}
# ... child code here ...
else {
# Run caller's code wihtout any args.
# And exit based on the success or failure of $coderef.
$coderef->() ? exit 0 : exit 1;
}
# And test that the child returned successfully.
ok(($? >> 8) == 0, $test_name);
return $?;
lib/Test/Fetchware.pm view on Meta::CPAN
print_ok(sub { some_func_that_prints()},
sub { # a coderef that returns true of some_func_that_prints() printed what it
#should print and returns false if it did not
}, 'checked some_func_that_prints() printed matched coderefs expectations.');
subtest 'some subtest that tests fetchware' => sub {
skip_all_unless_release_testing();
# ... Your tests go here that will be skipped unless
# FETCHWARE_RELEASE_TESTING among other env vars are set properly.
};
make_clean();
my $test_dist_path = make_test_dist(
file_name => $file_name,
ver_num = $ver_num,
# These are all optional...
destination_directory => rel2abs($destination_directory),
fetchwarefile => $fetchwarefile,
# You can only specify fetchwarefile *or* append_option.
append_option => q{fetchware_option 'some value';},
configure => <<EOF,
#!/bin/sh
# A test ./configure for testing ./configure failure...it always fails.
echo "fetchware: ./configure failed!
# Return failure exit status to truly indicate failure.
exit 1
EOF
makefile => <<EOF,
# Test Makefile.
all:
sh -c 'echo "fetchware make failed!"'
EOF
);
my $md5sum_fil_path = md5sum_file($archive_to_md5);
my $expected_filename_listing = expected_filename_listing()
=head1 DESCRIPTION
These subroutines provide miscellaneous subroutines that App::Fetchware's test
suite uses. Some are quite specific such as make_test_dist(), while others are
simple subroutines replacing entire CPAN modules such as eval_ok (similar to
Test::Exception) and print_ok (similar to Test::Output). I wrote them instead of
using the CPAN dependency, because all it would take is a relatively simple
function that I could easily write and test. And their interfaces disagreed with
me.
=head1 TESTING SUBROUTINES
=head2 eval_ok()
eval_ok($code, $expected_exception_text_or_regex, $test_name);
Executes the $code coderef, and compares its thrown exception, C<$@>, to
$expected_exception_text_or_regex, and uses $test_name as the name for the test if
provided.
If $expected_exception_text_or_regex is a string then Test::More's is() is used,
and if $expected_exception_text_or_regex is a C<'Regexp'> according to ref(),
then like() is used, which will treat $expected_exception_text_or_regex as a
regex instead of as just a string.
=head2 print_ok()
print_ok(\&printer, $expected, $test_name);
Tests if $expected is in the output that C<\&printer-E<gt>()> produces on C<STDOUT>.
It passes $test_name along to the underlying L<Test::More> function that it uses
to do the test.
$expected can be a C<SCALAR>, C<Regexp>, or C<CODEREF> as returned by Perl's
L<ref()> function.
=over
=item * If $expected is a SCALAR according to ref()
=over
=item * Then Use eq to determine if the test passes.
=back
=item * If $expected is a Regexp according to ref()
=over
=item * Then use a regex comparision just like Test::More's like() function.
=back
=item * If $expected is a CODEREF according to ref()
=over
=item * Then execute the coderef with a copy of the $printer's STDOUT and use the result of that expression to determine if the test passed or failed .
=back
=back
=over
NOTICE: C<print_ok()'s> manipuation of STDOUT only works for the current Perl
process. STDOUT may be inherited by forks, but for some reason my knowledge of
Perl and Unix lacks a better explanation other than that print_ok() does not
work for testing what C<fork()ed> and C<exec()ed> processes do such as those
executed with run_prog().
I also have not tested other possibilities, such as using IO::Handle to
manipulate STDOUT, or tie()ing STDOUT like Test::Output does. These methods
probably would not survive a fork() and an exec() though either.
lib/Test/Fetchware.pm view on Meta::CPAN
Writes the provided $fetchwarefile_content to a C<Fetchwarefile> inside a
File::Temp::tempfile(), and returns that file's path, $fetchwarefile_path.
=head2 rmdashr_ok()
rmdashr_ok($dir_to_recursive_delete, $test_message)
Recursively deletes the specified directory using L<File::Path>'s remove_tree()
subroutine. Returns nothing, but does call L<Test::More>'s ok() for you with
your $test_message if remove_tree() was successful.
=over
=item NOTE:
rmdashr_ok() reports its test as PASS if I<any> number of files are successfully
deleted. It only reports FAIL if I<no> directories were deleted. L<Test::More>'s
note() is used to print out verbose info about exactly what files were deleted,
any errors, and number or errors/warnings and successfully deleted files are
printed using note(), which only shows the output if prove(1)'s C<-v> switch is
used.
=back
=head1 ERRORS
As with the rest of App::Fetchware, Test::Fetchware does not return any error
codes; instead, all errors are die()'d if it's Test::Fetchware's error, or
croak()'d if its the caller's fault. These exceptions are simple strings, and
usually more than just one line long to help further describe the problem to
make fixing it easier.
=head1 SEE ALSO
L<Test::Exception> is similar to Test::Fetchware's eval_ok().
L<Test::Output> is similar to Test::Fetchware's print_ok().
=head1 AUTHOR
David Yingling <deeelwy@gmail.com>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2016 by David Yingling.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
__END__
##TODO##=head1 DIAGNOSTICS
##TODO##
##TODO##App::Fetchware throws many exceptions. These exceptions are not listed below,
##TODO##because I have not yet added additional information explaining them. This is
##TODO##because fetchware throws very verbose error messages that don't need extra
##TODO##explanation. This section is reserved for when I have to actually add further
##TODO##information regarding one of these exceptions.
##TODO##
##TODO##=cut
( run in 1.733 second using v1.01-cache-2.11-cpan-140bd7fdf52 )