summaryrefslogtreecommitdiff
path: root/t/31utils-call-with-escape.t
blob: 973900c66a01fb514e5632c5d4eb15c322dbd9b1 (plain)
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
#!/usr/bin/perl

use strict;
use warnings;

use Test::More;
use Test::Refcount;

use Future;
use Future::Utils qw( call_with_escape );

# call_with_escape normal return
{
   my $ret_f;
   my $f = call_with_escape {
      return $ret_f = Future->new;
   };

   $ret_f->done( "result" );

   ok( $f->is_ready, 'call_with_escape ready after returned future ready' );
   is( scalar $f->get, "result", 'result of call_with_escape' );

   $f = call_with_escape {
      return $ret_f = Future->new;
   };

   $ret_f->fail( "failure" );

   ok( $f->is_ready, 'call_with_escape ready after returned future ready' );
   is( scalar $f->failure, "failure", 'result of call_with_escape' );

   undef $ret_f;
   is_oneref( $f, 'call_with_escape has refcount 1 before EOF' );
}

# call_with_escape synchronous escape
{
   my $f = call_with_escape {
      my $escape = shift;
      $escape->done( "escaped" );
   };

   ok( $f->is_ready, 'call_with_escape ready after synchronous escape' );
   is( scalar $f->get, "escaped", 'result of call_with_escape' );
}

# call_with_escape delayed escape
{
   my $ret_f = Future->new;
   my $inner_f;

   my $f = call_with_escape {
      my $escape = shift;
      return $inner_f = $ret_f->then( sub {
         return $escape->done( "later escape" );
      });
   };

   ok( !$f->is_ready, 'call_with_escape not yet ready before deferral' );

   $ret_f->done;

   ok( $f->is_ready, 'call_with_escape ready after deferral' );
   is( scalar $f->get, "later escape", 'result of call_with_escape' );

   ok( $inner_f->is_cancelled, 'code-returned future cancelled after escape' );
}

done_testing;