#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
use Future;
use Future::Utils qw( repeat try_repeat try_repeat_until_success );
# foreach without otherwise
{
my $trial_f;
my $arg;
my $future = repeat {
$arg = shift;
return $trial_f = Future->new;
} foreach => [qw( one two three )];
is( $arg, "one", '$arg one for first iteration' );
$trial_f->done;
ok( !$future->is_ready, '$future not ready' );
is( $arg, "two", '$arg two for second iteration' );
$trial_f->done( "another" );
ok( !$future->is_ready, '$future not ready' );
is( $arg, "three", '$arg three for third iteration' );
$trial_f->done( "result" );
ok( $future->is_ready, '$future now ready' );
is( scalar $future->get, "result", '$future->get' );
}
# foreach otherwise
{
my $last_trial_f;
my $future = repeat {
Future->done( "ignore me $_[0]" );
} foreach => [qw( one two three )],
otherwise => sub {
$last_trial_f = shift;
return Future->fail( "Nothing succeeded\n" );
};
is( scalar $future->failure, "Nothing succeeded\n", '$future returns otherwise failure' );
is( scalar $last_trial_f->get, "ignore me three", '$last_trial_f->get' );
$future = repeat {
Future->done( "ignore me" );
} foreach => [],
otherwise => sub { Future->fail( "Nothing to do\n" ) };
is( scalar $future->failure, "Nothing to do\n", '$future returns otherwise failure for empty list' );
}
# foreach on empty list
{
my $future = repeat { die "Not invoked" } foreach => [];
ok( $future->is_ready, 'repeat {} on empty foreach without otherwise already ready' );
is_deeply( [ $future->get ], [], 'Result of empty future' );
$future = repeat { die "Not invoked" } foreach => [],
otherwise => sub { Future->done( 1, 2, 3 ) };
ok( $future->is_ready, 'repeat {} on empty foreach with otherwise already ready' );
is_deeply( [ $future->get ], [ 1, 2, 3 ], 'Result of otherwise future' );
}
# foreach while
{
my $future = try_repeat {
my $arg = shift;
if( $arg eq "bad" ) {
return Future->fail( "bad" );
}
else {
return Future->done( $arg );
}
} foreach => [qw( bad good not-attempted )],
while => sub { shift->failure };
is( scalar $future->get, "good", '$future->get returns correct result for foreach+while' );
}
# foreach until
{
my $future = try_repeat {
my $arg = shift;
if( $arg eq "bad" ) {
return Future->fail( "bad" );
}
else {
return Future->done( $arg );
}
} foreach => [qw( bad good not-attempted )],
until => sub { !shift->failure };
is( scalar $future->get, "good", '$future->get returns correct result for foreach+until' );
}
# foreach while + otherwise
{
my $future = repeat {
Future->done( $_[0] );
} foreach => [ 1, 2, 3 ],
while => sub { $_[0]->get < 2 },
otherwise => sub { Future->fail( "Failed to find 2" ) };
is( scalar $future->get, 2, '$future->get returns successful result from while + otherwise' );
}
# try_repeat_until_success foreach
{
my $future = try_repeat_until_success {
my $arg = shift;
if( $arg eq "bad" ) {
return Future->fail( "bad" );
}
else {
return Future->done( $arg );
}
} foreach => [qw( bad good not-attempted )];
is( scalar $future->get, "good", '$future->get returns correct result for try_repeat_until_success' );
}
# main code dies
{
my $future = try_repeat {
$_[1]->failure if @_ > 1; # absorb the previous failure
die "It failed\n";
} foreach => [ 1, 2, 3 ];
is( $future->failure, "It failed\n", 'repeat foreach failure after code exception' );
}
# otherwise code dies
{
my $future = repeat {
Future->done;
} foreach => [],
otherwise => sub { die "It failed finally\n" };
is( $future->failure, "It failed finally\n", 'repeat foreach failure after otherwise exception' );
}
done_testing;