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