diff options
author | Chad Granum <chad.granum@dreamhost.com> | 2014-12-11 08:03:57 -0800 |
---|---|---|
committer | James E Keenan <jkeenan@cpan.org> | 2014-12-11 18:52:56 -0500 |
commit | 8f074d66877960697c1c72433068824e05aa0e9d (patch) | |
tree | b11eacf76cb319aed432f11c285d894c93a09013 /cpan | |
parent | f347d3e37893158fcefa9e51712d785eb38aaf0a (diff) | |
download | perl-8f074d66877960697c1c72433068824e05aa0e9d.tar.gz |
Test-Simple Version Bump, 1.301001_084 (RC4)
Diffstat (limited to 'cpan')
22 files changed, 1359 insertions, 123 deletions
diff --git a/cpan/Test-Simple/lib/Test/Builder.pm b/cpan/Test-Simple/lib/Test/Builder.pm index 2955e07c8d..fbd2dbf181 100644 --- a/cpan/Test-Simple/lib/Test/Builder.pm +++ b/cpan/Test-Simple/lib/Test/Builder.pm @@ -4,7 +4,7 @@ use 5.008001; use strict; use warnings; -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) diff --git a/cpan/Test-Simple/lib/Test/Builder/Module.pm b/cpan/Test-Simple/lib/Test/Builder/Module.pm index d0b3003426..11d4ff78da 100644 --- a/cpan/Test-Simple/lib/Test/Builder/Module.pm +++ b/cpan/Test-Simple/lib/Test/Builder/Module.pm @@ -8,7 +8,7 @@ use Test::Builder 0.99; require Exporter; our @ISA = qw(Exporter); -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) diff --git a/cpan/Test-Simple/lib/Test/Builder/Tester.pm b/cpan/Test-Simple/lib/Test/Builder/Tester.pm index f6711a77bd..0cd7d23dc2 100644 --- a/cpan/Test-Simple/lib/Test/Builder/Tester.pm +++ b/cpan/Test-Simple/lib/Test/Builder/Tester.pm @@ -1,7 +1,7 @@ package Test::Builder::Tester; use strict; -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) use Test::Stream 1.301001 '-internal'; diff --git a/cpan/Test-Simple/lib/Test/Builder/Tester/Color.pm b/cpan/Test-Simple/lib/Test/Builder/Tester/Color.pm index 98d690bf41..04cd6afdf0 100644 --- a/cpan/Test-Simple/lib/Test/Builder/Tester/Color.pm +++ b/cpan/Test-Simple/lib/Test/Builder/Tester/Color.pm @@ -1,7 +1,7 @@ package Test::Builder::Tester::Color; use strict; -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) use Test::Stream 1.301001 '-internal'; diff --git a/cpan/Test-Simple/lib/Test/CanFork.pm b/cpan/Test-Simple/lib/Test/CanFork.pm index b28a38226c..c94614cbd8 100644 --- a/cpan/Test-Simple/lib/Test/CanFork.pm +++ b/cpan/Test-Simple/lib/Test/CanFork.pm @@ -9,26 +9,24 @@ my $Can_Fork = $Config{d_fork} and $Config{useithreads} and $Config{ccflags} =~ /-DPERL_IMPLICIT_SYS/); -if (!$Can_Fork) { - require Test::More; - Test::More::plan(skip_all => "This system cannot fork"); - exit 0; -} - -if ($^O eq 'MSWin32' && $] == 5.010000) { - require Test::More; - Test::More::plan('skip_all' => "5.10 has fork/threading issues that break fork on win32"); - exit 0; -} - sub import { my $class = shift; + + if (!$Can_Fork) { + require Test::More; + Test::More::plan(skip_all => "This system cannot fork"); + } + + if ($^O eq 'MSWin32' && $] == 5.010000) { + require Test::More; + Test::More::plan('skip_all' => "5.10 has fork/threading issues that break fork on win32"); + } + for my $var (@_) { next if $ENV{$var}; require Test::More; Test::More::plan(skip_all => "This forking test will only run when the '$var' environment variable is set."); - exit 0; } } diff --git a/cpan/Test-Simple/lib/Test/CanThread.pm b/cpan/Test-Simple/lib/Test/CanThread.pm index a9d6aeb106..5902f84569 100644 --- a/cpan/Test-Simple/lib/Test/CanThread.pm +++ b/cpan/Test-Simple/lib/Test/CanThread.pm @@ -4,37 +4,34 @@ use warnings; use Config; -if ($] == 5.010000) { - require Test::More; - Test::More::plan(skip_all => "Threads are broken on 5.10.0"); - exit 0; -} - my $works = 1; $works &&= $] >= 5.008001; $works &&= $Config{'useithreads'}; $works &&= eval { require threads; 'threads'->import; 1 }; -unless ($works) { - require Test::More; - Test::More::plan(skip_all => "Skip no working threads"); - exit 0; -} - -if ($INC{'Devel/Cover.pm'}) { - require Test::More; - Test::More::plan(skip_all => "Devel::Cover does not work with threads yet"); - exit 0; -} - sub import { my $class = shift; + + if ($] == 5.010000) { + require Test::More; + Test::More::plan(skip_all => "Threads are broken on 5.10.0"); + } + + unless ($works) { + require Test::More; + Test::More::plan(skip_all => "Skip no working threads"); + } + + if ($INC{'Devel/Cover.pm'}) { + require Test::More; + Test::More::plan(skip_all => "Devel::Cover does not work with threads yet"); + } + while(my $var = shift(@_)) { next if $ENV{$var}; require Test::More; Test::More::plan(skip_all => "This threaded test will only run when the '$var' environment variable is set."); - exit 0; } unshift @_ => 'threads'; diff --git a/cpan/Test-Simple/lib/Test/More.pm b/cpan/Test-Simple/lib/Test/More.pm index b186cc965b..8b55adf8d7 100644 --- a/cpan/Test-Simple/lib/Test/More.pm +++ b/cpan/Test-Simple/lib/Test/More.pm @@ -4,12 +4,12 @@ use 5.008001; use strict; use warnings; -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) use Test::Stream 1.301001 '-internal'; use Test::Stream::Util qw/protect try spoof/; -use Test::Stream::Toolset; +use Test::Stream::Toolset qw/is_tester init_tester context before_import/; use Test::Stream::Subtest qw/subtest/; use Test::Stream::Carp qw/croak carp/; @@ -69,45 +69,6 @@ sub import_extra { 1 }; sub builder { Test::Builder->new } -sub before_import { - my $class = shift; - my ($importer, $list) = @_; - - my $meta = init_tester($importer); - - my $context = context(1); - my $other = []; - my $idx = 0; - - while ($idx <= $#{$list}) { - my $item = $list->[$idx++]; - next unless $item; - - if (defined $item and $item eq 'no_diag') { - Test::Stream->shared->set_no_diag(1); - } - elsif ($item eq 'tests') { - $context->plan($list->[$idx++]); - } - elsif ($item eq 'skip_all') { - $context->plan(0, 'SKIP', $list->[$idx++]); - } - elsif ($item eq 'no_plan') { - $context->plan(0, 'NO PLAN'); - } - elsif ($item eq 'import') { - push @$other => @{$list->[$idx++]}; - } - else { - carp("Unknown option: $item"); - } - } - - @$list = @$other; - - return; -} - sub ok ($;$) { my ($test, $name) = @_; my $ctx = context(); diff --git a/cpan/Test-Simple/lib/Test/Simple.pm b/cpan/Test-Simple/lib/Test/Simple.pm index bf140dcc4e..27ba03ece8 100644 --- a/cpan/Test-Simple/lib/Test/Simple.pm +++ b/cpan/Test-Simple/lib/Test/Simple.pm @@ -5,10 +5,10 @@ use 5.008001; use strict; use warnings; -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) -use Test::Stream 1.301001_079 '-internal'; +use Test::Stream 1.301001_084 '-internal'; use Test::Stream::Toolset; use Test::Stream::Exporter; diff --git a/cpan/Test-Simple/lib/Test/Stream.pm b/cpan/Test-Simple/lib/Test/Stream.pm index 2b47ed779e..705e0c3151 100644 --- a/cpan/Test-Simple/lib/Test/Stream.pm +++ b/cpan/Test-Simple/lib/Test/Stream.pm @@ -2,7 +2,7 @@ package Test::Stream; use strict; use warnings; -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) use Test::Stream::Context qw/context/; @@ -540,7 +540,7 @@ sub _process_event { my ($self, $e, $cache) = @_; if ($self->[MUNGERS]) { - $_->($self, $e) for @{$self->[MUNGERS]}; + $_->($self, $e, $e->subevents) for @{$self->[MUNGERS]}; } $self->_render_tap($cache) unless $cache->{no_out}; diff --git a/cpan/Test-Simple/lib/Test/Stream/API.pm b/cpan/Test-Simple/lib/Test/Stream/API.pm new file mode 100644 index 0000000000..68b1e558d1 --- /dev/null +++ b/cpan/Test-Simple/lib/Test/Stream/API.pm @@ -0,0 +1,687 @@ +package Test::Stream::API; +use strict; +use warnings; + +use Test::Stream::Tester qw/intercept/; +use Test::Stream::Carp qw/croak confess/; +use Test::Stream::Meta qw/is_tester init_tester/; +use Test::Stream qw/cull tap_encoding OUT_STD OUT_ERR OUT_TODO/; + +use Test::Stream::Exporter qw/import exports export_to/; +exports qw{ + listen munge follow_up + enable_forking cull + peek_todo push_todo pop_todo set_todo inspect_todo + is_tester init_tester + is_modern set_modern + context peek_context clear_context set_context + intercept + state_count state_failed state_plan state_ended is_passing + current_stream + + disable_tap enable_tap subtest_tap_instant subtest_tap_delayed tap_encoding + enable_numbers disable_numbers set_tap_outputs get_tap_outputs +}; +Test::Stream::Exporter->cleanup(); + +BEGIN { + require Test::Stream::Context; + Test::Stream::Context->import(qw/context inspect_todo/); + *peek_context = \&Test::Stream::Context::peek; + *clear_context = \&Test::Stream::Context::clear; + *set_context = \&Test::Stream::Context::set; + *push_todo = \&Test::Stream::Context::push_todo; + *pop_todo = \&Test::Stream::Context::pop_todo; + *peek_todo = \&Test::Stream::Context::peek_todo; +} + +sub listen(&) { Test::Stream->shared->listen($_[0]) } +sub munge(&) { Test::Stream->shared->munge($_[0]) } +sub follow_up(&) { Test::Stream->shared->follow_up($_[0]) } +sub enable_forking { Test::Stream->shared->use_fork() } +sub disable_tap { Test::Stream->shared->set_use_tap(0) } +sub enable_tap { Test::Stream->shared->set_use_tap(1) } +sub enable_numbers { Test::Stream->shared->set_use_numbers(1) } +sub disable_numbers { Test::Stream->shared->set_use_numbers(0) } +sub current_stream { Test::Stream->shared() } +sub state_count { Test::Stream->shared->count() } +sub state_failed { Test::Stream->shared->failed() } +sub state_plan { Test::Stream->shared->plan() } +sub state_ended { Test::Stream->shared->ended() } +sub is_passing { Test::Stream->shared->is_passing } + +sub subtest_tap_instant { + Test::Stream->shared->set_subtest_tap_instant(1); + Test::Stream->shared->set_subtest_tap_delayed(0); +} + +sub subtest_tap_delayed { + Test::Stream->shared->set_subtest_tap_instant(0); + Test::Stream->shared->set_subtest_tap_delayed(1); +} + +sub is_modern { + my ($package) = @_; + my $meta = is_tester($package) || croak "'$package' is not a tester package"; + return $meta->modern ? 1 : 0; +} + +sub set_modern { + my $package = shift; + croak "set_modern takes a package and a value" unless @_; + my $value = shift; + my $meta = is_tester($package) || croak "'$package' is not a tester package"; + return $meta->set_modern($value); +} + +sub set_todo { + my ($pkg, $why) = @_; + my $meta = is_tester($pkg) || croak "'$pkg' is not a tester package"; + $meta->set_todo($why); +} + +sub set_tap_outputs { + my %params = @_; + my $encoding = delete $params{encoding} || 'legacy'; + my $std = delete $params{std}; + my $err = delete $params{err}; + my $todo = delete $params{todo}; + + my @bad = keys %params; + croak "set_tap_output does not recognise these keys: " . join ", ", @bad + if @bad; + + my $ioset = Test::Stream->shared->io_sets; + my $enc = $ioset->init_encoding($encoding); + + $enc->[OUT_STD] = $std if $std; + $enc->[OUT_ERR] = $err if $err; + $enc->[OUT_TODO] = $todo if $todo; + + return $enc; +} + +sub get_tap_outputs { + my ($enc) = @_; + my $set = Test::Stream->shared->io_sets->init_encoding($enc || 'legacy'); + return { + encoding => $enc || 'legacy', + std => $set->[0], + err => $set->[1], + todo => $set->[2], + }; +} + +1; + +__END__ + +=head1 NAME + +Test::Stream::API - Single point of access to Test::Stream extendability +features. + +=head1 DESCRIPTION + +There are times where you want to extend or alter the bahvior of a test file or +test suite. This module collects all the features and tools that +L<Test::Stream> offers for such actions. Everything in this file is accessible +in other places, but with less sugar coating. + +=head1 SYNOPSYS + +Nothing is exported by default, you must request it. + + use Test::Stream::API qw/ ... /; + +=head2 MODIFYING EVENTS + + use Test::Stream::API qw/ munge /; + + munge { + my ($stream, $event, @subevents) = @_; + + if($event->isa('Test::Stream::Diag')) { + $event->set_message( "KILROY WAS HERE: " . $event->message ); + } + }; + +=head2 REPLACING TAP WITH ALTERNATIVE OUTPUT + + use Test::Stream::API qw/ disable_tap listen /; + + disable_tap(); + + listen { + my $stream = shift; + my ($event, @subevents) = @_; + + # Tracking results in a db? + my $id = log_event_to_db($e); + log_subevent_to_db($id, $_) for @subevents; + } + +=head2 END OF TEST BEHAVIORS + + use Test::Stream::API qw/ follow_up is_passing /; + + follow_up { + my ($context) = @_; + + if (is_passing()) { + print "KILROY Says the test file passed!\n"; + } + else { + print "KILROY is not happy with you!\n"; + } + }; + +=head2 ENABLING FORKING SUPPORT + + use Test::More; + use Test::Stream::API qw/ enable_forking /; + + enable_forking(); + + # This all just works now! + my $pid = fork(); + if ($pid) { # Parent + ok(1, "From Parent"); + } + else { # child + ok(1, "From Child"); + exit 0; + } + + done_testing; + +B<Note:> Result order between processes is not guarenteed, but the test number +is handled for you meaning you don't need to care. + +Results: + + ok 1 - From Child + ok 2 - From Parent + +Or: + + ok 1 - From Parent + ok 2 - From Child + +=head2 REDIRECTING TAP OUTPUT + +You may omit any arguments to leave a specific handle unchanged. It is not +possible to set a handle to undef or 0 or any other false value. + + use Test::Stream::API qw/ set_tap_outputs /; + + set_tap_outputs( + encoding => 'legacy', # Default, + std => $STD_IO_HANDLE, # equivilent to $TB->output() + err => $ERR_IO_HANDLE, # equivilent to $TB->failure_output() + todo => $TODO_IO_HANDLE, # equivilent to $TB->todo_output() + ); + +B<Note:> Each encoding has independant filehandles. + +=head1 GENERATING EVENTS + +=head2 EASY WAY + +The best way to generate an event is through a L<Test::Stream::Context> +object. All events have a method associated with them on the context object. +The method will be the last part of the evene package name lowercased, for +example L<Test::Stream::Event::Ok> can be issued via C<< $context->ok(...) >>. + + use Test::Stream::API qw/ context /; + my $context = context(); + $context->EVENT_TYPE(...); + +The arguments to the event method are the values for event accessors in order, +excluding the C<context>, C<created>, and C<in_subtest> arguments. For instance +here is how the Ok event is defined: + + package Test::Stream::Event::Ok; + use Test::Stream::Event( + accessors => [qw/real_bool name diag .../], + ... + ); + +This means that the C<< $context->ok >> method takes up to 5 arguments. The +first argument is a boolean true/false, the second is the name of the test, and +the third is an arrayref of diagnostics messages or +L<Test::Stream::Event::Diag> objects. + + $context->ok($bool, $name, [$diag]); + +Here are the main event methods, as well as their standard arguments: + +=over 4 + +=item $context->ok($bool, $name, \@diag) + +Issue an L<Test::Stream::Event::Ok> event. + +=item $context->diag($msg) + +Issue an L<Test::Stream::Event::Diag> event. + +=item $context->note($msg) + +Issue an L<Test::Stream::Event::Note> event. + +=item $context->plan($max, $directive, $reason) + +Issue an L<Test::Stream::Event::Plan> event. C<$max> is the number of expected +tests. C<$directive> is a plan directive such as 'no_plan' or 'skip_all'. +C<$reason> is the reason for the directive (only applicable to skip_all). + +=item $context->bail($reason) + +Issue an L<Test::Stream::Event::Bail> event. + +=back + +=head2 HARD WAY + +This is not recommended, but it demonstrates just how much the context shortcut +methods do for you. + + # First make a context + my $context = Test::Stream::Context->new_from_pairs( + frame => ..., # Where to report errors + stream => ..., # Test::Stream object to use + encoding => ..., # encoding from test package meta-data + in_todo => ..., # Are we in a todo? + todo => ..., # Which todo message should be used? + modern => ..., # Is the test package modern? + pid => ..., # Current PID + skip => ..., # Are we inside a 'skip' state? + provider => ..., # What tool created the context? + ); + + # Make the event + my $ok = Test::Stream::Event::Ok->new_from_pairs( + # Should reflect where the event was produced, NOT WHERE ERRORS ARE REPORTED + created => [__PACKAGE__, __FILE__, __LINE__], + context => $context, # A context is required + in_subtest => 0, + + bool => $bool, + name => $name, + diag => \@diag, + ); + + # Send the event to the stream. + Test::Stream->shared->send($ok); + + +=head1 EXPORTED FUNCTIONS + +All of these are functions. These functions all effect the current-shared +L<Test::Stream> object only. + +=head2 EVENT MANAGEMENT + +These let you install a callback that is triggered for all primary events. The +first argument is the L<Test::Stream> object, the second is the primary +L<Test::Stream::Event>, any additional arguments are subevents. All subevents +are L<Test::Stream::Event> objects which are directly tied to the primary one. +The main example of a subevent is the failure L<Test::Stream::Event::Diag> +object associated with a failed L<Test::Stream::Event::Ok>, events within a +subtest are another example. + +=over 4 + +=item listen { my ($stream, $event, @subevents) = @_; ... } + +Listen callbacks happen just after TAP is rendered (or just after it would be +rendered if TAP is disabled). + +=item munge { my ($stream, $event, @subevents) = @_; ... } + +Muinspect_todonge callbacks happen just before TAP is rendered (or just before +it would be rendered if TAP is disabled). + +=back + +=head2 POST-TEST BEHAVIOR + +=over 4 + +=item follow_up { my ($context) = @_; ... } + +A followup callback allows you to install behavior that happens either when +C<done_testing()> is called, or when the test file completes. + +B<CAVEAT:> If done_testing is not used, the callback will happen in the +C<END {...}> block used by L<Test::Stream> to enact magic at the end of the +test. + +=back + +=head2 CONCURRENCY + +=over 4 + +=item enable_forking() + +Turns forking support on. This turns on a synchronization method that *just +works* when you fork inside a test. This must be turned on prior to any +forking. + +=item cull() + +This can only be called in the main process or thread. This is a way to +manually pull in results from other processes or threads. Typically this +happens automatically, but this allows you to ensure results have been gathered +by a specific point. + +=back + +=head2 CONTROL OVER TAP + +=over 4 + +=item enable_tap() + +Turn TAP on (on by default). + +=item disable_tap() + +Turn TAP off. + +=item enable_numbers() + +Show test numbers when rendering TAP. + +=item disable_numbers() + +Do not show test numbers when rendering TAP. + +=item subtest_tap_instant() + +This is the default way to render subtests: + + # Subtest: a_subtest + ok 1 - pass + 1..1 + ok 1 - a_subtest + +Using this will automatically turn off C<subtest_tap_delayed> + +=item subtest_tap_delayed() + +This is an alternative way to render subtests, this method waits until the +subtest is complete then renders it in a structured way: + + ok 1 - a_subtest { + ok 1 - pass + 1..1 + } + +Using this will automatically turn off C<subtest_tap_instant> + +=item tap_encoding($ENCODING) + +This lets you change the encoding for TAP output. This only effects the current +test package. + +=item set_tap_outputs(encoding => 'legacy', std => $IO, err => $IO, todo => $IO) + +This lets you replace the filehandles used to output TAP for any specific +encoding. All fields are optional, any handles not specified will not be +changed. The C<encoding> parameter defaults to 'legacy'. + +B<Note:> The todo handle is used for failure output inside subtests where the +subtest was started already in todo. + +=item $hashref = get_tap_outputs($encoding) + +'legacy' is used when encoding is not specified. + +Returns a hashref with the output handles: + + { + encoding => $encoding, + std => $STD_HANDLE, + err => $ERR_HANDLE, + todo => $TODO_HANDLE, + } + +B<Note:> The todo handle is used for failure output inside subtests where the +subtest was started already in todo. + +=back + +=head2 TEST PACKAGE METADATA + +=over 4 + +=item $bool = is_modern($package) + +Check if a test package has the 'modern' flag. + +B<Note:> Throws an exception if C<$package> is not already a test package. + +=item set_modern($package, $value) + +Turn on the modern flag for the specified test package. + +B<Note:> Throws an exception if C<$package> is not already a test package. + +=back + +=head2 TODO MANAGEMENT + +=over 4 + +=item push_todo($todo) + +=item $todo = pop_todo() + +=item $todo = peek_todo() + +These can be used to manipulate a global C<todo> state. When a true value is at +the top of the todo stack it will effect any events generated via an +L<Test::Stream::Context> object. Typically all events are generated this way. + +=item set_todo($package, $todo) + +This lets you set the todo state for the specified test package. This will +throw an exception if the package is not a test package. + +=item $todo_hashref = inspect_todo($package) + +=item $todo_hashref = inspect_todo() + +This lets you inspect the TODO state. Optionally you can specify a package to +inspect. The return is a hashref with several keys: + + { + TODO => $TODO_STACK_ARRAYREF, + TB => $TEST_BUILDER_TODO_STATE, + META => $PACKAGE_METADATA_TODO_STATE, + PKG => $package::TODO, + } + +This lets you see what todo states are set where. This is primarily useful when +debugging to see why something is unexpectedly TODO, or when something is not +TODO despite expectations. + +=back + +=head2 TEST PACKAGE MANAGEMENT + +=over 4 + +=item $meta = is_tester($package) + +Check if a package is a tester, if it is the meta-object for the tester is +returned. + +=item $meta = init_tester($package) + +Set the package as a tester and return the meta-object. If the package is +already a tester it will return the existing meta-object. + +=back + +=head2 CONTEXTUAL INFORMATION + +=over 4 + +=item $context = context() + +This will get the correct L<Test::Stream::Context> object. This may be one that +was previously initialized, or it may generate a new one. Read the +L<Test::Stream::Context> documentation for more info. + +=item $stream = current_stream() + +This will return the current L<Test::Stream> Object. L<Test::Stream> objects +typically live on a global stack, the topmost item on the stack is the one that +is normally used. + +=back + +=head2 CAPTURING EVENTS + +=over 4 + +=item $events_arrayref = intercept { ... }; + +Any events generated inside the codeblock will be intercepted and returned. No +events within the block will go to the real L<Test::Stream> instance. + +B<Note:> This comes from the L<Test::Stream::Tester> package which provides +addiitonal tools that are useful for testing/validating events. + +=back + +=head2 TEST STATE + +=over 4 + +=item $num = state_count() + +Check how many tests have been run. + +=item $num = state_failed() + +Check how many tests have failed. + +=item $plan_event = state_plan() + +Check if a plan has been issued, if so the L<Test::Stream::Event::Plan> +instance will be returned. + +=item $bool = state_ended() + +True if the test is complete (after done_testing). + +=item $bool = is_passing() + +Check if the test state is passing. + +=back + +=encoding utf8 + +=head1 SOURCE + +The source code repository for Test::More can be found at +F<http://github.com/Test-More/test-more/>. + +=head1 MAINTAINER + +=over 4 + +=item Chad Granum E<lt>exodist@cpan.orgE<gt> + +=back + +=head1 AUTHORS + +The following people have all contributed to the Test-More dist (sorted using +VIM's sort function). + +=over 4 + +=item Chad Granum E<lt>exodist@cpan.orgE<gt> + +=item Fergal Daly E<lt>fergal@esatclear.ie>E<gt> + +=item Mark Fowler E<lt>mark@twoshortplanks.comE<gt> + +=item Michael G Schwern E<lt>schwern@pobox.comE<gt> + +=item 唐鳳 + +=back + +=head1 COPYRIGHT + +There has been a lot of code migration between modules, +here are all the original copyrights together: + +=over 4 + +=item Test::Stream + +=item Test::Stream::Tester + +Copyright 2014 Chad Granum E<lt>exodist7@gmail.comE<gt>. + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +See F<http://www.perl.com/perl/misc/Artistic.html> + +=item Test::Simple + +=item Test::More + +=item Test::Builder + +Originally authored by Michael G Schwern E<lt>schwern@pobox.comE<gt> with much +inspiration from Joshua Pritikin's Test module and lots of help from Barrie +Slaymaker, Tony Bowden, blackstar.co.uk, chromatic, Fergal Daly and the perl-qa +gang. + +Idea by Tony Bowden and Paul Johnson, code by Michael G Schwern +E<lt>schwern@pobox.comE<gt>, wardrobe by Calvin Klein. + +Copyright 2001-2008 by Michael G Schwern E<lt>schwern@pobox.comE<gt>. + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +See F<http://www.perl.com/perl/misc/Artistic.html> + +=item Test::use::ok + +To the extent possible under law, 唐鳳 has waived all copyright and related +or neighboring rights to L<Test-use-ok>. + +This work is published from Taiwan. + +L<http://creativecommons.org/publicdomain/zero/1.0> + +=item Test::Tester + +This module is copyright 2005 Fergal Daly <fergal@esatclear.ie>, some parts +are based on other people's work. + +Under the same license as Perl itself + +See http://www.perl.com/perl/misc/Artistic.html + +=item Test::Builder::Tester + +Copyright Mark Fowler E<lt>mark@twoshortplanks.comE<gt> 2002, 2004. + +This program is free software; you can redistribute it +and/or modify it under the same terms as Perl itself. + +=back diff --git a/cpan/Test-Simple/lib/Test/Stream/Context.pm b/cpan/Test-Simple/lib/Test/Stream/Context.pm index 51b89e26ca..333fe4fd61 100644 --- a/cpan/Test-Simple/lib/Test/Stream/Context.pm +++ b/cpan/Test-Simple/lib/Test/Stream/Context.pm @@ -15,8 +15,9 @@ use Test::Stream::ArrayBase( accessors => [qw/frame stream encoding in_todo todo modern pid skip diag_todo provider monkeypatch_stash/], ); -use Test::Stream::Exporter qw/import export_to default_exports/; +use Test::Stream::Exporter qw/import export_to default_exports exports/; default_exports qw/context/; +exports qw/inspect_todo/; Test::Stream::Exporter->cleanup(); { @@ -24,6 +25,7 @@ Test::Stream::Exporter->cleanup(); $Test::Builder::Level ||= 1; } +my @TODO; my $CURRENT; sub init { @@ -36,6 +38,10 @@ sub init { sub peek { $CURRENT } sub clear { $CURRENT = undef } +sub push_todo { push @TODO => pop @_ } +sub pop_todo { pop @TODO } +sub peek_todo { @TODO ? $TODO[-1] : undef } + sub set { $CURRENT = pop; weaken($CURRENT); @@ -68,7 +74,11 @@ sub context { my $todo_pkg = $meta->[Test::Stream::Meta::PACKAGE]; no strict 'refs'; no warnings 'once'; - if ($todo = $meta->[Test::Stream::Meta::TODO]) { + if (@TODO) { + $todo = $TODO[-1]; + $in_todo = 1; + } + elsif ($todo = $meta->[Test::Stream::Meta::TODO]) { $in_todo = 1; } elsif ($todo = ${"$pkg\::TODO"}) { @@ -341,23 +351,35 @@ sub register_event { sub meta { is_tester($_[0]->[FRAME]->[0]) } +sub inspect_todo { + my ($pkg) = @_; + my $meta = $pkg ? is_tester($pkg) : undef; + + no strict 'refs'; + return { + TODO => [@TODO], + $Test::Builder::Test ? (TB => $Test::Builder::Test->{Todo}) : (), + $meta ? (META => $meta->[Test::Stream::Meta::TODO]) : (), + $pkg ? (PKG => ${"$pkg\::TODO"}) : (), + }; +} + sub hide_todo { my $self = shift; - no strict 'refs'; - no warnings 'once'; my $pkg = $self->[FRAME]->[0]; my $meta = is_tester($pkg); - my $found = { - TB => $Test::Builder::Test ? $Test::Builder::Test->{Todo} : undef, - META => $meta->[Test::Stream::Meta::TODO], - PKG => ${"$pkg\::TODO"}, - }; + my $found = inspect_todo($pkg); + @TODO = (); $Test::Builder::Test->{Todo} = undef; $meta->[Test::Stream::Meta::TODO] = undef; - ${"$pkg\::TODO"} = undef; + { + no strict 'refs'; + no warnings 'once'; + ${"$pkg\::TODO"} = undef; + } return $found; } @@ -365,26 +387,25 @@ sub hide_todo { sub restore_todo { my $self = shift; my ($found) = @_; - no strict 'refs'; - no warnings 'once'; my $pkg = $self->[FRAME]->[0]; my $meta = is_tester($pkg); + @TODO = @{$found->{TODO}}; $Test::Builder::Test->{Todo} = $found->{TB}; $meta->[Test::Stream::Meta::TODO] = $found->{META}; - ${"$pkg\::TODO"} = $found->{PKG}; + { + no strict 'refs'; + no warnings 'once'; + ${"$pkg\::TODO"} = $found->{PKG}; + } - my $found2 = { - TB => $Test::Builder::Test ? $Test::Builder::Test->{Todo} : undef, - META => $meta->[Test::Stream::Meta::TODO] || undef, - PKG => ${"$pkg\::TODO"} || undef, - }; + my $found2 = inspect_todo($pkg); for my $k (qw/TB META PKG/) { no warnings 'uninitialized'; next if "$found->{$k}" eq "$found2->{$k}"; - die "Mismatch! $k:\t$found->{$k}\n\t$found2->{$k}\n" + die "INTERNAL ERROR: Mismatch! $k:\t$found->{$k}\n\t$found2->{$k}\n" } return; @@ -543,6 +564,24 @@ be found. The returned C<$stash> must be used to restore it later. =back +=head2 CLASS METHODS + +B<Note:> These can effect all test packages, if that is not what you want do not use them!. + +=over 4 + +=item $msg = Test::Stream::Context->push_todo($msg) + +=item $msg = Test::Stream::Context->pop_todo() + +=item $msg = Test::Stream::Context->peek_todo() + +These manage a global todo stack. Any new context created will check here first +for a TODO. Changing this will not effect any existing context instances. This +is a reliable way to set a global todo that effects any/all packages. + +=back + =encoding utf8 =head1 SOURCE diff --git a/cpan/Test-Simple/lib/Test/Stream/Event.pm b/cpan/Test-Simple/lib/Test/Stream/Event.pm index 0e35225589..e814205a5e 100644 --- a/cpan/Test-Simple/lib/Test/Stream/Event.pm +++ b/cpan/Test-Simple/lib/Test/Stream/Event.pm @@ -74,6 +74,8 @@ sub summary { ); } +sub subevents { } + 1; __END__ diff --git a/cpan/Test-Simple/lib/Test/Stream/Event/Ok.pm b/cpan/Test-Simple/lib/Test/Stream/Event/Ok.pm index 9b1be21aa5..bfc614b29e 100644 --- a/cpan/Test-Simple/lib/Test/Stream/Event/Ok.pm +++ b/cpan/Test-Simple/lib/Test/Stream/Event/Ok.pm @@ -139,6 +139,8 @@ sub add_diag { } } +sub subevents { @{$_[0]->[DIAG] || []} } + sub to_legacy { my $self = shift; diff --git a/cpan/Test-Simple/lib/Test/Stream/Event/Subtest.pm b/cpan/Test-Simple/lib/Test/Stream/Event/Subtest.pm index ec54743ddf..4557796953 100644 --- a/cpan/Test-Simple/lib/Test/Stream/Event/Subtest.pm +++ b/cpan/Test-Simple/lib/Test/Stream/Event/Subtest.pm @@ -11,6 +11,13 @@ use Test::Stream::Event( accessors => [qw/state events exception/], ); +sub subevents { + return ( + @{$_[0]->[DIAG] || []}, + map { $_, $_->subevents } @{$_[0]->[EVENTS] || []}, + ); +} + sub init { my $self = shift; diff --git a/cpan/Test-Simple/lib/Test/Stream/Tester.pm b/cpan/Test-Simple/lib/Test/Stream/Tester.pm index 80e45bd0d5..91e9781f0d 100644 --- a/cpan/Test-Simple/lib/Test/Stream/Tester.pm +++ b/cpan/Test-Simple/lib/Test/Stream/Tester.pm @@ -261,7 +261,7 @@ your tools! =item $events = intercept(sub { ... }) -Capture the L<Test::Builder::Event> objects generated by tests inside the block. +Capture the L<Test::Stream::Event> objects generated by tests inside the block. =item events_are(\@events, $check) @@ -370,23 +370,23 @@ the C<$events> array reference. =head2 EVENT TYPES -All events will be subclasses of L<Test::Builder::Event> +All events will be subclasses of L<Test::Stream::Event> =over 4 -=item L<Test::Builder::Event::Ok> +=item L<Test::Stream::Event::Ok> -=item L<Test::Builder::Event::Note> +=item L<Test::Stream::Event::Note> -=item L<Test::Builder::Event::Diag> +=item L<Test::Stream::Event::Diag> -=item L<Test::Builder::Event::Plan> +=item L<Test::Stream::Event::Plan> -=item L<Test::Builder::Event::Finish> +=item L<Test::Stream::Event::Finish> -=item L<Test::Builder::Event::Bail> +=item L<Test::Stream::Event::Bail> -=item L<Test::Builder::Event::Subtest> +=item L<Test::Stream::Event::Subtest> =back @@ -493,32 +493,32 @@ Specify a sub that will validate the value of the field. =head2 WHAT FIELDS ARE AVAILABLE? This is specific to the event type. All events inherit from -L<Test::Builder::Event> which provides a C<summary()> method. The C<summary()> +L<Test::Stream::Event> which provides a C<summary()> method. The C<summary()> method returns a list of key/value pairs I<(not a reference!)> with all fields that are for public consumption. For each of the following modules see the B<SUMMARY FIELDS> section for a list of fields made available. These fields are inherited when events are subclassed, and all events have the summary fields present in -L<Test::Builder::Event>. +L<Test::Stream::Event>. =over 4 -=item L<Test::Builder::Event/"SUMMARY FIELDS"> +=item L<Test::Stream::Event/"SUMMARY FIELDS"> -=item L<Test::Builder::Event::Ok/"SUMMARY FIELDS"> +=item L<Test::Stream::Event::Ok/"SUMMARY FIELDS"> -=item L<Test::Builder::Event::Note/"SUMMARY FIELDS"> +=item L<Test::Stream::Event::Note/"SUMMARY FIELDS"> -=item L<Test::Builder::Event::Diag/"SUMMARY FIELDS"> +=item L<Test::Stream::Event::Diag/"SUMMARY FIELDS"> -=item L<Test::Builder::Event::Plan/"SUMMARY FIELDS"> +=item L<Test::Stream::Event::Plan/"SUMMARY FIELDS"> -=item L<Test::Builder::Event::Finish/"SUMMARY FIELDS"> +=item L<Test::Stream::Event::Finish/"SUMMARY FIELDS"> -=item L<Test::Builder::Event::Bail/"SUMMARY FIELDS"> +=item L<Test::Stream::Event::Bail/"SUMMARY FIELDS"> -=item L<Test::Builder::Event::Subtest/"SUMMARY FIELDS"> +=item L<Test::Stream::Event::Subtest/"SUMMARY FIELDS"> =back diff --git a/cpan/Test-Simple/lib/Test/Stream/Toolset.pm b/cpan/Test-Simple/lib/Test/Stream/Toolset.pm index 74a66bd257..41b4bbeb5d 100644 --- a/cpan/Test-Simple/lib/Test/Stream/Toolset.pm +++ b/cpan/Test-Simple/lib/Test/Stream/Toolset.pm @@ -15,10 +15,51 @@ use Test::Stream::Event::Ok; use Test::Stream::Event::Plan; use Test::Stream::Event::Subtest; -use Test::Stream::Exporter qw/import export_to default_exports/; +use Test::Stream::Exporter qw/import export_to default_exports export/; default_exports qw/is_tester init_tester context/; + +export before_import => sub { + my $class = shift; + my ($importer, $list) = @_; + + my $meta = init_tester($importer); + + my $context = context(1); + my $other = []; + my $idx = 0; + + while ($idx <= $#{$list}) { + my $item = $list->[$idx++]; + next unless $item; + + if (defined $item and $item eq 'no_diag') { + Test::Stream->shared->set_no_diag(1); + } + elsif ($item eq 'tests') { + $context->plan($list->[$idx++]); + } + elsif ($item eq 'skip_all') { + $context->plan(0, 'SKIP', $list->[$idx++]); + } + elsif ($item eq 'no_plan') { + $context->plan(0, 'NO PLAN'); + } + elsif ($item eq 'import') { + push @$other => @{$list->[$idx++]}; + } + else { + carp("Unknown option: $item"); + } + } + + @$list = @$other; + + return; +}; + Test::Stream::Exporter->cleanup(); + 1; =head1 NAME @@ -77,6 +118,25 @@ of integrating with L<Test::Builder> and other testing tools much easier. 1; +=head2 TEST-MORE STYLE IMPORT + +If you want to be able to pass Test-More arguments such as 'tests', 'skip_all', +and 'no_plan', then use the following: + + package My::Tester; + use Test::Stream::Exporter; # Gives us 'import()' + use Test::Stream::Toolset; # default exports + use Test::Stream::Toolset 'before_import' # Test-More style argument support + +2 'use' statements were used above for clarity, you can get all the desired +imports at once: + + use Test::Stream::Toolset qw/context init_tester is_tester before_import/; + +Then in the test: + + use My::Tester tests => 5; + =head1 EXPORTS =over 4 @@ -106,6 +166,14 @@ will return the existing meta object. This method can be used to check if an object is a tester. If the object is a tester it will return the meta object for the tester. +=item before_import + +This method is used by C<import()> to parse Test-More style import arguments. +You should never need to run this yourself, it works just by being imported. + +B<NOTE:> This will only work if you use Test::Stream::Exporter for your +'import' method. + =back =head1 GENERATING EVENTS diff --git a/cpan/Test-Simple/lib/Test/Tester.pm b/cpan/Test-Simple/lib/Test/Tester.pm index 2f36c8f9b8..e758a50cca 100644 --- a/cpan/Test-Simple/lib/Test/Tester.pm +++ b/cpan/Test-Simple/lib/Test/Tester.pm @@ -16,7 +16,7 @@ require Exporter; use vars qw( @ISA @EXPORT $VERSION ); -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) @EXPORT = qw( run_tests check_tests check_test cmp_results show_space ); diff --git a/cpan/Test-Simple/lib/Test/use/ok.pm b/cpan/Test-Simple/lib/Test/use/ok.pm index a07c0a7f9e..18d10261fd 100644 --- a/cpan/Test-Simple/lib/Test/use/ok.pm +++ b/cpan/Test-Simple/lib/Test/use/ok.pm @@ -3,7 +3,7 @@ use strict; use warnings; use 5.005; -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) use Test::Stream 1.301001 '-internal'; diff --git a/cpan/Test-Simple/lib/ok.pm b/cpan/Test-Simple/lib/ok.pm index 088ec7e478..f7fa459dc0 100644 --- a/cpan/Test-Simple/lib/ok.pm +++ b/cpan/Test-Simple/lib/ok.pm @@ -6,7 +6,7 @@ use Test::Stream 1.301001 '-internal'; use Test::More 1.301001 (); use Test::Stream::Carp qw/croak/; -our $VERSION = '1.301001_079'; +our $VERSION = '1.301001_084'; $VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval) sub import { diff --git a/cpan/Test-Simple/t/Behavior/CustomOutput.t b/cpan/Test-Simple/t/Behavior/CustomOutput.t new file mode 100644 index 0000000000..e4d7185809 --- /dev/null +++ b/cpan/Test-Simple/t/Behavior/CustomOutput.t @@ -0,0 +1,137 @@ +use strict; +use warnings; + +use Test::Stream; +use Test::More; +use Scalar::Util qw/blessed/; + +# This will replace the main Test::Stream object for the scope of the coderef. +# We apply our output changes only in that scope so that this test itself can +# verify things with regular TAP output. The things done inside thise sub would +# work just fine when used by any module to alter the output. + +my @OUTPUT; +Test::Stream->intercept(sub { + # Turn off normal TAP output + Test::Stream->shared->set_use_tap(0); + + # Turn off legacy storage of results. + Test::Stream->shared->set_use_legacy(0); + + Test::Stream->shared->listen(sub { + my ($stream, $event) = @_; + + push @OUTPUT => "We got an event of type " . blessed($event); + }); + + # Now we run some tests, no TAP will be produced, instead all events will + # be added to @OUTPUT. + + ok(1, "pass"); + ok(0, "fail"); + + subtest foo => sub { + ok(1, "pass"); + ok(0, "fail"); + }; + + diag "Hello"; +}); + +is_deeply( + \@OUTPUT, + [ + 'We got an event of type Test::Stream::Event::Ok', + 'We got an event of type Test::Stream::Event::Ok', + 'We got an event of type Test::Stream::Event::Note', + 'We got an event of type Test::Stream::Event::Subtest', + 'We got an event of type Test::Stream::Event::Diag', + ], + "Got all events" +); + +# Now for something more complicated, lets have everything be normal TAP, +# except subtests + +my (@STDOUT, @STDERR, @TODO); +my @IO = (\@STDOUT, \@STDERR, \@TODO); + +Test::Stream->intercept(sub { + # Turn off normal TAP output + Test::Stream->shared->set_use_tap(0); + + # Turn off legacy storage of results. + Test::Stream->shared->set_use_legacy(0); + + my $number = 1; + Test::Stream->shared->listen(sub { + my ($stream, $e) = @_; + + # Do not output results inside subtests + return if $e->in_subtest; + + return unless $e->can('to_tap'); + + my $num = $stream->use_numbers ? $number++ : undef; + + # Get the TAP for the event + my @sets; + if ($e->isa('Test::Stream::Event::Subtest')) { + # Subtest is a subclass of Ok, use Ok's to_tap method: + @sets = Test::Stream::Event::Ok::to_tap($e, $num); + # Here you can also add whatever output you want. + } + else { + @sets = $e->to_tap($num); + } + + for my $set (@sets) { + my ($hid, $msg) = @$set; + next unless $msg; + my $enc = $e->encoding || die "Could not find encoding!"; + + # This is how you get the proper handle to use (STDERR, STDOUT, ETC). + my $io = $stream->io_sets->{$enc}->[$hid] || die "Could not find IO $hid for $enc"; + $io = $IO[$hid]; + + # Make sure we don't alter these vars. + local($\, $", $,) = (undef, ' ', ''); + + # Normally you print to the IO, but here we are pushing to arrays + chomp($msg); + push @$io => $msg; + } + }); + + # Now we run some tests, no TAP will be produced, instead all events will + # be added to our ourputs + + ok(1, "pass"); + ok(0, "fail"); + + subtest foo => sub { + ok(1, "pass"); + ok(0, "fail"); + }; + + diag "Hello"; +}); + +is(@TODO, 0, "No TODO output"); + +is_deeply( + \@STDOUT, + [ + 'ok 1 - pass', + 'not ok 2 - fail', + '# Subtest: foo', + # As planned, none of the events inside the subtest got rendered. + 'not ok 4 - foo' + ], + "Got expected TAP" +); + +is(pop(@STDERR), "# Hello", "Got the hello diag"); +is(@STDERR, 2, "got diag for 2 failed tests"); + +done_testing; diff --git a/cpan/Test-Simple/t/Legacy/subtest/fork.t b/cpan/Test-Simple/t/Legacy/subtest/fork.t index 8d763a49fd..7e0c6851ff 100644 --- a/cpan/Test-Simple/t/Legacy/subtest/fork.t +++ b/cpan/Test-Simple/t/Legacy/subtest/fork.t @@ -8,6 +8,13 @@ use IO::Pipe; use Test::Builder; use Test::More tests => 1; +# On systems that fake forking, localized vars get unwound improperly +# post-fork. the 'subtest' function localizes $@ and $!, as such this +# test will fail on fake-fork systems up until 5.20.2 +plan skip_all => "Skipping fork tests on $^O" + if ($^O eq 'MSWin32' || $^O eq 'NetWare') + && !eval { require v5.20.2 }; + subtest 'fork within subtest' => sub { plan tests => 2; diff --git a/cpan/Test-Simple/t/Test-Stream-API.t b/cpan/Test-Simple/t/Test-Stream-API.t new file mode 100644 index 0000000000..688d9d469d --- /dev/null +++ b/cpan/Test-Simple/t/Test-Stream-API.t @@ -0,0 +1,331 @@ +use strict; +use warnings; + +use Test::Stream; +use Test::More; +use Test::Stream::Tester qw/events_are event directive check/; +use Test::MostlyLike; + +require Test::Builder; +require Test::CanFork; + +use Test::Stream::API qw{ + listen munge follow_up + enable_forking cull + peek_todo push_todo pop_todo set_todo inspect_todo + is_tester init_tester + is_modern set_modern + context peek_context clear_context set_context + intercept + state_count state_failed state_plan state_ended is_passing + current_stream + + disable_tap enable_tap subtest_tap_instant subtest_tap_delayed tap_encoding + enable_numbers disable_numbers set_tap_outputs get_tap_outputs +}; + +can_ok(__PACKAGE__, qw{ + listen munge follow_up + enable_forking cull + peek_todo push_todo pop_todo set_todo inspect_todo + is_tester init_tester + is_modern set_modern + context peek_context clear_context set_context + intercept + state_count state_failed state_plan state_ended is_passing + current_stream + + disable_tap enable_tap subtest_tap_instant subtest_tap_delayed tap_encoding + enable_numbers disable_numbers set_tap_outputs get_tap_outputs +}); + +ok(!is_tester('My::Tester'), "Not a tester"); +isa_ok(init_tester('My::Tester'), 'Test::Stream::Meta'); +isa_ok(is_tester('My::Tester'), 'Test::Stream::Meta'); + +ok(!is_modern('My::Tester'), "Not a modern tester"); +set_modern('My::Tester', 1); +ok(is_modern('My::Tester'), "a modern tester"); +set_modern('My::Tester', 0); +ok(!is_modern('My::Tester'), "Not a modern tester"); + +ok(my $ctx = context(), "Got context"); +isa_ok($ctx, 'Test::Stream::Context'); +is(context(), $ctx, "Got the same instance again"); +is(peek_context(), $ctx, "peek"); +my $ref = "$ctx"; + +clear_context(); +my $ne = context() . "" ne $ref; +ok($ne, "cleared"); + +set_context($ctx); +is(context(), $ctx, "Got the same instance again"); + +$ctx = undef; +$ne = context() . "" ne $ref; +ok($ne, "New instance"); + +isa_ok(current_stream(), 'Test::Stream'); + +my @munge; +my @listen; +my @follow; +intercept { + munge { push @munge => $_[1] }; + listen { push @listen => $_[1] }; + + follow_up { push @follow => $_[0]->snapshot }; + + ok(1, "pass"); + diag "foo"; + + done_testing; +}; + +is(@listen, 3, "listen got 3 events"); +is(@munge, 3, "munge got 3 events"); +is(@follow, 1, "Follow was triggered"); + +my $want = check { + event ok => { bool => 1 }; + event diag => { message => 'foo' }; + event plan => { max => 1 }; + directive 'end'; +}; +events_are( \@listen, $want, "Listen events" ); +events_are( \@munge, $want, "Munge events" ); +isa_ok($follow[0], 'Test::Stream::Context'); + + +my $events = intercept { + Test::CanFork->import; + + # On systems that fake forking, localized vars get unwound improperly + # post-fork. the 'intercept' function localizes $@ and $!, as such this + # test will fail on fake-fork systems up until 5.20.2 + plan skip_all => "Skipping fork tests on $^O" + if ($^O eq 'MSWin32' || $^O eq 'NetWare') + && !eval { require v5.20.2 }; + + enable_forking; + + my $pid = fork(); + if ($pid) { # Parent + waitpid($pid, 0); + cull; + ok(1, "From Parent"); + } + else { # child + ok(1, "From Child"); + exit 0; + } +}; + +if (@$events == 1) { + events_are ( + $events, + check { + event plan => {}; + }, + "Not testing forking" + ); +} +else { + events_are ( + $events, + check { + event ok => { name => 'From Child' }; + event ok => { name => 'From Parent' }; + }, + "Got forked events" + ); +} + +events_are( + intercept { + ok(0, "fail"); + push_todo('foo'); + ok(0, "fail"); + push_todo('bar'); + ok(0, "fail"); + is(peek_todo(), 'bar', "peek works"); + pop_todo(); + ok(0, "fail"); + pop_todo(); + ok(0, "fail"); + }, + check { + event ok => {todo => '', in_todo => 0}; + event ok => {todo => 'foo', in_todo => 1}; + event ok => {todo => 'bar', in_todo => 1}; + event ok => {bool => 1, real_bool => 1}; # Verify peek + event ok => {todo => 'foo', in_todo => 1}; + event ok => {todo => '', in_todo => 0}; + }, + "Verified TODO stack" +); + +my $meta = init_tester('My::Tester'); +ok(!$meta->todo, "Package is not in todo"); +set_todo('My::Tester', 'foo'); +is($meta->todo, 'foo', "Package is in todo"); + +my @todos = ( + inspect_todo, + inspect_todo('My::Tester'), +); +push_todo('foo'); +push_todo('bar'); +Test::Builder->new->todo_start('tb todo'); +$My::Tester::TODO = 'pkg todo'; +push @todos => inspect_todo, inspect_todo('My::Tester'); +$My::Tester::TODO = undef; +Test::Builder->new->todo_end(); +pop_todo; +pop_todo; +set_todo('My::Tester', undef); +push @todos => inspect_todo, inspect_todo('My::Tester'); + +is_deeply( + \@todos, + [ + { + TB => undef, + TODO => [], + }, + { + META => 'foo', + PKG => undef, + TB => undef, + TODO => [], + }, + { + TB => 'tb todo', + TODO => [qw/foo bar/], + }, + { + META => 'foo', + PKG => 'pkg todo', + TB => 'tb todo', + TODO => [qw/foo bar/], + }, + { + TB => undef, + TODO => [], + }, + { + META => undef, + PKG => undef, + TB => undef, + TODO => [], + } + ], + "Todo state from inspect todo" +); + +my @state; +intercept { + plan tests => 3; + ok(1, "pass"); + ok(2, "pass"); + + push @state => { + count => state_count() || 0, + failed => state_failed() || 0, + plan => state_plan() || undef, + ended => state_ended() || undef, + passing => is_passing(), + }; + + ok(0, "fail"); + done_testing; + + push @state => { + count => state_count() || 0, + failed => state_failed() || 0, + plan => state_plan() || undef, + ended => state_ended() || undef, + passing => is_passing(), + }; +}; + +mostly_like( + \@state, + [ + { count => 2, failed => 0, passing => 1, ended => undef }, + { count => 3, failed => 1, passing => 0 }, + ], + "Verified Test state" +); + +events_are( + [ $state[0]->{plan}, $state[1]->{plan} ], + check { + event plan => { max => 3 }; + event plan => { max => 3 }; + }, + "Parts of state that are events check out." +); + +isa_ok( $state[1]->{ended}, 'Test::Stream::Context' ); + +my $got; +my $results = ""; +my $utf8 = ""; +open( my $fh, ">>", \$results ) || die "Could not open handle to scalar!"; +open( my $fh_utf8, ">>", \$utf8 ) || die "Could not open handle to scalar!"; + +intercept { + enable_tap(); # Disabled by default in intercept() + set_tap_outputs( std => $fh, err => $fh, todo => $fh ); + $got = get_tap_outputs(); + + ok(1, "pass"); + + disable_tap(); + ok(0, "fail"); + + enable_tap(); + tap_encoding('utf8'); + set_tap_outputs( encoding => 'utf8', std => $fh_utf8, err => $fh_utf8, todo => $fh_utf8 ); + ok(1, "pass"); + tap_encoding('legacy'); + + disable_numbers(); + ok(1, "pass"); + enable_numbers(); + ok(1, "pass"); + + subtest_tap_instant(); + subtest foo => sub { ok(1, 'pass') }; + + subtest_tap_delayed(); + subtest foo => sub { ok(1, 'pass') }; +}; + +is_deeply( + $got, + { encoding => 'legacy', std => $fh, err => $fh, todo => $fh }, + "Got outputs" +); + +is( $results, <<EOT, "got TAP output"); +ok 1 - pass +ok - pass +ok 5 - pass +# Subtest: foo + ok 1 - pass + 1..1 +ok 6 - foo +ok 7 - foo { + ok 1 - pass + 1..1 +} +EOT + +is( $utf8, <<EOT, "got utf8 TAP output"); +ok 3 - pass +EOT + +done_testing; |