xref: /openbsd-src/gnu/usr.bin/perl/cpan/Test-Simple/lib/Test2/IPC/Driver.pm (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
15759b3d2Safresh1package Test2::IPC::Driver;
25759b3d2Safresh1use strict;
35759b3d2Safresh1use warnings;
45759b3d2Safresh1
5*5486feefSafresh1our $VERSION = '1.302199';
65759b3d2Safresh1
75759b3d2Safresh1
85759b3d2Safresh1use Carp qw/confess/;
95759b3d2Safresh1use Test2::Util::HashBase qw{no_fatal no_bail};
105759b3d2Safresh1
115759b3d2Safresh1use Test2::API qw/test2_ipc_add_driver/;
125759b3d2Safresh1
135759b3d2Safresh1my %ADDED;
145759b3d2Safresh1sub import {
155759b3d2Safresh1    my $class = shift;
165759b3d2Safresh1    return if $class eq __PACKAGE__;
175759b3d2Safresh1    return if $ADDED{$class}++;
185759b3d2Safresh1    test2_ipc_add_driver($class);
195759b3d2Safresh1}
205759b3d2Safresh1
21f3efcd01Safresh1sub pending { -1 }
22f3efcd01Safresh1sub set_pending { -1 }
235759b3d2Safresh1
245759b3d2Safresh1for my $meth (qw/send cull add_hub drop_hub waiting is_viable/) {
255759b3d2Safresh1    no strict 'refs';
265759b3d2Safresh1    *$meth = sub {
275759b3d2Safresh1        my $thing = shift;
285759b3d2Safresh1        confess "'$thing' did not define the required method '$meth'."
295759b3d2Safresh1    };
305759b3d2Safresh1}
315759b3d2Safresh1
325759b3d2Safresh1# Print the error and call exit. We are not using 'die' cause this is a
335759b3d2Safresh1# catastrophic error that should never be caught. If we get here it
345759b3d2Safresh1# means some serious shit has happened in a child process, the only way
355759b3d2Safresh1# to inform the parent may be to exit false.
365759b3d2Safresh1
375759b3d2Safresh1sub abort {
385759b3d2Safresh1    my $self = shift;
395759b3d2Safresh1    chomp(my ($msg) = @_);
405759b3d2Safresh1
415759b3d2Safresh1    $self->driver_abort($msg) if $self->can('driver_abort');
425759b3d2Safresh1
435759b3d2Safresh1    print STDERR "IPC Fatal Error: $msg\n";
445759b3d2Safresh1    print STDOUT "Bail out! IPC Fatal Error: $msg\n" unless $self->no_bail;
455759b3d2Safresh1
465759b3d2Safresh1    CORE::exit(255) unless $self->no_fatal;
475759b3d2Safresh1}
485759b3d2Safresh1
495759b3d2Safresh1sub abort_trace {
505759b3d2Safresh1    my $self = shift;
515759b3d2Safresh1    my ($msg) = @_;
525759b3d2Safresh1    # Older versions of Carp do not export longmess() function, so it needs to be called with package name
535759b3d2Safresh1    $self->abort(Carp::longmess($msg));
545759b3d2Safresh1}
555759b3d2Safresh1
565759b3d2Safresh11;
575759b3d2Safresh1
585759b3d2Safresh1__END__
595759b3d2Safresh1
605759b3d2Safresh1=pod
615759b3d2Safresh1
625759b3d2Safresh1=encoding UTF-8
635759b3d2Safresh1
645759b3d2Safresh1=head1 NAME
655759b3d2Safresh1
665759b3d2Safresh1Test2::IPC::Driver - Base class for Test2 IPC drivers.
675759b3d2Safresh1
685759b3d2Safresh1=head1 SYNOPSIS
695759b3d2Safresh1
705759b3d2Safresh1    package Test2::IPC::Driver::MyDriver;
715759b3d2Safresh1
725759b3d2Safresh1    use base 'Test2::IPC::Driver';
735759b3d2Safresh1
745759b3d2Safresh1    ...
755759b3d2Safresh1
765759b3d2Safresh1=head1 METHODS
775759b3d2Safresh1
785759b3d2Safresh1=over 4
795759b3d2Safresh1
805759b3d2Safresh1=item $self->abort($msg)
815759b3d2Safresh1
825759b3d2Safresh1If an IPC encounters a fatal error it should use this. This will print the
835759b3d2Safresh1message to STDERR with C<'IPC Fatal Error: '> prefixed to it, then it will
845759b3d2Safresh1forcefully exit 255. IPC errors may occur in threads or processes other than
855759b3d2Safresh1the main one, this method provides the best chance of the harness noticing the
865759b3d2Safresh1error.
875759b3d2Safresh1
885759b3d2Safresh1=item $self->abort_trace($msg)
895759b3d2Safresh1
905759b3d2Safresh1This is the same as C<< $ipc->abort($msg) >> except that it uses
915759b3d2Safresh1C<Carp::longmess> to add a stack trace to the message.
925759b3d2Safresh1
935759b3d2Safresh1=back
945759b3d2Safresh1
955759b3d2Safresh1=head1 LOADING DRIVERS
965759b3d2Safresh1
975759b3d2Safresh1Test2::IPC::Driver has an C<import()> method. All drivers inherit this import
985759b3d2Safresh1method. This import method registers the driver.
995759b3d2Safresh1
1005759b3d2Safresh1In most cases you just need to load the desired IPC driver to make it work. You
1015759b3d2Safresh1should load this driver as early as possible. A warning will be issued if you
1025759b3d2Safresh1load it too late for it to be effective.
1035759b3d2Safresh1
1045759b3d2Safresh1    use Test2::IPC::Driver::MyDriver;
1055759b3d2Safresh1    ...
1065759b3d2Safresh1
1075759b3d2Safresh1=head1 WRITING DRIVERS
1085759b3d2Safresh1
1095759b3d2Safresh1    package Test2::IPC::Driver::MyDriver;
1105759b3d2Safresh1    use strict;
1115759b3d2Safresh1    use warnings;
1125759b3d2Safresh1
1135759b3d2Safresh1    use base 'Test2::IPC::Driver';
1145759b3d2Safresh1
1155759b3d2Safresh1    sub is_viable {
1165759b3d2Safresh1        return 0 if $^O eq 'win32'; # Will not work on windows.
1175759b3d2Safresh1        return 1;
1185759b3d2Safresh1    }
1195759b3d2Safresh1
1205759b3d2Safresh1    sub add_hub {
1215759b3d2Safresh1        my $self = shift;
1225759b3d2Safresh1        my ($hid) = @_;
1235759b3d2Safresh1
1245759b3d2Safresh1        ... # Make it possible to contact the hub
1255759b3d2Safresh1    }
1265759b3d2Safresh1
1275759b3d2Safresh1    sub drop_hub {
1285759b3d2Safresh1        my $self = shift;
1295759b3d2Safresh1        my ($hid) = @_;
1305759b3d2Safresh1
1315759b3d2Safresh1        ... # Nothing should try to reach the hub anymore.
1325759b3d2Safresh1    }
1335759b3d2Safresh1
1345759b3d2Safresh1    sub send {
1355759b3d2Safresh1        my $self = shift;
1365759b3d2Safresh1        my ($hid, $e, $global) = @_;
1375759b3d2Safresh1
1385759b3d2Safresh1        ... # Send the event to the proper hub.
1395759b3d2Safresh1
140f3efcd01Safresh1        # This may notify other procs/threads that there is a pending event.
1415759b3d2Safresh1        Test2::API::test2_ipc_set_pending($uniq_val);
1425759b3d2Safresh1    }
1435759b3d2Safresh1
1445759b3d2Safresh1    sub cull {
1455759b3d2Safresh1        my $self = shift;
1465759b3d2Safresh1        my ($hid) = @_;
1475759b3d2Safresh1
1485759b3d2Safresh1        my @events = ...; # Here is where you get the events for the hub
1495759b3d2Safresh1
1505759b3d2Safresh1        return @events;
1515759b3d2Safresh1    }
1525759b3d2Safresh1
1535759b3d2Safresh1    sub waiting {
1545759b3d2Safresh1        my $self = shift;
1555759b3d2Safresh1
1565759b3d2Safresh1        ... # Notify all listening procs and threads that the main
1575759b3d2Safresh1        ... # process/thread is waiting for them to finish.
1585759b3d2Safresh1    }
1595759b3d2Safresh1
1605759b3d2Safresh1    1;
1615759b3d2Safresh1
1625759b3d2Safresh1=head2 METHODS SUBCLASSES MUST IMPLEMENT
1635759b3d2Safresh1
1645759b3d2Safresh1=over 4
1655759b3d2Safresh1
1665759b3d2Safresh1=item $ipc->is_viable
1675759b3d2Safresh1
1685759b3d2Safresh1This should return true if the driver works in the current environment. This
1695759b3d2Safresh1should return false if it does not. This is a CLASS method.
1705759b3d2Safresh1
1715759b3d2Safresh1=item $ipc->add_hub($hid)
1725759b3d2Safresh1
1735759b3d2Safresh1This is used to alert the driver that a new hub is expecting events. The driver
1745759b3d2Safresh1should keep track of the process and thread ids, the hub should only be dropped
1755759b3d2Safresh1by the proc+thread that started it.
1765759b3d2Safresh1
1775759b3d2Safresh1    sub add_hub {
1785759b3d2Safresh1        my $self = shift;
1795759b3d2Safresh1        my ($hid) = @_;
1805759b3d2Safresh1
1815759b3d2Safresh1        ... # Make it possible to contact the hub
1825759b3d2Safresh1    }
1835759b3d2Safresh1
1845759b3d2Safresh1=item $ipc->drop_hub($hid)
1855759b3d2Safresh1
1865759b3d2Safresh1This is used to alert the driver that a hub is no longer accepting events. The
1875759b3d2Safresh1driver should keep track of the process and thread ids, the hub should only be
1885759b3d2Safresh1dropped by the proc+thread that started it (This is the drivers responsibility
1895759b3d2Safresh1to enforce).
1905759b3d2Safresh1
1915759b3d2Safresh1    sub drop_hub {
1925759b3d2Safresh1        my $self = shift;
1935759b3d2Safresh1        my ($hid) = @_;
1945759b3d2Safresh1
1955759b3d2Safresh1        ... # Nothing should try to reach the hub anymore.
1965759b3d2Safresh1    }
1975759b3d2Safresh1
1985759b3d2Safresh1=item $ipc->send($hid, $event);
1995759b3d2Safresh1
2005759b3d2Safresh1=item $ipc->send($hid, $event, $global);
2015759b3d2Safresh1
2025759b3d2Safresh1Used to send events from the current process/thread to the specified hub in its
2035759b3d2Safresh1process+thread.
2045759b3d2Safresh1
2055759b3d2Safresh1    sub send {
2065759b3d2Safresh1        my $self = shift;
2075759b3d2Safresh1        my ($hid, $e) = @_;
2085759b3d2Safresh1
2095759b3d2Safresh1        ... # Send the event to the proper hub.
2105759b3d2Safresh1
211f3efcd01Safresh1        # This may notify other procs/threads that there is a pending event.
2125759b3d2Safresh1        Test2::API::test2_ipc_set_pending($uniq_val);
2135759b3d2Safresh1    }
2145759b3d2Safresh1
2155759b3d2Safresh1If C<$global> is true then the driver should send the event to all hubs in all
2165759b3d2Safresh1processes and threads.
2175759b3d2Safresh1
2185759b3d2Safresh1=item @events = $ipc->cull($hid)
2195759b3d2Safresh1
2205759b3d2Safresh1Used to collect events that have been sent to the specified hub.
2215759b3d2Safresh1
2225759b3d2Safresh1    sub cull {
2235759b3d2Safresh1        my $self = shift;
2245759b3d2Safresh1        my ($hid) = @_;
2255759b3d2Safresh1
2265759b3d2Safresh1        my @events = ...; # Here is where you get the events for the hub
2275759b3d2Safresh1
2285759b3d2Safresh1        return @events;
2295759b3d2Safresh1    }
2305759b3d2Safresh1
2315759b3d2Safresh1=item $ipc->waiting()
2325759b3d2Safresh1
2335759b3d2Safresh1This is called in the parent process when it is complete and waiting for all
2345759b3d2Safresh1child processes and threads to complete.
2355759b3d2Safresh1
2365759b3d2Safresh1    sub waiting {
2375759b3d2Safresh1        my $self = shift;
2385759b3d2Safresh1
2395759b3d2Safresh1        ... # Notify all listening procs and threads that the main
2405759b3d2Safresh1        ... # process/thread is waiting for them to finish.
2415759b3d2Safresh1    }
2425759b3d2Safresh1
2435759b3d2Safresh1=back
2445759b3d2Safresh1
2455759b3d2Safresh1=head2 METHODS SUBCLASSES MAY IMPLEMENT OR OVERRIDE
2465759b3d2Safresh1
2475759b3d2Safresh1=over 4
2485759b3d2Safresh1
2495759b3d2Safresh1=item $ipc->driver_abort($msg)
2505759b3d2Safresh1
2515759b3d2Safresh1This is a hook called by C<< Test2::IPC::Driver->abort() >>. This is your
2525759b3d2Safresh1chance to cleanup when an abort happens. You cannot prevent the abort, but you
2535759b3d2Safresh1can gracefully except it.
2545759b3d2Safresh1
2555759b3d2Safresh1=back
2565759b3d2Safresh1
2575759b3d2Safresh1=head1 SOURCE
2585759b3d2Safresh1
2595759b3d2Safresh1The source code repository for Test2 can be found at
260*5486feefSafresh1L<https://github.com/Test-More/test-more/>.
2615759b3d2Safresh1
2625759b3d2Safresh1=head1 MAINTAINERS
2635759b3d2Safresh1
2645759b3d2Safresh1=over 4
2655759b3d2Safresh1
2665759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt>
2675759b3d2Safresh1
2685759b3d2Safresh1=back
2695759b3d2Safresh1
2705759b3d2Safresh1=head1 AUTHORS
2715759b3d2Safresh1
2725759b3d2Safresh1=over 4
2735759b3d2Safresh1
2745759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt>
2755759b3d2Safresh1
2765759b3d2Safresh1=back
2775759b3d2Safresh1
2785759b3d2Safresh1=head1 COPYRIGHT
2795759b3d2Safresh1
280256a93a4Safresh1Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>.
2815759b3d2Safresh1
2825759b3d2Safresh1This program is free software; you can redistribute it and/or
2835759b3d2Safresh1modify it under the same terms as Perl itself.
2845759b3d2Safresh1
285*5486feefSafresh1See L<https://dev.perl.org/licenses/>
2865759b3d2Safresh1
2875759b3d2Safresh1=cut
288