diff --git a/t/db_dependent/Koha/Plugins/Barcode_transform_hooks.t b/t/db_dependent/Koha/Plugins/Barcode_transform_hooks.t index cbd50360df..7b4095beb8 100755 --- a/t/db_dependent/Koha/Plugins/Barcode_transform_hooks.t +++ b/t/db_dependent/Koha/Plugins/Barcode_transform_hooks.t @@ -47,15 +47,17 @@ subtest 'patron_barcode_transform() and item_barcode_transform() hook tests' => $schema->storage->txn_begin; - # Avoid testing useless warnings - my $test_plugin = Test::MockModule->new('Koha::Plugin::Test'); - $test_plugin->mock( 'after_item_action', undef ); - $test_plugin->mock( 'after_biblio_action', undef ); - my $plugins = Koha::Plugins->new; warning_is { $plugins->InstallPlugins; } undef; + # Avoid testing useless warnings. Must be applied after InstallPlugins, + # which reloads plugin classes from disk and would otherwise wipe the + # mocks. + my $test_plugin = Test::MockModule->new('Koha::Plugin::Test'); + $test_plugin->mock( 'after_item_action', undef ); + $test_plugin->mock( 'after_biblio_action', undef ); + C4::Context->dbh->do("DELETE FROM plugin_methods WHERE plugin_class LIKE '%TestBarcodes%'"); my $plugin = Koha::Plugin::Test->new->enable; diff --git a/t/db_dependent/Koha/Plugins/Plugins.t b/t/db_dependent/Koha/Plugins/Plugins.t index 97b0fcbee9..c2996520eb 100755 --- a/t/db_dependent/Koha/Plugins/Plugins.t +++ b/t/db_dependent/Koha/Plugins/Plugins.t @@ -26,7 +26,7 @@ use List::MoreUtils qw(none); use Module::Load::Conditional qw(can_load); use Test::MockModule; use Test::NoWarnings; -use Test::More tests => 21; +use Test::More tests => 22; use Test::Warn; use Test::Exception; @@ -264,6 +264,72 @@ subtest 'InstallPlugins() tests' => sub { $schema->storage->txn_rollback; }; +subtest 'InstallPlugins() reloads stale symbol tables tests' => sub { + + plan tests => 5; + + $schema->storage->txn_begin; + + Koha::Plugins::Methods->delete; + $schema->resultset('PluginData')->delete; + + my $plugins = Koha::Plugins->new( { enable_plugins => 1 } ); + $plugins->InstallPlugins( { include => ['Koha::Plugin::Test'] } ); + + # Simulate the stale-symbol-table scenario that a long-lived Plack worker + # would hit when a plugin is upgraded in place: inject a method into the + # loaded package that is not present in the .pm file on disk, and add a + # matching plugin_methods row as if a previous version of the plugin had + # this method and had loaded the older version into memory. + # A run of InstallPlugins should reload from disk and the phantom method + # should disappear. + { + no strict 'refs'; + *{'Koha::Plugin::Test::stale_phantom_method'} = sub { 1 }; + } + + Koha::Plugins::Method->new( + { + plugin_class => 'Koha::Plugin::Test', + plugin_method => 'stale_phantom_method', + } + )->store; + + ok( + Koha::Plugin::Test->can('stale_phantom_method'), + 'Phantom method is in the in-memory symbol table before reinstall' + ); + + ok( + Koha::Plugins::Methods->search( + { plugin_class => 'Koha::Plugin::Test', plugin_method => 'stale_phantom_method' } + )->count, + 'Phantom method row is present in plugin_methods before reinstall' + ); + + $plugins->InstallPlugins( { include => ['Koha::Plugin::Test'] } ); + + ok( + !Koha::Plugin::Test->can('stale_phantom_method'), + 'Phantom method is gone from the symbol table after reinstall (package was reloaded)' + ); + + is( + Koha::Plugins::Methods->search( + { plugin_class => 'Koha::Plugin::Test', plugin_method => 'stale_phantom_method' } + )->count, + 0, + 'Phantom method absent from the .pm file is not persisted to plugin_methods after reinstall' + ); + + ok( + Koha::Plugins::Methods->search( { plugin_class => 'Koha::Plugin::Test', plugin_method => 'tool' } )->count, + 'Real methods from the .pm file are persisted to plugin_methods' + ); + + $schema->storage->txn_rollback; +}; + subtest 'Version upgrade tests' => sub { plan tests => 1;