X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2Flib%2FDBICTest.pm;h=42a691b47e42d84c30858b5f876000f6213bab4d;hb=410a6bced6035333d48c2b92ad968a722a0a0b09;hp=df3587eb89c1e6fab873d4dd275e5096edad4296;hpb=65d351219882184861384aedac6f251b6797d0d7;p=dbsrgits%2FDBIx-Class-Historic.git diff --git a/t/lib/DBICTest.pm b/t/lib/DBICTest.pm index df3587e..42a691b 100644 --- a/t/lib/DBICTest.pm +++ b/t/lib/DBICTest.pm @@ -5,9 +5,12 @@ use strict; use warnings; use DBICTest::RunMode; use DBICTest::Schema; -use DBICTest::Util qw/populate_weakregistry assert_empty_weakregistry/; +use DBICTest::Util::LeakTracer qw/populate_weakregistry assert_empty_weakregistry/; +use DBICTest::Util 'local_umask'; use Carp; use Path::Class::File (); +use File::Spec; +use Fcntl qw/:DEFAULT :flock/; =head1 NAME @@ -50,20 +53,106 @@ default, unless the no_deploy or no_populate flags are set. =cut -sub has_custom_dsn { - return $ENV{"DBICTEST_DSN"} ? 1:0; +# some tests are very time sensitive and need to run on their own, without +# being disturbed by anything else grabbing CPU or disk IO. Hence why everything +# using DBICTest grabs a shared lock, and the few tests that request a :GlobalLock +# will ask for an exclusive one and block until they can get it +our ($global_lock_fh, $global_exclusive_lock); +sub import { + my $self = shift; + + my $tmpdir = DBICTest::RunMode->tmpdir; + my $lockpath = $tmpdir->file('.dbictest_global.lock'); + + { + my $u = local_umask(0); # so that the file opens as 666, and any user can lock + sysopen ($global_lock_fh, $lockpath, O_RDWR|O_CREAT) or do { + my $err = $!; + + my @x_tests = map { (defined $_) ? ( $_ ? 1 : 0 ) : 'U' } map {(-e, -d, -f, -r, -w, -x, -o)} ($tmpdir, $lockpath); + + die sprintf <<"EOE", $lockpath, $err, scalar $>, scalar $), (stat($tmpdir))[4,5,2], @x_tests; +Unable to open %s: %s +Process EUID/EGID: %s / %s +TmpDir UID/GID: %s / %s +TmpDir StatMode: %o +TmpDir X-tests: -e:%s -d:%s -f:%s -r:%s -w:%s -x:%s -o:%s +TmpFile X-tests: -e:%s -d:%s -f:%s -r:%s -w:%s -x:%s -o:%s +EOE + }; + } + + for (@_) { + if ($_ eq ':GlobalLock') { + flock ($global_lock_fh, LOCK_EX) or die "Unable to lock $lockpath: $!"; + $global_exclusive_lock = 1; + } + else { + croak "Unknown export $_ requested from $self"; + } + } + + unless ($global_exclusive_lock) { + flock ($global_lock_fh, LOCK_SH) or die "Unable to lock $lockpath: $!"; + } +} + +END { + if ($global_lock_fh) { + # delay destruction even more + } } -sub _sqlite_dbfilename { +{ my $dir = Path::Class::File->new(__FILE__)->dir->parent->subdir('var'); $dir->mkpath unless -d "$dir"; - return $dir->file('DBIxClass.db')->stringify; + $dir = "$dir"; + + sub _sqlite_dbfilename { + my $holder = $ENV{DBICTEST_LOCK_HOLDER} || $$; + $holder = $$ if $holder == -1; + + # useful for missing cleanup debugging + #if ( $holder == $$) { + # my $x = $0; + # $x =~ s/\//#/g; + # $holder .= "-$x"; + #} + + return "$dir/DBIxClass-$holder.db"; + } + + END { + _cleanup_dbfile(); + } +} + +$SIG{INT} = sub { _cleanup_dbfile(); exit 1 }; + +sub _cleanup_dbfile { + # cleanup if this is us + if ( + ! $ENV{DBICTEST_LOCK_HOLDER} + or + $ENV{DBICTEST_LOCK_HOLDER} == -1 + or + $ENV{DBICTEST_LOCK_HOLDER} == $$ + ) { + my $db_file = _sqlite_dbfilename(); + unlink $_ for ($db_file, "${db_file}-journal"); + } +} + +sub has_custom_dsn { + return $ENV{"DBICTEST_DSN"} ? 1:0; } sub _sqlite_dbname { my $self = shift; my %args = @_; - return $self->_sqlite_dbfilename if $args{sqlite_use_file} or $ENV{"DBICTEST_SQLITE_USE_FILE"}; + return $self->_sqlite_dbfilename if ( + defined $args{sqlite_use_file} ? $args{sqlite_use_file} : $ENV{'DBICTEST_SQLITE_USE_FILE'} + ); return ":memory:"; } @@ -98,6 +187,15 @@ sub _database { # no fsync on commit $dbh->do ('PRAGMA synchronous = OFF'); + if ($ENV{DBICTEST_SQLITE_REVERSE_DEFAULT_ORDER}) { + + $storage->throw_exception( + 'PRAGMA reverse_unordered_selects does not work correctly before libsqlite 3.7.9' + ) if $storage->_server_info->{normalized_dbms_version} < 3.007009; + + $dbh->do ('PRAGMA reverse_unordered_selects = ON'); + } + # set a *DBI* disconnect callback, to make sure the physical SQLite # file is still there (i.e. the test does not attempt to delete # an open database, which fails on Win32) @@ -114,7 +212,7 @@ sub _database { } sub __mk_disconnect_guard { - return if DBIx::Class::_ENV_::PEEPEENESS(); # leaks handles, delaying DESTROY, can't work right + return if DBIx::Class::_ENV_::PEEPEENESS; # leaks handles, delaying DESTROY, can't work right my $db_file = shift; return unless -f $db_file; @@ -239,6 +337,9 @@ sub deploy_schema { my $schema = shift; my $args = shift || {}; + local $schema->storage->{debug} + if ($ENV{TRAVIS}||'') eq 'true'; + if ($ENV{"DBICTEST_SQLT_DEPLOY"}) { $schema->deploy($args); } else { @@ -267,6 +368,9 @@ sub populate_schema { my $self = shift; my $schema = shift; + local $schema->storage->{debug} + if ($ENV{TRAVIS}||'') eq 'true'; + $schema->populate('Genre', [ [qw/genreid name/], [qw/1 emo /],