File-AptFetch
view release on metacpan or search on metacpan
t/TestSuite.pm view on Meta::CPAN
=head1 FILES AND DIRECTORIES
=over
=cut
=item B<FAFTS_tempfile()>
use t::TestSuite qw/ :temp /;
$tempfile = FAFTS_tempfile %args;
Creates a temporal file.
This file is scheduled for deletion when test-unit completes.
The file is named:
F<skip_$caller_$nick_XXXX>
Known parameters are:
=over
=item I<$caller>
If unset, reasonable default based on B<caller> return is provided.
=item I<$content>
If set will be fed into just created file.
=item I<$dir>
Requests file to be created in specific directory.
B<cwd()> isa default.
=item I<$nick>
Arbitrary identification what has meaning in calling code.
C<void> isa deafult.
=item I<$suffix>
Obvious.
=item I<$unlink>
If TRUE then just created temporal is removed.
Only filename what's left.
=back
Returns a filename.
Due to I<$args{dir}> defaulting filename is always fully qualified;
probably canonicalized.
A filehandle is implicitly closed.
=cut
my @Tempfiles = ( $$ );
sub FAFTS_tempfile ( % ) {
my %args = @_;
my $fn =
sprintf q|skip_%s_%s_XXXX|,
$args{caller} || ( split m{/}, ( caller )[1])[-1],
$args{nick} || q|void|;
my $fh;
( $fh, $fn ) = tempfile $fn,
DIR => $args{dir} || cwd, SUFFIX => $args{suffix} || '';
push @Tempfiles, $fn;
print $fh $args{content} if $args{content};
unlink $fn or croak qq|[unlink] ($fn): $!| if $args{unlink};
return $fn }
END { unlink @Tempfiles if $$ == shift @Tempfiles }
=item B<FAFTS_tempdir()>
use t::TestSuite qw/ :temp /;
$tempdir = FAFTS_tempdir %args;
Creates a temporal directory.
This directory is scheduled for deletion when test-unit completes.
The directory is named:
F<skip_$caller_$nick_XXXX>.
Known parameters are:
=over
=item I<$caller>
If unset, reasonable default based on B<caller> return is provided.
=item I<$dir>
Overrides default provided by B<File::Temp::tempdir()>.
=item I<$nick>
Arbitrary identification what has meaning in callig code.
C<void> isa default.
=item I<$suffix>
Obvious.
=back
Returns dirname.
If I<$args{dir}> is set, then dirname is expanded to be fully qualified;
no canonicalization.
=cut
sub FAFTS_tempdir ( % ) {
my %args = @_;
my $dn = sprintf q|skip_%s_%s_XXXX|,
$args{caller} || ( split m{/}, ( caller )[1])[-1],
$args{nick} || q|void|;
$dn = tempdir $dn,
DIR => $args{dir}, SUFFIX => $args{suffix}, CLEANUP => 1;
$dn = sprintf q|%s/%s|, cwd, $dn unless $args{dir};
return $dn }
=item B<FAFTS_cat_fn()>
use t::TestSuite qw/ :temp /;
$new_file = FAFTS_cat_fn $new_dir, $old_file;
A helper routine.
Assists with a target filename preparation.
Returns a basename of I<$old_file> concatenated with I<$new_dir>.
B<(note)> Stolen from DFS (should've been done years ago).
=cut
sub FAFTS_cat_fn ( $$ ) { sprintf q|%s/%s|, shift, ( split m{/}, shift )[-1] }
=item B<FAFTS_get_file()>
use t::TestSuite qw/ :file /;
$content = FAFTS_get_file $filename;
Simple file content retriever.
Whatever has been retrieved is passed to L</B<FAFTS_diag()>>.
=cut
sub FAFTS_get_file ( $ ) {
my $fn = shift @_;
open my $fho, q|<|, $fn or croak qq|[open]{r} ($fn): $!|;
read $fho, my $buf, -s $fho;
FAFTS_diag $buf;
open $fho, q|>|, $fn or croak qq|[open]{w} ($fn): $!|;
$buf }
=item B<FAFTS_set_file()>
use t::TestSuite qw/ :file /;
FAFTS_set_file $filename, $content;
Simple file content setter.
I<filename> is set to I<$content>.
Returns a size I<filename> gets
(pretty useles, for simmetry reasons).
If B<open> fails then B<croaks>.
=cut
sub FAFTS_set_file ( $$ ) {
my( $fn, $content ) = @_;
open my $fh, q|>|, $fn or croak qq|[open] ($fn): $!|;
print $fh $content;
-s $fh }
=item B<FAFTS_append_file()>
use t::TestSuite qw/ :file /;
FAFTS_append_file $filename, $content;
Simple file content appender.
I<content> is appended to I<filename>.
Returns a size I<filename> gets
(pretty useles, but whatever).
If B<open> fails then B<croaks>.
=cut
sub FAFTS_append_file ( $$ ) {
my( $fn, $content ) = @_;
open my $fh, q|>>|, $fn or croak qq|[open] ($fn): $!|;
print $fh $content;
-s $fh }
=back
=cut
=head1 METHODS AND WRAPPERS
=over
=cut
=item B<FAFTS_prepare_method()>
use t::TestSuite qw/ :mthd /;
$method = FAFTS_prepare_method
$method_path, $method_name, $stderr_name, @cmds;
Simple method preparation wrapper.
I<method_path> is path where to store prepared wanabe method;
I<method_name> is basename of method template, it's supposed to be in F<./t/>
directory of distribution.
I<stderr_name> is path where I<STDERR> of wanabe method will be redirected
(it'll be stuck at the end of wanabe method)
(defaults to F</dev/null>).
I<@cmds> are commands that will be stuck at the end of wanabe method, just
after I<stderr_name>
(they might be ignored by method itself unless supported).
Returns basename of I<method_path> (courtesy);
that basename can be passed to B<F::AF::init()>
(proper configuration through I<$F::AF::CD{lib_method}> provided).
=cut
sub FAFTS_prepare_method ( $$$@ ) {
my( $fh, $method, $stderr, @cmds ) = ( @_ );
$stderr ||= q|/dev/null|;
# XXX:201403151708:whynot: Can't use B<FAFTS_get_file()> because it will B<diag()> retrieved. And it's not going to change.
open my $fhi, q|<|, qq|t/$method|;
read $fhi, my $buf, -s $fhi;
FAFTS_set_file $fh, <<END_OF_METHOD . join '', map qq|$_\n|, @cmds;
$buf;
__DATA__
$stderr
END_OF_METHOD
chmod 0755, $fh or croak qq|[chmod] ($fh): $!|;
( split m{/}, $fh )[-1] }
=item B<FAFTS_wrap()>
use t::TestSuite qw/ :mthd /;
( $rv, $stderr, $stdout ) = FAFTS_wrap { die q|gotch ya| };
Safety wrapper around code that could B<die> or B<fork>-and-B<die>.
Returns whatever I<code>.
If I<code> fails, then I<$@> is returned.
In list context also returns whatever has been printed
on I<STDERR> and I<STDOUT>.
In either case I<STDERR> and I<STDOUT> are passed to L</B<FAFTS_diag()>>.
=cut
my $root_pid = $$;
sub FAFTS_wrap ( & ) {
require POSIX or die q|<POSIX> is missing\n|;
my $code = shift;
my $stderr = FAFTS_tempfile nick => q|stderr|;
open my $bckerr, q|>&|, \*STDERR or croak qq|push [dup] (STDERR): $!|;
my $stdout = FAFTS_tempfile nick => q|stdout|;
open my $bckout, q|>&|, \*STDOUT or croak qq|push [dup] (STDOUT): $!|;
open STDERR, q|>|, $stderr;
open STDOUT, q|>|, $stdout;
my( $rv, $ee );
eval { $rv = $code->(); 1 } or $ee = $@;
$$ != $root_pid and POSIX::_exit( !!$ee );
open STDERR, q|>&|, $bckerr or croak qq|pop [dup] (STDERR): $!|;
open STDOUT, q|>&|, $bckout or croak qq|pop [dup] (STDOUT): $!|;
$rv = $ee unless defined $rv;
FAFTS_diag !defined $rv ? q|RV: (undef)| :
ref $rv && $rv->isa( q|File::AptFetch| ) ? qq|method: ($rv->{pid})| :
qq|RV: ($rv)|;
$stderr = FAFTS_get_file $stderr;
$stdout = FAFTS_get_file $stdout;
wantarray ? ( $rv, $stderr, $stdout ) : $rv }
=item B<FAFTS_wait_and_gain()>
use t::TestSuite qw/ :mthd /;
( $rv, $stderr ) = FAFTS_wait_and_gain;
Very special wrapper for B<File::AptFetch::gain()>.
Waits ~10sec until any activity happens on a method side.
Then returns whatever B<F::AF::gain()> has returned
(RV is also passed to B<FAFTS_diag()>).
In list context collected I<STDERR> is returned too.
=cut
sub FAFTS_wait_and_gain ( $;$ ) {
my $eng = shift @_;
# XXX:201402232036:whynot: Probably fixes this: http://www.cpantesters.org/cpan/report/b9de484c-9594-11e3-ae04-8631d666d1b8
my $timeout = shift @_ || 20;
my( $rc, $stderr );
my $mark = $eng->{message};
while( 0 < $timeout-- ) {
( run in 0.396 second using v1.01-cache-2.11-cpan-71847e10f99 )