Update Test-Simple to CPAN version 1.302160
authorChris 'BinGOs' Williams <chris@bingosnet.co.uk>
Sat, 19 Jan 2019 10:42:35 +0000 (10:42 +0000)
committerChris 'BinGOs' Williams <chris@bingosnet.co.uk>
Sat, 19 Jan 2019 11:05:14 +0000 (11:05 +0000)
  [DELTA]

1.302160  2019-01-18 11:44:33-08:00 America/Los_Angeles

    - No Changes since last trial release

1.302159  2019-01-09 13:21:37-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Add table support to ctx->fail and ctx->fail_and_return
    - Fix Instance.t on haiku-os

1.302158  2019-01-08 15:36:24-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix TAP test on windows
    - Fix math errors in table indentation
    - Devel requires Term::Table

1.302157  2019-01-08 14:10:29-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix minor typos and missing doc sections
    - Add table support in info facet and TAP formatter

1.302156  2019-01-07 11:13:07-08:00 America/Los_Angeles

    - No changes from last trial

1.302155  2019-01-04 11:25:17-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix test not to fail in non-english locales

1.302154  2019-01-04 10:20:54-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix SHM pid checking for some platforms in Instance.t
    - Add SHM errno/msg to warning about SHM going away

1.302153  2019-01-03 08:39:42-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Improve SHM verification and state awareness

1.302152  2018-12-26 12:21:32-08:00 America/Los_Angeles (TRIAL RELEASE)

    - More Instance.t improvements
    - Add trace to SHM error when possible

1.302151  2018-12-20 11:05:47-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix another locale error in Instance.t

1.302150  2018-12-20 10:57:09-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix locale error in Instance.t
    - Windows test fixes
    - perl 5.6 test fixes

1.302149  2018-12-20 09:47:31-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Even more SHM error improvements

1.302148  2018-12-17 13:08:23-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Further Improve SHM error message

1.302147  2018-12-17 12:59:14-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Improve SHM error message

1.302146  2018-12-17 09:06:44-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix SHM test to work on machines without SHM

1.302145  2018-12-12 11:26:32-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix localization error in new test (#820)

1.302144  2018-12-12 09:51:25-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Add tests for shmwrite fix (#815)

1.302143  2018-12-11 19:10:37-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix failure to check error code on shmwrite (#815)

1.302142  2018-12-11 11:55:22-08:00 America/Los_Angeles (TRIAL RELEASE)

    - Fix #814 Windows fork+test failure
    - Fix #819 Documentation updates
    - Fix #810 Verbose TAP newline regression
    - Fix #817 local $TODO bug
    - Fix #812 Another local $TODO bug
    - Fix #815 shm read warning
    - Merge doc fix PR's from magnolia-k (thanks!)

77 files changed:
MANIFEST
Makefile.SH
Porting/Maintainers.pl
cpan/Test-Simple/lib/Test/Builder.pm
cpan/Test-Simple/lib/Test/Builder/Formatter.pm
cpan/Test-Simple/lib/Test/Builder/Module.pm
cpan/Test-Simple/lib/Test/Builder/Tester.pm
cpan/Test-Simple/lib/Test/Builder/Tester/Color.pm
cpan/Test-Simple/lib/Test/Builder/TodoDiag.pm
cpan/Test-Simple/lib/Test/More.pm
cpan/Test-Simple/lib/Test/Simple.pm
cpan/Test-Simple/lib/Test/Tester.pm
cpan/Test-Simple/lib/Test/Tester/Capture.pm
cpan/Test-Simple/lib/Test/Tester/CaptureRunner.pm
cpan/Test-Simple/lib/Test/Tester/Delegate.pm
cpan/Test-Simple/lib/Test/use/ok.pm
cpan/Test-Simple/lib/Test2.pm
cpan/Test-Simple/lib/Test2/API.pm
cpan/Test-Simple/lib/Test2/API/Breakage.pm
cpan/Test-Simple/lib/Test2/API/Context.pm
cpan/Test-Simple/lib/Test2/API/Instance.pm
cpan/Test-Simple/lib/Test2/API/Stack.pm
cpan/Test-Simple/lib/Test2/Event.pm
cpan/Test-Simple/lib/Test2/Event/Bail.pm
cpan/Test-Simple/lib/Test2/Event/Diag.pm
cpan/Test-Simple/lib/Test2/Event/Encoding.pm
cpan/Test-Simple/lib/Test2/Event/Exception.pm
cpan/Test-Simple/lib/Test2/Event/Fail.pm
cpan/Test-Simple/lib/Test2/Event/Generic.pm
cpan/Test-Simple/lib/Test2/Event/Note.pm
cpan/Test-Simple/lib/Test2/Event/Ok.pm
cpan/Test-Simple/lib/Test2/Event/Pass.pm
cpan/Test-Simple/lib/Test2/Event/Plan.pm
cpan/Test-Simple/lib/Test2/Event/Skip.pm
cpan/Test-Simple/lib/Test2/Event/Subtest.pm
cpan/Test-Simple/lib/Test2/Event/TAP/Version.pm
cpan/Test-Simple/lib/Test2/Event/V2.pm
cpan/Test-Simple/lib/Test2/Event/Waiting.pm
cpan/Test-Simple/lib/Test2/EventFacet.pm
cpan/Test-Simple/lib/Test2/EventFacet/About.pm
cpan/Test-Simple/lib/Test2/EventFacet/Amnesty.pm
cpan/Test-Simple/lib/Test2/EventFacet/Assert.pm
cpan/Test-Simple/lib/Test2/EventFacet/Control.pm
cpan/Test-Simple/lib/Test2/EventFacet/Error.pm
cpan/Test-Simple/lib/Test2/EventFacet/Hub.pm
cpan/Test-Simple/lib/Test2/EventFacet/Info.pm
cpan/Test-Simple/lib/Test2/EventFacet/Info/Table.pm [new file with mode: 0644]
cpan/Test-Simple/lib/Test2/EventFacet/Meta.pm
cpan/Test-Simple/lib/Test2/EventFacet/Parent.pm
cpan/Test-Simple/lib/Test2/EventFacet/Plan.pm
cpan/Test-Simple/lib/Test2/EventFacet/Render.pm
cpan/Test-Simple/lib/Test2/EventFacet/Trace.pm
cpan/Test-Simple/lib/Test2/Formatter.pm
cpan/Test-Simple/lib/Test2/Formatter/TAP.pm
cpan/Test-Simple/lib/Test2/Hub.pm
cpan/Test-Simple/lib/Test2/Hub/Interceptor.pm
cpan/Test-Simple/lib/Test2/Hub/Interceptor/Terminator.pm
cpan/Test-Simple/lib/Test2/Hub/Subtest.pm
cpan/Test-Simple/lib/Test2/IPC.pm
cpan/Test-Simple/lib/Test2/IPC/Driver.pm
cpan/Test-Simple/lib/Test2/IPC/Driver/Files.pm
cpan/Test-Simple/lib/Test2/Tools/Tiny.pm
cpan/Test-Simple/lib/Test2/Transition.pod
cpan/Test-Simple/lib/Test2/Util.pm
cpan/Test-Simple/lib/Test2/Util/ExternalMeta.pm
cpan/Test-Simple/lib/Test2/Util/Facets2Legacy.pm
cpan/Test-Simple/lib/Test2/Util/HashBase.pm
cpan/Test-Simple/lib/Test2/Util/Trace.pm
cpan/Test-Simple/lib/ok.pm
cpan/Test-Simple/t/Test2/acceptance/try_it_fork.t
cpan/Test-Simple/t/Test2/modules/API/Context.t
cpan/Test-Simple/t/Test2/modules/API/Instance.t
cpan/Test-Simple/t/Test2/modules/Formatter/TAP.t
cpan/Test-Simple/t/Test2/modules/IPC/Driver/Files.t
cpan/Test-Simple/t/Test2/regression/ipc_files_abort_exit.t
cpan/Test-Simple/t/regression/812-todo.t [new file with mode: 0644]
cpan/Test-Simple/t/regression/817-subtest-todo.t [new file with mode: 0644]

index 6ea2457..8473d8e 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -2252,6 +2252,7 @@ cpan/Test-Simple/lib/Test2/EventFacet/Control.pm
 cpan/Test-Simple/lib/Test2/EventFacet/Error.pm
 cpan/Test-Simple/lib/Test2/EventFacet/Hub.pm
 cpan/Test-Simple/lib/Test2/EventFacet/Info.pm
+cpan/Test-Simple/lib/Test2/EventFacet/Info/Table.pm
 cpan/Test-Simple/lib/Test2/EventFacet/Meta.pm
 cpan/Test-Simple/lib/Test2/EventFacet/Parent.pm
 cpan/Test-Simple/lib/Test2/EventFacet/Plan.pm
@@ -2441,6 +2442,8 @@ cpan/Test-Simple/t/regression/694_note_diag_return_values.t
 cpan/Test-Simple/t/regression/696-intercept_skip_all.t
 cpan/Test-Simple/t/regression/721-nested-streamed-subtest.t
 cpan/Test-Simple/t/regression/757-reset_in_subtest.t
+cpan/Test-Simple/t/regression/812-todo.t
+cpan/Test-Simple/t/regression/817-subtest-todo.t
 cpan/Test-Simple/t/regression/buffered_subtest_plan_buffered.t
 cpan/Test-Simple/t/regression/builder_does_not_init.t
 cpan/Test-Simple/t/regression/errors_facet.t
index bd0c24f..61b1eeb 100755 (executable)
@@ -1434,29 +1434,30 @@ _cleaner2:
        -rmdir lib/Unicode/Collate/CJK lib/Unicode/Collate lib/Tie/Hash
        -rmdir lib/Thread lib/Text lib/Test2/Util lib/Test2/Tools
        -rmdir lib/Test2/IPC/Driver lib/Test2/IPC lib/Test2/Hub/Interceptor
-       -rmdir lib/Test2/Hub lib/Test2/Formatter lib/Test2/EventFacet
-       -rmdir lib/Test2/Event/TAP lib/Test2/Event lib/Test2/API lib/Test2
-       -rmdir lib/Test/use lib/Test/Tester lib/Test/Builder/Tester
-       -rmdir lib/Test/Builder/IO lib/Test/Builder lib/Test lib/Term
-       -rmdir lib/TAP/Parser/YAMLish lib/TAP/Parser/SourceHandler
-       -rmdir lib/TAP/Parser/Scheduler lib/TAP/Parser/Result
-       -rmdir lib/TAP/Parser/Iterator lib/TAP/Parser lib/TAP/Harness
-       -rmdir lib/TAP/Formatter/File lib/TAP/Formatter/Console
-       -rmdir lib/TAP/Formatter lib/TAP lib/Sys/Syslog lib/Sys lib/Sub
-       -rmdir lib/Search lib/Scalar lib/Pod/Text lib/Pod/Simple
-       -rmdir lib/Pod/Perldoc lib/PerlIO/via lib/PerlIO lib/Perl
-       -rmdir lib/Parse/CPAN lib/Parse lib/Params lib/Net/FTP lib/Module/Load
-       -rmdir lib/Module/CoreList lib/Module lib/Memoize lib/Math/BigInt
-       -rmdir lib/Math/BigFloat lib/Math lib/MIME lib/Locale/Maketext
-       -rmdir lib/Locale lib/List/Util lib/List lib/JSON/PP lib/JSON lib/IPC
-       -rmdir lib/IO/Uncompress/Adapter lib/IO/Uncompress lib/IO/Socket
-       -rmdir lib/IO/Compress/Zlib lib/IO/Compress/Zip lib/IO/Compress/Gzip
-       -rmdir lib/IO/Compress/Base lib/IO/Compress/Adapter lib/IO/Compress
-       -rmdir lib/IO lib/I18N/LangTags lib/I18N lib/Hash/Util lib/Hash
-       -rmdir lib/HTTP lib/Filter/Util lib/Filter lib/File/Spec
-       -rmdir lib/ExtUtils/Typemaps lib/ExtUtils/ParseXS
-       -rmdir lib/ExtUtils/MakeMaker/version lib/ExtUtils/MakeMaker
-       -rmdir lib/ExtUtils/Liblist lib/ExtUtils/Constant lib/ExtUtils/Command
+       -rmdir lib/Test2/Hub lib/Test2/Formatter lib/Test2/EventFacet/Info
+       -rmdir lib/Test2/EventFacet lib/Test2/Event/TAP lib/Test2/Event
+       -rmdir lib/Test2/API lib/Test2 lib/Test/use lib/Test/Tester
+       -rmdir lib/Test/Builder/Tester lib/Test/Builder/IO lib/Test/Builder
+       -rmdir lib/Test lib/Term lib/TAP/Parser/YAMLish
+       -rmdir lib/TAP/Parser/SourceHandler lib/TAP/Parser/Scheduler
+       -rmdir lib/TAP/Parser/Result lib/TAP/Parser/Iterator lib/TAP/Parser
+       -rmdir lib/TAP/Harness lib/TAP/Formatter/File
+       -rmdir lib/TAP/Formatter/Console lib/TAP/Formatter lib/TAP
+       -rmdir lib/Sys/Syslog lib/Sys lib/Sub lib/Search lib/Scalar
+       -rmdir lib/Pod/Text lib/Pod/Simple lib/Pod/Perldoc lib/PerlIO/via
+       -rmdir lib/PerlIO lib/Perl lib/Parse/CPAN lib/Parse lib/Params
+       -rmdir lib/Net/FTP lib/Module/Load lib/Module/CoreList lib/Module
+       -rmdir lib/Memoize lib/Math/BigInt lib/Math/BigFloat lib/Math lib/MIME
+       -rmdir lib/Locale/Maketext lib/Locale lib/List/Util lib/List
+       -rmdir lib/JSON/PP lib/JSON lib/IPC lib/IO/Uncompress/Adapter
+       -rmdir lib/IO/Uncompress lib/IO/Socket lib/IO/Compress/Zlib
+       -rmdir lib/IO/Compress/Zip lib/IO/Compress/Gzip lib/IO/Compress/Base
+       -rmdir lib/IO/Compress/Adapter lib/IO/Compress lib/IO
+       -rmdir lib/I18N/LangTags lib/I18N lib/Hash/Util lib/Hash lib/HTTP
+       -rmdir lib/Filter/Util lib/Filter lib/File/Spec lib/ExtUtils/Typemaps
+       -rmdir lib/ExtUtils/ParseXS lib/ExtUtils/MakeMaker/version
+       -rmdir lib/ExtUtils/MakeMaker lib/ExtUtils/Liblist
+       -rmdir lib/ExtUtils/Constant lib/ExtUtils/Command
        -rmdir lib/ExtUtils/CBuilder/Platform/Windows
        -rmdir lib/ExtUtils/CBuilder/Platform lib/ExtUtils/CBuilder
        -rmdir lib/Exporter lib/Encode/Unicode lib/Encode/MIME/Header
index 453d2d9..776b088 100755 (executable)
@@ -1050,7 +1050,7 @@ use File::Glob qw(:case);
     },
 
     'Test::Simple' => {
-        'DISTRIBUTION' => 'EXODIST/Test-Simple-1.302141.tar.gz',
+        'DISTRIBUTION' => 'EXODIST/Test-Simple-1.302160.tar.gz',
         'FILES'        => q[cpan/Test-Simple],
         'EXCLUDED'     => [
             qr{^examples/},
index ee89441..933b725 100644 (file)
@@ -4,7 +4,7 @@ use 5.006;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN {
     if( $] < 5.008 ) {
@@ -64,18 +64,13 @@ sub _add_ts_hooks {
         $todo = ${"$cpkg\::TODO"} if $cpkg;
         $todo = ${"$epkg\::TODO"} if $epkg && !$todo;
 
-        return $e unless $todo;
+        return $e unless defined $todo;
 
         # Turn a diag into a todo diag
         return Test::Builder::TodoDiag->new(%$e) if ref($e) eq 'Test2::Event::Diag';
 
-        if ($active_hub == $hub) {
-            $e->set_todo($todo) if $e->can('set_todo');
-            $e->add_amnesty({tag => 'TODO', details => $todo});
-        }
-        else {
-            $e->add_amnesty({tag => 'TODO', details => $todo, inherited => 1});
-        }
+        $e->set_todo($todo) if $e->can('set_todo');
+        $e->add_amnesty({tag => 'TODO', details => $todo});
 
         # Set todo on ok's
         if ($e->isa('Test2::Event::Ok')) {
@@ -2578,7 +2573,17 @@ L<Test::Exception> and L<Test::Differences> all use Test::Builder.
 
 =head1 SEE ALSO
 
-L<Test::Simple>, L<Test::More>, L<Test::Harness>
+=head2 INTERNALS
+
+L<Test2>, L<Test2::API>
+
+=head2 LEGACY
+
+L<Test::Simple>, L<Test::More>
+
+=head2 EXTERNAL
+
+L<Test::Harness>
 
 =head1 AUTHORS
 
index 33ccaf8..c73160f 100644 (file)
@@ -2,7 +2,7 @@ package Test::Builder::Formatter;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::Formatter::TAP; our @ISA = qw(Test2::Formatter::TAP) }
 
@@ -95,7 +95,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 1efb6f7..46e863b 100644 (file)
@@ -7,7 +7,7 @@ use Test::Builder;
 require Exporter;
 our @ISA = qw(Exporter);
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 =head1 NAME
index 4eb9bf9..2bdf6d3 100644 (file)
@@ -1,7 +1,7 @@
 package Test::Builder::Tester;
 
 use strict;
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Test::Builder;
 use Symbol;
index b452847..d3fc0fb 100644 (file)
@@ -1,7 +1,7 @@
 package Test::Builder::Tester::Color;
 
 use strict;
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 require Test::Builder::Tester;
 
index d321f70..2f8c97e 100644 (file)
@@ -2,7 +2,7 @@ package Test::Builder::TodoDiag;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::Event::Diag; our @ISA = qw(Test2::Event::Diag) }
 
@@ -58,7 +58,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 48eaf93..e716031 100644 (file)
@@ -17,7 +17,7 @@ sub _carp {
     return warn @_, " at $file line $line\n";
 }
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Test::Builder::Module;
 our @ISA    = qw(Test::Builder::Module);
@@ -95,8 +95,10 @@ Test::More - yet another framework for writing test scripts
 =head1 DESCRIPTION
 
 B<STOP!> If you're just getting started writing tests, have a look at
-L<Test::Simple> first.  This is a drop in replacement for Test::Simple
-which you can switch to once you get the hang of basic testing.
+L<Test2::Suite> first.
+
+This is a drop in replacement for Test::Simple which you can switch to once you
+get the hang of basic testing.
 
 The purpose of this module is to provide a wide range of testing
 utilities.  Various ways to say "ok" with better diagnostics,
@@ -1918,6 +1920,8 @@ magic side-effects are kept to a minimum.  WYSIWYG.
 
 =head2 ALTERNATIVES
 
+L<Test2::Suite> is the most recent and modern set of tools for testing.
+
 L<Test::Simple> if all this confuses you and you just want to write
 some tests.  You can upgrade to Test::More later (it's forward
 compatible).
@@ -1926,15 +1930,6 @@ L<Test::Legacy> tests written with Test.pm, the original testing
 module, do not play well with other testing libraries.  Test::Legacy
 emulates the Test.pm interface and does play well with others.
 
-=head2 TESTING FRAMEWORKS
-
-L<Fennec> The Fennec framework is a testers toolbox. It uses L<Test::Builder>
-under the hood. It brings enhancements for forking, defining state, and
-mocking. Fennec enhances several modules to work better together than they
-would if you loaded them individually on your own.
-
-L<Fennec::Declare> Provides enhanced (L<Devel::Declare>) syntax for Fennec.
-
 =head2 ADDITIONAL LIBRARIES
 
 L<Test::Differences> for more ways to test complex data structures.
index b44def7..e334592 100644 (file)
@@ -4,7 +4,7 @@ use 5.006;
 
 use strict;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Test::Builder::Module;
 our @ISA    = qw(Test::Builder::Module);
index 2d0404a..e0af629 100644 (file)
@@ -18,7 +18,7 @@ require Exporter;
 
 use vars qw( @ISA @EXPORT );
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 @EXPORT = qw( run_tests check_tests check_test cmp_results show_space );
 @ISA = qw( Exporter );
index abc8c5b..9b021f6 100644 (file)
@@ -2,7 +2,7 @@ use strict;
 
 package Test::Tester::Capture;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Test::Builder;
index ed090c2..20f00fe 100644 (file)
@@ -3,7 +3,7 @@ use strict;
 
 package Test::Tester::CaptureRunner;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Test::Tester::Capture;
index 3e0c7a7..88439a1 100644 (file)
@@ -3,7 +3,7 @@ use warnings;
 
 package Test::Tester::Delegate;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Scalar::Util();
 
index 35ac9b1..ca0e178 100644 (file)
@@ -1,7 +1,7 @@
 package Test::use::ok;
 use 5.005;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 __END__
index 648a2e0..54f29f8 100644 (file)
@@ -2,7 +2,7 @@ package Test2;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 1;
@@ -203,7 +203,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 5e176fc..1c97df7 100644 (file)
@@ -9,7 +9,7 @@ BEGIN {
     $ENV{TEST2_ACTIVE} = 1;
 }
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 my $INST;
@@ -1590,7 +1590,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 6a2230b..29f47f0 100644 (file)
@@ -2,7 +2,7 @@ package Test2::API::Breakage;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Test2::Util qw/pkg_to_file/;
@@ -168,7 +168,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index b954626..030348a 100644 (file)
@@ -2,7 +2,7 @@ package Test2::API::Context;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Carp qw/confess croak/;
@@ -325,7 +325,15 @@ sub fail {
         "Test2::Event::Fail"
     );
 
-    $e->add_info({tag => 'DIAG', debug => 1, details => $_}) for @diag;
+    for my $msg (@diag) {
+        if (ref($msg) eq 'Test2::EventFacet::Info::Table') {
+            $e->add_info({tag => 'DIAG', debug => 1, $msg->info_args});
+        }
+        else {
+            $e->add_info({tag => 'DIAG', debug => 1, details => $msg});
+        }
+    }
+
     $self->{+HUB}->send($e);
     return $e;
 }
@@ -342,7 +350,15 @@ sub fail_and_release {
         "Test2::Event::Fail"
     );
 
-    $e->add_info({tag => 'DIAG', debug => 1, details => $_}) for @diag;
+    for my $msg (@diag) {
+        if (ref($msg) eq 'Test2::EventFacet::Info::Table') {
+            $e->add_info({tag => 'DIAG', debug => 1, $msg->info_args});
+        }
+        else {
+            $e->add_info({tag => 'DIAG', debug => 1, details => $msg});
+        }
+    }
+
     $self->{+HUB}->send($e);
     $self->release;
     return 0;
@@ -490,7 +506,14 @@ should always use C<context()> which is exported by the L<Test2::API> module.
     sub my_ok {
         my ($bool, $name) = @_;
         my $ctx = context();
-        $ctx->ok($bool, $name);
+
+        if ($bool) {
+            $ctx->pass($name);
+        }
+        else {
+            $ctx->fail($name);
+        }
+
         $ctx->release; # You MUST do this!
         return $bool;
     }
@@ -715,6 +738,10 @@ write more clear and compact code.
 This lets you send an L<Test2::Event::Fail> event. You may optionally provide a
 C<$name> and C<@diagnostics> messages.
 
+Diagnostics messages can be simple strings, data structures, or instances of
+L<Test2::EventFacet::Info::Table> (which are converted inline into the
+L<Test2::EventFacet::Info> structure).
+
 =item my $false = $ctx->fail_and_release()
 
 =item my $false = $ctx->fail_and_release($name)
@@ -760,7 +787,8 @@ failure. If you do not want automatic diagnostics you should use the
 C<send_event()> method directly.
 
 The third argument C<\@on_fail>) is an optional set of diagnostics to be sent in
-the event of a test failure.
+the event of a test failure. Unlike with C<fail()> these diagnostics must be
+plain strings, data structures are not supported.
 
 =item $event = $ctx->note($message)
 
@@ -975,7 +1003,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 0764e60..0b0e805 100644 (file)
@@ -2,7 +2,7 @@ package Test2::API::Instance;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 our @CARP_NOT = qw/Test2::API Test2::API::Instance Test2::IPC::Driver Test2::Formatter/;
@@ -33,6 +33,7 @@ use Test2::Util::HashBase qw{
     ipc_drivers
     ipc_timeout
     formatters
+    _shm_warned
 
     exit_callbacks
     post_load_callbacks
@@ -368,16 +369,22 @@ sub enable_ipc_polling {
             return unless $self->{+IPC_POLLING};
             return $_[0]->{hub}->cull unless $self->{+IPC_SHM_ID};
 
+            # You may notice that we are not handling the error case of shmread
+            # returning false. In the case where SHM returns false it falls
+            # through to the call to 'cull'. shmread is used as an optimization
+            # to avoid needing to call cull() too often. In the case of failure
+            # the optimization fails and we call 'cull' more often than needed,
+            # this is slower, but completely safe.
             my $val;
             if(shmread($self->{+IPC_SHM_ID}, $val, 0, $self->{+IPC_SHM_SIZE})) {
                 return if $val eq $self->{+IPC_SHM_LAST};
                 $self->{+IPC_SHM_LAST} = $val;
-            }
-            else {
-                warn "SHM Read error: $!\n";
+                return $_[0]->{hub}->cull;
             }
 
-            $_[0]->{hub}->cull;
+            # Do not come back if shm is gone.
+            delete $self->{+IPC_SHM_ID};
+            return;
         }
     ) unless defined $self->ipc_polling;
 
@@ -427,6 +434,7 @@ sub ipc_free_shm {
     my $id = delete $self->{+IPC_SHM_ID};
     return unless defined $id;
 
+    $self->{+IPC}->stop_shm() if $self->{+IPC} && $self->{+IPC}->can('stop_shm');
     shmctl($id, IPC::SysV::IPC_RMID(), 0);
 }
 
@@ -434,10 +442,22 @@ sub get_ipc_pending {
     my $self = shift;
     return -1 unless defined $self->{+IPC_SHM_ID};
     my $val;
-    shmread($self->{+IPC_SHM_ID}, $val, 0, $self->{+IPC_SHM_SIZE}) or return -1;
-    return 0 if $val eq $self->{+IPC_SHM_LAST};
-    $self->{+IPC_SHM_LAST} = $val;
-    return 1;
+
+    if (shmread($self->{+IPC_SHM_ID}, $val, 0, $self->{+IPC_SHM_SIZE})) {
+        return 0 if $val eq $self->{+IPC_SHM_LAST};
+        $self->{+IPC_SHM_LAST} = $val;
+        return 1;
+    }
+
+    $self->{+IPC}->stop_shm() if $self->{+IPC} && $self->{+IPC}->can('stop_shm');
+    delete $self->{+IPC_SHM_ID};
+    return -1;
+}
+
+sub _check_pid {
+    my $self = shift;
+    my ($pid) = @_;
+    return kill(0, $pid);
 }
 
 sub set_ipc_pending {
@@ -450,7 +470,53 @@ sub set_ipc_pending {
     confess "value is required for set_ipc_pending"
         unless $val;
 
-    shmwrite($self->{+IPC_SHM_ID}, $val, 0, $self->{+IPC_SHM_SIZE});
+    return if shmwrite($self->{+IPC_SHM_ID}, $val, 0, $self->{+IPC_SHM_SIZE});
+    my $errno = 0 + $!;
+    my $err = "$!";
+
+    # Do not come back if shm is gone.
+    my $id = delete $self->{+IPC_SHM_ID};
+
+    my $ppid = defined $self->{+_PID} ? $self->{+_PID} : '?';
+    my $ptid = defined $self->{+_TID} ? $self->{+_TID} : '?';
+    my $cpid = $$;
+    my $ctid = get_tid();
+
+    my $shm_stopped = $self->{+IPC} && $self->{+IPC}->can('shm_stopped') && $self->{+IPC}->shm_stopped || 0;
+
+    if (defined($self->{+_PID}) && ($ppid == $$ || $self->_check_pid($ppid)) && !$shm_stopped) {
+        return if $self->{+_SHM_WARNED}++;
+
+        my $warn = "($$) It looks like SHM has gone away unexpectedly ($errno: $err). The parent process is still active. This is not fatal, but may slow things down slightly.";
+        $warn = Carp::longmess($warn) if Carp->can('longmess');
+        warn $warn;
+        return;
+    }
+
+    chomp(my $msg = <<"    EOT");
+IPC shmwrite($id, '$val', 0, $self->{+IPC_SHM_SIZE}) failed, the parent process appears to have exited. This is a fatal error.
+  Error: ($errno) $err
+  Parent  PID: $ppid
+  Current PID: $cpid
+  Parent  TID: $ptid
+  Current TID: $ctid
+  SHM State:   $shm_stopped
+  IPC errors like this usually indicate a race condition in a test where the
+  parent thread/process is allowed to exit before all child processes/threads
+  are complete.
+  Trace:
+    EOT
+    $self->_fatal_error($msg);
+}
+
+sub _fatal_error {
+    my $self = shift;
+    my ($msg) = @_;
+
+    $msg = Carp::longmess($msg) if Carp->can('longmess');
+
+    print STDERR $msg;
+    CORE::exit(255);
 }
 
 sub disable_ipc_polling {
@@ -525,8 +591,9 @@ sub DESTROY {
     return unless defined($self->{+_PID}) && $self->{+_PID} == $$;
     return unless defined($self->{+_TID}) && $self->{+_TID} == get_tid();
 
+    $self->{+IPC}->stop_shm() if $self->{+IPC} && $self->{+IPC}->can('stop_shm');
     shmctl($self->{+IPC_SHM_ID}, IPC::SysV::IPC_RMID(), 0)
-        if defined $self->{+IPC_SHM_ID};
+        if defined $self->{+IPC_SHM_ID} && IPC::SysV->can('IPC_RMID');
 }
 
 sub set_exit {
@@ -906,7 +973,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 6739145..45119dc 100644 (file)
@@ -2,7 +2,7 @@ package Test2::API::Stack;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Test2::Hub();
@@ -210,7 +210,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 70fa080..d051103 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Scalar::Util qw/blessed reftype/;
 use Carp qw/croak/;
@@ -768,7 +768,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 89a0713..0ba7866 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Bail;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 BEGIN { require Test2::Event; our @ISA = qw(Test2::Event) }
@@ -99,7 +99,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 4ead7a2..419f200 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Diag;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 BEGIN { require Test2::Event; our @ISA = qw(Test2::Event) }
@@ -89,7 +89,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index dd4364a..9cfedd3 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Encoding;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Carp qw/croak/;
 
@@ -87,7 +87,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 307688d..21a9269 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Exception;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 BEGIN { require Test2::Event; our @ISA = qw(Test2::Event) }
@@ -103,7 +103,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index c6cf834..98f7eaf 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Fail;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Test2::EventFacet::Info;
 
@@ -108,7 +108,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 9acd5f8..86ed00b 100644 (file)
@@ -5,7 +5,7 @@ use warnings;
 use Carp qw/croak/;
 use Scalar::Util qw/reftype/;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::Event; our @ISA = qw(Test2::Event) }
 use Test2::Util::HashBase;
@@ -270,7 +270,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 6d77eb2..c8903ae 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Note;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 BEGIN { require Test2::Event; our @ISA = qw(Test2::Event) }
@@ -87,7 +87,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index c635bbb..66cd5ea 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Ok;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 BEGIN { require Test2::Event; our @ISA = qw(Test2::Event) }
@@ -152,7 +152,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index b65aa8f..0a49207 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Pass;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Test2::EventFacet::Info;
 
@@ -104,7 +104,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 435353c..8273d29 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Plan;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 BEGIN { require Test2::Event; our @ISA = qw(Test2::Event) }
@@ -159,7 +159,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 36b41d2..63e2bb7 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Skip;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 BEGIN { require Test2::Event::Ok; our @ISA = qw(Test2::Event::Ok) }
@@ -117,7 +117,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 430703b..b499341 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Subtest;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::Event::Ok; our @ISA = qw(Test2::Event::Ok) }
 use Test2::Util::HashBase qw{subevents buffered subtest_id subtest_uuid};
@@ -150,7 +150,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index f814a11..429eca9 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::TAP::Version;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Carp qw/croak/;
 
@@ -91,7 +91,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index b6462b0..773914f 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::V2;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Scalar::Util qw/reftype/;
 use Carp qw/croak/;
@@ -228,7 +228,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 1d9f1f7..459d11d 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Event::Waiting;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 BEGIN { require Test2::Event; our @ISA = qw(Test2::Event) }
@@ -66,7 +66,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 0bcf6e4..da4d5ba 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Test2::Util::HashBase qw/-details/;
 use Carp qw/croak/;
@@ -83,7 +83,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 04bdaf9..b1c9d3f 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::About;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::EventFacet; our @ISA = qw(Test2::EventFacet) }
 use Test2::Util::HashBase qw{ -package -no_display -uuid -eid };
@@ -82,7 +82,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index e1af0c2..a828bde 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Amnesty;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 sub is_list { 1 }
 
@@ -81,7 +81,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 1ad411d..3db30dd 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Assert;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::EventFacet; our @ISA = qw(Test2::EventFacet) }
 use Test2::Util::HashBase qw{ -pass -no_debug -number };
@@ -83,7 +83,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 7da7a0c..5cf9f2e 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Control;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::EventFacet; our @ISA = qw(Test2::EventFacet) }
 use Test2::Util::HashBase qw{ -global -terminate -halt -has_callback -encoding };
@@ -90,7 +90,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 3ccdc89..b7d131f 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Error;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 sub facet_key { 'errors' }
 sub is_list { 1 }
@@ -83,7 +83,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index d594971..20bcf6a 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Hub;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 sub is_list { 1 }
 sub facet_key { 'hubs' }
@@ -99,7 +99,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 1a8e085..3087f4e 100644 (file)
@@ -2,12 +2,12 @@ package Test2::EventFacet::Info;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 sub is_list { 1 }
 
 BEGIN { require Test2::EventFacet; our @ISA = qw(Test2::EventFacet) }
-use Test2::Util::HashBase qw{-tag -debug -important};
+use Test2::Util::HashBase qw{-tag -debug -important -table};
 
 1;
 
@@ -42,6 +42,36 @@ Human readable string or data structure, this is the information to display.
 Formatters are free to render the structures however they please. This may
 contain a blessed object.
 
+If the C<table> attribute (see below) is set then a renderer may choose to
+display the table instead of the details.
+
+=item $structure = $info->{table}
+
+=item $structure = $info->table()
+
+If the data the C<info> facet needs to convey can be represented as a table
+then the data may be placed in this attribute in a more raw form for better
+display. The data must also be represented in the C<details> attribute for
+renderers which do not support rendering tables directly.
+
+The table structure:
+
+    my %table = {
+        header => [ 'column 1 header', 'column 2 header', ... ], # Optional
+
+        rows => [
+            ['row 1 column 1', 'row 1, column 2', ... ],
+            ['row 2 column 1', 'row 2, column 2', ... ],
+            ...
+        ],
+
+        # Allow the renderer to hide empty columns when true, Optional
+        collapse => $BOOL,
+
+        # List by name or number columns that should never be collapsed
+        no_collapse => \@LIST,
+    }
+
 =item $short_string = $info->{tag}
 
 =item $short_string = $info->tag()
@@ -92,7 +122,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
diff --git a/cpan/Test-Simple/lib/Test2/EventFacet/Info/Table.pm b/cpan/Test-Simple/lib/Test2/EventFacet/Info/Table.pm
new file mode 100644 (file)
index 0000000..64bd955
--- /dev/null
@@ -0,0 +1,142 @@
+package Test2::EventFacet::Info::Table;
+use strict;
+use warnings;
+
+use Carp qw/confess/;
+
+use Test2::Util::HashBase qw{-header -rows -collapse -no_collapse -as_string};
+
+sub init {
+    my $self = shift;
+
+    confess "Table may not be empty" unless ref($self->{+ROWS}) eq 'ARRAY' && @{$self->{+ROWS}};
+
+    $self->{+AS_STRING} ||= '<TABLE NOT DISPLAYED>';
+}
+
+sub as_hash { my $out = +{%{$_[0]}}; delete $out->{as_string}; $out }
+
+sub info_args {
+    my $self = shift;
+
+    my $hash = $self->as_hash;
+    my $desc = $self->as_string;
+
+    return (table => $hash, details => $desc);
+}
+
+1;
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Test2::EventFacet::Info::Table - Intermediary representation of a table.
+
+=head1 DESCRIPTION
+
+Intermediary representation of a table for use in specialized
+L<Test::API::Context> methods which generate L<Test2::EventFacet::Info> facets.
+
+=head1 SYNOPSIS
+
+    use Test2::EventFacet::Info::Table;
+    use Test2::API qw/context/;
+
+    sub my_tool {
+        my $ctx = context();
+
+        ...
+
+        $ctx->fail(
+            $name,
+            "failure diag message",
+            Test2::EventFacet::Info::Table->new(
+                # Required
+                rows => [['a', 'b'], ['c', 'd'], ...],
+
+                # Strongly Recommended
+                as_string => "... string to print when table cannot be rendered ...",
+
+                # Optional
+                header => ['col1', 'col2'],
+                collapse => $bool,
+                no_collapse => ['col1', ...],
+            ),
+        );
+
+        ...
+
+        $ctx->release;
+    }
+
+    my_tool();
+
+=head1 ATTRIBUTES
+
+=over 4
+
+=item $header_aref = $t->header()
+
+=item $rows_aref = $t->rows()
+
+=item $bool = $t->collapse()
+
+=item $aref = $t->no_collapse()
+
+The above are all directly tied to the table hashref structure described in
+L<Test2::EventFacet::Info>.
+
+=item $str = $t->as_string()
+
+This returns the string form of the table if it was set, otherwise it returns
+the string C<< "<TABLE NOT DISPLAYED>" >>.
+
+=item $href = $t->as_hash()
+
+This returns the data structure used for tables by L<Test2::EventFacet::Info>.
+
+=item %args = $t->info_args()
+
+This returns the arguments that should be used to construct the proper
+L<Test2::EventFacet::Info> structure.
+
+    return (table => $t->as_hash(), details => $t->as_string());
+
+=back
+
+=head1 SOURCE
+
+The source code repository for Test2 can be found at
+F<http://github.com/Test-More/test-more/>.
+
+=head1 MAINTAINERS
+
+=over 4
+
+=item Chad Granum E<lt>exodist@cpan.orgE<gt>
+
+=back
+
+=head1 AUTHORS
+
+=over 4
+
+=item Chad Granum E<lt>exodist@cpan.orgE<gt>
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+See F<http://dev.perl.org/licenses/>
+
+=cut
index d8ce84d..a2c0bbd 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Meta;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::EventFacet; our @ISA = qw(Test2::EventFacet) }
 use vars qw/$AUTOLOAD/;
@@ -94,7 +94,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 14ae547..77fba6e 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Parent;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Carp qw/confess/;
 
@@ -26,7 +26,7 @@ __END__
 
 =head1 NAME
 
-Test2::EventFacet::Parent - Base class for all event facets.
+Test2::EventFacet::Parent - Facet for events contains other events
 
 =head1 DESCRIPTION
 
@@ -88,7 +88,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index c11f4de..19a0edc 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Plan;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::EventFacet; our @ISA = qw(Test2::EventFacet) }
 use Test2::Util::HashBase qw{ -count -skip -none };
@@ -84,7 +84,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 4544a68..bd80063 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Render;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 sub is_list { 1 }
 
@@ -53,7 +53,7 @@ Tag that should prefix/identify the main text.
 Optional, if the display text was generated from another facet this should
 state what facet it was.
 
-=item $mode = $render->[#]->mode{}
+=item $mode = $render->[#]->{mode}
 
 =item $mode = $render->[#]->mode()
 
@@ -96,7 +96,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 1adab72..53235f1 100644 (file)
@@ -2,7 +2,7 @@ package Test2::EventFacet::Trace;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::EventFacet; our @ISA = qw(Test2::EventFacet) }
 
@@ -269,7 +269,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 2922de0..cb9951b 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Formatter;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 my %ADDED;
@@ -19,6 +19,8 @@ sub new_root {
     return $class->new(@_);
 }
 
+sub supports_tables { 0 }
+
 sub hide_buffered { 1 }
 
 sub terminate { }
@@ -61,6 +63,8 @@ A formatter is any package or object with a C<write($event, $num)> method.
 
     sub finalize { }
 
+    sub supports_tables { return $BOOL }
+
     sub new_root {
         my $class = shift;
         ...
@@ -92,11 +96,14 @@ The C<finalize> method is always the last thing called on the formatter, I<<
 except when C<terminate> is called for a Bail event >>. It is passed the
 following arguments:
 
-The C<new_root> method is called when C<Test2::API::Stack> Initializes the root
-hub for the first time. Most formatters will simply have this call C<<
-$class->new >>, which is the default behavior. Some formatters however may want
-to take extra action during construction of the root formatter, this is where
-they can do that.
+The C<supports_tables> method should be true if the formatter supports directly
+rendering table data from the C<info> facets. This is a newer feature and many
+older formatters may not support it. When not supported the formatter falls
+back to rendering C<detail> instead of the C<table> data.
+
+The C<new_root> method is used when constructing a root formatter. The default
+is to just delegate to the regular C<new()> method, most formatters can ignore
+this.
 
 =over 4
 
@@ -112,6 +119,12 @@ they can do that.
 
 =back
 
+The C<new_root> method is called when C<Test2::API::Stack> Initializes the root
+hub for the first time. Most formatters will simply have this call C<<
+$class->new >>, which is the default behavior. Some formatters however may want
+to take extra action during construction of the root formatter, this is where
+they can do that.
+
 =head1 SOURCE
 
 The source code repository for Test2 can be found at
@@ -135,7 +148,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index c3017d0..fa2f25e 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Formatter::TAP;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Test2::Util qw/clone_io/;
 
@@ -16,6 +16,18 @@ sub OUT_ERR() { 1 }
 
 BEGIN { require Test2::Formatter; our @ISA = qw(Test2::Formatter) }
 
+# Not constants because this is a method, and can be overriden
+BEGIN {
+    local $SIG{__DIE__} = 'DEFAULT';
+    local $@;
+    if (($INC{'Term/Table.pm'} && $INC{'Term/Table/Util.pm'}) || eval { require Term::Table; require Term::Table::Util; 1 }) {
+        *supports_tables = sub { 1 };
+    }
+    else {
+        *supports_tables = sub { 0 };
+    }
+}
+
 sub _autoflush {
     my($fh) = pop;
     my $old_fh = select $fh;
@@ -104,10 +116,9 @@ sub write {
 
         print $io "\n"
             if $ENV{HARNESS_ACTIVE}
-            && !$ENV{HARNESS_IS_VERBOSE}
             && $hid == OUT_ERR
             && $self->{+_LAST_FH} != $io
-            && $msg =~ m/^#\s*Failed test /;
+            && $msg =~ m/^#\s*Failed( \(TODO\))? test /;
 
         $msg =~ s/^/$indent/mg if $nesting;
         print $io $msg;
@@ -363,11 +374,23 @@ sub info_tap {
 
     return map {
         my $details = $_->{details};
+        my $table   = $_->{table};
 
         my $IO = $_->{debug} && !($f->{amnesty} && @{$f->{amnesty}}) ? OUT_ERR : OUT_STD;
 
         my $msg;
-        if (ref($details)) {
+        if ($table && $self->supports_tables) {
+            $msg = join "\n" => map { "# $_" } Term::Table->new(
+                header      => $table->{header},
+                rows        => $table->{rows},
+                collapse    => $table->{collapse},
+                no_collapse => $table->{no_collapse},
+                sanitize    => 1,
+                mark_tail   => 1,
+                max_width   => $self->calc_table_size($f),
+            )->render();
+        }
+        elsif (ref($details)) {
             require Data::Dumper;
             my $dumper = Data::Dumper->new([$details])->Indent(2)->Terse(1)->Pad('# ')->Useqq(1)->Sortkeys(1);
             chomp($msg = $dumper->Dump);
@@ -394,6 +417,20 @@ sub summary_tap {
     return [OUT_STD, "$summary\n"];
 }
 
+sub calc_table_size {
+    my $self = shift;
+    my ($f) = @_;
+
+    my $term = Term::Table::Util::term_size();
+    my $nesting = 2 + (($f->{trace}->{nested} || 0) * 4); # 4 spaces per level, also '# ' prefix
+    my $total = $term - $nesting;
+
+    # Sane minimum width, any smaller and we are asking for pain
+    return 50 if $total < 50;
+
+    return $total;
+}
+
 1;
 
 __END__
@@ -477,7 +514,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 37959cb..623dd81 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Hub;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Carp qw/carp croak confess/;
@@ -899,7 +899,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 11b0d88..b6fbc3d 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Hub::Interceptor;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Test2::Hub::Interceptor::Terminator();
@@ -78,7 +78,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 3c94361..d7864c8 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Hub::Interceptor::Terminator;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 1;
@@ -41,7 +41,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 41d3442..aff2d61 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Hub::Subtest;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::Hub; our @ISA = qw(Test2::Hub) }
 use Test2::Util::HashBase qw/nested exit_code manual_skip_all/;
@@ -126,7 +126,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 4bd67a6..dc930de 100644 (file)
@@ -2,7 +2,7 @@ package Test2::IPC;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Test2::API::Instance;
@@ -150,7 +150,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index e8a3245..ed1a152 100644 (file)
@@ -2,7 +2,7 @@ package Test2::IPC::Driver;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Carp qw/confess/;
@@ -267,6 +267,14 @@ True if you want to make use of the L<Test2::API>/L<Test2::API::Instance> SHM.
 Use this to customize the size of the SHM space. There are no guarantees about
 what the size will be if you do not implement this.
 
+=item $ipc->stop_shm()
+
+The Test2 API will call this when it is about to free the SHM memory.
+
+=item $bool = $ipc->shm_stopped()
+
+Returns true if C<< $ipc->stop_shm >> has been called.
+
 =back
 
 =head1 SOURCE
@@ -292,7 +300,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index df29e64..167c4d8 100644 (file)
@@ -2,12 +2,11 @@ package Test2::IPC::Driver::Files;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
-
+our $VERSION = '1.302160';
 
 BEGIN { require Test2::IPC::Driver; our @ISA = qw(Test2::IPC::Driver) }
 
-use Test2::Util::HashBase qw{tempdir event_ids read_ids timeouts tid pid globals};
+use Test2::Util::HashBase qw{tempdir event_ids read_ids timeouts tid pid globals shm_stop_file};
 
 use Scalar::Util qw/blessed/;
 use File::Temp();
@@ -23,6 +22,19 @@ sub shm_size() { 64 }
 
 sub is_viable { 1 }
 
+sub stop_shm {
+    my $self = shift;
+    open(my $fh, '>>', $self->{+SHM_STOP_FILE}) or die "Could not open shm top file: $!";
+    print $fh $$, "\n";
+    return;
+}
+
+sub shm_stopped {
+    my $self = shift;
+    return 1 if -e $self->{+SHM_STOP_FILE};
+    return 0;
+}
+
 sub init {
     my $self = shift;
 
@@ -36,6 +48,8 @@ sub init {
 
     $self->{+TEMPDIR} = File::Spec->canonpath($tmpdir);
 
+    $self->{+SHM_STOP_FILE} = File::Spec->catfile($tmpdir, 'stop_shm');
+
     print STDERR "\nIPC Temp Dir: $tmpdir\n\n"
         if $ENV{T2_KEEP_TEMPDIR};
 
@@ -383,7 +397,7 @@ sub DESTROY {
         my $full = File::Spec->catfile($tempdir, $file);
 
         my $sep = ipc_separator;
-        if ($aborted || $file =~ m/^(GLOBAL|HUB$sep)/) {
+        if ($aborted || $file =~ m/^(GLOBAL|HUB$sep|stop_shm)/) {
             $full =~ m/^(.*)$/;
             $full = $1; # Untaint it
             next if $ENV{T2_KEEP_TEMPDIR};
@@ -473,7 +487,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 93e6948..7e5c9d3 100644 (file)
@@ -16,7 +16,7 @@ use Test2::API qw/context run_subtest test2_stack/;
 use Test2::Hub::Interceptor();
 use Test2::Hub::Interceptor::Terminator();
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 BEGIN { require Exporter; our @ISA = qw(Exporter) }
 our @EXPORT = qw{
@@ -425,7 +425,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 12c46ee..de6442c 100644 (file)
@@ -502,7 +502,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 0050f9a..1481de0 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Util;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use POSIX();
 use Config qw/%Config/;
@@ -183,7 +183,7 @@ my %PERLIO_SKIP = (
 
 sub clone_io {
     my ($fh) = @_;
-    my $fileno = fileno($fh);
+    my $fileno = eval { fileno($fh) };
 
     return $fh if !defined($fileno) || !length($fileno) || $fileno < 0;
 
@@ -438,7 +438,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 829122c..f15362c 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Util::ExternalMeta;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 
 use Carp qw/croak/;
@@ -172,7 +172,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 0d057fe..1d37a5f 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Util::Facets2Legacy;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use Carp qw/croak confess/;
 use Scalar::Util qw/blessed/;
@@ -289,7 +289,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index a2a7c7e..ed09d41 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Util::HashBase;
 use strict;
 use warnings;
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 #################################################################
 #                                                               #
@@ -425,7 +425,7 @@ F<http://github.com/Test-More/HashBase/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 4747d13..6fb540f 100644 (file)
@@ -2,7 +2,7 @@ package Test2::Util::Trace;
 require Test2::EventFacet::Trace;
 @ISA = ('Test2::EventFacet::Trace');
 
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 1;
 
@@ -44,7 +44,7 @@ F<http://github.com/Test-More/test-more/>.
 
 =head1 COPYRIGHT
 
-Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
+Copyright 2019 Chad Granum E<lt>exodist@cpan.orgE<gt>.
 
 This program is free software; you can redistribute it and/or
 modify it under the same terms as Perl itself.
index 4ab7f6e..b3bbe19 100644 (file)
@@ -1,5 +1,5 @@
 package ok;
-our $VERSION = '1.302141';
+our $VERSION = '1.302160';
 
 use strict;
 use Test::More ();
index f6d72f6..35097fa 100644 (file)
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use Test2::Util qw/CAN_FORK/;
+use Test2::Util qw/CAN_REALLY_FORK/;
 use Test2::IPC;
 use Test2::API qw/context/;
 
@@ -18,7 +18,7 @@ sub ok($;$) {
     $ctx->release;
 }
 
-plan(0, skip_all => 'System cannot fork') unless CAN_FORK();
+plan(0, skip_all => 'System cannot fork') unless CAN_REALLY_FORK();
 
 plan(6);
 
index abb86b6..207f3d0 100644 (file)
@@ -447,4 +447,34 @@ sub {
     is($?,     33,    "Destroy does not restore \$?");
 }->();
 
+sub {
+    require Test2::EventFacet::Info::Table;
+
+    my $events = intercept {
+        my $ctx = context();
+
+        $ctx->fail('foo', 'bar', Test2::EventFacet::Info::Table->new(rows => [['a', 'b']]));
+        $ctx->fail_and_release('foo', 'bar', Test2::EventFacet::Info::Table->new(rows => [['a', 'b']], as_string => 'a, b'));
+    };
+
+    is(@$events, 2, "got 2 events");
+
+    is($events->[0]->{info}->[0]->{details}, 'bar', "got first diag");
+    is($events->[0]->{info}->[1]->{details}, '<TABLE NOT DISPLAYED>', "second diag has default details");
+    is_deeply(
+        $events->[0]->{info}->[1]->{table},
+        {rows => [['a', 'b']]},
+        "Got the table rows"
+    );
+
+    is($events->[1]->{info}->[0]->{details}, 'bar', "got first diag");
+    is($events->[1]->{info}->[1]->{details}, 'a, b', "second diag has custom details");
+    is_deeply(
+        $events->[1]->{info}->[1]->{table},
+        {rows => [['a', 'b']]},
+        "Got the table rows"
+    );
+
+}->();
+
 done_testing;
index 4238b1d..de425f0 100644 (file)
@@ -133,7 +133,7 @@ ok($one->finalized, "calling format finalized the object");
 
 {
     local $ENV{T2_FORMATTER} = 'TAP';
-    $one->reset;
+    my $one = $CLASS->new;
     is($one->formatter, 'Test2::Formatter::TAP', "got specified formatter");
     ok($one->finalized, "calling format finalized the object");
 
@@ -177,7 +177,7 @@ like(
 );
 
 if (CAN_REALLY_FORK) {
-    $one->reset;
+    my $one = $CLASS->new;
     my $pid = fork;
     die "Failed to fork!" unless defined $pid;
     unless($pid) { exit 0 }
@@ -208,7 +208,7 @@ if (CAN_REALLY_FORK) {
 
 if (CAN_THREAD && $] ge '5.010') {
     require threads;
-    $one->reset;
+    my $one = $CLASS->new;
 
     threads->new(sub { 1 });
     is(Test2::API::Instance::_ipc_wait, 0, "No errors");
@@ -229,14 +229,14 @@ if (CAN_THREAD && $] ge '5.010') {
 }
 
 {
-    $one->reset();
+    my $one = $CLASS->new;
     local $? = 0;
     $one->set_exit;
     is($?, 0, "no errors on exit");
 }
 
 {
-    $one->reset();
+    my $one = $CLASS->new;
     $one->set__tid(1);
     local $? = 0;
     $one->set_exit;
@@ -244,7 +244,7 @@ if (CAN_THREAD && $] ge '5.010') {
 }
 
 {
-    $one->reset();
+    my $one = $CLASS->new;
     $one->stack->top;
     $one->no_wait(1);
     local $? = 0;
@@ -253,7 +253,7 @@ if (CAN_THREAD && $] ge '5.010') {
 }
 
 {
-    $one->reset();
+    my $one = $CLASS->new;
     $one->stack->top->set_no_ending(1);
     local $? = 0;
     $one->set_exit;
@@ -261,7 +261,7 @@ if (CAN_THREAD && $] ge '5.010') {
 }
 
 {
-    $one->reset();
+    my $one = $CLASS->new;
     $one->load();
     $one->stack->top->set_failed(2);
     local $? = 0;
@@ -270,7 +270,7 @@ if (CAN_THREAD && $] ge '5.010') {
 }
 
 {
-    $one->reset();
+    my $one = $CLASS->new;
     $one->load();
     local $? = 500;
     $one->set_exit;
@@ -280,7 +280,7 @@ if (CAN_THREAD && $] ge '5.010') {
 {
     local %INC = %INC;
     delete $INC{'Test2/IPC.pm'};
-    $one->reset();
+    my $one = $CLASS->new;
     $one->load();
     my @events;
     $one->stack->top->filter(sub { push @events => $_[1]; undef});
@@ -293,7 +293,7 @@ if (CAN_THREAD && $] ge '5.010') {
 
 SKIP: {
     last SKIP if $] lt "5.008";
-    $one->reset;
+    my $one = $CLASS->new;
     my $stderr = "";
     {
         local $INC{'Test/Builder.pm'} = __FILE__;
@@ -327,7 +327,7 @@ SKIP: {
     my $ran = 0;
     local *Test2::API::Breakage::report = sub { $ran++; return "foo" };
     use warnings qw/redefine once/;
-    $one->reset();
+    my $one = $CLASS->new;
     $one->load();
 
     my $stderr = "";
@@ -349,7 +349,7 @@ foo
 
 
 {
-    $one->reset();
+    my $one = $CLASS->new;
     $one->load();
     my @events;
     $one->stack->top->filter(sub { push @events => $_[1]; undef});
@@ -368,7 +368,7 @@ foo
 
 if (CAN_REALLY_FORK) {
     local $SIG{__WARN__} = sub { };
-    $one->reset();
+    my $one = $CLASS->new;
     my $pid = fork;
     die "Failed to fork!" unless defined $pid;
     unless ($pid) { exit 255 }
@@ -392,6 +392,7 @@ if (CAN_REALLY_FORK) {
 }
 
 {
+    my $one = $CLASS->new;
     my $ctx = bless {
         trace => Test2::EventFacet::Trace->new(frame => ['Foo::Bar', 'Foo/Bar.pm', 42, 'xxx']),
         hub => Test2::Hub->new(),
@@ -409,6 +410,7 @@ if (CAN_REALLY_FORK) {
         ],
         "Warned about unfreed context"
     );
+    $one->set_no_wait(0);
 }
 
 {
@@ -417,7 +419,7 @@ if (CAN_REALLY_FORK) {
     delete $INC{'threads.pm'};
     ok(!USE_THREADS, "Sanity Check");
 
-    $one->reset;
+    my $one = $CLASS->new;
     ok(!$one->ipc, 'IPC not loaded, no IPC object');
     ok($one->finalized, "calling ipc finalized the object");
     is($one->ipc_polling, undef, "no polling defined");
@@ -469,7 +471,7 @@ if (CAN_REALLY_FORK) {
 }
 
 {
-    $one->reset;
+    my $one = $CLASS->new;
 
     ok(!@{$one->context_init_callbacks}, "no callbacks");
     is($one->ipc_polling, undef, "no polling, undef");
@@ -513,7 +515,7 @@ if (CAN_REALLY_FORK) {
     require Test2::IPC::Driver::Files;
 
     local $ENV{T2_NO_IPC} = 1;
-    $one->reset;
+    my $one = $CLASS->new;
     $one->add_ipc_driver('Test2::IPC::Driver::Files');
     ok($one->ipc_disabled, "IPC is disabled by env var");
     ok(!$one->ipc, 'IPC not loaded');
@@ -534,4 +536,128 @@ if (CAN_REALLY_FORK) {
     ok($one->ipc_disabled, "IPC is disabled directly");
 }
 
+SKIP: {
+    last SKIP if $] lt "5.008";
+    no warnings 'redefine';
+    my $error;
+    local *Test2::API::Instance::_fatal_error = sub { die "$_[1]\n" };
+
+    my $two = $CLASS->new;
+    $two->{ipc_shm_id} = undef;
+    is($two->set_ipc_pending, undef, "No shm");
+
+    $two->{ipc_shm_id} = -1;
+    $two->{ipc_shm_size} = 32;
+
+    my $ok = eval { $two->set_ipc_pending(); 1 };
+    ok(!$ok, "Exception");
+    like($@, qr/value is required for set_ipc_pending/, "Got expected exception");
+
+    my $ctid = get_tid();
+
+    my $ec;
+    {
+        local $! = 22;
+        $ec = "$!";
+    }
+
+    $ok = eval { $two->set_ipc_pending('message'); 1 };
+    my $err = $@;
+    ok(!$ok, "Exception");
+
+    is($err, <<"    EOT", "Got exception when shm write fails (no tid/pid)") unless $err =~ m/not implemented/;
+IPC shmwrite(-1, 'message', 0, 32) failed, the parent process appears to have exited. This is a fatal error.
+  Error: (22) $ec
+  Parent  PID: ?
+  Current PID: $$
+  Parent  TID: ?
+  Current TID: $ctid
+  SHM State:   0
+  IPC errors like this usually indicate a race condition in a test where the
+  parent thread/process is allowed to exit before all child processes/threads
+  are complete.
+  Trace:
+    EOT
+
+    # Need a fake PID that cannot actually be signaled, but is a real number....
+    $two->{_pid} = 10000000000000000;
+    $two->{_tid} = $ctid;
+
+    $two->{ipc_shm_id} = -1; # Reset this
+    $ok = eval {
+        # override check_pid, some platforms will return true with our absurd PID above.
+        no warnings 'redefine';
+        local *Test2::API::Instance::_check_pid = sub { () };
+        $two->set_ipc_pending('message');
+        1;
+    };
+    $err = $@;
+    ok(!$ok, "Exception");
+
+    is($err, <<"    EOT", "Got exception when shm write fails (with tid/pid)") unless $err =~ m/not implemented/;
+IPC shmwrite(-1, 'message', 0, 32) failed, the parent process appears to have exited. This is a fatal error.
+  Error: (22) $ec
+  Parent  PID: $two->{_pid}
+  Current PID: $$
+  Parent  TID: $ctid
+  Current TID: $ctid
+  SHM State:   0
+  IPC errors like this usually indicate a race condition in a test where the
+  parent thread/process is allowed to exit before all child processes/threads
+  are complete.
+  Trace:
+    EOT
+
+    $two->{_pid} = $$; # Parent that has not exited
+    $two->{_tid} = $ctid;
+
+    my $warn = undef;
+    $two->{ipc_shm_id} = -1; # Reset this
+    $ok = eval {
+        local $SIG{__WARN__} = sub { $warn = $_[0] };
+        $two->set_ipc_pending('message');
+        1;
+    };
+    $err = $@;
+    unless ($err =~ m/not implemented/) {
+        ok($ok, "No Exception");
+
+        like(
+            $warn,
+            qr/^\($$\) It looks like SHM has gone away unexpectedly \(22: $ec\)\. The parent process is still active\. This is not fatal, but may slow things down slightly/,
+            "Got warning when shm write fails but parent is open"
+        );
+    }
+}
+
+
+if (CAN_REALLY_FORK && $] ge "5.008") {
+    my ($rh, $wh);
+    pipe($rh, $wh) or die "no pipe: $!";
+
+    my $pid = fork;
+    die "Could not fork" unless defined $pid;
+    if ($pid) {
+        close($wh);
+        my $check = waitpid($pid, 0);
+        my $exit = $?;
+        is($check, $pid, "Waited on process");
+        my $err = ($exit >> 8);
+        my $sig = ($exit & 127);
+        ok(!$sig, "did not exit via a signal");
+        is($err, 255, "exit code 255");
+
+        my $msg = join "" => <$rh>;
+        like($msg, qr/^blah, I died\nfoo bar at \Q${ \__FILE__ }\E line \d+/, "Saw error message");
+    }
+    else {
+        close($rh);
+        open(STDERR, '>&', $wh) or print "Could not open: $!";
+        $CLASS->_fatal_error("blah, I died\nfoo bar");
+        exit 1;
+    }
+}
+
+Test2::API::test2_ipc_wait_enable();
+
 done_testing;
index 6f31c88..ee54a15 100644 (file)
@@ -13,7 +13,7 @@ BEGIN {
     select $old;
 
     require Test2::Formatter::TAP;
-    $CLASS = 'Test2::Formatter::TAP';
+    $CLASS   = 'Test2::Formatter::TAP';
     *OUT_STD = $CLASS->can('OUT_STD') or die "Could not get OUT_STD constant";
     *OUT_ERR = $CLASS->can('OUT_ERR') or die "Could not get OUT_ERR constant";
 }
@@ -24,7 +24,7 @@ use Test2::API qw/context/;
 BEGIN {
     eval {
         require PerlIO;
-        PerlIO->VERSION(1.02); # required for PerlIO::get_layers
+        PerlIO->VERSION(1.02);    # required for PerlIO::get_layers
     } or do {
         print "1..0 # SKIP Don't have PerlIO 1.02\n";
         exit 0;
@@ -33,8 +33,8 @@ BEGIN {
 
 sub grabber {
     my ($std, $err);
-    open( my $stdh, '>', \$std ) || die "Ooops";
-    open( my $errh, '>', \$err ) || die "Ooops";
+    open(my $stdh, '>', \$std) || die "Ooops";
+    open(my $errh, '>', \$err) || die "Ooops";
 
     my $it = $CLASS->new(
         handles => [$stdh, $errh, $stdh],
@@ -87,7 +87,7 @@ tests "IO handle stuff" => sub {
     ok($|, "AUTOFLUSH was turned on for copy-STDERR");
     select $old;
 
-    ok($CLASS->hide_buffered, "TAP will hide buffered events");
+    ok($CLASS->hide_buffered,     "TAP will hide buffered events");
     ok(!$CLASS->no_subtest_space, "Default formatter does not have subtest space");
 };
 
@@ -125,9 +125,9 @@ tests optimal_pass => sub {
     $pass = Test2::Event::Ok->new(pass => 1, name => 'xxx');
     ok($it->print_optimal_pass($pass, 1), "Printed an 'Ok' pass with a name");
 
-    $pass = Test2::Event::Pass->new(name => 'xxx', trace => { nested => 1 });
+    $pass = Test2::Event::Pass->new(name => 'xxx', trace => {nested => 1});
     ok($it->print_optimal_pass($pass, 1), "Printed a nested pass");
-    $pass = Test2::Event::Pass->new(name => 'xxx', trace => { nested => 3 });
+    $pass = Test2::Event::Pass->new(name => 'xxx', trace => {nested => 3});
     ok($it->print_optimal_pass($pass, 1), "Printed a deeply nested pass");
 
     $pass = Test2::Event::Pass->new(name => 'xxx');
@@ -154,25 +154,25 @@ tests plan_tap => sub {
     is_deeply([$it->plan_tap({})], [], "Nothing with no plan facet");
 
     is_deeply(
-        [$it->plan_tap({plan => { none => 1 }})],
+        [$it->plan_tap({plan => {none => 1}})],
         [],
         "no-plan has no output"
     );
 
     is_deeply(
-        [$it->plan_tap({plan => { count => 20 }})],
+        [$it->plan_tap({plan => {count => 20}})],
         [[OUT_STD, "1..20\n"]],
         "Wrote the plan from, count"
     );
 
     is_deeply(
-        [$it->plan_tap({plan => { count => 'anything', skip => 1 }})],
+        [$it->plan_tap({plan => {count => 'anything', skip => 1}})],
         [[OUT_STD, "1..0 # SKIP\n"]],
         "Skip, no reason"
     );
 
     is_deeply(
-        [$it->plan_tap({plan => { count => 'anything', skip => 1, details => 'I said so' }})],
+        [$it->plan_tap({plan => {count => 'anything', skip => 1, details => 'I said so'}})],
         [[OUT_STD, "1..0 # SKIP I said so\n"]],
         "Skip with reason"
     );
@@ -605,7 +605,7 @@ tests debug_tap => sub {
             $it->debug_tap(
                 {
                     assert => {details => 'foo bar', pass => 0},
-                    trace => {frame => ['foo', 'foo.t', 42]},
+                    trace   => {frame => ['foo', 'foo.t', 42]},
                     amnesty => [],
                 },
                 1
@@ -622,7 +622,7 @@ tests debug_tap => sub {
             $it->debug_tap(
                 {
                     assert => {details => 'foo bar', pass => 0},
-                    trace => {frame => ['foo', 'foo.t', 42]},
+                    trace   => {frame => ['foo', 'foo.t', 42]},
                     amnesty => [{tag => 'TODO', details => 'xxx'}],
                 },
                 1
@@ -634,32 +634,31 @@ tests debug_tap => sub {
         "Debug empty amnesty"
     );
 
-
     ok(!$$out, "No std output yet");
     ok(!$$err, "No err output yet");
 
     my $event = Test2::Event::Fail->new(trace => {frame => ['foo', 'foo.pl', 42]});
 
     {
-        local $ENV{HARNESS_ACTIVE} = 0;
+        local $ENV{HARNESS_ACTIVE}     = 0;
         local $ENV{HARNESS_IS_VERBOSE} = 0;
 
         $event->{name} = 'no harness';
         $it->write($event, 1);
 
-        $ENV{HARNESS_ACTIVE} = 0;
+        $ENV{HARNESS_ACTIVE}     = 0;
         $ENV{HARNESS_IS_VERBOSE} = 1;
 
         $event->{name} = 'no harness, but strangely verbose';
         $it->write($event, 1);
 
-        $ENV{HARNESS_ACTIVE} = 1;
+        $ENV{HARNESS_ACTIVE}     = 1;
         $ENV{HARNESS_IS_VERBOSE} = 0;
 
         $event->{name} = 'harness, but not verbose';
         $it->write($event, 1);
 
-        $ENV{HARNESS_ACTIVE} = 1;
+        $ENV{HARNESS_ACTIVE}     = 1;
         $ENV{HARNESS_IS_VERBOSE} = 1;
 
         $event->{name} = 'harness that is verbose';
@@ -681,6 +680,7 @@ not ok 1 - harness that is verbose
 
 # Failed test 'harness, but not verbose'
 # at foo.pl line 42.
+
 # Failed test 'harness that is verbose'
 # at foo.pl line 42.
     EOT
@@ -697,7 +697,7 @@ tests halt_tap => sub {
 
     is_deeply(
         [$it->halt_tap({trace => {nested => 1, buffered => 1}})],
-        [[OUT_STD, "Bail out!\n" ]],
+        [[OUT_STD, "Bail out!\n"]],
         "Got tap for nested buffered bail"
     );
 
@@ -733,19 +733,19 @@ tests summary_tap => sub {
     my ($it, $out, $err) = grabber();
 
     is_deeply(
-        [$it->summary_tap({about => { no_display => 1, details => "Should not see me"}})],
+        [$it->summary_tap({about => {no_display => 1, details => "Should not see me"}})],
         [],
         "no display"
     );
 
     is_deeply(
-        [$it->summary_tap({about => { no_display => 0, details => ""}})],
+        [$it->summary_tap({about => {no_display => 0, details => ""}})],
         [],
         "no summary"
     );
 
     is_deeply(
-        [$it->summary_tap({about => { no_display => 0, details => "foo bar"}})],
+        [$it->summary_tap({about => {no_display => 0, details => "foo bar"}})],
         [[OUT_STD, "# foo bar\n"]],
         "summary"
     );
@@ -832,7 +832,6 @@ tests error_tap => sub {
     ok(!$$err, "No err output yet");
 };
 
-
 tests event_tap => sub {
     my ($it, $out, $err) = grabber();
 
@@ -919,7 +918,7 @@ tests event_tap => sub {
             $it->event_tap(
                 {
                     errors => [{details => "foo"}],
-                    about  => {details  => 'xyz'},
+                    about  => {details => 'xyz'},
                 },
                 1
             )
@@ -1016,4 +1015,114 @@ Bail out!  blah
     EOT
 };
 
+my $can_table      = $CLASS->supports_tables;
+my $author_testing = $ENV{AUTHOR_TESTING};
+
+if ($author_testing && !$can_table) {
+    die "This test requires Term::Table to be installed, and must be run in AUTHOR_TESTING mode";
+}
+elsif ($can_table) {
+    tests tables => sub {
+        my ($it, $out, $err) = grabber();
+
+        no warnings 'redefine';
+        local *Term::Table::Util::term_size = sub { 70 };
+
+        my %table_data = (
+            header => ['H1', 'H2'],
+            rows   => [
+                ["R1C1\n", 'R1C2'],
+                ['R2C1', 'R2C2'],
+                [('x' x 30), ('y' x 30)],
+            ],
+        );
+
+        {
+            local *Test2::Formatter::TAP::supports_tables = sub { 0 };
+            $it->write(
+                undef, 1, {
+                    info => [
+                        {
+                            tag     => 'DIAG',
+                            details => 'should see only this',
+                            debug   => 1,
+                            table   => \%table_data,
+                        },
+                        {
+                            tag     => 'NOTE',
+                            details => 'should see only this',
+                            table   => \%table_data,
+                        },
+                    ]
+                },
+            );
+        }
+
+        $it->write(
+            undef, 1, {
+                info => [
+                    {
+                        tag     => 'DIAG',
+                        details => 'should not see',
+                        debug   => 1,
+                        table   => \%table_data,
+                    },
+                    {
+                        tag     => 'NOTE',
+                        details => 'should not see',
+                        table   => \%table_data,
+                    },
+                ]
+            },
+        );
+
+        $it->write(
+            undef, 1, {
+                trace => {nested => 2},
+                info  => [
+                    {
+                        tag     => 'DIAG',
+                        details => 'should not see',
+                        debug   => 1,
+                        table   => \%table_data,
+                    },
+                    {
+                        tag     => 'NOTE',
+                        details => 'should not see',
+                        table   => \%table_data,
+                    },
+                ]
+            },
+        );
+
+        my $table1 = join "\n" => map { "# $_" } Term::Table->new(
+            %table_data,
+            max_width => Term::Table::Util::term_size() - 2,    # 2 for '# '
+            collapse  => 1,
+            sanitize  => 1,
+            mark_tail => 1,
+        )->render;
+
+        my $table2 = join "\n" => map { "        # $_" } Term::Table->new(
+            %table_data,
+            max_width => Term::Table::Util::term_size() - 10,    # 2 for '# ', 8 for indentation
+            collapse  => 1,
+            sanitize  => 1,
+            mark_tail => 1,
+        )->render;
+
+        is($$out, <<"        EOT", "Showed detail OR tables, properly sized and indented in STDOUT");
+# should see only this
+$table1
+$table2
+        EOT
+
+        is($$err, <<"        EOT", "Showed detail OR tables, properly sized and indented in STDERR");
+# should see only this
+$table1
+$table2
+        EOT
+    };
+}
+
 done_testing;
index f896db0..a2c1b7d 100644 (file)
@@ -94,6 +94,11 @@ $ipc->send($hid, bless({global => 1}, 'Foo'), 'GLOBAL');
 my @got = $ipc->cull($hid);
 ok(@got == 0, "did not get our own global event");
 
+ok(!-e $ipc->shm_stop_file, "No stop file");
+$ipc->stop_shm;
+ok(-e $ipc->shm_stop_file, "stop file added");
+ok($ipc->shm_stopped, "stopped shm");
+
 my $tmpdir = $ipc->tempdir;
 ok(-d $tmpdir, "still have temp dir");
 $ipc = undef;
index b425443..5550f17 100644 (file)
@@ -1,11 +1,11 @@
 use strict;
 use warnings;
 use Test2::Tools::Tiny;
-use Test2::Util qw/CAN_FORK/;
+use Test2::Util qw/CAN_REALLY_FORK/;
 
 BEGIN {
     skip_all "Set AUTHOR_TESTING to run this test" unless $ENV{AUTHOR_TESTING};
-    skip_all "System cannot fork" unless CAN_FORK;
+    skip_all "System cannot fork" unless CAN_REALLY_FORK;
     skip_all "known to fail on $]" if $] le "5.006002";
 }
 
diff --git a/cpan/Test-Simple/t/regression/812-todo.t b/cpan/Test-Simple/t/regression/812-todo.t
new file mode 100644 (file)
index 0000000..dd4e0b4
--- /dev/null
@@ -0,0 +1,21 @@
+use strict;
+use warnings;
+
+use Test2::API qw/intercept/;
+use Test::More;
+
+my @values = (
+    "",               # false but defined -> inconsistent
+    0,                # false but defined -> inconsistent
+    0.0,              # false but defined -> inconsistent
+    "0.0",            # true -> TODO
+    "this is why",    # as expected
+);
+
+for my $value (@values) {
+    local $TODO = $value;
+    my $x = defined($value) ? "\"$value\"" : 'UNDEF';
+    fail "Testing: $x";
+}
+
+done_testing;
diff --git a/cpan/Test-Simple/t/regression/817-subtest-todo.t b/cpan/Test-Simple/t/regression/817-subtest-todo.t
new file mode 100644 (file)
index 0000000..fa6f5f8
--- /dev/null
@@ -0,0 +1,48 @@
+use Test2::API qw(run_subtest context intercept);
+use Test::More;
+use Test2::Tools::Tiny qw/todo/;
+
+sub aaa {
+    my $ctx = context();
+    run_subtest(
+        "bad pass",
+        sub {
+            local $TODO = "third test";
+            ok(1, "ok");
+        }
+    );
+    $ctx->release;
+}
+
+sub bbb {
+    my $ctx = context();
+    run_subtest(
+        "bad fail",
+        sub {
+            local $TODO = "fourth test";
+            ok(0, "ok");
+        }
+    );
+
+    $ctx->release;
+}
+
+my $events = intercept {
+    Test::Builder->new->_add_ts_hooks();
+    aaa();
+    bbb();
+};
+
+is_deeply(
+    $events->[1]->{subevents}->[0]->{amnesty}->[0],
+    { tag => 'TODO', details => "third test" },
+    "Amnesty was set properly for first subtest assertion",
+);
+
+is_deeply(
+    $events->[3]->{subevents}->[0]->{amnesty}->[0],
+    { tag => 'TODO', details => "fourth test" },
+    "Amnesty was set properly for second subtest assertion",
+);
+
+done_testing;