File Coverage

blib/lib/Test/Warnings.pm
Criterion Covered Total %
statement 59 59 100.0
branch 18 20 90.0
condition 22 26 84.6
subroutine 16 16 100.0
pod 5 5 100.0
total 120 126 95.2


line stmt bran cond sub pod time code
1 23     23   1620322 use strict;
  23         251  
  23         701  
2 23     23   124 use warnings;
  23         76  
  23         1437  
3             package Test::Warnings; # git description: v0.031-5-g17d6729
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.032';
9              
10 23     23   10455 use parent 'Exporter';
  23         7350  
  23         133  
11 23     23   1300 use Test::Builder;
  23         45  
  23         12757  
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 24     24   205 my $class = shift @_;
30              
31 24         94 my %names; @names{@_} = ();
  24         95  
32             # END block will check for this status
33 24         61 $no_end_test = exists $names{':no_end_test'};
34             # __WARN__ handler will check for this status
35 24         45 $fail_on_warning = exists $names{':fail_on_warning'};
36             # Collect and report warnings at the end
37 24         42 $report_warnings = exists $names{':report_warnings'};
38              
39 24         85 delete @names{qw(:no_end_test :fail_on_warning :report_warnings)};
40 24         19973 __PACKAGE__->export_to_level(1, $class, keys %names);
41             }
42              
43             # for testing this module only!
44             my $tb;
45             sub _builder(;$) {
46 42 100   42   5499 if (not @_) {
47 38   66     220 $tb ||= Test::Builder->new;
48 38         355 return $tb;
49             }
50              
51 4         13 $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 3429 if (!@_) {
85 1         53 return 'warnings';
86             }
87 11         26 my $code = shift;
88 11         18 my @warnings;
89             local $SIG{__WARN__} = sub {
90 10     10   167 push @warnings, shift;
91 11         58 };
92 11         36 $code->();
93 11         1293 @warnings;
94             }
95              
96             sub warning(&) {
97 4     4 1 1895 my @warnings = &warnings(@_);
98 4 100       24 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 23     23   207 no strict 'refs';
  23         58  
  23         1207  
107             my $orig = *{'Test::Builder::done_testing'}{CODE};
108 23     23   167 no warnings 'redefine';
  23         57  
  23         10237  
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   23724 my $builder = _builder;
112 16         132 my $in_subtest_sub = $builder->can('in_subtest');
113 16 50 100     83 if (not $no_end_test
    100          
114             and not ($in_subtest_sub ? $builder->$in_subtest_sub : $builder->parent)) {
115 4         543 local $Test::Builder::Level = $Test::Builder::Level + 3;
116 4         17 had_no_warnings('no (unexpected) warnings (via done_testing)');
117 4         9 $done_testing_called = 1;
118             }
119              
120 16         213 $orig->(@_);
121             };
122             }
123              
124             END {
125 20 100 100 20   130188 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         249 local $Test::Builder::Level = $Test::Builder::Level + 1;
132 2         7 had_no_warnings('no (unexpected) warnings (via END block)');
133             }
134             }
135              
136             # setter
137             sub allow_warnings(;$) {
138 3 100 66 3 1 23 $warnings_allowed = @_ || defined $_[0] ? $_[0] : 1;
139             }
140              
141             # getter
142 3     3 1 18 sub allowing_warnings() { $warnings_allowed }
143              
144             # call at any time to assert no (unexpected) warnings so far
145             sub had_no_warnings(;$) {
146 10 100   10 1 456 if ($ENV{PERL_TEST_WARNINGS_ONLY_REPORT_WARNINGS}) {
147 1 50       4 $forbidden_warnings_found
148             and _builder->diag("Found $forbidden_warnings_found warnings but allowing them because PERL_TEST_WARNINGS_ONLY_REPORT_WARNINGS is set");
149             }
150             else {
151 9   100     23 _builder->ok(!$forbidden_warnings_found, shift || 'no (unexpected) warnings');
152             }
153 10 100 66     3306 if (($report_warnings or $ENV{PERL_TEST_WARNINGS_ONLY_REPORT_WARNINGS})
      66        
154             and $forbidden_warnings_found) {
155 2         7 _builder->diag("Got the following unexpected warnings:");
156 2         247 for my $i (1 .. @collected_warnings) {
157 2         6 _builder->diag(" $i: $collected_warnings[ $i - 1 ]");
158             }
159             }
160             }
161              
162             1;
163              
164             __END__