15759b3d2Safresh1use strict;
25759b3d2Safresh1use warnings;
35759b3d2Safresh1
4*de8cc8edSafresh1BEGIN { no warnings 'once'; $main::cleanup1 = bless {}, 'My::Cleanup' }
5*de8cc8edSafresh1
65759b3d2Safresh1use Test2::API qw/context/;
75759b3d2Safresh1
85759b3d2Safresh1my ($LOADED, $INIT);
95759b3d2Safresh1BEGIN {
105759b3d2Safresh1    $INIT   = Test2::API::test2_init_done;
115759b3d2Safresh1    $LOADED = Test2::API::test2_load_done;
125759b3d2Safresh1};
135759b3d2Safresh1
145759b3d2Safresh1use Test2::IPC;
155759b3d2Safresh1use Test2::Tools::Tiny;
165759b3d2Safresh1use Test2::Util qw/get_tid/;
175759b3d2Safresh1my $CLASS = 'Test2::API';
185759b3d2Safresh1
195759b3d2Safresh1# Ensure we do not break backcompat later by removing anything
205759b3d2Safresh1ok(Test2::API->can($_), "$_ method is present") for qw{
215759b3d2Safresh1    context_do
225759b3d2Safresh1    no_context
235759b3d2Safresh1
245759b3d2Safresh1    test2_init_done
255759b3d2Safresh1    test2_load_done
265759b3d2Safresh1
275759b3d2Safresh1    test2_pid
285759b3d2Safresh1    test2_tid
295759b3d2Safresh1    test2_stack
305759b3d2Safresh1    test2_no_wait
31*de8cc8edSafresh1    test2_is_testing_done
325759b3d2Safresh1
335759b3d2Safresh1    test2_add_callback_context_init
345759b3d2Safresh1    test2_add_callback_context_release
355759b3d2Safresh1    test2_add_callback_exit
365759b3d2Safresh1    test2_add_callback_post_load
375759b3d2Safresh1    test2_list_context_init_callbacks
385759b3d2Safresh1    test2_list_context_release_callbacks
395759b3d2Safresh1    test2_list_exit_callbacks
405759b3d2Safresh1    test2_list_post_load_callbacks
415759b3d2Safresh1
425759b3d2Safresh1    test2_ipc
435759b3d2Safresh1    test2_ipc_disable
445759b3d2Safresh1    test2_ipc_disabled
455759b3d2Safresh1    test2_ipc_drivers
465759b3d2Safresh1    test2_ipc_add_driver
475759b3d2Safresh1    test2_ipc_polling
485759b3d2Safresh1    test2_ipc_disable_polling
495759b3d2Safresh1    test2_ipc_enable_polling
505759b3d2Safresh1
515759b3d2Safresh1    test2_formatter
525759b3d2Safresh1    test2_formatters
535759b3d2Safresh1    test2_formatter_add
545759b3d2Safresh1    test2_formatter_set
555759b3d2Safresh1};
565759b3d2Safresh1
575759b3d2Safresh1ok(!$LOADED, "Was not load_done right away");
585759b3d2Safresh1ok(!$INIT, "Init was not done right away");
595759b3d2Safresh1ok(Test2::API::test2_load_done, "We loaded it");
605759b3d2Safresh1
615759b3d2Safresh1# Note: This is a check that stuff happens in an END block.
625759b3d2Safresh1{
635759b3d2Safresh1    {
645759b3d2Safresh1        package FOLLOW;
655759b3d2Safresh1
665759b3d2Safresh1        sub DESTROY {
675759b3d2Safresh1            return if $_[0]->{fixed};
685759b3d2Safresh1            print "not ok - Did not run end ($_[0]->{name})!";
695759b3d2Safresh1            $? = 255;
705759b3d2Safresh1            exit 255;
715759b3d2Safresh1        }
725759b3d2Safresh1    }
735759b3d2Safresh1
745759b3d2Safresh1    our $kill1 = bless {fixed => 0, name => "Custom Hook"}, 'FOLLOW';
755759b3d2Safresh1    Test2::API::test2_add_callback_exit(
765759b3d2Safresh1        sub {
775759b3d2Safresh1            print "# Running END hook\n";
785759b3d2Safresh1            $kill1->{fixed} = 1;
795759b3d2Safresh1        }
805759b3d2Safresh1    );
815759b3d2Safresh1
825759b3d2Safresh1    our $kill2 = bless {fixed => 0, name => "set exit"}, 'FOLLOW';
835759b3d2Safresh1    my $old = Test2::API::Instance->can('set_exit');
845759b3d2Safresh1    no warnings 'redefine';
855759b3d2Safresh1    *Test2::API::Instance::set_exit = sub {
865759b3d2Safresh1        $kill2->{fixed} = 1;
875759b3d2Safresh1        print "# Running set_exit\n";
885759b3d2Safresh1        $old->(@_);
895759b3d2Safresh1    };
905759b3d2Safresh1}
915759b3d2Safresh1
925759b3d2Safresh1ok($CLASS->can('test2_init_done')->(), "init is done.");
935759b3d2Safresh1ok($CLASS->can('test2_load_done')->(), "Test2 is finished loading");
945759b3d2Safresh1
955759b3d2Safresh1is($CLASS->can('test2_pid')->(), $$, "got pid");
965759b3d2Safresh1is($CLASS->can('test2_tid')->(), get_tid(), "got tid");
975759b3d2Safresh1
985759b3d2Safresh1ok($CLASS->can('test2_stack')->(), 'got stack');
995759b3d2Safresh1is($CLASS->can('test2_stack')->(), $CLASS->can('test2_stack')->(), "always get the same stack");
1005759b3d2Safresh1
1015759b3d2Safresh1ok($CLASS->can('test2_ipc')->(), 'got ipc');
1025759b3d2Safresh1is($CLASS->can('test2_ipc')->(), $CLASS->can('test2_ipc')->(), "always get the same IPC");
1035759b3d2Safresh1
1045759b3d2Safresh1is_deeply([$CLASS->can('test2_ipc_drivers')->()], [qw/Test2::IPC::Driver::Files/], "Got driver list");
1055759b3d2Safresh1
1065759b3d2Safresh1# Verify it reports to the correct file/line, there was some trouble with this...
1075759b3d2Safresh1my $file = __FILE__;
1085759b3d2Safresh1my $line = __LINE__ + 1;
1095759b3d2Safresh1my $warnings = warnings { $CLASS->can('test2_ipc_add_driver')->('fake') };
1105759b3d2Safresh1my $sub1 = sub {
1115759b3d2Safresh1like(
1125759b3d2Safresh1    $warnings->[0],
1135759b3d2Safresh1    qr{^IPC driver fake loaded too late to be used as the global ipc driver at \Q$file\E line $line},
1145759b3d2Safresh1    "got warning about adding driver too late"
1155759b3d2Safresh1);
1165759b3d2Safresh1};
1175759b3d2Safresh1if ($] le "5.006002") {
1185759b3d2Safresh1    todo("TODO known to fail on $]", $sub1);
1195759b3d2Safresh1} else {
1205759b3d2Safresh1    $sub1->();
1215759b3d2Safresh1}
1225759b3d2Safresh1
1235759b3d2Safresh1is_deeply([$CLASS->can('test2_ipc_drivers')->()], [qw/fake Test2::IPC::Driver::Files/], "Got updated list");
1245759b3d2Safresh1
1255759b3d2Safresh1ok($CLASS->can('test2_ipc_polling')->(), "Polling is on");
1265759b3d2Safresh1$CLASS->can('test2_ipc_disable_polling')->();
1275759b3d2Safresh1ok(!$CLASS->can('test2_ipc_polling')->(), "Polling is off");
1285759b3d2Safresh1$CLASS->can('test2_ipc_enable_polling')->();
1295759b3d2Safresh1ok($CLASS->can('test2_ipc_polling')->(), "Polling is on");
1305759b3d2Safresh1
1315759b3d2Safresh1ok($CLASS->can('test2_formatter')->(), "Got a formatter");
1325759b3d2Safresh1is($CLASS->can('test2_formatter')->(), $CLASS->can('test2_formatter')->(), "always get the same Formatter (class name)");
1335759b3d2Safresh1
1345759b3d2Safresh1my $ran = 0;
1355759b3d2Safresh1$CLASS->can('test2_add_callback_post_load')->(sub { $ran++ });
1365759b3d2Safresh1is($ran, 1, "ran the post-load");
1375759b3d2Safresh1
1385759b3d2Safresh1like(
1395759b3d2Safresh1    exception { $CLASS->can('test2_formatter_set')->() },
1405759b3d2Safresh1    qr/No formatter specified/,
1415759b3d2Safresh1    "formatter_set requires an argument"
1425759b3d2Safresh1);
1435759b3d2Safresh1
1445759b3d2Safresh1like(
1455759b3d2Safresh1    exception { $CLASS->can('test2_formatter_set')->('fake') },
1465759b3d2Safresh1    qr/Global Formatter already set/,
1475759b3d2Safresh1    "formatter_set doesn't work after initialization",
1485759b3d2Safresh1);
1495759b3d2Safresh1
1505759b3d2Safresh1ok(!$CLASS->can('test2_no_wait')->(), "no_wait is not set");
1515759b3d2Safresh1$CLASS->can('test2_no_wait')->(1);
1525759b3d2Safresh1ok($CLASS->can('test2_no_wait')->(), "no_wait is set");
1535759b3d2Safresh1$CLASS->can('test2_no_wait')->(undef);
1545759b3d2Safresh1ok(!$CLASS->can('test2_no_wait')->(), "no_wait is not set");
1555759b3d2Safresh1
1565759b3d2Safresh1ok($CLASS->can('test2_ipc_wait_enabled')->(), "IPC waiting enabled");
1575759b3d2Safresh1$CLASS->can('test2_ipc_wait_disable')->();
1585759b3d2Safresh1ok(!$CLASS->can('test2_ipc_wait_enabled')->(), "IPC waiting disabled");
1595759b3d2Safresh1$CLASS->can('test2_ipc_wait_enable')->();
1605759b3d2Safresh1ok($CLASS->can('test2_ipc_wait_enabled')->(), "IPC waiting enabled");
1615759b3d2Safresh1
1625759b3d2Safresh1my $pctx;
1635759b3d2Safresh1sub tool_a($;$) {
1645759b3d2Safresh1    Test2::API::context_do {
1655759b3d2Safresh1        my $ctx = shift;
1665759b3d2Safresh1        my ($bool, $name) = @_;
1675759b3d2Safresh1        $pctx = wantarray;
1685759b3d2Safresh1        die "xyz" unless $bool;
1695759b3d2Safresh1        $ctx->ok($bool, $name);
1705759b3d2Safresh1        return unless defined $pctx;
1715759b3d2Safresh1        return (1, 2) if $pctx;
1725759b3d2Safresh1        return 'a';
1735759b3d2Safresh1    } @_;
1745759b3d2Safresh1}
1755759b3d2Safresh1
1765759b3d2Safresh1$pctx = 'x';
1775759b3d2Safresh1tool_a(1, "void context test");
1785759b3d2Safresh1ok(!defined($pctx), "void context");
1795759b3d2Safresh1
1805759b3d2Safresh1my $x = tool_a(1, "scalar context test");
1815759b3d2Safresh1ok(defined($pctx) && $pctx == 0, "scalar context");
1825759b3d2Safresh1is($x, 'a', "got scalar return");
1835759b3d2Safresh1
1845759b3d2Safresh1my @x = tool_a(1, "array context test");
1855759b3d2Safresh1ok($pctx, "array context");
1865759b3d2Safresh1is_deeply(\@x, [1, 2], "Got array return");
1875759b3d2Safresh1
1885759b3d2Safresh1like(
1895759b3d2Safresh1    exception { tool_a(0) },
1905759b3d2Safresh1    qr/^xyz/,
1915759b3d2Safresh1    "got exception"
1925759b3d2Safresh1);
1935759b3d2Safresh1
1945759b3d2Safresh1sub {
1955759b3d2Safresh1    my $outer = context();
1965759b3d2Safresh1    sub {
1975759b3d2Safresh1        my $middle = context();
1985759b3d2Safresh1        is($outer->trace, $middle->trace, "got the same context before calling no_context");
1995759b3d2Safresh1
2005759b3d2Safresh1        Test2::API::no_context {
2015759b3d2Safresh1            my $inner = context();
2025759b3d2Safresh1            ok($inner->trace != $outer->trace, "Got a different context inside of no_context()");
2035759b3d2Safresh1            $inner->release;
2045759b3d2Safresh1        };
2055759b3d2Safresh1
2065759b3d2Safresh1        $middle->release;
2075759b3d2Safresh1    }->();
2085759b3d2Safresh1
2095759b3d2Safresh1    $outer->release;
2105759b3d2Safresh1}->();
2115759b3d2Safresh1
2125759b3d2Safresh1sub {
2135759b3d2Safresh1    my $outer = context();
2145759b3d2Safresh1    sub {
2155759b3d2Safresh1        my $middle = context();
2165759b3d2Safresh1        is($outer->trace, $middle->trace, "got the same context before calling no_context");
2175759b3d2Safresh1
2185759b3d2Safresh1        Test2::API::no_context {
2195759b3d2Safresh1            my $inner = context();
2205759b3d2Safresh1            ok($inner->trace != $outer->trace, "Got a different context inside of no_context({}, hid)");
2215759b3d2Safresh1            $inner->release;
2225759b3d2Safresh1        } $outer->hub->hid;
2235759b3d2Safresh1
2245759b3d2Safresh1        $middle->release;
2255759b3d2Safresh1    }->();
2265759b3d2Safresh1
2275759b3d2Safresh1    $outer->release;
2285759b3d2Safresh1}->();
2295759b3d2Safresh1
2305759b3d2Safresh1sub {
2315759b3d2Safresh1    my @warnings;
2325759b3d2Safresh1    my $outer = context();
2335759b3d2Safresh1    sub {
2345759b3d2Safresh1        my $middle = context();
2355759b3d2Safresh1        is($outer->trace, $middle->trace, "got the same context before calling no_context");
2365759b3d2Safresh1
2375759b3d2Safresh1        local $SIG{__WARN__} = sub { push @warnings => @_ };
2385759b3d2Safresh1        Test2::API::no_context {
2395759b3d2Safresh1            my $inner = context();
2405759b3d2Safresh1            ok($inner->trace != $outer->trace, "Got a different context inside of no_context({}, hid)");
2415759b3d2Safresh1        } $outer->hub->hid;
2425759b3d2Safresh1
2435759b3d2Safresh1        $middle->release;
2445759b3d2Safresh1    }->();
2455759b3d2Safresh1
2465759b3d2Safresh1    $outer->release;
2475759b3d2Safresh1
2485759b3d2Safresh1    is(@warnings, 1, "1 warning");
2495759b3d2Safresh1    like(
2505759b3d2Safresh1        $warnings[0],
2515759b3d2Safresh1        qr/A context appears to have been destroyed without first calling release/,
2525759b3d2Safresh1        "Got warning about unreleased context"
2535759b3d2Safresh1    );
2545759b3d2Safresh1}->();
2555759b3d2Safresh1
2565759b3d2Safresh1
2575759b3d2Safresh1sub {
2585759b3d2Safresh1    my $hub = Test2::Hub->new();
2595759b3d2Safresh1    my $ctx = context(hub => $hub);
2605759b3d2Safresh1    is($ctx->hub,$hub, 'got the hub of context() argument');
2615759b3d2Safresh1    $ctx->release;
2625759b3d2Safresh1}->();
2635759b3d2Safresh1
2645759b3d2Safresh1
2655759b3d2Safresh1my $sub = sub { };
2665759b3d2Safresh1
2675759b3d2Safresh1Test2::API::test2_add_callback_context_acquire($sub);
2685759b3d2Safresh1Test2::API::test2_add_callback_context_init($sub);
2695759b3d2Safresh1Test2::API::test2_add_callback_context_release($sub);
2705759b3d2Safresh1Test2::API::test2_add_callback_exit($sub);
2715759b3d2Safresh1Test2::API::test2_add_callback_post_load($sub);
2725759b3d2Safresh1
2735759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_context_acquire_callbacks()), 1, "got the one instance of the hook");
2745759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_context_init_callbacks()),    1, "got the one instance of the hook");
2755759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_context_release_callbacks()), 1, "got the one instance of the hook");
2765759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_exit_callbacks()),            1, "got the one instance of the hook");
2775759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_post_load_callbacks()),       1, "got the one instance of the hook");
2785759b3d2Safresh1
2795759b3d2Safresh1Test2::API::test2_add_callback_context_acquire($sub);
2805759b3d2Safresh1Test2::API::test2_add_callback_context_init($sub);
2815759b3d2Safresh1Test2::API::test2_add_callback_context_release($sub);
2825759b3d2Safresh1Test2::API::test2_add_callback_exit($sub);
2835759b3d2Safresh1Test2::API::test2_add_callback_post_load($sub);
2845759b3d2Safresh1
2855759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_context_acquire_callbacks()), 2, "got the two instances of the hook");
2865759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_context_init_callbacks()),    2, "got the two instances of the hook");
2875759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_context_release_callbacks()), 2, "got the two instances of the hook");
2885759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_exit_callbacks()),            2, "got the two instances of the hook");
2895759b3d2Safresh1is((grep { $_ == $sub } Test2::API::test2_list_post_load_callbacks()),       2, "got the two instances of the hook");
2905759b3d2Safresh1
291*de8cc8edSafresh1ok(!Test2::API::test2_is_testing_done(), "Testing is not done");
292*de8cc8edSafresh1
2935759b3d2Safresh1done_testing;
2945759b3d2Safresh1
295*de8cc8edSafresh1die "Testing should be done, but it is not!" unless Test2::API::test2_is_testing_done();
296*de8cc8edSafresh1
297*de8cc8edSafresh1{
298*de8cc8edSafresh1    package My::Cleanup;
299*de8cc8edSafresh1
300*de8cc8edSafresh1    sub DESTROY {
301*de8cc8edSafresh1        return if Test2::API::test2_is_testing_done();
302*de8cc8edSafresh1        print "not ok - Testing should be done, but it is not!\n";
303*de8cc8edSafresh1        warn "Testing should be done, but it is not!";
304*de8cc8edSafresh1        eval "END { $? = 255 }; 1" or die $@;
305*de8cc8edSafresh1        exit 255;
306*de8cc8edSafresh1    }
307*de8cc8edSafresh1}
308*de8cc8edSafresh1
309*de8cc8edSafresh1# This should destroy the thing
310*de8cc8edSafresh1END { no warnings 'once'; $main::cleanup2 = bless {}, 'My::Cleanup' }
311