)
EOM
-### load any test classes that are defined further down in the file
+### load any test classes that are defined further down in the file via BEGIN blocks
our @test_classes; #< array that will be pushed into by test classes defined in this file
DBICTest::Schema->load_classes( map {s/.+:://;$_} @test_classes ) if @test_classes;
-### pre-connect tests
+### pre-connect tests (keep each test separate as to make sure rebless() runs)
{
my $s = DBICTest::Schema->connect($dsn, $user, $pass);
ok (!$s->storage->_dbh, 'definitely not connected');
# Check that datetime_parser returns correctly before we explicitly connect.
- SKIP: {
+ SKIP: {
eval { require DateTime::Format::Pg };
skip "DateTime::Format::Pg required", 2 if $@;
is( $parser, 'DateTime::Format::Pg', 'datetime_parser is as expected');
}
-
+ ok (!$s->storage->_dbh, 'still not connected');
+}
+{
+ my $s = DBICTest::Schema->connect($dsn, $user, $pass);
# make sure sqlt_type overrides work (::Storage::DBI::Pg does this)
+ ok (!$s->storage->_dbh, 'definitely not connected');
is ($s->storage->sqlt_type, 'PostgreSQL', 'sqlt_type correct pre-connection');
+ ok (!$s->storage->_dbh, 'still not connected');
}
### connect, create postgres-specific test schema
my $schema = DBICTest::Schema->connect($dsn, $user, $pass);
-drop_test_schema($schema, 'no warn');
+drop_test_schema($schema);
create_test_schema($schema);
### begin main tests
run_apk_tests($schema); #< older set of auto-pk tests
run_extended_apk_tests($schema); #< new extended set of auto-pk tests
+
+
+
+
### type_info tests
my $test_type_info = {
__PACKAGE__->load_components(qw/Core/);
__PACKAGE__->table('dbic_t_schema.casecheck');
- __PACKAGE__->add_columns(qw/id name NAME uc_name storecolumn/);
+ __PACKAGE__->add_columns(qw/id name NAME uc_name/);
__PACKAGE__->column_info_from_storage(1);
__PACKAGE__->set_primary_key('id');
-
- sub store_column {
- my ($self, $name, $value) = @_;
- $value = '#'.$value if($name eq "storecolumn");
- $self->maybe::next::method($name, $value);
- }
}
-# store_column is called once for create() for non sequence columns
-ok(my $storecolumn = $schema->resultset('Casecheck')->create({'storecolumn' => 'a'}));
-is($storecolumn->storecolumn, '#a'); # was '##a'
-
my $name_info = $schema->source('Casecheck')->column_info( 'name' );
is( $name_info->{size}, 1, "Case sensitive matching info for 'name'" );
## Test SELECT ... FOR UPDATE
-my $HaveSysSigAction = eval "require Sys::SigAction" && !$@;
-if( $HaveSysSigAction ) {
- Sys::SigAction->import( 'set_sig_handler' );
-}
SKIP: {
- skip "Sys::SigAction is not available", 3 unless $HaveSysSigAction;
- # create a new schema
- my $schema2 = DBICTest::Schema->connect($dsn, $user, $pass);
- $schema2->source("Artist")->name("dbic_t_schema.artist");
+ if(eval "require Sys::SigAction" && !$@) {
+ Sys::SigAction->import( 'set_sig_handler' );
+ }
+ else {
+ skip "Sys::SigAction is not available", 6;
+ }
- $schema->txn_do( sub {
- my $artist = $schema->resultset('Artist')->search(
- {
- artistid => 1
- },
- {
- for => 'update'
- }
- )->first;
- is($artist->artistid, 1, "select for update returns artistid = 1");
-
- my $artist_from_schema2;
- my $error_ok = 0;
- eval {
- my $h = set_sig_handler( 'ALRM', sub { die "DBICTestTimeout" } );
- alarm(2);
- $artist_from_schema2 = $schema2->resultset('Artist')->find(1);
- $artist_from_schema2->name('fooey');
- $artist_from_schema2->update;
- alarm(0);
- };
- if (my $e = $@) {
- $error_ok = $e =~ /DBICTestTimeout/;
- }
+ my ($timed_out, $artist2);
+ for my $t (
+ {
# Make sure that an error was raised, and that the update failed
- ok($error_ok, "update from second schema times out");
- ok($artist_from_schema2->is_column_changed('name'), "'name' column is still dirty from second schema");
- });
-}
-
-SKIP: {
- skip "Sys::SigAction is not available", 3 unless $HaveSysSigAction;
- # create a new schema
- my $schema2 = DBICTest::Schema->connect($dsn, $user, $pass);
- $schema2->source("Artist")->name("dbic_t_schema.artist");
-
- $schema->txn_do( sub {
+ update_lock => 1,
+ test_sub => sub {
+ ok($timed_out, "update from second schema times out");
+ ok($artist2->is_column_changed('name'), "'name' column is still dirty from second schema");
+ },
+ },
+ {
+ # Make sure that an error was NOT raised, and that the update succeeded
+ update_lock => 0,
+ test_sub => sub {
+ ok(! $timed_out, "update from second schema DOES NOT timeout");
+ ok(! $artist2->is_column_changed('name'), "'name' column is NOT dirty from second schema");
+ },
+ },
+ ) {
+ # create a new schema
+ my $schema2 = DBICTest::Schema->connect($dsn, $user, $pass);
+ $schema2->source("Artist")->name("dbic_t_schema.artist");
+
+ $schema->txn_do( sub {
my $artist = $schema->resultset('Artist')->search(
{
artistid => 1
},
+ $t->{update_lock} ? { for => 'update' } : {}
)->first;
- is($artist->artistid, 1, "select for update returns artistid = 1");
+ is($artist->artistid, 1, "select returns artistid = 1");
- my $artist_from_schema2;
- my $error_ok = 0;
+ $timed_out = 0;
eval {
my $h = set_sig_handler( 'ALRM', sub { die "DBICTestTimeout" } );
alarm(2);
- $artist_from_schema2 = $schema2->resultset('Artist')->find(1);
- $artist_from_schema2->name('fooey');
- $artist_from_schema2->update;
+ $artist2 = $schema2->resultset('Artist')->find(1);
+ $artist2->name('fooey');
+ $artist2->update;
alarm(0);
};
- if (my $e = $@) {
- $error_ok = $e =~ /DBICTestTimeout/;
- }
+ $timed_out = $@ =~ /DBICTestTimeout/;
+ });
- # Make sure that an error was NOT raised, and that the update succeeded
- ok(! $error_ok, "update from second schema DOES NOT timeout");
- ok(! $artist_from_schema2->is_column_changed('name'), "'name' column is NOT dirty from second schema");
- });
+ $t->{test_sub}->();
+ }
}
exit;
END {
+ return unless $schema;
drop_test_schema($schema);
eapk_drop_all( $schema)
};
, "name" VARCHAR(1)
, "NAME" VARCHAR(2)
, "UC_NAME" VARCHAR(3)
- , "storecolumn" VARCHAR(10)
)
EOS
$dbh->do(<<EOS);
sub drop_test_schema {
- my ( $schema, $no_warn ) = @_;
+ my ( $schema, $warn_exceptions ) = @_;
$schema->storage->dbh_do(sub {
my (undef,$dbh) = @_;
'DROP SCHEMA dbic_t_schema_3 CASCADE',
) {
eval { $dbh->do ($stat) };
- diag $@ if $@ && !$no_warn;
+ diag $@ if $@ && $warn_exceptions;
}
});
}
my $schema = shift;
#save the search path and reset it at the end
- my $search_path_save = $schema->storage->dbh_do('_get_pg_search_path');
+ my $search_path_save = eapk_get_search_path($schema);
- eapk_drop_all($schema,'no warn');
+ eapk_drop_all($schema);
# make the test schemas and sequences
$schema->storage->dbh_do(sub {
for @eapk_schemas;
$dbh->do("CREATE SEQUENCE $eapk_schemas[5].fooseq");
+ $dbh->do("CREATE SEQUENCE $eapk_schemas[4].fooseq");
+ $dbh->do("CREATE SEQUENCE $eapk_schemas[3].fooseq");
$dbh->do("SET search_path = ".join ',', @eapk_schemas );
});
with_search_path => ['public',0,1],
qualify_table => 2,
);
+ eapk_create( $schema,
+ with_search_path => [3,1,0,'public'],
+ nextval => "$eapk_schemas[4].fooseq",
+ );
+ eapk_create( $schema,
+ with_search_path => [3,1,0,'public'],
+ nextval => "$eapk_schemas[3].fooseq",
+ qualify_table => 4,
+ );
eapk_poke( $schema, 0 );
eapk_poke( $schema, 2 );
+ eapk_poke( $schema, 4 );
eapk_poke( $schema, 1 );
eapk_poke( $schema, 0 );
eapk_poke( $schema, 1 );
+ eapk_poke( $schema, 4 );
+ eapk_poke( $schema, 3 );
eapk_poke( $schema, 1 );
eapk_poke( $schema, 2 );
eapk_poke( $schema, 0 );
? $eapk_schemas[$schema_num]
: '';
- my $schema_name_actual = $schema_name || $s->storage->dbh_do('_get_pg_search_path')->[0];
+ my $schema_name_actual = $schema_name || eapk_get_search_path($s)->[0];
$s->source('ExtAPK')->name($schema_name ? $schema_name.'.apk' : 'apk');
#< clear sequence name cache
my $new;
for my $inc (1,2,3) {
$new = $schema->resultset('ExtAPK')->create({});
- for my $id (@eapk_id_columns) {
+ my $proper_seqval = ++$seqs{"$schema_name_actual.apk.id2"};
+ is( $new->id2, $proper_seqval, "$schema_name_actual.apk.id2 correct inc $inc" )
+ or eapk_seq_diag($s,$schema_name);
+ $new->discard_changes;
+ for my $id (grep $_ ne 'id2', @eapk_id_columns) {
my $proper_seqval = ++$seqs{"$schema_name_actual.apk.$id"};
- is( $new->$id, $proper_seqval, "correct $id inc $inc" )
- or eapk_seq_diag($s);
+ is( $new->$id, $proper_seqval, "$schema_name_actual.apk.$id correct inc $inc" )
+ or eapk_seq_diag($s,$schema_name);
}
}
} "create in schema '$schema_name' lives"
- or eapk_seq_diag($s);
+ or eapk_seq_diag($s,$schema_name);
}
# print diagnostic info on which sequences were found in the ExtAPK
# class
sub eapk_seq_diag {
my $s = shift;
- my $schema = shift || $s->storage->dbh_do('_get_pg_search_path')->[0];
+ my $schema = shift || eapk_get_search_path($s)->[0];
diag "$schema.apk sequences: ",
join(', ',
);
}
+# get the postgres search path as an arrayref
+sub eapk_get_search_path {
+ my ( $s ) = @_;
+ # cache the search path as ['schema','schema',...] in the storage
+ # obj
+
+ return $s->storage->dbh_do(sub {
+ my (undef, $dbh) = @_;
+ my @search_path;
+ my ($sp_string) = $dbh->selectrow_array('SHOW search_path');
+ while ( $sp_string =~ s/("[^"]+"|[^,]+),?// ) {
+ unless( defined $1 and length $1 ) {
+ die "search path sanity check failed: '$1'";
+ }
+ push @search_path, $1;
+ }
+ \@search_path
+ });
+}
sub eapk_set_search_path {
my ($s,@sp) = @_;
my $sp = join ',',@sp;
}
sub eapk_drop_all {
- my ( $schema, $no_warn ) = @_;
+ my ( $schema, $warn_exceptions ) = @_;
$schema->storage->dbh_do(sub {
my (undef,$dbh) = @_;
# drop the test schemas
for (@eapk_schemas ) {
eval{ $dbh->do("DROP SCHEMA $_ CASCADE") };
- diag $@ if $@ && !$no_warn;
+ diag $@ if $@ && $warn_exceptions;
}