590 changes: 590 additions & 0 deletions lib/DBIx/Class/Schema/SanityChecker.pm

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions lib/DBIx/Class/Schema/Versioned.pm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ use base 'DBIx::Class::Schema';
use strict;
use warnings;

# no point sanity checking, unless we are running asserts
__PACKAGE__->schema_sanity_checker(
DBIx::Class::_ENV_::ASSERT_NO_FAILING_SANITY_CHECKS
? 'DBIx::Class::Schema::SanityChecker'
: ''
);

__PACKAGE__->register_class('Table', 'DBIx::Class::Version::Table');

package # Hide from PAUSE
Expand All @@ -57,6 +64,13 @@ use base 'DBIx::Class::Schema';
use strict;
use warnings;

# no point sanity checking, unless we are running asserts
__PACKAGE__->schema_sanity_checker(
DBIx::Class::_ENV_::ASSERT_NO_FAILING_SANITY_CHECKS
? 'DBIx::Class::Schema::SanityChecker'
: ''
);

__PACKAGE__->register_class('TableCompat', 'DBIx::Class::Version::TableCompat');


Expand Down
1 change: 1 addition & 0 deletions lib/DBIx/Class/_Util.pm
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ BEGIN {
DBIC_ASSERT_NO_INTERNAL_WANTARRAY
DBIC_ASSERT_NO_INTERNAL_INDIRECT_CALLS
DBIC_ASSERT_NO_ERRONEOUS_METAINSTANCE_USE
DBIC_ASSERT_NO_FAILING_SANITY_CHECKS
DBIC_STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE
DBIC_STRESSTEST_COLUMN_INFO_UNAWARE_STORAGE
)
Expand Down
18 changes: 18 additions & 0 deletions t/cdbi/DeepAbstractSearch/01_search.t
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,24 @@ my @DSN = ("dbi:SQLite:dbname=$DB", '', '', { AutoCommit => 0 });
package Music::DBI;
use base qw(DBIx::Class::CDBICompat);
use Class::DBI::Plugin::DeepAbstractSearch;

BEGIN {
# offset the warning from DBIx::Class::Schema on 5.8
# keep the ::Schema default as-is otherwise
DBIx::Class::_ENV_::OLD_MRO
and
( eval <<'EOS' or die $@ );
sub setup_schema_instance {
my $s = shift->next::method(@_);
$s->schema_sanity_checker('');
$s;
}
1;
EOS
}

__PACKAGE__->connection(@DSN);

my $sql = <<'SQL_END';
Expand Down
17 changes: 17 additions & 0 deletions t/cdbi/testlib/DBIC/Test/SQLite.pm
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@ use DBICTest;

use base qw/DBIx::Class/;

BEGIN {
# offset the warning from DBIx::Class::Schema on 5.8
# keep the ::Schema default as-is otherwise
DBIx::Class::_ENV_::OLD_MRO
and
( eval <<'EOS' or die $@ );
sub setup_schema_instance {
my $s = shift->next::method(@_);
$s->schema_sanity_checker('');
$s;
}
1;
EOS
}

__PACKAGE__->load_components(qw/CDBICompat Core DB/);

my $DB = DBICTest->_sqlite_dbfilename;
Expand Down
17 changes: 17 additions & 0 deletions t/cdbi/testlib/MyBase.pm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ use strict;
use DBI;
use DBICTest;

BEGIN {
# offset the warning from DBIx::Class::Schema on 5.8
# keep the ::Schema default as-is otherwise
DBIx::Class::_ENV_::OLD_MRO
and
( eval <<'EOS' or die $@ );
sub setup_schema_instance {
my $s = shift->next::method(@_);
$s->schema_sanity_checker('');
$s;
}
1;
EOS
}

use base qw(DBIx::Class::CDBICompat);

my @connect = (@ENV{map { "DBICTEST_MYSQL_${_}" } qw/DSN USER PASS/}, { PrintError => 0});
Expand Down
47 changes: 47 additions & 0 deletions t/lib/DBICTest/BaseSchema.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,55 @@ use DBIx::Class::_Util qw( emit_loud_diag scope_guard set_subname get_subname );
use DBICTest::Util::LeakTracer qw(populate_weakregistry assert_empty_weakregistry);
use DBICTest::Util qw( local_umask tmpdir await_flock dbg DEBUG_TEST_CONCURRENCY_LOCKS );
use Scalar::Util qw( refaddr weaken );
use Devel::GlobalDestruction ();
use namespace::clean;

# Unless we are running assertions there is no value in checking ourselves
# during regular tests - the CI will do it for us
#
if (
DBIx::Class::_ENV_::ASSERT_NO_FAILING_SANITY_CHECKS
and
# full-blown 5.8 sanity-checking is waaaaaay too slow, even for CI
(
! DBIx::Class::_ENV_::OLD_MRO
or
# still run a couple test with this, even on 5.8
$ENV{DBICTEST_OLD_MRO_SANITY_CHECK_ASSERTIONS}
)
) {

__PACKAGE__->schema_sanity_checker('DBIx::Class::Schema::SanityChecker');

# Repeat the check on going out of scope (will catch weird runtime tinkering)
# Add only in case we will be using it, as it slows tests down
eval <<'EOD' or die $@;
sub DESTROY {
if (
! Devel::GlobalDestruction::in_global_destruction()
and
my $checker = $_[0]->schema_sanity_checker
) {
$checker->perform_schema_sanity_checks($_[0]);
}
# *NOT* using next::method here - it (currently) will confuse Class::C3
# in some obscure cases ( 5.8 naturally )
shift->SUPER::DESTROY();
}
1;
EOD

}
else {
# otherwise just unset the default
__PACKAGE__->schema_sanity_checker('');
}


if( $ENV{DBICTEST_ASSERT_NO_SPURIOUS_EXCEPTION_ACTION} ) {
my $ea = __PACKAGE__->exception_action( sub {

Expand Down
3 changes: 3 additions & 0 deletions t/storage/txn.t
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Test is sufficiently involved to *want* to run with "maximum paranoia"
BEGIN { $ENV{DBICTEST_OLD_MRO_SANITY_CHECK_ASSERTIONS} = 1 }

BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }

use strict;
Expand Down
3 changes: 3 additions & 0 deletions t/storage/txn_scope_guard.t
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Test is sufficiently involved to *want* to run with "maximum paranoia"
BEGIN { $ENV{DBICTEST_OLD_MRO_SANITY_CHECK_ASSERTIONS} = 1 }

BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }

use strict;
Expand Down
13 changes: 10 additions & 3 deletions xt/dist/pod_coverage.t
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use Test::More;
use Module::Runtime 'require_module';
use lib 'maint/.Generated_Pod/lib';
use DBICTest;
use DBIx::Class::Schema::SanityChecker;
use namespace::clean;

# this has already been required but leave it here for CPANTS static analysis
Expand Down Expand Up @@ -102,6 +103,11 @@ my $exceptions = {
connection
/]
},
'DBIx::Class::Schema::SanityChecker' => {
ignore => [ map {
qr/^ (?: check_${_} | format_${_}_errors ) $/x
} @{ DBIx::Class::Schema::SanityChecker->available_checks } ]
},

'DBIx::Class::Admin' => {
ignore => [ qw/
Expand Down Expand Up @@ -181,9 +187,10 @@ foreach my $module (@modules) {

# build parms up from ignore list
my $parms = {};
$parms->{trustme} =
[ map { qr/^$_$/ } @{ $ex->{ignore} } ]
if exists($ex->{ignore});
$parms->{trustme} = [ map
{ ref $_ eq 'Regexp' ? $_ : qr/^\Q$_\E$/ }
@{ $ex->{ignore} }
] if exists($ex->{ignore});

# run the test with the potentially modified parm set
Test::Pod::Coverage::pod_coverage_ok($module, $parms, "$module POD coverage");
Expand Down
48 changes: 48 additions & 0 deletions xt/extra/diagnostics/invalid_component_composition.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }

BEGIN { delete $ENV{DBIC_ASSERT_NO_FAILING_SANITY_CHECKS} }

use strict;
use warnings;

use Test::More;

use DBICTest::Util 'capture_stderr';
use DBICTest;


{
package DBICTest::Some::BaseResult;
use base "DBIx::Class::Core";

# order is important
__PACKAGE__->load_components(qw( FilterColumn InflateColumn::DateTime ));
}

{
package DBICTest::Some::Result;
use base "DBICTest::Some::BaseResult";

__PACKAGE__->table("sometable");

__PACKAGE__->add_columns(
somecolumn => { data_type => "datetime" },
);
}

{
package DBICTest::Some::Schema;
use base "DBIx::Class::Schema";
__PACKAGE__->schema_sanity_checker("DBIx::Class::Schema::SanityChecker");
__PACKAGE__->register_class( some_result => "DBICTest::Some::Result" );
}

like(
capture_stderr {
DBICTest::Some::Schema->connection(sub {} );
},
qr/Class 'DBICTest::Some::Result' was originally using the 'dfs' MRO affecting .+ register_column\(\)/,
'Proper incorrect composition warning emitted on StdErr'
);

done_testing;
3 changes: 3 additions & 0 deletions xt/extra/internals/ithread_stress.t
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }

# Test is sufficiently involved to *want* to run with "maximum paranoia"
BEGIN { $ENV{DBICTEST_OLD_MRO_SANITY_CHECK_ASSERTIONS} = 1 }

use warnings;
use strict;

Expand Down
4 changes: 4 additions & 0 deletions xt/extra/lean_startup.t
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ BEGIN {
DBICTEST_DEBUG_CONCURRENCY_LOCKS
)};

# ensures the checker won't be disabled in
# t/lib/DBICTest/BaseSchema.pm
$ENV{DBIC_ASSERT_NO_FAILING_SANITY_CHECKS} = 1;

$ENV{DBICTEST_ANFANG_DEFANG} = 1;

# make sure extras do not load even when this is set
Expand Down