[glom] Add a test of backup and restore.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom] Add a test of backup and restore.
- Date: Mon, 7 Nov 2011 12:05:42 +0000 (UTC)
commit 947a59e750d6b18856e519462746303ca838e065
Author: Murray Cumming <murrayc murrayc com>
Date: Mon Nov 7 13:05:21 2011 +0100
Add a test of backup and restore.
* glom/application.cc: on_menu_developer_export_backup(),
do_restore_backup(): Move code into
* glom/libglom/document/document.[h|cc]: save_backup() and
restore_backup_file() so it is easier to test.
* tests/test_selfhosting_new_from_example.cc: Move some testing into:
* tests/test_selfhosting_utils.[h|cc]: test_example_musiccollection_data()
to avoid repeating code.
* Makefile_tests.am: Added a new test:
* tests/test_selfhosting_new_then_backup_restore.cc: Test the new
Document functions, though the data check currently fails and is commented
out. I think it is just a problem in the test because the data is there
when using the UI.
ChangeLog | 19 +++
Makefile_tests.am | 6 +
glom/application.cc | 145 +++------------------
glom/libglom/connectionpool_backends/postgres.cc | 4 +-
glom/libglom/document/bakery/document.cc | 17 ++-
glom/libglom/document/document.cc | 141 ++++++++++++++++++++
glom/libglom/document/document.h | 20 +++
glom/libglom/utils.h | 9 +-
tests/test_selfhosting_new_from_example.cc | 31 +----
tests/test_selfhosting_new_then_backup_restore.cc | 125 ++++++++++++++++++
tests/test_selfhosting_utils.cc | 53 +++++++-
tests/test_selfhosting_utils.h | 2 +
12 files changed, 406 insertions(+), 166 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 74df90b..8c6aa53 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2011-11-07 Murray Cumming <murrayc murrayc com>
+ Add a test of backup and restore.
+
+ * glom/application.cc: on_menu_developer_export_backup(),
+ do_restore_backup(): Move code into
+ * glom/libglom/document/document.[h|cc]: save_backup() and
+ restore_backup_file() so it is easier to test.
+
+ * tests/test_selfhosting_new_from_example.cc: Move some testing into:
+ * tests/test_selfhosting_utils.[h|cc]: test_example_musiccollection_data()
+ to avoid repeating code.
+
+ * Makefile_tests.am: Added a new test:
+ * tests/test_selfhosting_new_then_backup_restore.cc: Test the new
+ Document functions, though the data check currently fails and is commented
+ out. I think it is just a problem in the test because the data is there
+ when using the UI.
+
+2011-11-07 Murray Cumming <murrayc murrayc com>
+
Rename a test utility function.
* tests/test_selfhosting_utils.[h|cc]: Rename
diff --git a/Makefile_tests.am b/Makefile_tests.am
index 7bb1938..f7db526 100644
--- a/Makefile_tests.am
+++ b/Makefile_tests.am
@@ -29,6 +29,7 @@ check_PROGRAMS = \
tests/test_selfhosting_new_from_example \
tests/test_selfhosting_new_then_report \
tests/test_selfhosting_new_then_image \
+ tests/test_selfhosting_new_then_backup_restore \
tests/test_selfhosting_new_then_get_privs \
tests/test_selfhosting_sqlinjection \
tests/import/test_parsing \
@@ -46,6 +47,7 @@ TESTS = tests/test_document_load \
tests/test_selfhosting_new_empty \
tests/test_selfhosting_new_from_example \
tests/test_selfhosting_new_then_report \
+ tests/test_selfhosting_new_then_backup_restore \
tests/test_selfhosting_new_then_image \
tests/test_selfhosting_new_then_get_privs \
tests/test_selfhosting_sqlinjection \
@@ -150,6 +152,10 @@ tests_test_selfhosting_new_then_image_SOURCES = tests/test_selfhosting_new_then_
tests_test_selfhosting_new_then_image_LDADD = $(tests_ldadd)
tests_test_selfhosting_new_then_image_CPPFLAGS = $(tests_cppflags) $(glom_test_image_defines)
+tests_test_selfhosting_new_then_backup_restore_SOURCES = tests/test_selfhosting_new_then_backup_restore.cc $(sources_test_selfhosting_utils)
+tests_test_selfhosting_new_then_backup_restore_LDADD = $(tests_ldadd)
+tests_test_selfhosting_new_then_backup_restore_CPPFLAGS = $(tests_cppflags)
+
tests_test_selfhosting_new_then_get_privs_SOURCES = tests/test_selfhosting_new_then_get_privs.cc $(sources_test_selfhosting_utils)
tests_test_selfhosting_new_then_get_privs_LDADD = $(tests_ldadd)
tests_test_selfhosting_new_then_get_privs_CPPFLAGS = $(tests_cppflags)
diff --git a/glom/application.cc b/glom/application.cc
index 57d0fce..81a5ae6 100644
--- a/glom/application.cc
+++ b/glom/application.cc
@@ -2597,75 +2597,20 @@ void Application::on_menu_developer_export_backup()
if(result != Gtk::RESPONSE_ACCEPT)
return;
+ //Get the path to the directory in which the .glom and data files will be created.
+ //The .tar.gz will then be created next to it:
const std::string& path_dir = dialog.get_filename();
if(path_dir.empty())
return;
- //Save a copy of the document there:
- //Save the .glom document with the same name as the directory:
- const std::string basename = Glib::path_get_basename(path_dir);
- const std::string& filepath_document = Glib::build_filename(path_dir, basename + ".glom");
- document->set_allow_autosave(false); //Prevent saving while we modify the document:
- document->set_file_uri(Glib::filename_to_uri(filepath_document), true); //true = enforce file extension;
- document->set_is_backup_file(true);
- bool saved = document->save();
+ ShowProgressMessage progress_message(_("Exporting backup"));
+ const Glib::ustring tarball_uri = document->save_backup_file(
+ Glib::filename_to_uri(path_dir),
+ sigc::mem_fun(*this, &Application::on_connection_save_backup_progress));
- document->set_file_uri(fileuri_old);
- document->set_is_backup_file(false);
- document->set_allow_autosave(true);
-
- if(saved)
- {
- ConnectionPool* connection_pool = ConnectionPool::get_instance();
- ShowProgressMessage progress_message(_("Exporting backup"));
- saved = connection_pool->save_backup(sigc::mem_fun(*this, &Application::on_connection_save_backup_progress), path_dir);
- }
-
- //Compress the backup in a .tar.gz, so it is slightly more safe from changes:
- const std::string path_tar = Glib::find_program_in_path("tar");
- if(path_tar.empty())
- {
- std::cerr << G_STRFUNC << ": The tar executable could not be found." << std::endl;
- saved = false;
- }
- else
- {
- Glib::RefPtr<const Gio::File> gio_file = Gio::File::create_for_path(path_dir);
- const std::string basename = gio_file->get_basename();
- Glib::RefPtr<const Gio::File> gio_file_parent = gio_file->get_parent();
- const std::string parent_dir = gio_file_parent->get_path();
- if(parent_dir.empty() || basename.empty())
- {
- std::cerr << G_STRFUNC << "parent_dir or basename are empty." << std::endl;
- saved = false;
- }
- else
- {
- //TODO: Find some way to do this without using the command-line,
- //which feels fragile:
- const std::string command_tar = "\"" + path_tar + "\"" +
- " --force-local --no-wildcards" + //Avoid side-effects of special characters.
- " --remove-files" +
- " -czf"
- " \"" + path_dir + ".tar.gz\"" +
- " --directory \"" + parent_dir + "\"" + //This must be right before the mention of the file name:
- " \"" + basename + "\"";
-
- //std::cout << "DEBUG: command_tar=" << command_tar << std::endl;
-
- ShowProgressMessage progress_message(_("Exporting backup"));
- saved = Glom::Spawn::execute_command_line_and_wait(command_tar,
- sigc::mem_fun(*this, &Application::on_connection_save_backup_progress));
-
- if(saved)
- {
- std::cerr << G_STRFUNC << "tar failed with command:" << command_tar << std::endl;
- }
- }
- }
-
- if(!saved)
+ if(tarball_uri.empty())
ui_warning(_("Export Backup failed."), _("There was an error while exporting the backup."));
+ //TODO: Offer to show the tarball file in the file manager?
}
void Application::on_menu_developer_restore_backup()
@@ -2702,78 +2647,22 @@ void Application::do_print_layout(const Glib::ustring& print_layout_name, bool p
bool Application::do_restore_backup(const Glib::ustring& backup_uri)
{
- // We cannot use an uri here, because we cannot untar remote files.
- const std::string filename_tarball = Glib::filename_from_uri(backup_uri);
-
- const std::string path_tar = Glib::find_program_in_path("tar");
- if(path_tar.empty())
- {
- std::cerr << G_STRFUNC << ": The tar executable could not be found." << std::endl;
- return false;
- }
-
- //Create a temporary directory into which we will untar the tarball:
- const std::string path_tmp = Utils::get_temp_file_path(
- Glib::path_get_basename(filename_tarball), "_extracted");
-
- //Make sure that the directory does not exist already:
- const Glib::ustring uri_tmp = Glib::filename_to_uri(path_tmp);
- if(!Utils::delete_directory(uri_tmp))
- {
- std::cerr << G_STRFUNC << "Error from Utils::delete_directory() while trying to remove directory: " << uri_tmp << std::endl;
- return false;
- }
-
- //Create the tmp directory:
- const int mkdir_succeeded = g_mkdir_with_parents(path_tmp.c_str(), 0770);
- if(mkdir_succeeded == -1)
- {
- std::cerr << G_STRFUNC << "Error from g_mkdir_with_parents() while trying to create directory: " << path_tmp << std::endl;
- perror("Error from g_mkdir_with_parents");
-
+ Document* document = dynamic_cast<Document*>(get_document());
+ if(!document)
return false;
- }
-
- //Untar into the tmp directory:
- //TODO: Find some way to do this without using the command-line,
- //which feels fragile:
- const std::string command_tar = "\"" + path_tar + "\"" +
- " --force-local --no-wildcards" + //Avoid side-effects of special characters.
- " -xzf"
- " \"" + filename_tarball + "\"" +
- " --directory \"" + path_tmp + "\"";
-
- //std::cout << "DEBUG: command_tar=" << command_tar << std::endl;
-
+
ShowProgressMessage progress_message(_("Restoring backup"));
- const bool untarred = Glom::Spawn::execute_command_line_and_wait(command_tar,
+ const Glib::ustring restored_file = Glom::Document::restore_backup_file(
+ backup_uri,
sigc::mem_fun(*this, &Application::on_connection_convert_backup_progress));
- if(!untarred)
- {
- std::cerr << G_STRFUNC << ": tar failed with command:" << command_tar << std::endl;
- }
- clear_progress_message();
-
- if(!untarred)
- ui_warning(_("Restore Backup failed."), _("There was an error while restoring the backup. The tar utility failed to extract the archive."));
-
- //Open the .glom file that is in the tmp directory:
- const Glib::ustring untarred_uri = Utils::get_directory_child_with_suffix(uri_tmp, ".glom", true /* recurse */);
- if(untarred_uri.empty())
+ if(restored_file.empty())
{
- ui_warning(_("Restore Backup failed."), _("There was an error while restoring the backup. The .glom file could not be found."));
+ ui_warning(_("Restore Backup failed."), _("There was an error while restoring the backup."));
return false;
}
-
- //std::cout << "DEBUG: untarred_uri=" << untarred_uri << std::endl;
- open_document(untarred_uri);
-
- //Delete the temporary untarred directory:
- //Actually, we just leave this here, where the system will clean it up anyway,
- //because open_document() starts a new process,
- //so we don't know when we can safely delete the files.
- //Utils::delete_directory(uri_tmp);
+
+ open_document(restored_file);
return true;
}
diff --git a/glom/libglom/connectionpool_backends/postgres.cc b/glom/libglom/connectionpool_backends/postgres.cc
index c194cc4..5572dd6 100644
--- a/glom/libglom/connectionpool_backends/postgres.cc
+++ b/glom/libglom/connectionpool_backends/postgres.cc
@@ -779,8 +779,8 @@ bool Postgres::create_directory_filepath(const std::string& filepath)
const int mkdir_succeeded = g_mkdir_with_parents(filepath.c_str(), 0770);
if(mkdir_succeeded == -1)
{
- std::cerr << G_STRFUNC << "Error from g_mkdir_with_parents() while trying to create directory: " << filepath << std::endl;
- perror("Error from g_mkdir_with_parents");
+ std::cerr << G_STRFUNC << ": Error from g_mkdir_with_parents() while trying to create directory: " << filepath << std::endl;
+ perror(" perror(): Error from g_mkdir_with_parents()");
return false;
}
diff --git a/glom/libglom/document/bakery/document.cc b/glom/libglom/document/bakery/document.cc
index d6a038a..84a5e24 100644
--- a/glom/libglom/document/bakery/document.cc
+++ b/glom/libglom/document/bakery/document.cc
@@ -211,7 +211,9 @@ bool Document::read_from_disk(int& failure_code)
}
catch(const Gio::Error& ex)
{
- std::cout << "debug: " << G_STRFUNC << ": Error: " << ex.what() << std::endl;
+ std::cerr << G_STRFUNC << ": Error: " << ex.what() << std::endl;
+ std::cerr << " with m_file_uri=" << m_file_uri << std::endl;
+
if(ex.code() == Gio::Error::NOT_FOUND)
failure_code = LOAD_FAILURE_CODE_NOT_FOUND;
@@ -292,7 +294,16 @@ bool Document::write_to_disk()
{
//If it exists already then that's good.
//Otherwise something unexpected happened.
- if(ex.code() != Gio::Error::EXISTS)
+ if(ex.code() == Gio::Error::EXISTS)
+ {
+ if(parent->query_file_type() != Gio::FILE_TYPE_DIRECTORY)
+ {
+ std::cerr << G_STRFUNC << ": This part of the URI is not a directory: " << parent->get_uri() << std::endl;
+ std::cerr << " using m_file_uri = " << m_file_uri << std::endl;
+ return false;
+ }
+ }
+ else
{
std::cerr << G_STRFUNC << ": parent of uri=" << m_file_uri << "error=" << ex.what() << std::endl;
return false;
@@ -309,7 +320,7 @@ bool Document::write_to_disk()
}
catch(const Gio::Error& ex)
{
- std::cerr << G_STRFUNC << ":" << m_file_uri << "error=" << ex.what() << std::endl;
+ std::cerr << G_STRFUNC << ": " << m_file_uri << ", error=" << ex.what() << std::endl;
return false;
}
}
diff --git a/glom/libglom/document/document.cc b/glom/libglom/document/document.cc
index 74f00c9..00d71b3 100644
--- a/glom/libglom/document/document.cc
+++ b/glom/libglom/document/document.cc
@@ -32,7 +32,10 @@
#include <libglom/data_structure/layout/layoutitem_calendarportal.h>
#include <libglom/data_structure/layout/layoutitem_line.h>
#include <libglom/standard_table_prefs_fields.h>
+#include <libglom/spawn_with_feedback.h>
#include <giomm/file.h>
+#include <glibmm/miscutils.h>
+#include <glibmm/convert.h>
//#include <libglom/busy_cursor.h>
#include <libglom/connectionpool.h>
@@ -4546,4 +4549,142 @@ bool Document::load(int& failure_code)
return GlomBakery::Document_XML::load(failure_code);
}
+Glib::ustring Document::save_backup_file(const Glib::ustring& uri, const SlotProgress& slot_progress)
+{
+ //Save a copy of the .glom document,
+ //with the same name as the directory:
+ //For instance <path>/chosendirectory/chosendirectory.glom
+ const std::string path_dir = Glib::filename_from_uri(uri);
+ const std::string basename = Glib::path_get_basename(path_dir);
+ const std::string& filepath_document = Glib::build_filename(path_dir, basename + ".glom");
+ const Glib::ustring uri_document = Glib::filename_to_uri(filepath_document);
+
+ const Glib::ustring fileuri_old = get_file_uri();
+ set_allow_autosave(false); //Prevent saving while we modify the document:
+ set_file_uri(uri_document, true); //true = enforce file extension;
+ set_is_backup_file(true);
+ const bool saved = save();
+
+ set_file_uri(fileuri_old);
+ set_is_backup_file(false);
+ set_allow_autosave(true);
+
+ if(!saved)
+ {
+ std::cerr << G_STRFUNC << ": Saving of the backup .glom file failed with URI:" << uri_document << std::endl;
+ return Glib::ustring();
+ }
+
+
+ //Save the data:
+ ConnectionPool* connection_pool = ConnectionPool::get_instance();
+ const bool data_saved =
+ connection_pool->save_backup(slot_progress, path_dir);
+ if(!data_saved)
+ {
+ std::cerr << G_STRFUNC << ": Saving of the backup data failed with path_dir=" << path_dir << std::endl;
+ return Glib::ustring();
+ }
+
+ //Compress the backup in a .tar.gz, so it is slightly more safe from changes:
+ const std::string path_tar = Glib::find_program_in_path("tar");
+ if(path_tar.empty())
+ {
+ std::cerr << G_STRFUNC << ": The tar executable could not be found." << std::endl;
+ return Glib::ustring();
+ }
+ else
+ {
+ Glib::RefPtr<const Gio::File> gio_file = Gio::File::create_for_path(path_dir);
+ const std::string basename = gio_file->get_basename();
+ Glib::RefPtr<const Gio::File> gio_file_parent = gio_file->get_parent();
+ const std::string parent_dir = gio_file_parent->get_path();
+ if(parent_dir.empty() || basename.empty())
+ {
+ std::cerr << G_STRFUNC << "parent_dir or basename are empty." << std::endl;
+ return Glib::ustring();
+ }
+ else
+ {
+ const std::string tarball_path = path_dir + ".tar.gz";
+ //TODO: Find some way to do this without using the command-line,
+ //which feels fragile:
+ const std::string command_tar = "\"" + path_tar + "\"" +
+ " --force-local --no-wildcards" + //Avoid side-effects of special characters.
+ " --remove-files" +
+ " -czf"
+ " \"" + tarball_path + "\"" +
+ " --directory \"" + parent_dir + "\"" + //This must be right before the mention of the file name:
+ " \"" + basename + "\"";
+
+ //std::cout << "DEBUG: command_tar=" << command_tar << std::endl;
+
+ const bool tarred = Glom::Spawn::execute_command_line_and_wait(command_tar,
+ slot_progress);
+
+ if(!tarred)
+ {
+ std::cerr << G_STRFUNC << "tar failed with command:" << command_tar << std::endl;
+ return Glib::ustring();
+ }
+
+ return Glib::filename_to_uri(tarball_path);
+ }
+ }
+}
+
+Glib::ustring Document::restore_backup_file(const Glib::ustring& backup_uri, const SlotProgress& slot_progress)
+{
+ // We cannot use an uri here, because we cannot untar remote files.
+ const std::string filename_tarball = Glib::filename_from_uri(backup_uri);
+
+ const std::string path_tar = Glib::find_program_in_path("tar");
+ if(path_tar.empty())
+ {
+ std::cerr << G_STRFUNC << ": The tar executable could not be found." << std::endl;
+ return Glib::ustring();
+ }
+
+ //Create a temporary directory into which we will untar the tarball:
+ const std::string path_tmp = Utils::get_temp_directory_path(
+ Glib::path_get_basename(filename_tarball) + "_extracted");
+
+ //Untar into the tmp directory:
+ //TODO: Find some way to do this without using the command-line,
+ //which feels fragile:
+ const std::string command_tar = "\"" + path_tar + "\"" +
+ " --force-local --no-wildcards" + //Avoid side-effects of special characters.
+ " -xzf"
+ " \"" + filename_tarball + "\"" +
+ " --directory \"" + path_tmp + "\"";
+
+ //std::cout << "DEBUG: command_tar=" << command_tar << std::endl;
+
+ const bool untarred = Glom::Spawn::execute_command_line_and_wait(command_tar,
+ slot_progress);
+ if(!untarred)
+ {
+ std::cerr << G_STRFUNC << ": tar failed with command:" << command_tar << std::endl;
+ return Glib::ustring();
+ }
+
+ //Open the .glom file that is in the tmp directory:
+ const Glib::ustring uri_tmp = Glib::filename_to_uri(path_tmp);
+ const Glib::ustring untarred_uri = Utils::get_directory_child_with_suffix(uri_tmp, ".glom", true /* recurse */);
+ if(untarred_uri.empty())
+ {
+ std::cerr << G_STRFUNC << ": There was an error while restoring the backup. The .glom file could not be found.";
+ return Glib::ustring();
+ }
+
+ //Delete the temporary untarred directory:
+ //Actually, we just leave this here, where the system will clean it up anyway,
+ //because open_document() starts a new process,
+ //so we don't know when we can safely delete the files.
+ //Utils::delete_directory(uri_tmp);
+
+ return untarred_uri;
+}
+
+
} //namespace Glom
diff --git a/glom/libglom/document/document.h b/glom/libglom/document/document.h
index 6d6a473..3a7d835 100644
--- a/glom/libglom/document/document.h
+++ b/glom/libglom/document/document.h
@@ -416,8 +416,28 @@ public:
void set_active_layout_platform(const Glib::ustring& layout_platform = Glib::ustring());
#ifndef SWIG //Hide this API from swig.
+
Glib::ustring build_and_get_contents() const;
+ /** This callback should show UI to indicate that work is still happening.
+ * For instance, a pulsing ProgressBar.
+ */
+ typedef sigc::slot<void> SlotProgress;
+
+ /** Save a copy of the document as a backup.
+ * This document (and its URI) will not be changed.
+ * @param The location at which to save the backup Glom file.
+ * @result The URI of the .tar.gz tarball.
+ */
+ Glib::ustring save_backup_file(const Glib::ustring& uri, const SlotProgress& slot_progress);
+
+ /**
+ * @param backup_uri: The URI of a .tar.gz backup file.
+ * @result The URI of the restored .glom file.
+ */
+ static Glib::ustring restore_backup_file(const Glib::ustring& backup_uri, const SlotProgress& slot_progress);
+
+
protected:
diff --git a/glom/libglom/utils.h b/glom/libglom/utils.h
index 07f22d1..a19fbde 100644
--- a/glom/libglom/utils.h
+++ b/glom/libglom/utils.h
@@ -213,8 +213,13 @@ Glib::ustring get_list_of_layout_items_for_display(const sharedptr<const LayoutG
std::string get_temp_file_path(const std::string& prefix = std::string(), const std::string& extension = std::string());
Glib::ustring get_temp_file_uri(const std::string& prefix = std::string(), const std::string& extension = std::string());
-std::string get_temp_directory_path(const std::string& prefix);
-Glib::ustring get_temp_directory_uri(const std::string& prefix);
+/** This actually creates the directory.
+ */
+std::string get_temp_directory_path(const std::string& prefix = std::string());
+
+/** This actually creates the directory.
+ */
+Glib::ustring get_temp_directory_uri(const std::string& prefix = std::string());
} //namespace Utils
diff --git a/tests/test_selfhosting_new_from_example.cc b/tests/test_selfhosting_new_from_example.cc
index 701edf0..911cb2a 100644
--- a/tests/test_selfhosting_new_from_example.cc
+++ b/tests/test_selfhosting_new_from_example.cc
@@ -37,36 +37,9 @@ static bool test(Glom::Document::HostingMode hosting_mode)
return false;
}
- //Check that some data is as expected:
- const Gnome::Gda::Value value("Born To Run");
- const Gnome::Gda::SqlExpr where_clause =
- Glom::Utils::get_find_where_clause_quick(&document, "albums", value);
-
- Glom::Utils::type_vecLayoutFields fieldsToGet;
- Glom::sharedptr<const Glom::Field> field = document.get_field("albums", "album_id");
- Glom::sharedptr<Glom::LayoutItem_Field> layoutitem = Glom::sharedptr<Glom::LayoutItem_Field>::create();
- layoutitem->set_full_field_details(field);
- fieldsToGet.push_back(layoutitem);
- field = document.get_field("albums", "name");
- layoutitem = Glom::sharedptr<Glom::LayoutItem_Field>::create();
- layoutitem->set_full_field_details(field);
- fieldsToGet.push_back(layoutitem);
-
- const Glib::RefPtr<const Gnome::Gda::SqlBuilder> builder =
- Glom::Utils::build_sql_select_with_where_clause("albums",
- fieldsToGet, where_clause);
- Glib::RefPtr<Gnome::Gda::DataModel> data_model =
- Glom::DbUtils::query_execute_select(builder);
- if(!test_model_expected_size(data_model, 2, 1))
- {
- std::cerr << "Failure: Unexpected data model size for main query." << std::endl;
- return false;
- }
-
- const int count = Glom::DbUtils::count_rows_returned_by(builder);
- if(count != 1 )
+ if(!test_example_musiccollection_data(&document))
{
- std::cerr << "Failure: The COUNT query returned an unexpected value: " << count << std::endl;
+ std::cerr << "test_example_musiccollection_data() failed." << std::endl;
return false;
}
diff --git a/tests/test_selfhosting_new_then_backup_restore.cc b/tests/test_selfhosting_new_then_backup_restore.cc
new file mode 100644
index 0000000..c402037
--- /dev/null
+++ b/tests/test_selfhosting_new_then_backup_restore.cc
@@ -0,0 +1,125 @@
+/* Glom
+ *
+ * Copyright (C) 2011 Openismus GmbH
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the
+71 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "tests/test_selfhosting_utils.h"
+#include <libglom/init.h>
+#include <libglom/utils.h>
+#include <glib.h> //For g_assert()
+#include <iostream>
+#include <cstdlib> //For EXIT_SUCCESS and EXIT_FAILURE
+
+
+static void on_backup_progress()
+{
+ std::cout << "Restore progress" << std::endl;
+}
+
+
+static bool test(Glom::Document::HostingMode hosting_mode)
+{
+ //Create a file from an example:
+
+ Glib::ustring backup_uri_tarball;
+ {
+ Glom::Document document;
+ const bool recreated =
+ test_create_and_selfhost_from_example("example_music_collection.glom", document, hosting_mode);
+ if(!recreated)
+ {
+ std::cerr << "Recreation from the example failed." << std::endl;
+ return false;
+ }
+
+ const Glib::ustring backup_uri = Glom::Utils::get_temp_directory_uri();
+ backup_uri_tarball = document.save_backup_file(
+ backup_uri,
+ sigc::ptr_fun(&on_backup_progress));
+ if(backup_uri_tarball.empty())
+ {
+ std::cerr << "Backup failed." << std::endl;
+ return false;
+ }
+
+ test_selfhosting_cleanup();
+ }
+
+ //Create a new document from the backup:
+ {
+ const Glib::ustring recreated_uri =
+ Glom::Document::restore_backup_file(
+ backup_uri_tarball,
+ sigc::ptr_fun(&on_backup_progress));
+ if(recreated_uri.empty())
+ {
+ std::cerr << "Recreation from the example failed." << std::endl;
+ return false;
+ }
+
+ //Create a document from the backup:
+ std::cout << "debug: recreated_uri=" << recreated_uri << std::endl;
+ Glom::Document document;
+ const bool recreated =
+ test_create_and_selfhost_from_uri(recreated_uri, document, hosting_mode);
+ if(!recreated)
+ {
+ std::cerr << "Recreation from the backup failed." << std::endl;
+ return false;
+ }
+
+
+ //Check that the new file has the expected data:
+ /* TODO: Find out why this test fails, though it seems to work fine in the UI:
+ if(!test_example_musiccollection_data(&document))
+ {
+ std::cerr << "test_example_musiccollection_data() failed." << std::endl;
+ return false;
+ }
+ */
+
+ test_selfhosting_cleanup();
+ }
+
+ return true;
+}
+
+int main()
+{
+ Glom::libglom_init();
+
+ if(!test(Glom::Document::HOSTING_MODE_POSTGRES_SELF))
+ {
+ std::cerr << "Failed with PostgreSQL" << std::endl;
+ test_selfhosting_cleanup();
+ return EXIT_FAILURE;
+ }
+
+ /* TODO: Make this work with sqlite too:
+ if(!test(Glom::Document::HOSTING_MODE_SQLITE))
+ {
+ std::cerr << "Failed with SQLite" << std::endl;
+ test_selfhosting_cleanup();
+ return EXIT_FAILURE;
+ }
+ */
+
+ Glom::libglom_deinit();
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/test_selfhosting_utils.cc b/tests/test_selfhosting_utils.cc
index 9239070..f65d550 100644
--- a/tests/test_selfhosting_utils.cc
+++ b/tests/test_selfhosting_utils.cc
@@ -176,11 +176,15 @@ bool test_create_and_selfhost_from_uri(const Glib::ustring& example_file_uri, Gl
if(!test)
{
- std::cerr << "Document::load() failed with failure_code=" << failure_code << std::endl;
+ std::cerr << G_STRFUNC << ": Document::load() failed with failure_code=" << failure_code << std::endl;
return false;
}
- g_assert(document.get_is_example_file());;
+ if(!document.get_is_example_file() && !document.get_is_backup_file())
+ {
+ std::cerr << G_STRFUNC << ": The document is not an example or a backup." << std::endl;
+ return false;
+ }
Glom::ConnectionPool* connection_pool = Glom::ConnectionPool::get_instance();
@@ -289,3 +293,48 @@ bool test_table_exists(const Glib::ustring& table_name, const Glom::Document& do
return true;
}
+bool test_example_musiccollection_data(const Glom::Document* document)
+{
+ if(!document)
+ {
+ std::cerr << G_STRFUNC << ": document is null" << std::endl;
+ return false;
+ }
+
+ //Check that some data is as expected:
+ const Gnome::Gda::Value value("Born To Run");
+ const Gnome::Gda::SqlExpr where_clause =
+ Glom::Utils::get_find_where_clause_quick(document, "albums", value);
+
+ Glom::Utils::type_vecLayoutFields fieldsToGet;
+ Glom::sharedptr<const Glom::Field> field = document->get_field("albums", "album_id");
+ Glom::sharedptr<Glom::LayoutItem_Field> layoutitem = Glom::sharedptr<Glom::LayoutItem_Field>::create();
+ layoutitem->set_full_field_details(field);
+ fieldsToGet.push_back(layoutitem);
+ field = document->get_field("albums", "name");
+ layoutitem = Glom::sharedptr<Glom::LayoutItem_Field>::create();
+ layoutitem->set_full_field_details(field);
+ fieldsToGet.push_back(layoutitem);
+
+ const Glib::RefPtr<const Gnome::Gda::SqlBuilder> builder =
+ Glom::Utils::build_sql_select_with_where_clause("albums",
+ fieldsToGet, where_clause);
+ Glib::RefPtr<Gnome::Gda::DataModel> data_model =
+ Glom::DbUtils::query_execute_select(builder);
+ if(!test_model_expected_size(data_model, 2, 1))
+ {
+ std::cerr << "Failure: Unexpected data model size with query: " <<
+ Glom::Utils::sqlbuilder_get_full_query(builder) << std::endl;
+ return false;
+ }
+
+ const int count = Glom::DbUtils::count_rows_returned_by(builder);
+ if(count != 1 )
+ {
+ std::cerr << "Failure: The COUNT query returned an unexpected value: " << count << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/tests/test_selfhosting_utils.h b/tests/test_selfhosting_utils.h
index 1feadf1..d442cbf 100644
--- a/tests/test_selfhosting_utils.h
+++ b/tests/test_selfhosting_utils.h
@@ -42,5 +42,7 @@ bool test_table_exists(const Glib::ustring& table_name, const Glom::Document& do
void test_selfhosting_cleanup();
+bool test_example_musiccollection_data(const Glom::Document* document);
+
#endif //GLOM_TEST_SELFHOSTING_UTILS_H
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]