File Coverage

blib/lib/Test2/Tools/Tiny.pm
Criterion Covered Total %
statement 161 165 97.5
branch 53 68 77.9
condition 14 16 87.5
subroutine 31 31 100.0
pod 16 16 100.0
total 275 296 92.9


line stmt bran cond sub pod time code
1             package Test2::Tools::Tiny;
2 94     94   53758 use strict;
  94         607  
  94         2906  
3 94     94   483 use warnings;
  94         200  
  94         8518  
4              
5             BEGIN {
6 94 50   94   2837 if ($] lt "5.008") {
7 0         0 require Test::Builder::IO::Scalar;
8             }
9             }
10              
11 94     94   585 use Scalar::Util qw/blessed/;
  94         187  
  94         12042  
12              
13 94     94   30522 use Test2::Util qw/try/;
  94         293  
  94         6566  
14 94     94   43194 use Test2::API qw/context run_subtest test2_stack/;
  94         286  
  94         8208  
15              
16 94     94   709 use Test2::Hub::Interceptor();
  94         384  
  94         1577  
17 94     94   500 use Test2::Hub::Interceptor::Terminator();
  94         196  
  94         4767  
18              
19             our $VERSION = '1.302180';
20              
21 94     94   2788 BEGIN { require Exporter; our @ISA = qw(Exporter) }
  94         63722  
22             our @EXPORT = qw{
23             ok is isnt like unlike is_deeply diag note skip_all todo plan done_testing
24             warnings exception tests capture
25             };
26              
27             sub ok($;$@) {
28 683     683 1 6719 my ($bool, $name, @diag) = @_;
29 683         2140 my $ctx = context();
30              
31 683 100       3171 return $ctx->pass_and_release($name) if $bool;
32 13         55 return $ctx->fail_and_release($name, @diag);
33             }
34              
35             sub is($$;$@) {
36 667     667 1 2338436 my ($got, $want, $name, @diag) = @_;
37 667         2289 my $ctx = context();
38              
39 667         1260 my $bool;
40 667 100 100     3055 if (defined($got) && defined($want)) {
    100 75        
41 606         1762 $bool = "$got" eq "$want";
42             }
43             elsif (defined($got) xor defined($want)) {
44 2         5 $bool = 0;
45             }
46             else { # Both are undef
47 59         120 $bool = 1;
48             }
49              
50 667 100       2971 return $ctx->pass_and_release($name) if $bool;
51              
52 4 100       10 $got = '*NOT DEFINED*' unless defined $got;
53 4 100       11 $want = '*NOT DEFINED*' unless defined $want;
54 4         17 unshift @diag => (
55             "GOT: $got",
56             "EXPECTED: $want",
57             );
58              
59 4         17 return $ctx->fail_and_release($name, @diag);
60             }
61              
62             sub isnt($$;$@) {
63 16     16 1 2684463 my ($got, $want, $name, @diag) = @_;
64 16         103 my $ctx = context();
65              
66 16         59 my $bool;
67 16 100 100     151 if (defined($got) && defined($want)) {
    100 75        
68 13         72 $bool = "$got" ne "$want";
69             }
70             elsif (defined($got) xor defined($want)) {
71 2         5 $bool = 1;
72             }
73             else { # Both are undef
74 1         2 $bool = 0;
75             }
76              
77 16 100       124 return $ctx->pass_and_release($name) if $bool;
78              
79 2 50       10 unshift @diag => "Strings are the same (they should not be)"
80             unless $bool;
81              
82 2         7 return $ctx->fail_and_release($name, @diag);
83             }
84              
85             sub like($$;$@) {
86 154     154 1 2505 my ($thing, $pattern, $name, @diag) = @_;
87 154         518 my $ctx = context();
88              
89 154         320 my $bool;
90 154 100       451 if (defined($thing)) {
91 153         1559 $bool = "$thing" =~ $pattern;
92 153 100       555 unshift @diag => (
93             "Value: $thing",
94             "Does not match: $pattern"
95             ) unless $bool;
96             }
97             else {
98 1         3 $bool = 0;
99 1         5 unshift @diag => "Got an undefined value.";
100             }
101              
102 154 100       733 return $ctx->pass_and_release($name) if $bool;
103 2         9 return $ctx->fail_and_release($name, @diag);
104             }
105              
106             sub unlike($$;$@) {
107 3     3 1 48 my ($thing, $pattern, $name, @diag) = @_;
108 3         9 my $ctx = context();
109              
110 3         8 my $bool;
111 3 100       13 if (defined($thing)) {
112 2         14 $bool = "$thing" !~ $pattern;
113 2 100       14 unshift @diag => (
114             "Unexpected pattern match (it should not match)",
115             "Value: $thing",
116             "Matches: $pattern"
117             ) unless $bool;
118             }
119             else {
120 1         3 $bool = 0;
121 1         3 unshift @diag => "Got an undefined value.";
122             }
123              
124 3 100       12 return $ctx->pass_and_release($name) if $bool;
125 2         9 return $ctx->fail_and_release($name, @diag);
126             }
127              
128             sub is_deeply($$;$@) {
129 404     404 1 1956 my ($got, $want, $name, @diag) = @_;
130 404         1180 my $ctx = context();
131              
132 94     94   841 no warnings 'once';
  94         226  
  94         116271  
133 404         35361 require Data::Dumper;
134              
135             # Otherwise numbers might be unquoted
136 404         362999 local $Data::Dumper::Useperl = 1;
137              
138 404         791 local $Data::Dumper::Sortkeys = 1;
139 404         637 local $Data::Dumper::Deparse = 1;
140 404         674 local $Data::Dumper::Freezer = 'XXX';
141             local *UNIVERSAL::XXX = sub {
142 368     368   194502 my ($thing) = @_;
143 368 50       1028 if (ref($thing)) {
144 368 100       2571 $thing = {%$thing} if "$thing" =~ m/=HASH/;
145 368 100       1345 $thing = [@$thing] if "$thing" =~ m/=ARRAY/;
146 368 50       1076 $thing = \"$$thing" if "$thing" =~ m/=SCALAR/;
147             }
148 368         894 $_[0] = $thing;
149 404         2559 };
150              
151 404         1463 my $g = Data::Dumper::Dumper($got);
152 404         253578 my $w = Data::Dumper::Dumper($want);
153              
154 404         252044 my $bool = $g eq $w;
155              
156 404 100       2108 return $ctx->pass_and_release($name) if $bool;
157 1         6 return $ctx->fail_and_release($name, $g, $w, @diag);
158             }
159              
160             sub diag {
161 8     8 1 63 my $ctx = context();
162 8         47 $ctx->diag(join '', @_);
163 8         28 $ctx->release;
164             }
165              
166             sub note {
167 11     11 1 72 my $ctx = context();
168 11         78 $ctx->note(join '', @_);
169 11         46 $ctx->release;
170             }
171              
172             sub skip_all {
173 6     6 1 687 my ($reason) = @_;
174 6         20 my $ctx = context();
175 6         34 $ctx->plan(0, SKIP => $reason);
176 0 0       0 $ctx->release if $ctx;
177             }
178              
179             sub todo {
180 2     2 1 26 my ($reason, $sub) = @_;
181 2         8 my $ctx = context();
182              
183             # This code is mostly copied from Test2::Todo in the Test2-Suite
184             # distribution.
185 2         12 my $hub = test2_stack->top;
186             my $filter = $hub->pre_filter(
187             sub {
188 12     12   27 my ($active_hub, $event) = @_;
189 12 100       33 if ($active_hub == $hub) {
190 9 100       102 $event->set_todo($reason) if $event->can('set_todo');
191 9         45 $event->add_amnesty({tag => 'TODO', details => $reason});
192             }
193             else {
194 3         21 $event->add_amnesty({tag => 'TODO', details => $reason, inherited => 1});
195             }
196 12         30 return $event;
197             },
198 2         25 inherit => 1,
199             todo => $reason,
200             );
201 2         9 $sub->();
202 2         18 $hub->pre_unfilter($filter);
203              
204 2 50       11 $ctx->release if $ctx;
205             }
206              
207             sub plan {
208 7     7 1 57 my ($max) = @_;
209 7         33 my $ctx = context();
210 7         46 $ctx->plan($max);
211 7         38 $ctx->release;
212             }
213              
214             sub done_testing {
215 83     83 1 2691816 my $ctx = context();
216 83         641 $ctx->done_testing;
217 83         407 $ctx->release;
218             }
219              
220             sub warnings(&) {
221 12     12 1 156 my $code = shift;
222 12         41 my @warnings;
223 12     13   211 local $SIG{__WARN__} = sub { push @warnings => @_ };
  13         749  
224 12         94 $code->();
225 12         167 return \@warnings;
226             }
227              
228             sub exception(&) {
229 84     84 1 514 my $code = shift;
230 84         575 local ($@, $!, $SIG{__DIE__});
231 84         198 my $ok = eval { $code->(); 1 };
  84         261  
  8         23  
232 84   100     7634 my $error = $@ || 'SQUASHED ERROR';
233 84 100       1095 return $ok ? undef : $error;
234             }
235              
236             sub tests {
237 88     88 1 1495 my ($name, $code) = @_;
238 88         265 my $ctx = context();
239              
240 88         690 my $be = caller->can('before_each');
241              
242 88 100       263 $be->($name) if $be;
243              
244 88         357 my $bool = run_subtest($name, $code, 1);
245              
246 87         333 $ctx->release;
247              
248 87         226 return $bool;
249             }
250              
251             sub capture(&) {
252 7     7 1 42 my $code = shift;
253              
254 7         20 my ($err, $out) = ("", "");
255              
256 7         19 my $handles = test2_stack->top->format->handles;
257 7         15 my ($ok, $e);
258             {
259 7         12 my ($out_fh, $err_fh);
  7         12  
260              
261             ($ok, $e) = try {
262             # Scalar refs as filehandles were added in 5.8.
263 7 50   7   32 if ($] ge "5.008") {
264 7 50   3   157 open($out_fh, '>', \$out) or die "Failed to open a temporary STDOUT: $!";
  3         22  
  3         8  
  3         20  
265 7 50       2363 open($err_fh, '>', \$err) or die "Failed to open a temporary STDERR: $!";
266             }
267             # Emulate scalar ref filehandles with a tie.
268             else {
269 0 0       0 $out_fh = Test::Builder::IO::Scalar->new(\$out) or die "Failed to open a temporary STDOUT";
270 0 0       0 $err_fh = Test::Builder::IO::Scalar->new(\$err) or die "Failed to open a temporary STDERR";
271             }
272              
273 7         27 test2_stack->top->format->set_handles([$out_fh, $err_fh, $out_fh]);
274              
275 7         20 $code->();
276 7         50 };
277             }
278 7         67 test2_stack->top->format->set_handles($handles);
279              
280 7 50       24 die $e unless $ok;
281              
282 7         26 $err =~ s/ $/_/mg;
283 7         50 $out =~ s/ $/_/mg;
284              
285             return {
286 7         37 STDOUT => $out,
287             STDERR => $err,
288             };
289             }
290              
291             1;
292              
293             __END__