#!/usr/bin/perl
use v5.14;
use warnings;
use Test::More;
use Test::Refcount 0.09 import => [qw( is_refcount refcount )];
use Future;
use Future::AsyncAwait;
my $orig_cxstack_ix = Future::AsyncAwait::__cxstack_ix;
my $file = quotemeta __FILE__;
my $errgv_ref = \*@;
async sub identity
{
return await $_[0];
}
async sub func
{
my ( $f, @vals ) = @_;
my $pad = "foo" . ref($f);
my $x = 123;
$x + 1 + [ "a", await identity $f ];
}
# abandoned chain
{
my $f1 = Future->new;
my $fret = func( $f1, 1, 2 );
undef $fret;
pass( 'abandoned chain does not crash' );
}
# abandoned subsequent (RT129303)
{
my $f1 = Future->new;
my $fret = func( $f1, 3, 4 );
undef $fret;
my $warnings = "";
{
local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
$f1->done;
}
pass( 'abandoned subsequent does not crash' );
like( $warnings, qr/^Suspended async sub main::func lost its returning future at $file line \d+/,
'warning from attempted resume' );
}
# abandoned subsequent on anon sub
{
my $f1 = Future->new;
my $fret = (async sub { await $f1 })->();
undef $fret;
my $warnings = "";
{
local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
$f1->done;
}
pass( 'abandoned subsequent does not crash' );
like( $warnings, qr/^Suspended async sub CODE\(0x[0-9a-f]+\) in package main lost its returning future at $file line \d+/,
'warning from attempted resume' );
}
# abandoned foreach loop (RT129320)
{
my $f1 = Future->new;
my $fret = (async sub { foreach my $f ($f1) { await $f } })->();
undef $fret;
pass( "abandoned foreach loop does not crash" );
}
# abandoned local $@
{
my $errsv_refcount = refcount(\$@);
my $errgv_refcount = refcount($errgv_ref);
my $f1 = Future->new;
my $fret = (async sub { local $@; await $f1 })->();
undef $fret;
undef $f1;
pass( "abandoned local \$@ does not crash" );
is_refcount( \$@, $errsv_refcount, '$@ refcount preserved' );
is_refcount( $errgv_ref, $errgv_refcount, '*@ refcount preserved' );
}
is( Future::AsyncAwait::__cxstack_ix, $orig_cxstack_ix,
'cxstack_ix did not grow during the test' );
done_testing;