mirror of
https://github.com/DBD-SQLite/DBD-SQLite
synced 2025-06-07 06:08:38 -04:00
216 lines
5.3 KiB
Perl
216 lines
5.3 KiB
Perl
use 5.008001;
|
|
use strict;
|
|
use warnings;
|
|
|
|
package Test::FailWarnings;
|
|
# ABSTRACT: Add test failures if warnings are caught
|
|
our $VERSION = '0.008'; # VERSION
|
|
|
|
use Test::More 0.86;
|
|
use Cwd qw/getcwd/;
|
|
use File::Spec;
|
|
use Carp;
|
|
|
|
our $ALLOW_DEPS = 0;
|
|
our @ALLOW_FROM = ();
|
|
|
|
my $ORIG_DIR = getcwd(); # cache in case handler runs after a chdir
|
|
|
|
sub import {
|
|
my ( $class, @args ) = @_;
|
|
croak("import arguments must be key/value pairs")
|
|
unless @args % 2 == 0;
|
|
my %opts = @args;
|
|
$ALLOW_DEPS = $opts{'-allow_deps'};
|
|
if ( $opts{'-allow_from'} ) {
|
|
@ALLOW_FROM =
|
|
ref $opts{'-allow_from'} ? @{ $opts{'-allow_from'} } : $opts{'-allow_from'};
|
|
}
|
|
$SIG{__WARN__} = \&handler;
|
|
}
|
|
|
|
sub handler {
|
|
my $msg = shift;
|
|
$msg = '' unless defined $msg;
|
|
chomp $msg;
|
|
my ( $package, $filename, $line ) = _find_source();
|
|
|
|
# shortcut if ignoring dependencies and warning did not
|
|
# come from something local
|
|
if ($ALLOW_DEPS) {
|
|
$filename = File::Spec->abs2rel( $filename, $ORIG_DIR )
|
|
if File::Spec->file_name_is_absolute($filename);
|
|
return if $filename !~ /^(?:t|xt|lib|blib)/;
|
|
}
|
|
|
|
return if grep { $package eq $_ } @ALLOW_FROM;
|
|
|
|
if ( $msg !~ m/at .*? line \d/ ) {
|
|
chomp $msg;
|
|
$msg = "'$msg' at $filename line $line.";
|
|
}
|
|
else {
|
|
$msg = "'$msg'";
|
|
}
|
|
my $builder = Test::More->builder;
|
|
$builder->ok( 0, "Test::FailWarnings should catch no warnings" )
|
|
or $builder->diag("Warning was $msg");
|
|
}
|
|
|
|
sub _find_source {
|
|
my $i = 1;
|
|
while (1) {
|
|
my ( $pkg, $filename, $line ) = caller( $i++ );
|
|
return caller( $i - 2 ) unless defined $pkg;
|
|
next if $pkg =~ /^(?:Carp|warnings)/;
|
|
return ( $pkg, $filename, $line );
|
|
}
|
|
}
|
|
|
|
1;
|
|
|
|
|
|
# vim: ts=4 sts=4 sw=4 et:
|
|
|
|
__END__
|
|
|
|
=pod
|
|
|
|
=encoding utf-8
|
|
|
|
=head1 NAME
|
|
|
|
Test::FailWarnings - Add test failures if warnings are caught
|
|
|
|
=head1 VERSION
|
|
|
|
version 0.008
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
Test file:
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Test::More;
|
|
use Test::FailWarnings;
|
|
|
|
ok( 1, "first test" );
|
|
ok( 1 + "lkadjaks", "add non-numeric" );
|
|
|
|
done_testing;
|
|
|
|
Output:
|
|
|
|
ok 1 - first test
|
|
not ok 2 - Test::FailWarnings should catch no warnings
|
|
# Failed test 'Test::FailWarnings should catch no warnings'
|
|
# at t/bin/main-warn.pl line 7.
|
|
# Warning was 'Argument "lkadjaks" isn't numeric in addition (+) at t/bin/main-warn.pl line 7.'
|
|
ok 3 - add non-numeric
|
|
1..3
|
|
# Looks like you failed 1 test of 3.
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This module hooks C<$SIG{__WARN__}> and converts warnings to L<Test::More>
|
|
C<fail()> calls. It is designed to be used with C<done_testing>, when you
|
|
don't need to know the test count in advance.
|
|
|
|
Just as with L<Test::NoWarnings>, this does not catch warnings if other things
|
|
localize C<$SIG{__WARN__}>, as this is designed to catch I<unhandled> warnings.
|
|
|
|
=for Pod::Coverage handler
|
|
|
|
=head1 USAGE
|
|
|
|
=head2 Overriding C<$SIG{__WARN__}>
|
|
|
|
On C<import>, C<$SIG{__WARN__}> is replaced with
|
|
C<Test::FailWarnings::handler>.
|
|
|
|
use Test::FailWarnings; # global
|
|
|
|
If you don't want global replacement, require the module instead and localize
|
|
in whatever scope you want.
|
|
|
|
require Test::FailWarnings;
|
|
|
|
{
|
|
local $SIG{__WARN__} = \&Test::FailWarnings::handler;
|
|
# ... warnings will issue fail() here
|
|
}
|
|
|
|
When the handler reports on the source of the warning, it will look past
|
|
any calling packages starting with C<Carp> or C<warnings> to try to detect
|
|
the real origin of the warning.
|
|
|
|
=head2 Allowing warnings from dependencies
|
|
|
|
If you want to ignore failures from outside your own code, you can set
|
|
C<$Test::FailWarnings::ALLOW_DEPS> to a true value. You can
|
|
do that on the C<use> line with C<< -allow_deps >>.
|
|
|
|
use Test::FailWarnings -allow_deps => 1;
|
|
|
|
When true, warnings will only be thrown if they appear to originate from a filename
|
|
matching C<< qr/^(?:t|xt|lib|blib)/ >>
|
|
|
|
=head2 Allowing warnings from specific modules
|
|
|
|
If you want to white-list specific modules only, you can add their package
|
|
names to C<@Test::NoWarnings::ALLOW_FROM>. You can do that on the C<use> line
|
|
with C<< -allow_from >>.
|
|
|
|
use Test::FailWarnings -allow_from => [ qw/Annoying::Module/ ];
|
|
|
|
=head1 SEE ALSO
|
|
|
|
=over 4
|
|
|
|
=item *
|
|
|
|
L<Test::NoWarnings> -- catches warnings and reports in an C<END> block. Not (yet) friendly with C<done_testing>.
|
|
|
|
=item *
|
|
|
|
L<Test::Warnings> -- a replacement for Test::NoWarnings that works with done_testing
|
|
|
|
=item *
|
|
|
|
L<Test::Warn> -- test for warnings without triggering failures from this modules
|
|
|
|
=back
|
|
|
|
=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
|
|
|
|
=head1 SUPPORT
|
|
|
|
=head2 Bugs / Feature Requests
|
|
|
|
Please report any bugs or feature requests through the issue tracker
|
|
at L<https://github.com/dagolden/Test-FailWarnings/issues>.
|
|
You will be notified automatically of any progress on your issue.
|
|
|
|
=head2 Source Code
|
|
|
|
This is open source software. The code repository is available for
|
|
public review and contribution under the terms of the license.
|
|
|
|
L<https://github.com/dagolden/Test-FailWarnings>
|
|
|
|
git clone https://github.com/dagolden/Test-FailWarnings.git
|
|
|
|
=head1 AUTHOR
|
|
|
|
David Golden <dagolden@cpan.org>
|
|
|
|
=head1 COPYRIGHT AND LICENSE
|
|
|
|
This software is Copyright (c) 2013 by David Golden.
|
|
|
|
This is free software, licensed under:
|
|
|
|
The Apache License, Version 2.0, January 2004
|
|
|
|
=cut
|