15759b3d2Safresh1package Test2::Tools::Tiny; 25759b3d2Safresh1use strict; 35759b3d2Safresh1use warnings; 45759b3d2Safresh1 55759b3d2Safresh1BEGIN { 65759b3d2Safresh1 if ($] lt "5.008") { 75759b3d2Safresh1 require Test::Builder::IO::Scalar; 85759b3d2Safresh1 } 95759b3d2Safresh1} 105759b3d2Safresh1 115759b3d2Safresh1use Scalar::Util qw/blessed/; 125759b3d2Safresh1 135759b3d2Safresh1use Test2::Util qw/try/; 145759b3d2Safresh1use Test2::API qw/context run_subtest test2_stack/; 155759b3d2Safresh1 165759b3d2Safresh1use Test2::Hub::Interceptor(); 175759b3d2Safresh1use Test2::Hub::Interceptor::Terminator(); 185759b3d2Safresh1 19*5486feefSafresh1our $VERSION = '1.302199'; 205759b3d2Safresh1 215759b3d2Safresh1BEGIN { require Exporter; our @ISA = qw(Exporter) } 225759b3d2Safresh1our @EXPORT = qw{ 235759b3d2Safresh1 ok is isnt like unlike is_deeply diag note skip_all todo plan done_testing 245759b3d2Safresh1 warnings exception tests capture 255759b3d2Safresh1}; 265759b3d2Safresh1 275759b3d2Safresh1sub ok($;$@) { 285759b3d2Safresh1 my ($bool, $name, @diag) = @_; 295759b3d2Safresh1 my $ctx = context(); 305759b3d2Safresh1 315759b3d2Safresh1 return $ctx->pass_and_release($name) if $bool; 325759b3d2Safresh1 return $ctx->fail_and_release($name, @diag); 335759b3d2Safresh1} 345759b3d2Safresh1 355759b3d2Safresh1sub is($$;$@) { 365759b3d2Safresh1 my ($got, $want, $name, @diag) = @_; 375759b3d2Safresh1 my $ctx = context(); 385759b3d2Safresh1 395759b3d2Safresh1 my $bool; 405759b3d2Safresh1 if (defined($got) && defined($want)) { 415759b3d2Safresh1 $bool = "$got" eq "$want"; 425759b3d2Safresh1 } 435759b3d2Safresh1 elsif (defined($got) xor defined($want)) { 445759b3d2Safresh1 $bool = 0; 455759b3d2Safresh1 } 465759b3d2Safresh1 else { # Both are undef 475759b3d2Safresh1 $bool = 1; 485759b3d2Safresh1 } 495759b3d2Safresh1 505759b3d2Safresh1 return $ctx->pass_and_release($name) if $bool; 515759b3d2Safresh1 525759b3d2Safresh1 $got = '*NOT DEFINED*' unless defined $got; 535759b3d2Safresh1 $want = '*NOT DEFINED*' unless defined $want; 545759b3d2Safresh1 unshift @diag => ( 555759b3d2Safresh1 "GOT: $got", 565759b3d2Safresh1 "EXPECTED: $want", 575759b3d2Safresh1 ); 585759b3d2Safresh1 595759b3d2Safresh1 return $ctx->fail_and_release($name, @diag); 605759b3d2Safresh1} 615759b3d2Safresh1 625759b3d2Safresh1sub isnt($$;$@) { 635759b3d2Safresh1 my ($got, $want, $name, @diag) = @_; 645759b3d2Safresh1 my $ctx = context(); 655759b3d2Safresh1 665759b3d2Safresh1 my $bool; 675759b3d2Safresh1 if (defined($got) && defined($want)) { 685759b3d2Safresh1 $bool = "$got" ne "$want"; 695759b3d2Safresh1 } 705759b3d2Safresh1 elsif (defined($got) xor defined($want)) { 715759b3d2Safresh1 $bool = 1; 725759b3d2Safresh1 } 735759b3d2Safresh1 else { # Both are undef 745759b3d2Safresh1 $bool = 0; 755759b3d2Safresh1 } 765759b3d2Safresh1 775759b3d2Safresh1 return $ctx->pass_and_release($name) if $bool; 785759b3d2Safresh1 795759b3d2Safresh1 unshift @diag => "Strings are the same (they should not be)" 805759b3d2Safresh1 unless $bool; 815759b3d2Safresh1 825759b3d2Safresh1 return $ctx->fail_and_release($name, @diag); 835759b3d2Safresh1} 845759b3d2Safresh1 855759b3d2Safresh1sub like($$;$@) { 865759b3d2Safresh1 my ($thing, $pattern, $name, @diag) = @_; 875759b3d2Safresh1 my $ctx = context(); 885759b3d2Safresh1 895759b3d2Safresh1 my $bool; 905759b3d2Safresh1 if (defined($thing)) { 915759b3d2Safresh1 $bool = "$thing" =~ $pattern; 925759b3d2Safresh1 unshift @diag => ( 935759b3d2Safresh1 "Value: $thing", 945759b3d2Safresh1 "Does not match: $pattern" 955759b3d2Safresh1 ) unless $bool; 965759b3d2Safresh1 } 975759b3d2Safresh1 else { 985759b3d2Safresh1 $bool = 0; 995759b3d2Safresh1 unshift @diag => "Got an undefined value."; 1005759b3d2Safresh1 } 1015759b3d2Safresh1 1025759b3d2Safresh1 return $ctx->pass_and_release($name) if $bool; 1035759b3d2Safresh1 return $ctx->fail_and_release($name, @diag); 1045759b3d2Safresh1} 1055759b3d2Safresh1 1065759b3d2Safresh1sub unlike($$;$@) { 1075759b3d2Safresh1 my ($thing, $pattern, $name, @diag) = @_; 1085759b3d2Safresh1 my $ctx = context(); 1095759b3d2Safresh1 1105759b3d2Safresh1 my $bool; 1115759b3d2Safresh1 if (defined($thing)) { 1125759b3d2Safresh1 $bool = "$thing" !~ $pattern; 1135759b3d2Safresh1 unshift @diag => ( 1145759b3d2Safresh1 "Unexpected pattern match (it should not match)", 1155759b3d2Safresh1 "Value: $thing", 1165759b3d2Safresh1 "Matches: $pattern" 1175759b3d2Safresh1 ) unless $bool; 1185759b3d2Safresh1 } 1195759b3d2Safresh1 else { 1205759b3d2Safresh1 $bool = 0; 1215759b3d2Safresh1 unshift @diag => "Got an undefined value."; 1225759b3d2Safresh1 } 1235759b3d2Safresh1 1245759b3d2Safresh1 return $ctx->pass_and_release($name) if $bool; 1255759b3d2Safresh1 return $ctx->fail_and_release($name, @diag); 1265759b3d2Safresh1} 1275759b3d2Safresh1 1285759b3d2Safresh1sub is_deeply($$;$@) { 1295759b3d2Safresh1 my ($got, $want, $name, @diag) = @_; 1305759b3d2Safresh1 my $ctx = context(); 1315759b3d2Safresh1 1325759b3d2Safresh1 no warnings 'once'; 1335759b3d2Safresh1 require Data::Dumper; 1345759b3d2Safresh1 1355759b3d2Safresh1 # Otherwise numbers might be unquoted 1365759b3d2Safresh1 local $Data::Dumper::Useperl = 1; 1375759b3d2Safresh1 1385759b3d2Safresh1 local $Data::Dumper::Sortkeys = 1; 1395759b3d2Safresh1 local $Data::Dumper::Deparse = 1; 1405759b3d2Safresh1 local $Data::Dumper::Freezer = 'XXX'; 1415759b3d2Safresh1 local *UNIVERSAL::XXX = sub { 1425759b3d2Safresh1 my ($thing) = @_; 1435759b3d2Safresh1 if (ref($thing)) { 1445759b3d2Safresh1 $thing = {%$thing} if "$thing" =~ m/=HASH/; 1455759b3d2Safresh1 $thing = [@$thing] if "$thing" =~ m/=ARRAY/; 1465759b3d2Safresh1 $thing = \"$$thing" if "$thing" =~ m/=SCALAR/; 1475759b3d2Safresh1 } 1485759b3d2Safresh1 $_[0] = $thing; 1495759b3d2Safresh1 }; 1505759b3d2Safresh1 1515759b3d2Safresh1 my $g = Data::Dumper::Dumper($got); 1525759b3d2Safresh1 my $w = Data::Dumper::Dumper($want); 1535759b3d2Safresh1 1545759b3d2Safresh1 my $bool = $g eq $w; 1555759b3d2Safresh1 1565759b3d2Safresh1 return $ctx->pass_and_release($name) if $bool; 1575759b3d2Safresh1 return $ctx->fail_and_release($name, $g, $w, @diag); 1585759b3d2Safresh1} 1595759b3d2Safresh1 1605759b3d2Safresh1sub diag { 1615759b3d2Safresh1 my $ctx = context(); 1625759b3d2Safresh1 $ctx->diag(join '', @_); 1635759b3d2Safresh1 $ctx->release; 1645759b3d2Safresh1} 1655759b3d2Safresh1 1665759b3d2Safresh1sub note { 1675759b3d2Safresh1 my $ctx = context(); 1685759b3d2Safresh1 $ctx->note(join '', @_); 1695759b3d2Safresh1 $ctx->release; 1705759b3d2Safresh1} 1715759b3d2Safresh1 1725759b3d2Safresh1sub skip_all { 1735759b3d2Safresh1 my ($reason) = @_; 1745759b3d2Safresh1 my $ctx = context(); 1755759b3d2Safresh1 $ctx->plan(0, SKIP => $reason); 1765759b3d2Safresh1 $ctx->release if $ctx; 1775759b3d2Safresh1} 1785759b3d2Safresh1 1795759b3d2Safresh1sub todo { 1805759b3d2Safresh1 my ($reason, $sub) = @_; 1815759b3d2Safresh1 my $ctx = context(); 1825759b3d2Safresh1 1835759b3d2Safresh1 # This code is mostly copied from Test2::Todo in the Test2-Suite 1845759b3d2Safresh1 # distribution. 1855759b3d2Safresh1 my $hub = test2_stack->top; 1865759b3d2Safresh1 my $filter = $hub->pre_filter( 1875759b3d2Safresh1 sub { 1885759b3d2Safresh1 my ($active_hub, $event) = @_; 1895759b3d2Safresh1 if ($active_hub == $hub) { 1905759b3d2Safresh1 $event->set_todo($reason) if $event->can('set_todo'); 1915759b3d2Safresh1 $event->add_amnesty({tag => 'TODO', details => $reason}); 1925759b3d2Safresh1 } 1935759b3d2Safresh1 else { 1945759b3d2Safresh1 $event->add_amnesty({tag => 'TODO', details => $reason, inherited => 1}); 1955759b3d2Safresh1 } 1965759b3d2Safresh1 return $event; 1975759b3d2Safresh1 }, 1985759b3d2Safresh1 inherit => 1, 1995759b3d2Safresh1 todo => $reason, 2005759b3d2Safresh1 ); 2015759b3d2Safresh1 $sub->(); 2025759b3d2Safresh1 $hub->pre_unfilter($filter); 2035759b3d2Safresh1 2045759b3d2Safresh1 $ctx->release if $ctx; 2055759b3d2Safresh1} 2065759b3d2Safresh1 2075759b3d2Safresh1sub plan { 2085759b3d2Safresh1 my ($max) = @_; 2095759b3d2Safresh1 my $ctx = context(); 2105759b3d2Safresh1 $ctx->plan($max); 2115759b3d2Safresh1 $ctx->release; 2125759b3d2Safresh1} 2135759b3d2Safresh1 2145759b3d2Safresh1sub done_testing { 2155759b3d2Safresh1 my $ctx = context(); 2165759b3d2Safresh1 $ctx->done_testing; 2175759b3d2Safresh1 $ctx->release; 2185759b3d2Safresh1} 2195759b3d2Safresh1 2205759b3d2Safresh1sub warnings(&) { 2215759b3d2Safresh1 my $code = shift; 2225759b3d2Safresh1 my @warnings; 2235759b3d2Safresh1 local $SIG{__WARN__} = sub { push @warnings => @_ }; 2245759b3d2Safresh1 $code->(); 2255759b3d2Safresh1 return \@warnings; 2265759b3d2Safresh1} 2275759b3d2Safresh1 2285759b3d2Safresh1sub exception(&) { 2295759b3d2Safresh1 my $code = shift; 2305759b3d2Safresh1 local ($@, $!, $SIG{__DIE__}); 2315759b3d2Safresh1 my $ok = eval { $code->(); 1 }; 2325759b3d2Safresh1 my $error = $@ || 'SQUASHED ERROR'; 2335759b3d2Safresh1 return $ok ? undef : $error; 2345759b3d2Safresh1} 2355759b3d2Safresh1 2365759b3d2Safresh1sub tests { 2375759b3d2Safresh1 my ($name, $code) = @_; 2385759b3d2Safresh1 my $ctx = context(); 2395759b3d2Safresh1 2405759b3d2Safresh1 my $be = caller->can('before_each'); 2415759b3d2Safresh1 2425759b3d2Safresh1 $be->($name) if $be; 2435759b3d2Safresh1 2445759b3d2Safresh1 my $bool = run_subtest($name, $code, 1); 2455759b3d2Safresh1 2465759b3d2Safresh1 $ctx->release; 2475759b3d2Safresh1 2485759b3d2Safresh1 return $bool; 2495759b3d2Safresh1} 2505759b3d2Safresh1 2515759b3d2Safresh1sub capture(&) { 2525759b3d2Safresh1 my $code = shift; 2535759b3d2Safresh1 2545759b3d2Safresh1 my ($err, $out) = ("", ""); 2555759b3d2Safresh1 2565759b3d2Safresh1 my $handles = test2_stack->top->format->handles; 2575759b3d2Safresh1 my ($ok, $e); 2585759b3d2Safresh1 { 2595759b3d2Safresh1 my ($out_fh, $err_fh); 2605759b3d2Safresh1 2615759b3d2Safresh1 ($ok, $e) = try { 2625759b3d2Safresh1 # Scalar refs as filehandles were added in 5.8. 2635759b3d2Safresh1 if ($] ge "5.008") { 2645759b3d2Safresh1 open($out_fh, '>', \$out) or die "Failed to open a temporary STDOUT: $!"; 2655759b3d2Safresh1 open($err_fh, '>', \$err) or die "Failed to open a temporary STDERR: $!"; 2665759b3d2Safresh1 } 2675759b3d2Safresh1 # Emulate scalar ref filehandles with a tie. 2685759b3d2Safresh1 else { 2695759b3d2Safresh1 $out_fh = Test::Builder::IO::Scalar->new(\$out) or die "Failed to open a temporary STDOUT"; 2705759b3d2Safresh1 $err_fh = Test::Builder::IO::Scalar->new(\$err) or die "Failed to open a temporary STDERR"; 2715759b3d2Safresh1 } 2725759b3d2Safresh1 2735759b3d2Safresh1 test2_stack->top->format->set_handles([$out_fh, $err_fh, $out_fh]); 2745759b3d2Safresh1 2755759b3d2Safresh1 $code->(); 2765759b3d2Safresh1 }; 2775759b3d2Safresh1 } 2785759b3d2Safresh1 test2_stack->top->format->set_handles($handles); 2795759b3d2Safresh1 2805759b3d2Safresh1 die $e unless $ok; 2815759b3d2Safresh1 2825759b3d2Safresh1 $err =~ s/ $/_/mg; 2835759b3d2Safresh1 $out =~ s/ $/_/mg; 2845759b3d2Safresh1 2855759b3d2Safresh1 return { 2865759b3d2Safresh1 STDOUT => $out, 2875759b3d2Safresh1 STDERR => $err, 2885759b3d2Safresh1 }; 2895759b3d2Safresh1} 2905759b3d2Safresh1 2915759b3d2Safresh11; 2925759b3d2Safresh1 2935759b3d2Safresh1__END__ 2945759b3d2Safresh1 2955759b3d2Safresh1=pod 2965759b3d2Safresh1 2975759b3d2Safresh1=encoding UTF-8 2985759b3d2Safresh1 2995759b3d2Safresh1=head1 NAME 3005759b3d2Safresh1 3015759b3d2Safresh1Test2::Tools::Tiny - Tiny set of tools for unfortunate souls who cannot use 3025759b3d2Safresh1L<Test2::Suite>. 3035759b3d2Safresh1 3045759b3d2Safresh1=head1 DESCRIPTION 3055759b3d2Safresh1 3065759b3d2Safresh1You should really look at L<Test2::Suite>. This package is some very basic 3075759b3d2Safresh1essential tools implemented using L<Test2>. This exists only so that L<Test2> 3085759b3d2Safresh1and other tools required by L<Test2::Suite> can be tested. This is the package 3095759b3d2Safresh1L<Test2> uses to test itself. 3105759b3d2Safresh1 3115759b3d2Safresh1=head1 USE Test2::Suite INSTEAD 3125759b3d2Safresh1 3135759b3d2Safresh1Use L<Test2::Suite> if at all possible. 3145759b3d2Safresh1 3155759b3d2Safresh1=head1 EXPORTS 3165759b3d2Safresh1 3175759b3d2Safresh1=over 4 3185759b3d2Safresh1 3195759b3d2Safresh1=item ok($bool, $name) 3205759b3d2Safresh1 3215759b3d2Safresh1=item ok($bool, $name, @diag) 3225759b3d2Safresh1 3235759b3d2Safresh1Run a simple assertion. 3245759b3d2Safresh1 3255759b3d2Safresh1=item is($got, $want, $name) 3265759b3d2Safresh1 3275759b3d2Safresh1=item is($got, $want, $name, @diag) 3285759b3d2Safresh1 3295759b3d2Safresh1Assert that 2 strings are the same. 3305759b3d2Safresh1 3315759b3d2Safresh1=item isnt($got, $do_not_want, $name) 3325759b3d2Safresh1 3335759b3d2Safresh1=item isnt($got, $do_not_want, $name, @diag) 3345759b3d2Safresh1 3355759b3d2Safresh1Assert that 2 strings are not the same. 3365759b3d2Safresh1 3375759b3d2Safresh1=item like($got, $regex, $name) 3385759b3d2Safresh1 3395759b3d2Safresh1=item like($got, $regex, $name, @diag) 3405759b3d2Safresh1 3415759b3d2Safresh1Check that the input string matches the regex. 3425759b3d2Safresh1 3435759b3d2Safresh1=item unlike($got, $regex, $name) 3445759b3d2Safresh1 3455759b3d2Safresh1=item unlike($got, $regex, $name, @diag) 3465759b3d2Safresh1 3475759b3d2Safresh1Check that the input string does not match the regex. 3485759b3d2Safresh1 3495759b3d2Safresh1=item is_deeply($got, $want, $name) 3505759b3d2Safresh1 3515759b3d2Safresh1=item is_deeply($got, $want, $name, @diag) 3525759b3d2Safresh1 3535759b3d2Safresh1Check 2 data structures. Please note that this is a I<DUMB> implementation that 3545759b3d2Safresh1compares the output of L<Data::Dumper> against both structures. 3555759b3d2Safresh1 3565759b3d2Safresh1=item diag($msg) 3575759b3d2Safresh1 3585759b3d2Safresh1Issue a diagnostics message to STDERR. 3595759b3d2Safresh1 3605759b3d2Safresh1=item note($msg) 3615759b3d2Safresh1 3625759b3d2Safresh1Issue a diagnostics message to STDOUT. 3635759b3d2Safresh1 3645759b3d2Safresh1=item skip_all($reason) 3655759b3d2Safresh1 3665759b3d2Safresh1Skip all tests. 3675759b3d2Safresh1 3685759b3d2Safresh1=item todo $reason => sub { ... } 3695759b3d2Safresh1 3705759b3d2Safresh1Run a block in TODO mode. 3715759b3d2Safresh1 3725759b3d2Safresh1=item plan($count) 3735759b3d2Safresh1 3745759b3d2Safresh1Set the plan. 3755759b3d2Safresh1 3765759b3d2Safresh1=item done_testing() 3775759b3d2Safresh1 3785759b3d2Safresh1Set the plan to the current test count. 3795759b3d2Safresh1 3805759b3d2Safresh1=item $warnings = warnings { ... } 3815759b3d2Safresh1 3825759b3d2Safresh1Capture an arrayref of warnings from the block. 3835759b3d2Safresh1 3845759b3d2Safresh1=item $exception = exception { ... } 3855759b3d2Safresh1 3865759b3d2Safresh1Capture an exception. 3875759b3d2Safresh1 3885759b3d2Safresh1=item tests $name => sub { ... } 3895759b3d2Safresh1 3905759b3d2Safresh1Run a subtest. 3915759b3d2Safresh1 3925759b3d2Safresh1=item $output = capture { ... } 3935759b3d2Safresh1 3945759b3d2Safresh1Capture STDOUT and STDERR output. 3955759b3d2Safresh1 3965759b3d2Safresh1Result looks like this: 3975759b3d2Safresh1 3985759b3d2Safresh1 { 3995759b3d2Safresh1 STDOUT => "...", 4005759b3d2Safresh1 STDERR => "...", 4015759b3d2Safresh1 } 4025759b3d2Safresh1 4035759b3d2Safresh1=back 4045759b3d2Safresh1 4055759b3d2Safresh1=head1 SOURCE 4065759b3d2Safresh1 4075759b3d2Safresh1The source code repository for Test2 can be found at 408*5486feefSafresh1L<https://github.com/Test-More/test-more/>. 4095759b3d2Safresh1 4105759b3d2Safresh1=head1 MAINTAINERS 4115759b3d2Safresh1 4125759b3d2Safresh1=over 4 4135759b3d2Safresh1 4145759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt> 4155759b3d2Safresh1 4165759b3d2Safresh1=back 4175759b3d2Safresh1 4185759b3d2Safresh1=head1 AUTHORS 4195759b3d2Safresh1 4205759b3d2Safresh1=over 4 4215759b3d2Safresh1 4225759b3d2Safresh1=item Chad Granum E<lt>exodist@cpan.orgE<gt> 4235759b3d2Safresh1 4245759b3d2Safresh1=back 4255759b3d2Safresh1 4265759b3d2Safresh1=head1 COPYRIGHT 4275759b3d2Safresh1 428256a93a4Safresh1Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>. 4295759b3d2Safresh1 4305759b3d2Safresh1This program is free software; you can redistribute it and/or 4315759b3d2Safresh1modify it under the same terms as Perl itself. 4325759b3d2Safresh1 433*5486feefSafresh1See L<https://dev.perl.org/licenses/> 4345759b3d2Safresh1 4355759b3d2Safresh1=cut 436