300 lines
10 KiB
Perl
Executable File
300 lines
10 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
|
|
# This file is part of Koha
|
|
#
|
|
# Koha is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Koha is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Koha; if not, see <http://www.gnu.org/licenses>.
|
|
|
|
use Modern::Perl;
|
|
use utf8;
|
|
use Encode;
|
|
|
|
use Test::More tests => 5;
|
|
use Test::MockModule;
|
|
use Test::Exception;
|
|
|
|
use Koha::Database;
|
|
use Koha::BackgroundJobs;
|
|
use Koha::BackgroundJob::BatchUpdateItem;
|
|
use Koha::BackgroundJob::MARCImportCommitBatch;
|
|
|
|
use t::lib::Mocks;
|
|
use t::lib::Mocks::Logger;
|
|
use t::lib::TestBuilder;
|
|
use t::lib::Koha::BackgroundJob::BatchTest;
|
|
|
|
my $logger = t::lib::Mocks::Logger->new;
|
|
my $schema = Koha::Database->new->schema;
|
|
my $builder = t::lib::TestBuilder->new;
|
|
|
|
subtest '_derived_class() tests' => sub {
|
|
|
|
plan tests => 3;
|
|
|
|
$schema->storage->txn_begin;
|
|
|
|
my $job_object = Koha::BackgroundJob->new();
|
|
my $mapping = $job_object->type_to_class_mapping;
|
|
|
|
# pick the first
|
|
my $type = ( keys %{$mapping} )[0];
|
|
|
|
my $job = $builder->build_object(
|
|
{ class => 'Koha::BackgroundJobs',
|
|
value => { type => $type, data => 'Foo' }
|
|
}
|
|
);
|
|
|
|
my $derived = $job->_derived_class;
|
|
|
|
is( ref($derived), $mapping->{$type}, 'Job object class is correct' );
|
|
ok( $derived->in_storage, 'The object is correctly marked as in storage' );
|
|
|
|
$derived->data('Bar')->store->discard_changes;
|
|
$job->discard_changes;
|
|
|
|
is_deeply( $job->unblessed, $derived->unblessed, '_derived_class object refers to the same DB object and can be manipulated as expected' );
|
|
|
|
$schema->storage->txn_rollback;
|
|
};
|
|
|
|
subtest 'enqueue() tests' => sub {
|
|
|
|
plan tests => 10;
|
|
|
|
$schema->storage->txn_begin;
|
|
|
|
# Enqueue without args
|
|
throws_ok { Koha::BackgroundJob::BatchUpdateItem->new->enqueue }
|
|
'Koha::Exceptions::BackgroundJob',
|
|
'Enqueue BatchUpdateItem without data throws exception';
|
|
|
|
# The following test needs a mock to trigger the exception
|
|
my $mock = Test::MockModule->new('Net::Stomp');
|
|
$mock->mock( 'send_with_receipt', sub { 0 } );
|
|
throws_ok { Koha::BackgroundJob::MARCImportCommitBatch->new->enqueue }
|
|
'Koha::Exceptions::BackgroundJob',
|
|
'Enqueue MARCImportCommitBatch with mock throws exception';
|
|
$mock->unmock('send_with_receipt');
|
|
|
|
# FIXME: This all feels we need to do it better...
|
|
my $job_id = Koha::BackgroundJob::BatchUpdateItem->new->enqueue( { record_ids => [ 1, 2 ] } );
|
|
my $job = Koha::BackgroundJobs->find($job_id)->_derived_class;
|
|
|
|
is( $job->size, 2, 'Two steps' );
|
|
is( $job->status, 'new', 'Initial status set correctly' );
|
|
is( $job->borrowernumber, undef, 'No userenv, borrowernumber undef' );
|
|
|
|
my $interface = C4::Context->interface;
|
|
my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
|
|
t::lib::Mocks::mock_userenv( { patron => $patron } );
|
|
my $job_context = {
|
|
number => $patron->borrowernumber,
|
|
id => $patron->userid,
|
|
cardnumber => $patron->cardnumber,
|
|
firstname => $patron->firstname,
|
|
surname => $patron->surname,
|
|
branch => $patron->library->branchcode,
|
|
branchname => $patron->library->branchname,
|
|
flags => $patron->flags,
|
|
emailaddress => $patron->email,
|
|
register_id => undef,
|
|
register_name => undef,
|
|
shibboleth => undef,
|
|
desk_id => undef,
|
|
desk_name => undef,
|
|
interface => $interface
|
|
};
|
|
|
|
$job_id = Koha::BackgroundJob::BatchUpdateItem->new->enqueue( { record_ids => [ 1, 2, 3 ] } );
|
|
$job = Koha::BackgroundJobs->find($job_id)->_derived_class;
|
|
|
|
is( $job->size, 3, 'Three steps' );
|
|
is( $job->status, 'new', 'Initial status set correctly' );
|
|
is( $job->borrowernumber, $patron->id, 'Borrowernumber set from userenv' );
|
|
is( $job->queue, 'long_tasks', 'BatchUpdateItem should use the long_tasks queue' );
|
|
is_deeply( $job->json->decode( $job->context ), $job_context, 'Context set from userenv + interface' );
|
|
|
|
$schema->storage->txn_rollback;
|
|
};
|
|
|
|
subtest 'start(), step() and finish() tests' => sub {
|
|
|
|
plan tests => 19;
|
|
|
|
$schema->storage->txn_begin;
|
|
|
|
# FIXME: This all feels we need to do it better...
|
|
my $job_id = Koha::BackgroundJob::BatchUpdateItem->new->enqueue( { record_ids => [ 1, 2 ] } );
|
|
my $job = Koha::BackgroundJobs->find($job_id)->_derived_class;
|
|
|
|
is( $job->started_on, undef, 'started_on not set yet' );
|
|
is( $job->size, 2, 'Two steps' );
|
|
|
|
$job->start;
|
|
|
|
isnt( $job->started_on, undef, 'started_on set' );
|
|
is( $job->status, 'started' );
|
|
is( $job->progress, 0, 'No progress yet' );
|
|
|
|
$job->step;
|
|
is( $job->progress, 1, 'First step' );
|
|
$job->step;
|
|
is( $job->progress, 2, 'Second step' );
|
|
throws_ok
|
|
{ $job->step; }
|
|
'Koha::Exceptions::BackgroundJob::StepOutOfBounds',
|
|
'Tried to make a forbidden extra step';
|
|
|
|
is( $job->progress, 2, 'progress remains unchanged' );
|
|
|
|
my $data = { some => 'data' };
|
|
|
|
$job->status('cancelled')->store;
|
|
$job->finish( $data );
|
|
|
|
is( $job->status, 'cancelled', "'finish' leaves 'cancelled' untouched" );
|
|
isnt( $job->ended_on, undef, 'ended_on set' );
|
|
is_deeply( $job->json->decode( $job->data ), $data );
|
|
|
|
$job->status('started')->store;
|
|
$job->finish( $data );
|
|
|
|
is( $job->status, 'finished' );
|
|
isnt( $job->ended_on, undef, 'ended_on set' );
|
|
is_deeply( $job->json->decode( $job->data ), $data );
|
|
|
|
throws_ok
|
|
{ $job->start; }
|
|
'Koha::Exceptions::BackgroundJob::InconsistentStatus',
|
|
'Exception thrown trying to start a finished job';
|
|
|
|
is( $@->expected_status, 'new' );
|
|
|
|
throws_ok
|
|
{ $job->step; }
|
|
'Koha::Exceptions::BackgroundJob::InconsistentStatus',
|
|
'Exception thrown trying to start a finished job';
|
|
|
|
is( $@->expected_status, 'started' );
|
|
|
|
$schema->storage->txn_rollback;
|
|
};
|
|
|
|
subtest 'process tests' => sub {
|
|
|
|
plan tests => 5;
|
|
|
|
$schema->storage->txn_begin;
|
|
|
|
C4::Context->interface('intranet');
|
|
my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
|
|
t::lib::Mocks::mock_userenv( { patron => $patron } );
|
|
my $job_context = {
|
|
number => $patron->borrowernumber,
|
|
id => $patron->userid,
|
|
cardnumber => $patron->cardnumber,
|
|
firstname => $patron->firstname,
|
|
surname => $patron->surname,
|
|
branch => $patron->library->branchcode,
|
|
branchname => $patron->library->branchname,
|
|
flags => $patron->flags,
|
|
emailaddress => $patron->email,
|
|
register_id => undef,
|
|
register_name => undef,
|
|
shibboleth => undef,
|
|
desk_id => undef,
|
|
desk_name => undef,
|
|
};
|
|
|
|
my $background_job_module = Test::MockModule->new('Koha::BackgroundJob');
|
|
$background_job_module->mock(
|
|
'type_to_class_mapping',
|
|
sub {
|
|
return { batch_test => 't::lib::Koha::BackgroundJob::BatchTest' };
|
|
}
|
|
);
|
|
|
|
my $job_id = t::lib::Koha::BackgroundJob::BatchTest->new->enqueue(
|
|
{ size => 10, a => 'aaa', b => 'bbb' } );
|
|
my $job = Koha::BackgroundJobs->find($job_id);
|
|
|
|
C4::Context->_new_userenv(-1);
|
|
C4::Context->interface('opac');
|
|
is( C4::Context->userenv, undef, "Userenv unset prior to calling process");
|
|
is( C4::Context->interface, 'opac', "Interface set to opac prior to calling process");
|
|
|
|
$job->process();
|
|
is_deeply( C4::Context->userenv, $job_context, "Userenv set from job context on process" );
|
|
is_deeply( C4::Context->interface, 'intranet', "Interface set from job context on process" );
|
|
|
|
# Manually add a job (->new->store) without context
|
|
my $json = $job->json; # sorry, quickly borrowing your json object
|
|
my $data = $json->encode({ a => 'a', b => 'b' });
|
|
my $incomplete_job = t::lib::Koha::BackgroundJob::BatchTest->new(
|
|
{ status => 'new',
|
|
size => 1,
|
|
borrowernumber => $patron->borrowernumber,
|
|
type => 'batch_test',
|
|
data => $data,
|
|
}
|
|
)->store;
|
|
|
|
$incomplete_job = Koha::BackgroundJobs->find( $incomplete_job->id );
|
|
$incomplete_job->process();
|
|
$logger->warn_is( "A background job didn't have context defined (" . $incomplete_job->id . ")" );
|
|
|
|
$schema->storage->txn_rollback;
|
|
};
|
|
|
|
subtest 'decoded_data() and set_encoded_data() tests' => sub {
|
|
|
|
plan tests => 8;
|
|
$schema->storage->txn_begin;
|
|
|
|
my $job = Koha::BackgroundJob::BatchUpdateItem->new->set_encoded_data( undef );
|
|
is( $job->decoded_data, undef, 'undef is undef' );
|
|
|
|
my $data = { some => 'data' };
|
|
|
|
$job->set_encoded_data( $data );
|
|
|
|
is_deeply( $job->json->decode($job->data), $data, 'decode what we sent' );
|
|
is_deeply( $job->decoded_data, $data, 'check with decoded_data' );
|
|
|
|
# Let's get some Unicode stuff into the game
|
|
$data = { favorite_Chinese => [ '葑', '癱' ], latin_dancing => [ '¢', '¥', 'á', 'û' ] };
|
|
$job->set_encoded_data( $data )->store;
|
|
|
|
$job->discard_changes; # refresh
|
|
is_deeply( $job->decoded_data, $data, 'Deep compare with Unicode data' );
|
|
# To convince you even more
|
|
is( ord( $job->decoded_data->{favorite_Chinese}->[0] ), 33873, 'We still found Unicode \x8451' );
|
|
is( ord( $job->decoded_data->{latin_dancing}->[0] ), 162, 'We still found the equivalent of Unicode \x00A2' );
|
|
|
|
# Testing with sending encoded data (which we normally shouldn't do)
|
|
my $utf8_data;
|
|
foreach my $k ( 'favorite_Chinese', 'latin_dancing' ) {
|
|
foreach my $c ( @{$data->{$k}} ) {
|
|
push @{$utf8_data->{$k}}, Encode::encode('UTF-8', $c);
|
|
}
|
|
}
|
|
$job->set_encoded_data( $utf8_data )->store;
|
|
$job->discard_changes; # refresh
|
|
is_deeply( $job->decoded_data, $utf8_data, 'Deep compare with utf8_data' );
|
|
# Need more evidence?
|
|
is( ord( $job->decoded_data->{favorite_Chinese}->[0] ), 232, 'We still found a UTF8 encoded byte' ); # ord does not need substr here
|
|
|
|
$schema->storage->txn_rollback;
|
|
};
|