File Coverage

blib/lib/Test/Warnings.pm
Criterion Covered Total %
statement 57 57 100.0
branch 15 16 93.7
condition 20 23 86.9
subroutine 16 16 100.0
pod 5 5 100.0
total 113 117 96.5


line stmt bran cond sub pod time code
1 22     22   1619789 use strict;
  22         225  
  22         703  
2 22     22   125 use warnings;
  22         42  
  22         1331  
3             package Test::Warnings; # git description: v0.030-6-gf367162
4             # vim: set ts=8 sts=2 sw=2 tw=100 et :
5             # ABSTRACT: Test for warnings and the lack of them
6             # KEYWORDS: testing tests warnings
7              
8             our $VERSION = '0.031';
9              
10 22     22   11631 use parent 'Exporter';
  22         7220  
  22         122  
11 22     22   1309 use Test::Builder;
  22         48  
  22         14194  
12              
13             our @EXPORT_OK = qw(
14             allow_warnings allowing_warnings
15             had_no_warnings
16             warnings warning
17             );
18             our %EXPORT_TAGS = ( all => \@EXPORT_OK );
19              
20             my $warnings_allowed;
21             my $forbidden_warnings_found;
22             my $done_testing_called;
23             my $no_end_test;
24             my $fail_on_warning;
25             my $report_warnings;
26             my @collected_warnings;
27              
28             sub import {
29 23     23   203 my $class = shift @_;
30              
31 23         82 my %names; @names{@_} = ();
  23         81  
32             # END block will check for this status
33 23         53 $no_end_test = exists $names{':no_end_test'};
34             # __WARN__ handler will check for this status
35 23         43 $fail_on_warning = exists $names{':fail_on_warning'};
36             # Collect and report warnings at the end
37 23         51 $report_warnings = exists $names{':report_warnings'};
38              
39 23         90 delete @names{qw(:no_end_test :fail_on_warning :report_warnings)};
40 23         19717 __PACKAGE__->export_to_level(1, $class, keys %names);
41             }
42              
43             # for testing this module only!
44             my $tb;
45             sub _builder(;$) {
46 38 100   38   3487 if (not @_) {
47 35   66     166 $tb ||= Test::Builder->new;
48 35         289 return $tb;
49             }
50              
51 3         9 $tb = shift;
52             }
53              
54             my $_orig_warn_handler = $SIG{__WARN__};
55             $SIG{__WARN__} = sub {
56             if ($warnings_allowed) {
57             Test::Builder->new->note($_[0]);
58             }
59             else {
60             $forbidden_warnings_found++;
61             push @collected_warnings, $_[0] if $report_warnings;
62              
63             # TODO: this doesn't handle blessed coderefs... does anyone care?
64             goto &$_orig_warn_handler if $_orig_warn_handler
65             and ( (ref $_orig_warn_handler eq 'CODE')
66             or ($_orig_warn_handler ne 'DEFAULT'
67             and $_orig_warn_handler ne 'IGNORE'
68             and defined &$_orig_warn_handler));
69              
70             if ($_[0] =~ /\n$/) {
71             warn $_[0];
72             } else {
73             require Carp;
74             Carp::carp($_[0]);
75             }
76             _builder->ok(0, 'unexpected warning') if $fail_on_warning;
77             }
78             };
79              
80             sub warnings(;&) {
81             # if someone manually does warnings->import in the same namespace this is
82             # imported into, this sub will be called. in that case, just return the
83             # string "warnings" so it calls the correct method.
84 12 100   12 1 3348 if (!@_) {
85 1         57 return 'warnings';
86             }
87 11         23 my $code = shift;
88 11         17 my @warnings;
89             local $SIG{__WARN__} = sub {
90 10     10   159 push @warnings, shift;
91 11         65 };
92 11         37 $code->();
93 11         1737 @warnings;
94             }
95              
96             sub warning(&) {
97 4     4 1 2270 my @warnings = &warnings(@_);
98 4 100       26 return @warnings == 1 ? $warnings[0] : \@warnings;
99             }
100              
101             if (Test::Builder->can('done_testing')) {
102             # monkeypatch Test::Builder::done_testing:
103             # check for any forbidden warnings, and record that we have done so
104             # so we do not check again via END
105              
106 22     22   225 no strict 'refs';
  22         42  
  22         1094  
107             my $orig = *{'Test::Builder::done_testing'}{CODE};
108 22     22   167 no warnings 'redefine';
  22         52  
  22         9339  
109             *{'Test::Builder::done_testing'} = sub {
110             # only do this at the end of all tests, not at the end of a subtest
111 16     16   24116 my $builder = _builder;
112 16         114 my $in_subtest_sub = $builder->can('in_subtest');
113 16 50 100     86 if (not $no_end_test
    100          
114             and not ($in_subtest_sub ? $builder->$in_subtest_sub : $builder->parent)) {
115 4         552 local $Test::Builder::Level = $Test::Builder::Level + 3;
116 4         16 had_no_warnings('no (unexpected) warnings (via done_testing)');
117 4         11 $done_testing_called = 1;
118             }
119              
120 16         208 $orig->(@_);
121             };
122             }
123              
124             END {
125 19 100 100 19   21753 if (not $no_end_test
      100        
      100        
126             and not $done_testing_called
127             # skip this if there is no plan and no tests have been run (e.g.
128             # compilation tests of this module!)
129             and (_builder->expected_tests or _builder->current_test > 0)
130             ) {
131 2         305 local $Test::Builder::Level = $Test::Builder::Level + 1;
132 2         8 had_no_warnings('no (unexpected) warnings (via END block)');
133             }
134             }
135              
136             # setter
137             sub allow_warnings(;$) {
138 3 100 66 3 1 26 $warnings_allowed = @_ || defined $_[0] ? $_[0] : 1;
139             }
140              
141             # getter
142 3     3 1 19 sub allowing_warnings() { $warnings_allowed }
143              
144             # call at any time to assert no (unexpected) warnings so far
145             sub had_no_warnings(;$) {
146 9   100 9 1 397 _builder->ok(!$forbidden_warnings_found, shift || 'no (unexpected) warnings');
147 9 100 66     3223 if ($report_warnings and $forbidden_warnings_found) {
148 1         4 _builder->diag("Got the following unexpected warnings:");
149 1         131 for my $i (1 .. @collected_warnings) {
150 1         4 _builder->diag(" $i: $collected_warnings[ $i - 1 ]");
151             }
152             }
153             }
154              
155             1;
156              
157             __END__