1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
#!/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;
|