@@ -, +, @@ - Check that after aplying this patch, this still works: prove -v t/db_dependent/OAI/Server.t - Read the test to see what has been added: - ListIdentifiers verb with resumption token, until the whole catalog is harvested - ListRecords verb with resumption token, until the whole catalog is harvested - Returned metadata returned is tested --- installer/data/mysql/updatedatabase.pl | 3 +- t/db_dependent/OAI/Server.t | 246 ++++++++++++++++++++++++++------- 2 files changed, 198 insertions(+), 51 deletions(-) --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -11478,9 +11478,8 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { foreach my $subscription ( $sth->fetchrow_hashref() ) { next if !defined($subscription); - my $number_pattern = $subscription->numberpattern(); $sth2->execute( $subscription->{numberpattern} ); - $number_pattern = $sth2->fetchrow_hashref(); + my $number_pattern = $sth2->fetchrow_hashref(); my $numbering_method = $number_pattern->{numberingmethod}; # Get all the data between the enumeration values, we need --- a/t/db_dependent/OAI/Server.t +++ a/t/db_dependent/OAI/Server.t @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright Tamil s.a.r.l. 2015 +# Copyright Tamil s.a.r.l. 2016 # # This file is part of Koha. # @@ -21,12 +21,17 @@ use Modern::Perl; use C4::Context; use C4::Biblio; -use Test::More tests => 13; +use Test::More tests => 23; use Test::MockModule; use Test::Warn; use DateTime; use XML::Simple; use t::lib::Mocks; +use t::lib::TestBuilder; + +use YAML; +use Data::Dump qw/dump/; + BEGIN { @@ -47,48 +52,89 @@ BEGIN { # Mocked CGI module in order to be able to send CGI parameters to OAI Server my %param; my $module = Test::MockModule->new('CGI'); -$module->mock('Vars', sub { %param; }); + $module->mock('Vars', sub { %param; }); +my $schema = Koha::Database->schema; +$schema->storage->txn_begin; my $dbh = C4::Context->dbh; -$dbh->{AutoCommit} = 0; -$dbh->{RaiseError} = 1; -$dbh->do('DELETE FROM issues'); -$dbh->do('DELETE FROM biblio'); -$dbh->do('DELETE FROM biblioitems'); -$dbh->do('DELETE FROM items'); + +my $builder = t::lib::TestBuilder->new; + +$dbh->do('SET FOREIGN_KEY_CHECKS = 0'); +$dbh->do('TRUNCATE biblio'); +$dbh->do('TRUNCATE biblioitems'); +$dbh->do('TRUNCATE issues'); # Add 10 biblio records -my @bibs = map { +our $tz = DateTime::TimeZone->new( name => 'local' ); +my $date_added = DateTime->now(time_zone =>$tz) . 'Z'; +my $date_to = substr($date_added, 0, 10) . 'T23:59:59Z'; + +my (@header, @metadata, @record); +map { my $record = MARC::Record->new(); $record->append_fields( MARC::Field->new('245', '', '', 'a' => "Title $_" ) ); my ($biblionumber) = AddBiblio($record, ''); - $biblionumber; + $record = GetMarcBiblio($biblionumber); + $record = XMLin($record->as_xml_record); + $header[$biblionumber] = { datestamp => $date_added, identifier => "TEST:$biblionumber" }; + delete $record->{$_} for (('xmlns','xmlns:xsi','xsi:schemaLocation')); + $metadata[$biblionumber] = { collection => { + record => $record, + "xmlns" => "http://www.loc.gov/MARC21/slim", + "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", + "xsi:schemaLocation" => "http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd", + } }; + $record[$biblionumber] = { + header => $header[$biblionumber], + metadata => $metadata[$biblionumber], + }; + $biblionumber => undef; } (1..10); -t::lib::Mocks::mock_preference('LibraryName', 'My Library'); -t::lib::Mocks::mock_preference('OAI::PMH', 1); -t::lib::Mocks::mock_preference('OAI-PMH:archiveID', 'TEST'); -t::lib::Mocks::mock_preference('OAI-PMH:ConfFile', '' ); -t::lib::Mocks::mock_preference('OAI-PMH:MaxCount', 3); -t::lib::Mocks::mock_preference('OAI-PMH:DeletedRecord', 'persistent'); - -%param = ( verb => 'ListMetadataFormats' ); -my $response; -my $get_response = sub { - my $stdout; - local *STDOUT; - open STDOUT, '>', \$stdout; - Koha::OAI::Server::Repository->new(); - $response = XMLin($stdout); + +my $syspref = { + 'LibraryName' => 'My Library', + 'OAI::PMH' => 1, + 'OAI-PMH:archiveID' => 'TEST', + 'OAI-PMH:ConfFile' => '', + 'OAI-PMH:MaxCount' => 3, + 'OAI-PMH:DeletedRecord' => 'persistent', }; -$get_response->(); -my $now = DateTime->now . 'Z'; -my $expected = { - request => 'http://localhost', - responseDate => $now, - xmlns => 'http://www.openarchives.org/OAI/2.0/', - 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', - 'xsi:schemaLocation' => 'http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd', +while ( my ($name, $value) = each %$syspref ) { + t::lib::Mocks::mock_preference( $name => $value ); +} + + +sub test_query { + my ($test, $param, $expected) = @_; + + %param = %$param; + my %full_expected = ( + %$expected, + ( + request => 'http://localhost', + responseDate => DateTime->now . 'Z', + xmlns => 'http://www.openarchives.org/OAI/2.0/', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation' => 'http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd', + ) + ); + + my $response; + { + my $stdout; + local *STDOUT; + open STDOUT, '>', \$stdout; + Koha::OAI::Server::Repository->new(); + $response = XMLin($stdout); + } + + is_deeply($response, \%full_expected, $test); +} + + +test_query('ListMetadataFormats', {verb => 'ListMetadataFormats'}, { ListMetadataFormats => { metadataFormat => [ { @@ -103,23 +149,125 @@ my $expected = { }, ], }, -}; -is_deeply($response, $expected, "ListMetadataFormats"); - -%param = ( verb => 'ListIdentifiers' ); -$get_response->(); -$now = DateTime->now . 'Z'; -$expected = { - request => 'http://localhost', - responseDate => $now, - xmlns => 'http://www.openarchives.org/OAI/2.0/', - 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', - 'xsi:schemaLocation' => 'http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd', +} ); + +test_query('ListIdentifiers without metadataPrefix', {verb => 'ListIdentifiers'}, { error => { code => 'badArgument', content => "Required argument 'metadataPrefix' was undefined", }, -}; -is_deeply($response, $expected, "ListIdentifiers without metadaPrefix argument"); +}); + + +test_query('ListIdentifiers', {verb => 'ListIdentifiers', metadataPrefix => 'marcxml'}, { + ListIdentifiers => { + header => [ @header[1..3] ], + resumptionToken => { + content => "marcxml/3/1970-01-01T00:00:00Z/$date_to/", + cursor => 3, + }, + }, +}); + +test_query('ListIdentifiers', {verb => 'ListIdentifiers', metadataPrefix => 'marcxml'}, { + ListIdentifiers => { + header => [ @header[1..3] ], + resumptionToken => { + content => "marcxml/3/1970-01-01T00:00:00Z/$date_to/", + cursor => 3, + }, + }, +}); + +test_query( + 'ListIdentifiers with resumptionToken 1', + { verb => 'ListIdentifiers', resumptionToken => "marcxml/3/1970-01-01T00:00:00Z/$date_to/" }, + { + ListIdentifiers => { + header => [ @header[4..6] ], + resumptionToken => { + content => "marcxml/6/1970-01-01T00:00:00Z/$date_to/", + cursor => 6, + }, + }, + + }, +); + +test_query( + 'ListIdentifiers with resumptionToken 2', + { verb => 'ListIdentifiers', resumptionToken => "marcxml/6/1970-01-01T00:00:00Z/$date_to/" }, + { + ListIdentifiers => { + header => [ @header[7..9] ], + resumptionToken => { + content => "marcxml/9/1970-01-01T00:00:00Z/$date_to/", + cursor => 9, + }, + }, + + }, +); + +test_query( + 'ListIdentifiers with resumptionToken 3, response without resumption', + { verb => 'ListIdentifiers', resumptionToken => "marcxml/9/1970-01-01T00:00:00Z/$date_to/" }, + { + ListIdentifiers => { + header => $header[10], + }, + + }, +); + +test_query('ListRecords without metadataPrefix', {verb => 'ListRecords'}, { + error => { + code => 'badArgument', + content => "Required argument 'metadataPrefix' was undefined", + }, +}); + +test_query('ListRecords', {verb => 'ListRecords', metadataPrefix => 'marcxml'}, { + ListRecords => { + record => [ @record[1..3] ], + resumptionToken => { + content => "marcxml/3/1970-01-01T00:00:00Z/$date_to/", + cursor => 3, + }, + }, +}); + +test_query( + 'ListRecords with resumptionToken 1', + { verb => 'ListRecords', resumptionToken => "marcxml/3/1970-01-01T00:00:00Z/$date_to/" }, + { ListRecords => { + record => [ @record[4..6] ], + resumptionToken => { + content => "marcxml/6/1970-01-01T00:00:00Z/$date_to/", + cursor => 6, + }, + }, +}); + +test_query( + 'ListRecords with resumptionToken 2', + { verb => 'ListRecords', resumptionToken => "marcxml/6/1970-01-01T00:00:00Z/$date_to/" }, + { ListRecords => { + record => [ @record[7..9] ], + resumptionToken => { + content => "marcxml/9/1970-01-01T00:00:00Z/$date_to/", + cursor => 9, + }, + }, +}); + +# Last record, so no resumption token +test_query( + 'ListRecords with resumptionToken 3, response without resumption', + { verb => 'ListRecords', resumptionToken => "marcxml/9/1970-01-01T00:00:00Z/$date_to/" }, + { ListRecords => { + record => $record[10], + }, +}); -$dbh->rollback; +$schema->storage->txn_rollback; --