tag 746125 patch thanks On Thu, Sep 04, 2014 at 11:35:58PM +0100, Dominic Hargreaves wrote:
> Unhandled error: [DBD::SQLite::st execute failed: attempt to write a readonly > database at /usr/share/perl5/Wiki/Toolkit/Store/Database.pm line 567. This can be reduced to the attached script, which succeeds for me on wheezy but fails on sid. I think it's a bug in the tests, which first make a database connection and then remove the database file from underneath it. Older combinations of SQLite / DBD::SQLite are apparently more tolerant. From the SQLite 3.8.3 changelog: Add SQLITE_READONLY_DBMOVED error code, returned at the beginning of a transaction, to indicate that the underlying database file has been renamed or moved out from under SQLite. This is what shines through in the above message. It's a bit surprising that this ever worked. It looks like the new DBI->connect for a different database handle somehow used to reset the behaviour for the first handle too. If I omit the second DBI->connect in the test script, I get DBD::SQLite::db do failed: disk I/O error on wheezy, which matches my expectations better. Now, the fix for openguides is to call OpenGuides::Test::refresh_db() before OpenGuides->new(), which connects to the database and caches the connection handle. Patch attached, this makes the test suite pass for me. -- Niko Tyni nt...@debian.org
#!/usr/bin/perl -w use strict; use DBI; my $dbh = DBI->connect("dbi:SQLite:dbname=t.db", { PrintError => 1, RaiseError => 1}) or die("connect failed"); $dbh->do('create table t (name varchar)') or die("create failed"); $dbh->do("INSERT INTO t (name) VALUES ('old');") or die("insert old failed"); unlink 't.db' or die("unlink failed"); my $dbh2 = DBI->connect("dbi:SQLite:dbname=t.db", { PrintError => 1, RaiseError => 1}) or die("second connect failed"); $dbh->do("INSERT INTO t (name) VALUES ('new');") or die("insert new failed"); print "finished successfully\n";
>From b36e14a8df59fb13f066d68230a00d29991daa41 Mon Sep 17 00:00:00 2001 From: Niko Tyni <nt...@debian.org> Date: Sun, 14 Sep 2014 19:37:40 +0300 Subject: [PATCH] Refresh the database before caching a connection handle to it OpenGuides->new() caches a connection to the SQLite database. When OpenGuides::Test::refresh_db() is called, it removes the database file and reconnects to it. If that happens after OpenGuides->new(), the cached handle becomes read-only as of SQLite 3.8.3. From its changelog: Add SQLITE_READONLY_DBMOVED error code, returned at the beginning of a transaction, to indicate that the underlying database file has been renamed or moved out from under SQLite. This causes test failures with error messages like Unhandled error: [DBD::SQLite::st execute failed: attempt to write a readonly database at /usr/share/perl5/Wiki/Toolkit/Store/Database.pm line 567. ] at /usr/share/perl5/Wiki/Toolkit.pm line 849. Moving the refresh_db() call earlier fixes these failures. --- t/109_autocreate.t | 6 +++--- t/802_stylesheet.t | 6 +++--- t/809_recent_changes_ip_addr.t | 6 +++--- t/900_css_category_locale_classes.t | 6 +++--- t/901_username_in_templates.t | 6 +++--- t/902_node_name_from_cgi_obj.t | 6 +++--- t/903_redirect_without_spaces.t | 6 +++--- t/904_leaflet.t | 6 +++--- t/905_multiple_index.t | 6 +++--- t/907_auto_map_link.t | 6 +++--- t/908_custom_node_location_search.t | 6 +++--- t/909_external_class_metadata.t | 6 +++--- 12 files changed, 36 insertions(+), 36 deletions(-) diff --git a/t/109_autocreate.t b/t/109_autocreate.t index 7c44f18..b9a1f19 100644 --- a/t/109_autocreate.t +++ b/t/109_autocreate.t @@ -14,6 +14,9 @@ if ( $@ ) { plan tests => 13; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; $config->custom_template_path( cwd . "/t/templates/" ); my $guide = OpenGuides->new( config => $config ); @@ -21,9 +24,6 @@ my $wiki = $guide->wiki; my $categoriser = Wiki::Toolkit::Plugin::Categoriser->new; $wiki->register_plugin( plugin => $categoriser ); -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Check that unwelcome characters are stripped from autocreated cats/locales. # Double spaces: OpenGuides::Test->write_data( diff --git a/t/802_stylesheet.t b/t/802_stylesheet.t index 9a76518..5bda3bb 100644 --- a/t/802_stylesheet.t +++ b/t/802_stylesheet.t @@ -18,13 +18,13 @@ if ( $@ ) { plan tests => 3; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki; -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Write a node. OpenGuides::Test->write_data( guide => $guide, node => "Red Lion", return_output => 1 ); diff --git a/t/809_recent_changes_ip_addr.t b/t/809_recent_changes_ip_addr.t index a1ad33a..e2ba127 100644 --- a/t/809_recent_changes_ip_addr.t +++ b/t/809_recent_changes_ip_addr.t @@ -14,13 +14,13 @@ if ( $@ ) { plan tests => 10; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki; -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # First we need to make sure that the preferences are accessible # from the recent changes view. Can't test this using return_tt_vars # because the prefs TT var is set in OpenGuides::Template->output(), diff --git a/t/900_css_category_locale_classes.t b/t/900_css_category_locale_classes.t index 00bfc01..13ab74c 100644 --- a/t/900_css_category_locale_classes.t +++ b/t/900_css_category_locale_classes.t @@ -18,13 +18,13 @@ if ( $@ ) { plan tests => 3; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; $config->custom_template_path( cwd . "/t/templates/" ); my $guide = OpenGuides->new( config => $config ); -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Check that a node in one locale and one category has CSS classes for both. OpenGuides::Test->write_data( guide => $guide, diff --git a/t/901_username_in_templates.t b/t/901_username_in_templates.t index 2ae32bb..128ec16 100644 --- a/t/901_username_in_templates.t +++ b/t/901_username_in_templates.t @@ -14,13 +14,13 @@ if ( $@ ) { plan tests => 2; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; $config->custom_template_path( cwd . "/t/templates/tmp/" ); my $guide = OpenGuides->new( config => $config ); -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Write a node. OpenGuides::Test->write_data( guide => $guide, diff --git a/t/902_node_name_from_cgi_obj.t b/t/902_node_name_from_cgi_obj.t index acb1d4a..431664a 100644 --- a/t/902_node_name_from_cgi_obj.t +++ b/t/902_node_name_from_cgi_obj.t @@ -13,13 +13,13 @@ if ( $@ ) { plan tests => 18; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki; -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Write a node. OpenGuides::Test->write_data( guide => $guide, diff --git a/t/903_redirect_without_spaces.t b/t/903_redirect_without_spaces.t index a3b40c4..72fe398 100644 --- a/t/903_redirect_without_spaces.t +++ b/t/903_redirect_without_spaces.t @@ -13,13 +13,13 @@ if ( $@ ) { plan tests => 27; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki; -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Write a couple of nodes, one with a single-word name, one with multiple. OpenGuides::Test->write_data( guide => $guide, diff --git a/t/904_leaflet.t b/t/904_leaflet.t index 71732a0..a7d83b8 100644 --- a/t/904_leaflet.t +++ b/t/904_leaflet.t @@ -16,14 +16,14 @@ my $thc = $@ ? 0 : 1; plan tests => 25; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; $config->static_url( "http://example.com/static" ); my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki; -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Write a couple of nodes, two with legitimate geodata, another with # broken geodata, another with no geodata. OpenGuides::Test->write_data( diff --git a/t/905_multiple_index.t b/t/905_multiple_index.t index 2900b22..ccfa450 100644 --- a/t/905_multiple_index.t +++ b/t/905_multiple_index.t @@ -19,13 +19,13 @@ if ( $@ ) { plan tests => 18; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki; -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Write some nodes. OpenGuides::Test->write_data( guide => $guide, diff --git a/t/907_auto_map_link.t b/t/907_auto_map_link.t index f356544..db72c2f 100644 --- a/t/907_auto_map_link.t +++ b/t/907_auto_map_link.t @@ -14,14 +14,14 @@ if ( $@ ) { plan tests => 10; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; $config->custom_template_path( cwd . "/t/templates/tmp/" ); my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki; -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Write a couple of nodes, one with a map link and another # without; also with/without address # NOTE: the node with neither address nor map link diff --git a/t/908_custom_node_location_search.t b/t/908_custom_node_location_search.t index a2c02a6..2cc004f 100644 --- a/t/908_custom_node_location_search.t +++ b/t/908_custom_node_location_search.t @@ -14,14 +14,14 @@ if ( $@ ) { plan tests => 3; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; $config->custom_template_path( cwd . "/t/templates/tmp/" ); my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki; -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Write a couple of nodes, one with a map link and another # without; also with/without address # NOTE: the node with neither address nor map link diff --git a/t/909_external_class_metadata.t b/t/909_external_class_metadata.t index ed14703..d3e3df9 100644 --- a/t/909_external_class_metadata.t +++ b/t/909_external_class_metadata.t @@ -14,13 +14,13 @@ if ( $@ ) { plan tests => 2; +# Clear out the database from any previous runs. +OpenGuides::Test::refresh_db(); + my $config = OpenGuides::Test->make_basic_config; my $guide = OpenGuides->new( config => $config ); my $wiki = $guide->wiki; -# Clear out the database from any previous runs. -OpenGuides::Test::refresh_db(); - # Write out a node with a map link and external website OpenGuides::Test->write_data( guide => $guide, -- 2.1.0