[glom] Add test_selfhosting_new_from_example_operator.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom] Add test_selfhosting_new_from_example_operator.
- Date: Wed, 1 Feb 2012 09:00:23 +0000 (UTC)
commit 9c67be8dd6d161d5f78e162fc08d74c246a96470
Author: Murray Cumming <murrayc murrayc com>
Date: Wed Feb 1 09:59:58 2012 +0100
Add test_selfhosting_new_from_example_operator.
* glom/base_db.[h|cc]: Move add_user() to
* glom/libglom/db_utils.[h|cc]:
* glom/frame_glom.cc:
* glom/mode_design/users/dialog_users_list.cc: Adapted.
* glom/libglom/connectionpool.cc: invalidate_connection():
Also clear m_pFieldTypes to make sure that we refill it when making
a new connection.
* glom/libglom/data_structure/fieldtypes.[h|cc]: Add get_types_count().
* tests/test_selfhosting_utils.[h|cc]: Add test_selfhost() to
start an already-existing .glom system.
* Makefile_tests.am:
* tests/test_selfhosting_new_from_example_operator.cc:
Add this new test which attempts to re-open a .glom system as
a non-developer user. This currently fails to get the list of
tables from the database. I must investigate that.
ChangeLog | 22 +++
Makefile_tests.am | 6 +
glom/base_db.cc | 48 +------
glom/base_db.h | 5 -
glom/frame_glom.cc | 4 +-
glom/libglom/connectionpool.cc | 19 +++-
glom/libglom/data_structure/field.cc | 4 +
glom/libglom/data_structure/fieldtypes.cc | 16 ++
glom/libglom/data_structure/fieldtypes.h | 2 +
glom/libglom/db_utils.cc | 73 +++++++++-
glom/libglom/db_utils.h | 5 +
glom/mode_design/users/dialog_users_list.cc | 2 +-
tests/.gitignore | 1 +
.../test_selfhosting_new_from_example_operator.cc | 150 ++++++++++++++++++++
tests/test_selfhosting_utils.cc | 54 +++++--
tests/test_selfhosting_utils.h | 16 ++-
16 files changed, 352 insertions(+), 75 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index e75d3ce..04e715d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2012-02-01 Murray Cumming <murrayc murrayc com>
+
+ Add test_selfhosting_new_from_example_operator.
+
+ * glom/base_db.[h|cc]: Move add_user() to
+ * glom/libglom/db_utils.[h|cc]:
+ * glom/frame_glom.cc:
+ * glom/mode_design/users/dialog_users_list.cc: Adapted.
+
+ * glom/libglom/connectionpool.cc: invalidate_connection():
+ Also clear m_pFieldTypes to make sure that we refill it when making
+ a new connection.
+
+ * glom/libglom/data_structure/fieldtypes.[h|cc]: Add get_types_count().
+ * tests/test_selfhosting_utils.[h|cc]: Add test_selfhost() to
+ start an already-existing .glom system.
+ * Makefile_tests.am:
+ * tests/test_selfhosting_new_from_example_operator.cc:
+ Add this new test which attempts to re-open a .glom system as
+ a non-developer user. This currently fails to get the list of
+ tables from the database. I must investigate that.
+
2012-01-30 Murray Cumming <murrayc murrayc com>
Add test_selfhosting_new_empty_change_sysprefs.
diff --git a/Makefile_tests.am b/Makefile_tests.am
index ff0b9d3..f350e9d 100644
--- a/Makefile_tests.am
+++ b/Makefile_tests.am
@@ -37,6 +37,7 @@ check_PROGRAMS = \
tests/test_selfhosting_new_empty \
tests/test_selfhosting_new_empty_change_sysprefs \
tests/test_selfhosting_new_from_example \
+ tests/test_selfhosting_new_from_example_operator \
tests/test_selfhosting_new_from_example_strangepath \
tests/test_selfhosting_new_then_report \
tests/test_selfhosting_new_then_image \
@@ -71,6 +72,7 @@ TESTS = tests/test_document_load \
tests/test_selfhosting_new_empty \
tests/test_selfhosting_new_empty_change_sysprefs \
tests/test_selfhosting_new_from_example \
+ tests/test_selfhosting_new_from_example_operator \
tests/test_selfhosting_new_from_example_in_locales.sh \
tests/test_selfhosting_new_from_example_strangepath \
tests/test_selfhosting_new_then_report \
@@ -226,6 +228,10 @@ tests_test_selfhosting_new_from_example_SOURCES = tests/test_selfhosting_new_fro
tests_test_selfhosting_new_from_example_LDADD = $(tests_ldadd)
tests_test_selfhosting_new_from_example_CPPFLAGS = $(tests_cppflags)
+tests_test_selfhosting_new_from_example_operator_SOURCES = tests/test_selfhosting_new_from_example_operator.cc $(sources_test_selfhosting_utils)
+tests_test_selfhosting_new_from_example_operator_LDADD = $(tests_ldadd)
+tests_test_selfhosting_new_from_example_operator_CPPFLAGS = $(tests_cppflags)
+
tests_test_selfhosting_new_from_example_strangepath_SOURCES = tests/test_selfhosting_new_from_example_strangepath.cc $(sources_test_selfhosting_utils)
tests_test_selfhosting_new_from_example_strangepath_LDADD = $(tests_ldadd)
tests_test_selfhosting_new_from_example_strangepath_CPPFLAGS = $(tests_cppflags)
diff --git a/glom/base_db.cc b/glom/base_db.cc
index be2ec2a..039d11f 100644
--- a/glom/base_db.cc
+++ b/glom/base_db.cc
@@ -1584,53 +1584,7 @@ void Base_DB::set_found_set_where_clause_for_portal(FoundSet& found_set, const s
}
}
-bool Base_DB::add_user(const Glib::ustring& user, const Glib::ustring& password, const Glib::ustring& group)
-{
- if(user.empty() || password.empty() || group.empty())
- return false;
-
- //Create the user:
- //Note that ' around the user fails, so we use ".
- Glib::ustring strQuery = "CREATE USER " + DbUtils::escape_sql_id(user) + " PASSWORD '" + password + "'" ; //TODO: Escape the password.
- if(group == GLOM_STANDARD_GROUP_NAME_DEVELOPER)
- strQuery += " SUPERUSER CREATEDB CREATEROLE"; //Because SUPERUSER is not "inherited" from groups to members.
-
- bool test = DbUtils::query_execute_string(strQuery);
- if(!test)
- {
- std::cerr << G_STRFUNC << ": CREATE USER failed." << std::endl;
- return false;
- }
-
- //Add it to the group:
- strQuery = DbUtils::build_query_add_user_to_group(group, user);
- test = DbUtils::query_execute_string(strQuery);
- if(!test)
- {
- std::cerr << G_STRFUNC << ": ALTER GROUP failed." << std::endl;
- return false;
- }
-
- //Remove any user rights, so that all rights come from the user's presence in the group:
- Document* document = get_document();
- if(!document)
- return true;
-
- Document::type_listTableInfo table_list = document->get_tables();
-
- for(Document::type_listTableInfo::const_iterator iter = table_list.begin(); iter != table_list.end(); ++iter)
- {
- const Glib::ustring table_name = (*iter)->get_name();
- const Glib::ustring strQuery = "REVOKE ALL PRIVILEGES ON " + DbUtils::escape_sql_id(table_name) + " FROM " + DbUtils::escape_sql_id(user);
- const bool test = DbUtils::query_execute_string(strQuery);
- if(!test)
- std::cerr << G_STRFUNC << ": REVOKE failed." << std::endl;
- }
-
- return true;
-}
-
-
+//TODO: Move this into libglom and test it.
bool Base_DB::remove_user(const Glib::ustring& user)
{
if(user.empty())
diff --git a/glom/base_db.h b/glom/base_db.h
index 7436460..36f9fcb 100644
--- a/glom/base_db.h
+++ b/glom/base_db.h
@@ -290,11 +290,6 @@ protected:
typedef std::vector<Glib::ustring> type_vec_strings;
static type_vec_strings util_vecStrings_from_Fields(const type_vec_fields& fields);
- /** Add a @a user to the database, with the specified @a password, in the specified @a group.
- * @result true if the addition succeeded.
- */
- bool add_user(const Glib::ustring& user, const Glib::ustring& password, const Glib::ustring& group);
-
/** Remove the @a user from the database.
* @result true if the removal succeeded.
*/
diff --git a/glom/frame_glom.cc b/glom/frame_glom.cc
index c36ce2b..1524d65 100644
--- a/glom/frame_glom.cc
+++ b/glom/frame_glom.cc
@@ -844,7 +844,7 @@ void Frame_Glom::on_menu_file_toggle_share(const Glib::RefPtr<Gtk::ToggleAction>
const bool initial_password_provided = connection_request_initial_password(user, password);
bool added = false;
if(initial_password_provided)
- added = add_user(user, password, GLOM_STANDARD_GROUP_NAME_DEVELOPER);
+ added = DbUtils::add_user(document, user, password, GLOM_STANDARD_GROUP_NAME_DEVELOPER);
if(initial_password_provided && added)
{
@@ -942,7 +942,7 @@ void Frame_Glom::on_menu_file_toggle_share(const Glib::RefPtr<Gtk::ToggleAction>
Glib::ustring default_password;
const Glib::ustring default_user = Privs::get_default_developer_user_name(default_password);
- const bool added = add_user(default_user, default_password, GLOM_STANDARD_GROUP_NAME_DEVELOPER);
+ const bool added = DbUtils::add_user(document, default_user, default_password, GLOM_STANDARD_GROUP_NAME_DEVELOPER);
if(!added)
{
shared = true;
diff --git a/glom/libglom/connectionpool.cc b/glom/libglom/connectionpool.cc
index 4fa9298..cc29f1b 100644
--- a/glom/libglom/connectionpool.cc
+++ b/glom/libglom/connectionpool.cc
@@ -268,6 +268,8 @@ static bool on_connection_pool_cache_timeout()
sharedptr<SharedConnection> ConnectionPool::connect()
{
+ //std::cout << G_STRFUNC << ": debug" << std::endl;
+
//Don't try to connect if we don't have a backend to connect to.
g_return_val_if_fail(m_backend.get(), sharedptr<SharedConnection>(0));
@@ -340,11 +342,16 @@ sharedptr<SharedConnection> ConnectionPool::connect()
{
//update_meta_store_table_names() has been known to throw an exception.
//Glom is mostly unusable when it fails, but that's still better than a crash.
- m_refGdaConnection->update_meta_store_table_names(m_backend->get_public_schema_name());
+ //std::cout << G_STRFUNC << ": Before update_meta_store_table_name()" << std::endl;
+ const bool test = m_refGdaConnection->update_meta_store_table_names(m_backend->get_public_schema_name());
+ if(!test && !m_fake_connection)
+ {
+ std::cerr << G_STRFUNC << ": update_meta_store_table_names() failed without an exception." << std::endl;
+ }
}
catch(const Glib::Error& ex)
{
- //If the conneciton was not opened, because it is a fake connection,
+ //If the connection was not opened, because it is a fake connection,
//then we should not be surprised that this fails,
//and a warning will only be useful later when get_meta_store_data() fails when used in get_table_names_from_database().
if(!m_fake_connection)
@@ -496,6 +503,10 @@ Glib::ustring ConnectionPool::get_database() const
const FieldTypes* ConnectionPool::get_field_types() const
{
+ //TODO: Investigate this:
+ //if(!m_pFieldTypes)
+ // std::cerr << G_STRFUNC << ": m_pFieldTypes is null but this should never happen." << std::endl;
+
return m_pFieldTypes;
}
@@ -507,6 +518,7 @@ Gnome::Gda::SqlOperatorType ConnectionPool::get_string_find_operator() const
void ConnectionPool::invalidate_connection()
{
+ //std::cerr << G_STRFUNC << ": debug" << std::endl;
connection_cached.clear();
connection_cached_timeout_connection.disconnect();
connection_cached_finished_connection.disconnect();
@@ -516,6 +528,9 @@ void ConnectionPool::invalidate_connection()
m_refGdaConnection.reset();
m_sharedconnection_refcount = 0;
+
+ delete m_pFieldTypes;
+ m_pFieldTypes = 0;
}
void ConnectionPool::on_sharedconnection_finished()
diff --git a/glom/libglom/data_structure/field.cc b/glom/libglom/data_structure/field.cc
index c91fbfb..af23c7d 100644
--- a/glom/libglom/data_structure/field.cc
+++ b/glom/libglom/data_structure/field.cc
@@ -554,6 +554,10 @@ Glib::ustring Field::get_sql_type() const
const GType fieldType = m_field_info->get_g_type();
strType = pFieldTypes->get_string_name_for_gdavaluetype(fieldType);
}
+ else
+ {
+ std::cerr << G_STRFUNC << ": get_field_types() returned null" << std::endl;
+ }
}
if(strType == "unknowntype")
diff --git a/glom/libglom/data_structure/fieldtypes.cc b/glom/libglom/data_structure/fieldtypes.cc
index 82b539a..594b93f 100644
--- a/glom/libglom/data_structure/fieldtypes.cc
+++ b/glom/libglom/data_structure/fieldtypes.cc
@@ -82,6 +82,7 @@ FieldTypes::FieldTypes(const Glib::RefPtr<Gnome::Gda::Connection>& gda_connectio
//std::cout << "debug: schema_type_string=" << schema_type_string << ", gda type=" << gdatype << "(" << g_type_name(gdatype) << ")" << std::endl;
//Save it for later:
+ //std::cout << G_STRFUNC << ": debug: schema_type_string=" << schema_type_string << ", gdatype=" << g_type_name(gdatype) << std::endl;
m_mapSchemaStringsToGdaTypes[schema_type_string] = gdatype;
Glib::ustring gdatypestring = gda_g_type_to_string(gdatype); // TODO: What is this actually used for?
@@ -107,6 +108,21 @@ FieldTypes::~FieldTypes()
{
}
+guint FieldTypes::get_types_count() const
+{
+/*
+ if(!m_mapSchemaStringsToGdaTypes.empty())
+ {
+ const type_mapSchemaStringsToGdaTypes::const_iterator iter = m_mapSchemaStringsToGdaTypes.begin();
+ const Glib::ustring schema_type_string = iter->first;
+ const GType gdatype = iter->second;
+ std::cout << G_STRFUNC << ": debug: schema_type_string=" << schema_type_string << ", gdatype=" << g_type_name(gdatype) << std::endl;
+ }
+*/
+
+ return m_mapSchemaStringsToGdaTypes.size();
+}
+
Glib::ustring FieldTypes::get_string_name_for_gdavaluetype(GType field_type) const
{
//Special-case gchararray (G_TYPE_STRING) because Gda reports this GType for several
diff --git a/glom/libglom/data_structure/fieldtypes.h b/glom/libglom/data_structure/fieldtypes.h
index 4a765bf..6a47781 100644
--- a/glom/libglom/data_structure/fieldtypes.h
+++ b/glom/libglom/data_structure/fieldtypes.h
@@ -39,6 +39,8 @@ public:
Glib::ustring get_string_name_for_gdavaluetype(GType field_type) const;
GType get_fallback_type_for_gdavaluetype(GType field_type) const;
+
+ guint get_types_count() const;
private:
typedef std::map<Glib::ustring, GType> type_mapSchemaStringsToGdaTypes;
diff --git a/glom/libglom/db_utils.cc b/glom/libglom/db_utils.cc
index d7966bf..cffc9f9 100644
--- a/glom/libglom/db_utils.cc
+++ b/glom/libglom/db_utils.cc
@@ -246,8 +246,8 @@ bool recreate_database_from_document(Document* document, const sigc::slot<void>&
sharedptr<SharedConnection> sharedconnection;
try
{
+ //Check that we can connect:
sharedconnection = connection_pool->connect();
- connection_pool->set_database(db_name); //The database was successfully created, so specify it when connecting from now on.
}
catch(const ExceptionConnection& ex)
{
@@ -841,7 +841,7 @@ type_vec_fields get_fields_for_table_from_database(const Glib::ustring& table_na
Glib::RefPtr<Gnome::Gda::DataModel> data_model_fields;
try
{
- //This should work because we called update_meta_store_tables() in ConnectionPool,
+ //This should work because we called update_meta_store_table_names() in ConnectionPool,
//and that gets the tables' fields too.
data_model_fields = connection->get_meta_store_data(Gnome::Gda::CONNECTION_META_FIELDS, holder_list);
}
@@ -2015,6 +2015,75 @@ Glib::ustring build_query_add_user_to_group(const Glib::ustring& group, const Gl
return "ALTER GROUP " + escape_sql_id(group) + " ADD USER " + escape_sql_id(user);
}
+static Glib::ustring build_query_add_user(const Glib::ustring& user, const Glib::ustring& password, bool superuser)
+{
+ if(user.empty())
+ {
+ std::cerr << G_STRFUNC << ": user is empty" << std::endl;
+ }
+
+ if(password.empty())
+ {
+ std::cerr << G_STRFUNC << ": password is empty" << std::endl;
+ }
+
+ //Note that ' around the user fails, so we use ".
+ Glib::ustring strQuery = "CREATE USER " + DbUtils::escape_sql_id(user) + " PASSWORD '" + password + "'" ; //TODO: Escape the password.
+ if(superuser)
+ strQuery += " SUPERUSER CREATEDB CREATEROLE"; //Because SUPERUSER is not "inherited" from groups to members.
+
+ return strQuery;
+}
+
+bool add_user(const Document* document, const Glib::ustring& user, const Glib::ustring& password, const Glib::ustring& group)
+{
+ if(!document)
+ {
+ std::cerr << G_STRFUNC << ": document is null." << std::endl;
+ return false;
+ }
+
+ if(user.empty() || password.empty() || group.empty())
+ {
+ std::cerr << G_STRFUNC << ": user, password, or group are empty." << std::endl;
+ return false;
+ }
+
+ //Create the user:
+ const bool superuser = (group == GLOM_STANDARD_GROUP_NAME_DEVELOPER);
+ const Glib::ustring query_add = build_query_add_user(user, password, superuser);
+ bool test = DbUtils::query_execute_string(query_add);
+ if(!test)
+ {
+ std::cerr << G_STRFUNC << ": CREATE USER failed." << std::endl;
+ return false;
+ }
+
+ //Add it to the group:
+ const Glib::ustring query_add_to_group = build_query_add_user_to_group(group, user);
+ test = DbUtils::query_execute_string(query_add_to_group);
+ if(!test)
+ {
+ std::cerr << G_STRFUNC << ": ALTER GROUP failed." << std::endl;
+ return false;
+ }
+
+ //Remove any user rights, so that all rights come from the user's presence in the group:
+ Document::type_listTableInfo table_list = document->get_tables();
+
+ for(Document::type_listTableInfo::const_iterator iter = table_list.begin(); iter != table_list.end(); ++iter)
+ {
+ const Glib::ustring table_name = (*iter)->get_name();
+ const Glib::ustring strQuery = "REVOKE ALL PRIVILEGES ON " + DbUtils::escape_sql_id(table_name) + " FROM " + DbUtils::escape_sql_id(user);
+ const bool test = DbUtils::query_execute_string(strQuery);
+ if(!test)
+ std::cerr << G_STRFUNC << ": REVOKE failed." << std::endl;
+ }
+
+ return true;
+}
+
+
void set_fake_connection()
{
//Allow a fake connection, so sqlbuilder_get_full_query() can work:
diff --git a/glom/libglom/db_utils.h b/glom/libglom/db_utils.h
index 6b6dd83..66e7d36 100644
--- a/glom/libglom/db_utils.h
+++ b/glom/libglom/db_utils.h
@@ -179,6 +179,11 @@ Glib::ustring build_query_create_group(const Glib::ustring& group, bool superuse
Glib::ustring build_query_add_user_to_group(const Glib::ustring& group, const Glib::ustring& user);
+/** Add a @a user to the database, with the specified @a password, in the specified @a group.
+ * @result true if the addition succeeded.
+ */
+bool add_user(const Document* document, const Glib::ustring& user, const Glib::ustring& password, const Glib::ustring& group);
+
/** Get the value of the @a source_field from the @a relationship, using the @a key_value.
*/
Gnome::Gda::Value get_lookup_value(Document* document, const Glib::ustring& table_name, const sharedptr<const Relationship>& relationship, const sharedptr<const Field>& source_field, const Gnome::Gda::Value & key_value);
diff --git a/glom/mode_design/users/dialog_users_list.cc b/glom/mode_design/users/dialog_users_list.cc
index 44ad9c2..31b7749 100644
--- a/glom/mode_design/users/dialog_users_list.cc
+++ b/glom/mode_design/users/dialog_users_list.cc
@@ -258,7 +258,7 @@ void Dialog_UsersList::on_button_user_new()
if(response != Gtk::RESPONSE_OK)
return;
- add_user(user, password, m_combo_group->get_active_text() /* group */);
+ DbUtils::add_user(get_document(), user, password, m_combo_group->get_active_text() /* group */);
fill_list();
}
diff --git a/tests/.gitignore b/tests/.gitignore
index fbf004b..de7f842 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -19,6 +19,7 @@
/test_selfhosting_new_empty
/test_selfhosting_new_empty_change_sysprefs
/test_selfhosting_new_from_example
+/test_selfhosting_new_from_example_operator
/test_selfhosting_new_then_alter_table
/test_selfhosting_new_then_backup_restore
/test_selfhosting_new_then_get_privs
diff --git a/tests/test_selfhosting_new_from_example_operator.cc b/tests/test_selfhosting_new_from_example_operator.cc
new file mode 100644
index 0000000..a0e95e8
--- /dev/null
+++ b/tests/test_selfhosting_new_from_example_operator.cc
@@ -0,0 +1,150 @@
+/* Glom
+ *
+ * Copyright (C) 2010 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 <libglom/db_utils.h>
+#include <libglom/connectionpool.h>
+#include <glib.h> //For g_assert()
+#include <iostream>
+#include <cstdlib> //For EXIT_SUCCESS and EXIT_FAILURE
+
+static bool test(Glom::Document::HostingMode hosting_mode)
+{
+ Glib::ustring temp_file_uri;
+ const Glib::ustring operator_user = "someoperator";
+ const Glib::ustring operator_password = "somepassword";
+
+ //Create and self-host the document:
+ {
+ Glom::Document document;
+ const bool recreated =
+ test_create_and_selfhost_from_example("example_smallbusiness.glom", document, hosting_mode);
+ if(!recreated)
+ {
+ std::cerr << "Recreation failed." << std::endl;
+ return false;
+ }
+
+ temp_file_uri = test_get_temp_file_uri();
+ if(temp_file_uri.empty())
+ {
+ std::cerr << "temp_file_uri is empty." << std::endl;
+ return false;
+ }
+
+ //Add an operator user:
+ if(!Glom::DbUtils::add_user(&document, operator_user, operator_password, "personnel_department"))
+ {
+ std::cerr << "DbUtils::add_user() failed." << std::endl;
+ test_selfhosting_cleanup();
+ return false;
+ }
+
+ //Check that the developer user has access to database metadata:
+ const Glom::DbUtils::type_vec_strings tables =
+ Glom::DbUtils::get_table_names_from_database(true /* ignore system tables */);
+ if(tables.empty())
+ {
+ std::cerr << "get_table_names_from_database() failed for developer user." << std::endl;
+ return false;
+ }
+
+ test_selfhosting_cleanup(false /* do not delete the file. */);
+ }
+
+ //Self-host the document again, this time as operator:
+ {
+ Glom::Document document;
+ document.set_allow_autosave(false); //To simplify things and to not depend implicitly on autosave.
+ document.set_file_uri(temp_file_uri);
+ int failure_code = 0;
+ const bool test = document.load(failure_code);
+ //std::cout << "Document load result=" << test << std::endl;
+ if(!test)
+ {
+ std::cerr << "Document::load() failed with failure_code=" << failure_code << std::endl;
+ return false;
+ }
+
+ if(!test_selfhost(document, operator_user, operator_password))
+ {
+ std::cerr << "test_selfhost() failed." << std::endl;
+ return false;
+ }
+
+ //Check that the operator user still has access to database metadata:
+ Glom::ConnectionPool* connection_pool = Glom::ConnectionPool::get_instance();
+ connection_pool->connect();
+ const Glom::FieldTypes* field_types = connection_pool->get_field_types();
+ if(!field_types)
+ {
+ std::cerr << "get_field_types() returned null." << std::endl;
+ return false;
+ }
+
+ if(field_types->get_types_count() == 0)
+ {
+ std::cerr << "get_field_types() returned no types." << std::endl;
+ return false;
+ }
+
+ //std::cout << "field_types count=" << field_types->get_types_count() << std::endl;
+
+ const Glom::DbUtils::type_vec_strings tables =
+ Glom::DbUtils::get_table_names_from_database(true /* ignore system tables */);
+ if(tables.empty())
+ {
+ std::cerr << "get_table_names_from_database() failed for operator user." << std::endl;
+ return false;
+ }
+
+ test_selfhosting_cleanup(); //Delete the file this time.
+ }
+
+ 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;
+ }
+
+ /* SQLite does not have user/group access levels,
+ * so the SQL queries woudl fail.
+ 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 2fcaab2..f456adf 100644
--- a/tests/test_selfhosting_utils.cc
+++ b/tests/test_selfhosting_utils.cc
@@ -57,7 +57,8 @@ static void on_db_creation_progress()
//std::cout << "Database creation progress" << std::endl;
}
-std::string temp_filepath_dir;
+static std::string temp_filepath_dir; //Remembered so we can delete it later.
+static Glib::ustring temp_file_uri; //Rememered so we can return it sometimes.
static bool check_directory_exists()
{
@@ -115,13 +116,16 @@ static bool delete_directory(const std::string& uri)
return delete_directory(file);
}
-void test_selfhosting_cleanup()
+void test_selfhosting_cleanup(bool delete_file)
{
Glom::ConnectionPool* connection_pool = Glom::ConnectionPool::get_instance();
const bool stopped = connection_pool->cleanup( sigc::ptr_fun(&on_cleanup_progress) );
g_assert(stopped);
+ if(!delete_file)
+ return;
+
//Make sure the directory is removed at the end:
if(!temp_filepath_dir.empty())
{
@@ -141,6 +145,29 @@ void test_selfhosting_cleanup()
}
temp_filepath_dir.clear();
+ temp_file_uri.clear(); //Forget this too.
+}
+
+bool test_selfhost(Glom::Document& document, const Glib::ustring& user, const Glib::ustring& password)
+{
+ //TODO: Let this happen automatically on first connection?
+ Glom::ConnectionPool* connection_pool = Glom::ConnectionPool::get_instance();
+
+ connection_pool->setup_from_document(&document);
+
+ connection_pool->set_user(user);
+ connection_pool->set_password(password);
+
+ const Glom::ConnectionPool::StartupErrors started = connection_pool->startup( sigc::ptr_fun(&on_startup_progress) );
+ if(started != Glom::ConnectionPool::Backend::STARTUPERROR_NONE)
+ {
+ std::cerr << "connection_pool->startup(): result=" << started << std::endl;
+ test_selfhosting_cleanup();
+ return false;
+ }
+ g_assert(started == Glom::ConnectionPool::Backend::STARTUPERROR_NONE);
+
+ return true;
}
bool test_create_and_selfhost_new_empty(Glom::Document& document, Glom::Document::HostingMode hosting_mode, const std::string& subdirectory_path)
@@ -168,9 +195,9 @@ bool test_create_and_selfhost_new_empty(Glom::Document& document, Glom::Document
}
//Save the example as a real file:
- const Glib::ustring file_uri = Glib::filename_to_uri(temp_filepath);
+ temp_file_uri = Glib::filename_to_uri(temp_filepath);
document.set_allow_autosave(false); //To simplify things and to not depend implicitly on autosave.
- document.set_file_uri(file_uri);
+ document.set_file_uri(temp_file_uri);
document.set_hosting_mode(hosting_mode);
document.set_is_example_file(false);
@@ -195,20 +222,17 @@ bool test_create_and_selfhost_new_empty(Glom::Document& document, Glom::Document
if(!check_directory_exists())
{
- std::cerr << "Failure: The data directory does not exist after calling initialize()." << std::endl;
+ std::cerr << "Failure: The data directory does not exist after calling initialize()." << std::endl;
+ return false;
}
//Start self-hosting:
- //TODO: Let this happen automatically on first connection?
- const Glom::ConnectionPool::StartupErrors started = connection_pool->startup( sigc::ptr_fun(&on_startup_progress) );
- if(started != Glom::ConnectionPool::Backend::STARTUPERROR_NONE)
- {
- std::cerr << "connection_pool->startup(): result=" << started << std::endl;
- test_selfhosting_cleanup();
- }
- g_assert(started == Glom::ConnectionPool::Backend::STARTUPERROR_NONE);
+ return test_selfhost(document, user, password);
+}
- return true;
+Glib::ustring test_get_temp_file_uri()
+{
+ return temp_file_uri;
}
bool test_create_and_selfhost_new_database(Glom::Document& document, Glom::Document::HostingMode hosting_mode, const Glib::ustring& database_name, const std::string& subdirectory_path)
@@ -219,7 +243,7 @@ bool test_create_and_selfhost_new_database(Glom::Document& document, Glom::Docum
return false;
}
- const Glib::ustring db_name = Glom::DbUtils::get_unused_database_name("test_db");
+ const Glib::ustring db_name = Glom::DbUtils::get_unused_database_name(database_name);
if(db_name.empty())
{
std::cerr << "DbUtils::get_unused_database_name) failed." << std::endl;
diff --git a/tests/test_selfhosting_utils.h b/tests/test_selfhosting_utils.h
index a31c5f4..0233198 100644
--- a/tests/test_selfhosting_utils.h
+++ b/tests/test_selfhosting_utils.h
@@ -56,10 +56,24 @@ bool test_create_and_selfhost_from_example(const std::string& example_filename,
*/
bool test_create_and_selfhost_from_uri(const Glib::ustring& file_uri, Glom::Document& document, Glom::Document::HostingMode hosting_mode, const std::string& subdirectory_path = std::string());
+/** Start self-hosting of a .glom document.
+ * @param document The document must already be saved to a file.
+ */
+bool test_selfhost(Glom::Document& document, const Glib::ustring& user, const Glib::ustring& password);
+
+
bool test_model_expected_size(const Glib::RefPtr<Gnome::Gda::DataModel>& data_model, guint columns_count, guint rows_count);
bool test_table_exists(const Glib::ustring& table_name, const Glom::Document& document);
-void test_selfhosting_cleanup();
+/** Return the URI of the temporary .glom file created by the test_create_and_selfhost_*() methods.
+ * This should only be used by some special tests.
+ */
+Glib::ustring test_get_temp_file_uri();
+
+/** Stop the self-hosting server process,
+ * and (optionally) delete the temporary .glom file and its data.
+ */
+void test_selfhosting_cleanup(bool delete_file = true);
bool test_example_musiccollection_data(const Glom::Document* document);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]