package tests::ExtendedSchemaTest; use strict; use base qw/ Lire::Test::TestCase /; use Lire::DlfSchema; use Lire::ExtendedSchema; use Lire::DerivedSchema; use Lire::Field; use Lire::DlfStore; use Lire::Utils qw/tempdir/; use File::Basename qw/dirname/; use Cwd qw/realpath/; sub new { my $self = shift()->SUPER::new( @_ ); $self->{'tmpdir'} = tempdir( __PACKAGE__ . "XXXXXX", 'TMPDIR' => 1, CLEANUP => 1 ); return $self; } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'old_cache'} = { %Lire::DlfSchema::SCHEMA_CACHE }; %Lire::DlfSchema::SCHEMA_CACHE = (); # Make sure the Lire::DlfSchema can find our test schemas. $self->{'cfg'}{'lr_schemas_path'} = [ realpath( dirname(__FILE__) . "/schemas" ) ]; $self->{'schema'} = Lire::DlfSchema::load_schema( "test-extended" ); $self->{'cfg'}{'_lr_config_spec'} = $self->lire_default_config_spec(); # We don't open the store in new() because we need to # change the configuration before $self->{'store'} = Lire::DlfStore->open( "$self->{'tmpdir'}/store", 1 ) unless defined $self->{'store'}; return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); $self->{'store'}->_dbh()->rollback(); %Lire::DlfSchema::SCHEMA_CACHE = %{$self->{'old_cache'}}; return; } sub test_new { my $self = $_[0]; $self->assert_dies( qr/cannot find superservice in id: test_extended/, sub { new Lire::ExtendedSchema( 'id' => 'test_extended' ) } ); $self->assert_dies( qr/base schema cannot be an extended schema: test-extended/, sub { new Lire::ExtendedSchema( 'id' => 'test-another', 'base-schema' => 'test-extended' ) } ); my $schema = new Lire::ExtendedSchema( 'id' => 'test-extended', 'module' => 'MyModule', 'base-schema' => 'test' ); $self->assert_isa( 'Lire::ExtendedSchema', $schema ); $self->assert_str_equals( 'test-extended', $schema->{'id'} ); $self->assert_str_equals( 'test', $schema->{'superservice'} ); my $base = Lire::DlfSchema::load_schema( 'test' ); $self->assert_str_equals( $base, $schema->{'base'} ); $self->assert_deep_equals( [ $base->fields() ], $schema->{'fields_by_pos'} ); $self->assert_deep_equals( $base->{'fields_by_name'}, $schema->{'fields_by_name'} ); $self->assert_num_equals( 11, $schema->{'extended_start_idx'} ); } sub test_id { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->assert_str_equals( "test-extended", $self->{'schema'}->id() ); } sub test_superservice { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->assert_str_equals( "test", $self->{'schema'}->superservice() ); } sub test_base { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); my $base = $self->{'schema'}->base(); $self->assert_isa( 'Lire::DlfSchema', $base ); $self->assert_str_equals( "test", $base->id() ); } sub test_extended_fields { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); my $mockfield = bless { 'name' => 'dirname', 'type' => 'filename', 'pos' => 11, 'description' => "\n Contains the file's directory.\n ", 'label' => 'Directory', 'i18n_domain' => 'lire-test', }, 'Lire::Field'; $self->assert_deep_equals( [ $mockfield ], $self->{'schema'}->extended_fields() ); } sub test_can_join_schema { my $self = $_[0]; my $test = new Lire::DlfSchema( 'superservice' => 'test', 'timestamp' => 'time' ); $test->add_field( new Lire::Field( 'name' => 'time', 'type' => 'timestamp' ) ); $Lire::DlfSchema::SCHEMA_CACHE{'test'} = $test; my $test2 = new Lire::DlfSchema( 'superservice' => 'test2', 'timestamp' => 'time' ); $test2->add_field( new Lire::Field( 'name' => 'time', 'type' => 'timestamp' ) ); $Lire::DlfSchema::SCHEMA_CACHE{'test2'} = $test2; my $ext1 = new Lire::ExtendedSchema( 'id' => 'test-ext1', 'base-schema' => 'test', 'module' => 'MyModule' ); my $ext2 = new Lire::ExtendedSchema( 'id' => 'test2-ext2', 'base-schema' => 'test2', 'module' => 'MyModule' ); my $ext3 = new Lire::ExtendedSchema( 'id' => 'test-ext3', 'base-schema' => 'test', 'module' => 'MyModule' ); my $derived = new Lire::DerivedSchema( 'id' => 'test-derived', 'base-schema' => 'test', 'timestamp' => 'time', 'module' => 'MyModule' ); $self->assert( $ext1->can_join_schema( $ext3 ) ); $self->assert( ! $ext1->can_join_schema( $test ) ); $self->assert( ! $ext1->can_join_schema( $ext1 ) ); $self->assert( ! $ext1->can_join_schema( $ext2 ) ); $self->assert( ! $ext1->can_join_schema( $test2 ) ); $self->assert( ! $ext1->can_join_schema( $derived ) ); } sub test_sql_insert_query { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); my $e_sql = q{INSERT INTO "dlf_test-extended" (dlf_id, dlf_source, dirname) VALUES (?,?,?)}; $self->assert_str_equals( $e_sql, $self->{'schema'}->sql_insert_query() ); } sub test_create_sql_schema { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->{'schema'}->create_sql_schema( $self->{'store'} ); my $sql_def = $self->{'schema'}->_sql_fields_def(); chomp $sql_def; # Trailing newline removed by SQLite my $dbh = $self->{'store'}->_dbh(); my $table = $dbh->selectrow_hashref( "SELECT * FROM sqlite_master WHERE name = 'dlf_test-extended'" ); $self->assert_not_null( $table, "table dlf_test wasn't created" ); $self->assert_matches( qr/\Q$sql_def\E/, $table->{'sql'} ); my $index = $dbh->selectrow_hashref( "SELECT * FROM sqlite_master WHERE name = 'dlf_test-extended_time_start_idx'" ); $self->assert_null( $index, "index shouldn't exists" ); my $trigger = $dbh->selectrow_hashref( q{SELECT * FROM sqlite_master WHERE name = 'dlf_test-extended_delete_trigger'} ); $self->assert_not_null( $trigger, "trigger dlf_test-extended_delete_trigger wasn't created" ); $self->assert_str_equals( "trigger", $trigger->{'type'} ); my $trigger_sql = <assert_str_equals( $trigger_sql, $trigger->{'sql'} ); } sub test_sql_clean_query { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->assert_str_equals( 'DELETE FROM "dlf_test-extended"', $self->{'schema'}->sql_clean_query() ); $self->{'schema'}{'timestamp_field'} = 'time-start'; $self->assert_str_equals( 'DELETE FROM "dlf_test-extended" WHERE dlf_id IN ( SELECT e.dlf_id FROM dlf_test b, "dlf_test-extended" e WHERE b.dlf_id = e.dlf_id AND "b.time-start" < ? )', $self->{'schema'}->sql_clean_query( 1 ) ); } sub test_sql_clean_period_query { my $self = $_[0]; $self->assert_isa( 'Lire::ExtendedSchema', $self->{'schema'} ); $self->{'schema'}{'timestamp_field'} = 'time-start'; $self->assert_str_equals( 'DELETE FROM "dlf_test-extended" WHERE dlf_id IN ( SELECT e.dlf_id FROM dlf_test b, "dlf_test-extended" e WHERE b.dlf_id = e.dlf_id AND "b.time-start" >= ? AND "b.time-start" < ? )', $self->{'schema'}->sql_clean_period_query ); } sub test_dlf_query { my $self = $_[0]; my $query = $self->{'schema'}->dlf_query( 'time_start' ); $self->assert_isa( 'Lire::DlfQuery', $query ); $self->assert( $query->has_field( 'dlf_id' ), 'missing dlf_id' ); $self->assert_str_equals( '"dlf_test-extended".dlf_id', $query->field_def( 'dlf_id' ) ); $self->assert( $query->has_field( 'dlf_source' ), 'missing dlf_source' );; $self->assert_str_equals( '"dlf_test-extended".dlf_source', $query->field_def( 'dlf_source' ) ); $self->assert( $query->has_field( 'dirname' ), 'missing dirname' ); $self->assert_str_equals( 'time_start', $query->sort_spec() ); return; } 1;