#!/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;