From 915a2930f3a722ff64ec852c4916eb6e1c697f0b Mon Sep 17 00:00:00 2001 From: John Ralls Date: Tue, 16 Feb 2016 17:11:55 -0800 Subject: [PATCH] Remove close hook list; not used. --- src/backend/dbi/gnc-backend-dbi.cpp | 121 ++++++----- .../sql/test/utest-gnc-backend-sql.cpp | 2 +- src/backend/xml/gnc-backend-xml.cpp | 54 +++-- src/backend/xml/gnc-backend-xml.h | 5 +- src/engine/Transaction.c | 14 +- src/engine/gnc-pricedb.c | 42 ++-- src/gnc/Session.hpp | 8 - src/gnc/mainwindow-file.cpp | 1 - src/gnc/mainwindow.cpp | 2 - src/gnome-utils/gnc-file.c | 3 - src/libqof/CMakeLists.txt | 1 + src/libqof/qof/Makefile.am | 1 + src/libqof/qof/gnc-backend-prov.hpp | 81 +++++++ src/libqof/qof/qofbackend-p.h | 50 ----- src/libqof/qof/qofbackend.cpp | 14 ++ src/libqof/qof/qofbackend.h | 76 +++---- src/libqof/qof/qofsession.cpp | 205 +++++------------- src/libqof/qof/qofsession.h | 14 -- src/libqof/qof/test/CMakeLists.txt | 3 +- src/libqof/qof/test/Makefile.am | 2 +- ...{test-qofsession.c => test-qofsession.cpp} | 192 ++++++---------- 21 files changed, 372 insertions(+), 519 deletions(-) create mode 100644 src/libqof/qof/gnc-backend-prov.hpp rename src/libqof/qof/test/{test-qofsession.c => test-qofsession.cpp} (84%) diff --git a/src/backend/dbi/gnc-backend-dbi.cpp b/src/backend/dbi/gnc-backend-dbi.cpp index e0c191451d..beec3ca364 100644 --- a/src/backend/dbi/gnc-backend-dbi.cpp +++ b/src/backend/dbi/gnc-backend-dbi.cpp @@ -83,6 +83,7 @@ extern "C" #include #include +#include #include "gnc-backend-dbi.h" #include "gnc-backend-dbi-priv.h" @@ -93,6 +94,46 @@ extern "C" #endif #endif +struct QofSQLITEBackendProvider : public QofBackendProvider +{ + QofSQLITEBackendProvider (const char* name, const char* type) : + QofBackendProvider {name, type} {} + QofSQLITEBackendProvider(QofSQLITEBackendProvider&) = delete; + QofSQLITEBackendProvider operator=(QofSQLITEBackendProvider&) = delete; + QofSQLITEBackendProvider(QofSQLITEBackendProvider&&) = delete; + QofSQLITEBackendProvider operator=(QofSQLITEBackendProvider&&) = delete; + ~QofSQLITEBackendProvider () = default; + QofBackend* create_backend(void); + bool type_check(const char* type); +}; + +struct QofMYSQLBackendProvider : public QofBackendProvider +{ + QofMYSQLBackendProvider (const char* name, const char* type) : + QofBackendProvider {name, type} {} + QofMYSQLBackendProvider(QofMYSQLBackendProvider&) = delete; + QofMYSQLBackendProvider operator=(QofMYSQLBackendProvider&) = delete; + QofMYSQLBackendProvider(QofMYSQLBackendProvider&&) = delete; + QofMYSQLBackendProvider operator=(QofMYSQLBackendProvider&&) = delete; + ~QofMYSQLBackendProvider () = default; + QofBackend* create_backend(void); + bool type_check(const char* type) { return true; } +}; + +struct QofPGSQLBackendProvider : public QofBackendProvider +{ + QofPGSQLBackendProvider (const char* name, const char* type) : + QofBackendProvider {name, type} {} + QofPGSQLBackendProvider(QofPGSQLBackendProvider&) = delete; + QofPGSQLBackendProvider operator=(QofPGSQLBackendProvider&) = delete; + QofPGSQLBackendProvider(QofPGSQLBackendProvider&&) = delete; + QofPGSQLBackendProvider operator=(QofPGSQLBackendProvider&&) = delete; + ~QofPGSQLBackendProvider () = default; + QofBackend* create_backend(void); + bool type_check(const char* type) { return true; } + +}; + #if LIBDBI_VERSION >= 900 #define HAVE_LIBDBI_R 1 static dbi_inst dbi_instance = NULL; @@ -297,7 +338,7 @@ gnc_dbi_sqlite3_session_begin (QofBackend* qbe, QofSession* session, /* Remove uri type if present */ filepath = gnc_uri_get_path (book_id); GFileTest ftest = static_cast ( - G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS) ; + G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS) ; file_exists = g_file_test (filepath, ftest); if (!create && !file_exists) { @@ -915,7 +956,7 @@ gnc_dbi_mysql_session_begin (QofBackend* qbe, QofSession* session, /* Split the book-id * Format is protocol://username:password@hostname:port/dbname - where username, password and port are optional) */ + where username, password and port are optional) */ gnc_uri_get_components (book_id, &protocol, &host, &portnum, &username, &password, &dbname); @@ -1270,7 +1311,7 @@ gnc_dbi_postgres_session_begin (QofBackend* qbe, QofSession* session, /* Split the book-id * Format is protocol://username:password@hostname:port/dbname - where username, password and port are optional) */ + where username, password and port are optional) */ gnc_uri_get_components (book_id, &protocol, &host, &portnum, &username, &password, &dbname); if (portnum == 0) @@ -1595,7 +1636,7 @@ gnc_dbi_load (QofBackend* qbe, QofBook* book, QofBackendLoadType loadType) qof_backend_set_error (qbe, ERR_SQL_DB_TOO_OLD); } else if (GNUCASH_RESAVE_VERSION < gnc_sql_get_table_version (&be->sql_be, - "Gnucash-Resave")) + "Gnucash-Resave")) { /* Worse, the database was created with a newer version. We * can't safely write to this database, so the user will have @@ -1912,38 +1953,31 @@ new_backend (void (*session_begin) (QofBackend*, QofSession*, const gchar*, return be; } -static QofBackend* -gnc_dbi_backend_sqlite3_new (void) +QofBackend* +QofSQLITEBackendProvider::create_backend() { return new_backend (gnc_dbi_sqlite3_session_begin); } -static QofBackend* -gnc_dbi_backend_mysql_new (void) +QofBackend* +QofMYSQLBackendProvider::create_backend() { return new_backend (gnc_dbi_mysql_session_begin); } -static QofBackend* -gnc_dbi_backend_postgres_new (void) +QofBackend* +QofPGSQLBackendProvider::create_backend() { return new_backend (gnc_dbi_postgres_session_begin); } -static void -gnc_dbi_provider_free (QofBackendProvider* prov) -{ - g_return_if_fail (prov != NULL); - - g_free (prov); -} /* * Checks to see whether the file is an sqlite file or not * */ -static gboolean -gnc_dbi_check_sqlite3_file (const gchar* uri) +bool +QofSQLITEBackendProvider::type_check(const char *uri) { FILE* f; gchar buf[50]; @@ -1986,7 +2020,6 @@ gnc_dbi_check_sqlite3_file (const gchar* uri) void gnc_module_init_backend_dbi (void) { - QofBackendProvider* prov; const gchar* driver_dir; int num_drivers; gboolean have_sqlite3_driver = FALSE; @@ -2062,51 +2095,25 @@ gnc_module_init_backend_dbi (void) if (have_sqlite3_driver) { - prov = g_new0 (QofBackendProvider, 1); - g_assert (prov != NULL); - - prov->provider_name = "GnuCash Libdbi (SQLITE3) Backend"; - prov->access_method = FILE_URI_TYPE; - prov->backend_new = gnc_dbi_backend_sqlite3_new; - prov->provider_free = gnc_dbi_provider_free; - prov->check_data_type = gnc_dbi_check_sqlite3_file; - qof_backend_register_provider (prov); - - prov = g_new0 (QofBackendProvider, 1); - g_assert (prov != NULL); - - prov->provider_name = "GnuCash Libdbi (SQLITE3) Backend"; - prov->access_method = SQLITE3_URI_TYPE; - prov->backend_new = gnc_dbi_backend_sqlite3_new; - prov->provider_free = gnc_dbi_provider_free; - prov->check_data_type = gnc_dbi_check_sqlite3_file; - qof_backend_register_provider (prov); + const char* name = "GnuCash Libdbi (SQLITE3) Backend"; + auto prov = QofBackendProvider_ptr(new QofSQLITEBackendProvider{name, FILE_URI_TYPE}); + qof_backend_register_provider(std::move(prov)); + prov = QofBackendProvider_ptr(new QofSQLITEBackendProvider{name, SQLITE3_URI_TYPE}); + qof_backend_register_provider(std::move(prov)); } if (have_mysql_driver) { - prov = g_new0 (QofBackendProvider, 1); - g_assert (prov != NULL); - - prov->provider_name = "GnuCash Libdbi (MYSQL) Backend"; - prov->access_method = "mysql"; - prov->backend_new = gnc_dbi_backend_mysql_new; - prov->provider_free = gnc_dbi_provider_free; - prov->check_data_type = NULL; - qof_backend_register_provider (prov); + const char *name = "GnuCash Libdbi (MYSQL) Backend"; + auto prov = QofBackendProvider_ptr(new QofMYSQLBackendProvider{name, "mysql"}); + qof_backend_register_provider(std::move(prov)); } if (have_pgsql_driver) { - prov = g_new0 (QofBackendProvider, 1); - g_assert (prov != NULL); - - prov->provider_name = "GnuCash Libdbi (POSTGRESQL) Backend"; - prov->access_method = "postgres"; - prov->backend_new = gnc_dbi_backend_postgres_new; - prov->provider_free = gnc_dbi_provider_free; - prov->check_data_type = NULL; - qof_backend_register_provider (prov); + const char* name = "GnuCash Libdbi (POSTGRESQL) Backend"; + auto prov = QofBackendProvider_ptr(new QofPGSQLBackendProvider{name, "postgres"}); + qof_backend_register_provider(std::move(prov)); } /* If needed, set log level to DEBUG so that SQl statements will be put into diff --git a/src/backend/sql/test/utest-gnc-backend-sql.cpp b/src/backend/sql/test/utest-gnc-backend-sql.cpp index 566d3d6b99..9e474b5de0 100644 --- a/src/backend/sql/test/utest-gnc-backend-sql.cpp +++ b/src/backend/sql/test/utest-gnc-backend-sql.cpp @@ -593,7 +593,7 @@ test_gnc_sql_convert_timespec_to_string () GncSqlBackend be = {{ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, ERR_BACKEND_NO_ERR, nullptr, 0, nullptr, nullptr + nullptr, ERR_BACKEND_NO_ERR, nullptr, 0, nullptr, nullptr }, nullptr, nullptr, FALSE, FALSE, FALSE, 0, 0, nullptr, "%4d-%02d-%02d %02d:%02d:%02d" diff --git a/src/backend/xml/gnc-backend-xml.cpp b/src/backend/xml/gnc-backend-xml.cpp index 259e1e3a34..91bc09422b 100644 --- a/src/backend/xml/gnc-backend-xml.cpp +++ b/src/backend/xml/gnc-backend-xml.cpp @@ -78,7 +78,6 @@ extern "C" #include "gnc-uri-utils.h" #include "io-gncxml-v2.h" -#include "gnc-backend-xml.h" #include "gnc-prefs.h" #ifndef HAVE_STRPTIME @@ -86,6 +85,9 @@ extern "C" #endif } +#include +#include "gnc-backend-xml.h" +#include #include "gnc-xml-helper.h" #include "io-gncxml.h" @@ -105,6 +107,20 @@ static QofLogModule log_module = GNC_MOD_BACKEND; static gboolean save_may_clobber_data (QofBackend* bend); +struct QofXmlBackendProvider : public QofBackendProvider +{ + QofXmlBackendProvider (const char* name, const char* type) : + QofBackendProvider {name, type} {} + QofXmlBackendProvider(QofXmlBackendProvider&) = delete; + QofXmlBackendProvider operator=(QofXmlBackendProvider&) = delete; + QofXmlBackendProvider(QofXmlBackendProvider&&) = delete; + QofXmlBackendProvider operator=(QofXmlBackendProvider&&) = delete; + ~QofXmlBackendProvider () = default; + QofBackend* create_backend(void); + bool type_check(const char* type); + +}; + /* ================================================================= */ static gboolean @@ -598,8 +614,8 @@ gnc_xml_be_determine_file_type (const char* path) return GNC_BOOK_NOT_OURS; } -static gboolean -gnc_determine_file_type (const char* uri) +bool +QofXmlBackendProvider::type_check (const char *uri) { struct stat sbuf; int rc; @@ -1206,8 +1222,8 @@ gnc_xml_be_write_accounts_to_file (QofBackend* be, QofBook* book) /* ================================================================= */ -static QofBackend* -gnc_backend_new (void) +QofBackend* +QofXmlBackendProvider::create_backend(void) { FileBackend* gnc_be; QofBackend* be; @@ -1268,14 +1284,6 @@ business_core_xml_init (void) gnc_vendor_xml_initialize (); } -static void -gnc_provider_free (QofBackendProvider* prov) -{ - prov->provider_name = NULL; - prov->access_method = NULL; - g_free (prov); -} - #ifndef GNC_NO_LOADABLE_MODULES G_MODULE_EXPORT void qof_backend_module_init (void) @@ -1287,22 +1295,12 @@ qof_backend_module_init (void) void gnc_module_init_backend_xml (void) { - QofBackendProvider* prov; - prov = g_new0 (QofBackendProvider, 1); - prov->provider_name = "GnuCash File Backend Version 2"; - prov->access_method = "file"; - prov->backend_new = gnc_backend_new; - prov->provider_free = gnc_provider_free; - prov->check_data_type = gnc_determine_file_type; - qof_backend_register_provider (prov); + const char* name {"GnuCash File Backend Version 2"}; + auto prov = QofBackendProvider_ptr(new QofXmlBackendProvider{name, "xml"}); - prov = g_new0 (QofBackendProvider, 1); - prov->provider_name = "GnuCash File Backend Version 2"; - prov->access_method = "xml"; - prov->backend_new = gnc_backend_new; - prov->provider_free = gnc_provider_free; - prov->check_data_type = gnc_determine_file_type; - qof_backend_register_provider (prov); + qof_backend_register_provider(std::move(prov)); + prov = QofBackendProvider_ptr(new QofXmlBackendProvider{name, "file"}); + qof_backend_register_provider(std::move(prov)); /* And the business objects */ business_core_xml_init (); diff --git a/src/backend/xml/gnc-backend-xml.h b/src/backend/xml/gnc-backend-xml.h index 7271e83bee..2f021cffb9 100644 --- a/src/backend/xml/gnc-backend-xml.h +++ b/src/backend/xml/gnc-backend-xml.h @@ -34,10 +34,9 @@ extern "C" { #endif -#include "qof.h" +#include #include -#include "qofbackend-p.h" - +#include typedef enum { diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index 35923a20ba..deb43f9296 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -64,8 +64,8 @@ struct timeval #include "gnc-event.h" #include #include "SchedXaction.h" -#include "qofbackend-p.h" #include "gncBusiness.h" +#include /* Notes about xaccTransBeginEdit(), xaccTransCommitEdit(), and * xaccTransRollback(): @@ -1139,10 +1139,10 @@ xaccTransIsBalanced (const Transaction *trans) if (xaccTransUseTradingAccounts(trans)) { - /* Transaction is imbalanced if the value is imbalanced in either + /* Transaction is imbalanced if the value is imbalanced in either trading or non-trading splits. One can't be used to balance the other. */ - FOR_EACH_SPLIT(trans, + FOR_EACH_SPLIT(trans, { Account *acc = xaccSplitGetAccount(s); if (!acc || xaccAccountGetType(acc) != ACCT_TYPE_TRADING) @@ -1155,12 +1155,12 @@ xaccTransIsBalanced (const Transaction *trans) imbal_trading = gnc_numeric_add(imbal_trading, xaccSplitGetValue(s), GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT); } - } + } ); } else imbal = xaccTransGetImbalanceValue(trans); - + if (! gnc_numeric_zero_p(imbal) || ! gnc_numeric_zero_p(imbal_trading)) return FALSE; @@ -1815,7 +1815,7 @@ xaccTransRollbackEdit (Transaction *trans) be = qof_book_get_backend(qof_instance_get_book(trans)); /** \todo Fix transrollbackedit in QOF so that rollback is exposed via the API. */ - if (be && be->rollback) + if (qof_backend_can_rollback (be)) { QofBackendError errcode; @@ -1826,7 +1826,7 @@ xaccTransRollbackEdit (Transaction *trans) } while (ERR_BACKEND_NO_ERR != errcode); - (be->rollback) (be, &(trans->inst)); + qof_backend_rollback_instance (be, &(trans->inst)); errcode = qof_backend_get_error (be); if (ERR_BACKEND_MOD_DESTROY == errcode) diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c index cab57121c2..45adba3598 100644 --- a/src/engine/gnc-pricedb.c +++ b/src/engine/gnc-pricedb.c @@ -27,7 +27,7 @@ #include #include #include "gnc-pricedb-p.h" -#include "qofbackend-p.h" +#include /* This static indicates the debugging module that this .o belongs to. */ static QofLogModule log_module = GNC_MOD_PRICE; @@ -1457,7 +1457,7 @@ pricedb_price_list_merge (PriceList *a, PriceList *b) PriceList *merged_list = NULL; GList *next_a = a; GList *next_b = b; - + while (next_a || next_b) { if (next_a == NULL) @@ -1577,15 +1577,15 @@ typedef struct } UsesCommodity; /* price_list_scan_any_currency is the helper function used with - * pricedb_pricelist_traversal by the "any_currency" price lookup functions. It - * builds a list of prices that are either to or from the commodity "com". - * The resulting list will include the last price newer than "t" and the first - * price older than "t". All other prices will be ignored. Since in the most - * common cases we will be looking for recent prices which are at the front of - * the various price lists, this is considerably faster than concatenating all - * the relevant price lists and sorting the result. + * pricedb_pricelist_traversal by the "any_currency" price lookup functions. It + * builds a list of prices that are either to or from the commodity "com". + * The resulting list will include the last price newer than "t" and the first + * price older than "t". All other prices will be ignored. Since in the most + * common cases we will be looking for recent prices which are at the front of + * the various price lists, this is considerably faster than concatenating all + * the relevant price lists and sorting the result. */ - + static gboolean price_list_scan_any_currency(GList *price_list, gpointer data) { @@ -1593,18 +1593,18 @@ price_list_scan_any_currency(GList *price_list, gpointer data) GList *node = price_list; gnc_commodity *com; gnc_commodity *cur; - + if (!price_list) return TRUE; com = gnc_price_get_commodity(node->data); cur = gnc_price_get_currency(node->data); - + /* if this price list isn't for the commodity we are interested in, ignore it. */ if (com != helper->com && cur != helper->com) return TRUE; - + /* The price list is sorted in decreasing order of time. Find the first price on it that is older than the requested time and add it and the previous price to the result list. */ @@ -1900,7 +1900,7 @@ price_count_helper(gpointer key, gpointer value, gpointer data) { int *result = data; GList *price_list = value; - + *result += g_list_length(price_list); } @@ -1910,7 +1910,7 @@ gnc_pricedb_num_prices(GNCPriceDB *db, { int result = 0; GHashTable *currency_hash; - + if (!db || !c) return 0; ENTER ("db=%p commodity=%p", db, c); @@ -1919,7 +1919,7 @@ gnc_pricedb_num_prices(GNCPriceDB *db, { g_hash_table_foreach(currency_hash, price_count_helper, (gpointer)&result); } - + LEAVE ("count=%d", result); return result; } @@ -1933,10 +1933,10 @@ gnc_pricedb_nth_price (GNCPriceDB *db, { GNCPrice *result = NULL; GHashTable *currency_hash; - + if (!db || !c || n < 0) return NULL; ENTER ("db=%p commodity=%p index=%d", db, c, n); - + currency_hash = g_hash_table_lookup(db->commodity_hash, c); if (currency_hash) { @@ -1963,7 +1963,7 @@ gnc_pricedb_nth_price (GNCPriceDB *db, int i, j; GHashTableIter iter; gpointer key, value; - + /* Build an array of all the currencies this commodity has prices for */ for (i = 0, g_hash_table_iter_init(&iter, currency_hash); g_hash_table_iter_next(&iter, &key, &value) && i < num_currencies; @@ -1971,7 +1971,7 @@ gnc_pricedb_nth_price (GNCPriceDB *db, { price_array[i] = value; } - + /* Iterate n times to get the nth price, each time finding the currency with the latest price */ for (i = 0; i <= n; i++) @@ -2010,7 +2010,7 @@ gnc_pricedb_nth_price (GNCPriceDB *db, LEAVE ("price=%p", result); return result; } - + GNCPrice * gnc_pricedb_lookup_day(GNCPriceDB *db, const gnc_commodity *c, diff --git a/src/gnc/Session.hpp b/src/gnc/Session.hpp index 3b2ae98163..6010eb437d 100644 --- a/src/gnc/Session.hpp +++ b/src/gnc/Session.hpp @@ -99,14 +99,6 @@ public: { qof_session_save(gobj(), percentage_func); } - - - void call_close_hooks () - { - qof_session_call_close_hooks (gobj()); - } - - }; std::pair errorToStringPair(QofBackendError err); diff --git a/src/gnc/mainwindow-file.cpp b/src/gnc/mainwindow-file.cpp index a05268a6fd..432f0c6932 100644 --- a/src/gnc/mainwindow-file.cpp +++ b/src/gnc/mainwindow-file.cpp @@ -375,7 +375,6 @@ void MainWindow::loadFile(const QString &fileName) /* -------------- BEGIN CORE SESSION CODE ------------- */ /* -- this code is almost identical in FileOpen and FileSaveAs -- */ - m_session.call_close_hooks(); gnc_hook_run(HOOK_BOOK_CLOSED, m_session.gobj()); qof_session_destroy(m_session.gobj()); m_session.reset(); diff --git a/src/gnc/mainwindow.cpp b/src/gnc/mainwindow.cpp index edffca63ad..d68749cfff 100644 --- a/src/gnc/mainwindow.cpp +++ b/src/gnc/mainwindow.cpp @@ -577,7 +577,6 @@ void MainWindow::closeEvent(QCloseEvent *event) * transactions during shutdown would cause massive redraws */ qof_event_suspend (); - qof_session_call_close_hooks(m_session.gobj()); gnc_hook_run(HOOK_BOOK_CLOSED, m_session.gobj()); qof_session_destroy(m_session.gobj()); @@ -602,7 +601,6 @@ void MainWindow::newFile() * disable events so we don't gobj spammed by redraws. */ qof_event_suspend (); - m_session.call_close_hooks(); gnc_hook_run(HOOK_BOOK_CLOSED, m_session.gobj()); qof_session_destroy(m_session.gobj()); diff --git a/src/gnome-utils/gnc-file.c b/src/gnome-utils/gnc-file.c index 95521fa6b6..ddb301e159 100644 --- a/src/gnome-utils/gnc-file.c +++ b/src/gnome-utils/gnc-file.c @@ -527,7 +527,6 @@ gnc_file_new (void) * disable events so we don't get spammed by redraws. */ qof_event_suspend (); - qof_session_call_close_hooks(session); gnc_hook_run(HOOK_BOOK_CLOSED, session); gnc_close_gui_component_by_session (session); @@ -706,7 +705,6 @@ RESTART: if (gnc_current_session_exist()) { current_session = gnc_get_current_session(); - qof_session_call_close_hooks(current_session); gnc_hook_run(HOOK_BOOK_CLOSED, current_session); gnc_close_gui_component_by_session (current_session); gnc_state_save (current_session); @@ -1605,7 +1603,6 @@ gnc_file_quit (void) * transactions during shutdown would cause massive redraws */ qof_event_suspend (); - qof_session_call_close_hooks(session); gnc_hook_run(HOOK_BOOK_CLOSED, session); gnc_close_gui_component_by_session (session); gnc_state_save (session); diff --git a/src/libqof/CMakeLists.txt b/src/libqof/CMakeLists.txt index 75831b35ca..e1c97445df 100644 --- a/src/libqof/CMakeLists.txt +++ b/src/libqof/CMakeLists.txt @@ -35,6 +35,7 @@ SET (gnc_qof_HEADERS qof/qof-string-cache.h ) SET (gnc_qof_noinst_HEADERS + qof/gnc-backend-prov.hpp qof/qofbook-p.h qof/qofclass-p.h qof/gnc-date-p.h diff --git a/src/libqof/qof/Makefile.am b/src/libqof/qof/Makefile.am index 17f62d093e..1077642467 100644 --- a/src/libqof/qof/Makefile.am +++ b/src/libqof/qof/Makefile.am @@ -82,6 +82,7 @@ qofinclude_HEADERS = \ qof-gobject.h noinst_HEADERS = \ + gnc-backend-prov.hpp \ qofbook-p.h \ qofclass-p.h \ qofevent-p.h \ diff --git a/src/libqof/qof/gnc-backend-prov.hpp b/src/libqof/qof/gnc-backend-prov.hpp new file mode 100644 index 0000000000..1c55015e95 --- /dev/null +++ b/src/libqof/qof/gnc-backend-prov.hpp @@ -0,0 +1,81 @@ +/********************************************************************\ + * qofbackend-prov.hpp -- Manage creation of a QofBackend subclass. * + * * + * Copyright 2016 John Ralls * + * * + * 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, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gnu@gnu.org * + * * +\********************************************************************/ + +#ifndef __GNC_BACKEND_PROV_HPP__ +#define __GNC_BACKEND_PROV_HPP__ + +#include + +struct QofBackendProvider +{ + QofBackendProvider(const char* name, const char* type) : + provider_name {name}, access_method {type} {} + QofBackendProvider(QofBackendProvider&) = delete; + QofBackendProvider(QofBackendProvider&&) = delete; + virtual ~QofBackendProvider() {} + + /** Return a new, fully initialized backend. + * + * If the backend supports configuration, all configuration options + * should be initialised to usable values here. + * */ + virtual QofBackend * create_backend(void) = 0; + + /** \brief Distinguish two providers with same access method. + + More than 1 backend can be registered under the same access_method, + so each one is passed the path to the data (e.g. a file) and + should return TRUE only: + -# if the backend recognises the type as one that it can load and write or + -# if the path contains no data but can be used (e.g. a new session). + + \note If the backend can cope with more than one type, the backend + should not try to store or cache the sub-type for this data. + It is sufficient only to return TRUE if any ONE of the supported + types match the incoming data. The backend should not assume that + returning TRUE will mean that the data will naturally follow. + */ + /*@ null @*/ + virtual bool type_check(const char*) = 0; + /** Some arbitrary name given for this particular backend provider */ + const char * provider_name; + + /** The access method that this provider provides, for example, + * file:// http:// postgres:// or sqlite://, but without the :// at the end + */ + const char * access_method; +}; + +using QofBackendProvider_ptr = std::unique_ptr; + +/** Let the sytem know about a new provider of backends. This function + * is typically called by the provider library at library load time. + * This function allows the backend library to tell the QOF infrastructure + * that it can handle URL's of a certain type. Note that a single + * backend library may register more than one provider, if it is + * capable of handling more than one URL access method. + */ +void qof_backend_register_provider (QofBackendProvider_ptr&&); + +#endif // __GNC_BACKEND_PROV_HPP__ diff --git a/src/libqof/qof/qofbackend-p.h b/src/libqof/qof/qofbackend-p.h index b2ed3bf32c..d8f0a6804c 100644 --- a/src/libqof/qof/qofbackend-p.h +++ b/src/libqof/qof/qofbackend-p.h @@ -235,45 +235,6 @@ * This should be done in the function called from backend_new. */ -struct QofBackendProvider_s -{ - /** Some arbitrary name given for this particular backend provider */ - /*@ observer @*/ - const char * provider_name; - - /** The access method that this provider provides, for example, - * file:// http:// postgres:// or sqlite://, but without the :// at the end - */ - /*@ observer @*/ - const char * access_method; - - /** Return a new, fully initialized backend. - * - * If the backend supports configuration, all configuration options - * should be initialised to usable values here. - * */ - QofBackend * (*backend_new) (void); - - /** \brief Distinguish two providers with same access method. - - More than 1 backend can be registered under the same access_method, - so each one is passed the path to the data (e.g. a file) and - should return TRUE only: - -# if the backend recognises the type as one that it can load and write or - -# if the path contains no data but can be used (e.g. a new session). - - \note If the backend can cope with more than one type, the backend - should not try to store or cache the sub-type for this data. - It is sufficient only to return TRUE if any ONE of the supported - types match the incoming data. The backend should not assume that - returning TRUE will mean that the data will naturally follow. - */ - /*@ null @*/ - gboolean (*check_data_type) (const char*); - - /** Free this structure, unregister this backend handler. */ - void (*provider_free) (/*@ only @*/ QofBackendProvider *); -}; typedef enum { @@ -310,8 +271,6 @@ struct QofBackend_s QofBePercentageFunc percentage; - QofBackendProvider *provider; - QofBackendError last_err; char * error_msg; @@ -345,15 +304,6 @@ extern "C" { #endif -/** Let the sytem know about a new provider of backends. This function - * is typically called by the provider library at library load time. - * This function allows the backend library to tell the QOF infrastructure - * that it can handle URL's of a certain type. Note that a single - * backend library may register more than one provider, if it is - * capable of handling more than one URL access method. - */ -void qof_backend_register_provider (/*@ only @*/ QofBackendProvider *); - /** The qof_backend_set_message() assigns a string to the backend error message. */ void qof_backend_set_message(QofBackend *be, const char *format, ...); diff --git a/src/libqof/qof/qofbackend.cpp b/src/libqof/qof/qofbackend.cpp index 1a38181fc4..a805808244 100644 --- a/src/libqof/qof/qofbackend.cpp +++ b/src/libqof/qof/qofbackend.cpp @@ -79,6 +79,20 @@ qof_backend_check_error (QofBackend *be) return be->last_err != ERR_BACKEND_NO_ERR; } +gboolean +qof_backend_can_rollback (QofBackend* be) +{ + if (be == nullptr) return FALSE; + return be->rollback != nullptr; +} + +void +qof_backend_rollback_instance (QofBackend* be, QofInstance* inst) +{ + if (be == nullptr || be->rollback == nullptr) return; + (be->rollback)(be, inst); +} + void qof_backend_set_message (QofBackend *be, const char *format, ...) { diff --git a/src/libqof/qof/qofbackend.h b/src/libqof/qof/qofbackend.h index 52c70b2cbd..1fa87c98f9 100644 --- a/src/libqof/qof/qofbackend.h +++ b/src/libqof/qof/qofbackend.h @@ -127,15 +127,6 @@ typedef enum ERR_RPC_FAILED, /**< Operation failed */ ERR_RPC_NOT_ADDED, /**< object not added */ } QofBackendError; - -/** - * A structure that declares backend services that can be gotten. - * The Provider specifies a URL access method, and specifies the - * function to create a backend that can handle that URL access - * function. - */ -typedef struct QofBackendProvider_s QofBackendProvider; - /** \brief Pseudo-object providing an interface between the * engine and a persistant data store (e.g. a server, a database, * or a file). @@ -144,11 +135,45 @@ typedef struct QofBackendProvider_s QofBackendProvider; * engine. The backend can, however, report errors to the GUI & other * front-end users. */ -typedef struct QofBackend_s QofBackend; + typedef struct QofBackend_s QofBackend; + + /* The following functions are used in C files. */ +/** Get the last backend error. */ + QofBackendError qof_backend_get_error (QofBackend*); +/** Set the error on the specified QofBackend. */ + void qof_backend_set_error (QofBackend*, QofBackendError); + +/* Temporary wrapper so that we don't have to expose qofbackend-p.h to Transaction.c */ + gboolean qof_backend_can_rollback (QofBackend*); + void qof_backend_rollback_instance (QofBackend*, QofInstance*); + +/** \brief Load a QOF-compatible backend shared library. + + \param directory Can be NULL if filename is a complete path. + \param module_name Name of the .la file that describes the + shared library. This provides platform independence, + courtesy of libtool. + + \return FALSE in case or error, otherwise TRUE. +*/ + gboolean + qof_load_backend_library(const gchar *directory, const gchar* module_name); + +/** \brief Finalize all loaded backend sharable libraries. */ + void qof_finalize_backend_libraries(void); + +/** \brief Retrieve the backend used by this book */ + QofBackend* qof_book_get_backend (const QofBook *book); + + void qof_book_set_backend (QofBook *book, QofBackend *); + /** \brief DOCUMENT ME! */ typedef void (*QofBePercentageFunc) (/*@ null @*/ const char *message, double percent); +#ifdef __cplusplus +} + /** @name Allow access to the begin routine for this backend. */ //@{ @@ -161,15 +186,6 @@ void qof_backend_run_commit(QofBackend *be, QofInstance *inst); gboolean qof_backend_commit_exists(const QofBackend *be); //@} -/** The qof_backend_set_error() routine pushes an error code onto the error - * stack. (FIXME: the stack is 1 deep in current implementation). - */ -void qof_backend_set_error (QofBackend *be, QofBackendError err); - -/** The qof_backend_get_error() routine pops an error code off the error stack. - */ -QofBackendError qof_backend_get_error (QofBackend *be); - /** Report if the backend is in an error state. * Since get_error resets the error state, its use for branching as the backend * bubbles back up to the session would make the session think that there was @@ -179,28 +195,6 @@ QofBackendError qof_backend_get_error (QofBackend *be); */ gboolean qof_backend_check_error (QofBackend *be); -/** \brief Load a QOF-compatible backend shared library. - -\param directory Can be NULL if filename is a complete path. -\param module_name Name of the .la file that describes the - shared library. This provides platform independence, - courtesy of libtool. - -\return FALSE in case or error, otherwise TRUE. -*/ -gboolean -qof_load_backend_library(const gchar *directory, const gchar* module_name); - -/** \brief Finalize all loaded backend sharable libraries. */ -void qof_finalize_backend_libraries(void); - -/** \brief Retrieve the backend used by this book */ -QofBackend* qof_book_get_backend (const QofBook *book); - -void qof_book_set_backend (QofBook *book, QofBackend *); - -#ifdef __cplusplus -} #endif #endif /* QOF_BACKEND_H */ diff --git a/src/libqof/qof/qofsession.cpp b/src/libqof/qof/qofsession.cpp index 609c58d780..acf2c284cb 100644 --- a/src/libqof/qof/qofsession.cpp +++ b/src/libqof/qof/qofsession.cpp @@ -31,6 +31,9 @@ @author Copyright (c) 2005 Neil Williams */ +extern "C" +{ + #include "config.h" #include @@ -52,128 +55,71 @@ #include #include "qof.h" -#include "qofbackend-p.h" #include "qofbook-p.h" -#include "qofsession-p.h" #include "qofobject-p.h" -static GHookList * session_closed_hooks = NULL; static QofLogModule log_module = QOF_MOD_SESSION; -static GSList *provider_list = NULL; -static gboolean qof_providers_initialized = FALSE; +} //extern 'C' +#include "qofbackend-p.h" +#include "qofsession-p.h" +#include "gnc-backend-prov.hpp" + +#include +#include +#include +#include + +using ProviderVec = std::vector; +static ProviderVec s_providers; /* * These getters are used in tests to reach static vars from outside * They should be removed when no longer needed */ -#ifdef __cplusplus -extern "C" -{ -#endif - -GHookList* get_session_closed_hooks (void ); -GSList* get_provider_list (void ); -gboolean get_qof_providers_initialized (void ); +ProviderVec& get_providers (void ); +bool get_providers_initialized (void ); void unregister_all_providers (void ); -#ifdef __cplusplus -} -#endif - -GHookList* -get_session_closed_hooks (void) +ProviderVec& +get_providers (void) { - return session_closed_hooks; + return s_providers; } -GSList* -get_provider_list (void) +bool +get_providers_initialized (void) { - return provider_list; -} - -gboolean -get_qof_providers_initialized (void) -{ - return qof_providers_initialized; + return !s_providers.empty(); } void unregister_all_providers (void) { - if (provider_list) - { - g_slist_foreach (provider_list, (GFunc) g_free, NULL); - g_slist_free (provider_list); - provider_list = NULL; - } + s_providers.clear(); } /* ====================================================================== */ void -qof_backend_register_provider (QofBackendProvider *prov) +qof_backend_register_provider (QofBackendProvider_ptr&& prov) { - provider_list = g_slist_append (provider_list, prov); + s_providers.emplace_back(std::move(prov)); } +/* Called from C so we have to keep the GList for now. */ GList* qof_backend_get_registered_access_method_list(void) { GList* list = NULL; - GSList* node; - - for ( node = provider_list; node != NULL; node = node->next ) - { - QofBackendProvider *prov = static_cast(node->data); - list = g_list_append( list, (gchar*)prov->access_method ); - } - + std::for_each(s_providers.begin(), s_providers.end(), + [&list](QofBackendProvider_ptr& provider) { + gpointer method = reinterpret_cast(const_cast(provider->access_method)); + list = g_list_prepend(list, method); + }); return list; } -/* ====================================================================== */ - -/* hook routines */ - -void -qof_session_add_close_hook (GFunc fn, gpointer data) -{ - GHook *hook; - - if (session_closed_hooks == NULL) - { - session_closed_hooks = static_cast(malloc(sizeof(GHookList))); /* LEAKED */ - g_hook_list_init (session_closed_hooks, sizeof(GHook)); - } - - hook = g_hook_alloc(session_closed_hooks); - if (!hook) - return; - - hook->func = reinterpret_cast(fn); - hook->data = data; - g_hook_append(session_closed_hooks, hook); -} - -void -qof_session_call_close_hooks (QofSession *session) -{ - GHook *hook; - GFunc fn; - - if (session_closed_hooks == NULL) - return; - - hook = g_hook_first_valid (session_closed_hooks, FALSE); - while (hook) - { - fn = (GFunc)hook->func; - fn(session, hook->data); - hook = g_hook_next_valid (session_closed_hooks, hook, FALSE); - } -} /* ====================================================================== */ /* error handling routines */ @@ -337,70 +283,38 @@ qof_session_ensure_all_data_loaded (QofSession *session) /* ====================================================================== */ -/** Programs that use their own backends also need to call -the default QOF ones. The backends specified here are -loaded only by applications that do not have their own. */ -struct backend_providers -{ - const char *libdir; - const char *filename; -}; - static void qof_session_load_backend(QofSession * session, const char * access_method) { - GSList *p; - QofBackendProvider *prov; - char *msg; - gboolean prov_type; - gboolean (*type_check) (const char*); - ENTER (" list=%d, initted=%s", g_slist_length(provider_list), - qof_providers_initialized ? "true" : "false"); - prov_type = FALSE; - if (!qof_providers_initialized) + ENTER (" list=%lu", s_providers.size()); + for (QofBackendProvider_ptr& prov : s_providers) { - qof_providers_initialized = TRUE; - } - p = provider_list; - while (p != NULL) - { - prov = static_cast(p->data); /* Does this provider handle the desired access method? */ - if (0 == g_ascii_strcasecmp (access_method, prov->access_method)) + if (0 != g_ascii_strcasecmp (access_method, prov->access_method)) + continue; + + /* More than one backend could provide this + access method, check file type compatibility. */ + + if (!prov->type_check(session->book_id)) { - /* More than one backend could provide this - access method, check file type compatibility. */ - type_check = (gboolean (*)(const char*)) prov->check_data_type; - if (type_check) - { - prov_type = (type_check)(session->book_id); - if (!prov_type) - { - PINFO(" %s not usable", prov->provider_name); - p = p->next; - continue; - } - } - PINFO (" selected %s", prov->provider_name); - if (NULL == prov->backend_new) - { - p = p->next; - continue; - } - /* Use the providers creation callback */ - session->backend = (*(prov->backend_new))(); - session->backend->provider = prov; - /* Tell the book about the backend that they'll be using. */ - qof_book_set_backend (session->book, session->backend); - LEAVE (" "); - return; + PINFO(" %s not usable", prov->provider_name); + continue; } - p = p->next; + PINFO (" selected %s", prov->provider_name); + /* Use the providers creation callback */ + session->backend = prov->create_backend(); + /* Tell the book about the backend that they'll be using. */ + qof_book_set_backend (session->book, session->backend); + LEAVE (" "); + return; } - msg = g_strdup_printf("failed to load '%s' using access_method", access_method); - qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg); - g_free(msg); + + std::ostringstream msgstrm; + msgstrm << "Failed to load '" << access_method << "' using access_method"; + qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, + msgstrm.str().c_str()); LEAVE (" "); } @@ -866,21 +780,12 @@ qof_session_export (QofSession *tmp_session, /* ================= Static function access for testing ================= */ -#ifdef __cplusplus -extern "C" -{ -#endif - void init_static_qofsession_pointers (void); void (*p_qof_session_load_backend) (QofSession * session, const char * access_method); void (*p_qof_session_clear_error) (QofSession *session); void (*p_qof_session_destroy_backend) (QofSession *session); -#ifdef __cplusplus -} -#endif - void init_static_qofsession_pointers (void) { diff --git a/src/libqof/qof/qofsession.h b/src/libqof/qof/qofsession.h index cdef4bb614..afc6515d43 100644 --- a/src/libqof/qof/qofsession.h +++ b/src/libqof/qof/qofsession.h @@ -289,20 +289,6 @@ gboolean qof_session_events_pending (const QofSession *session); gboolean qof_session_process_events (QofSession *session); /** @} */ -/** Register a function to be called just before a session is closed. - * - * @param fn The function to be called. The function definition must - * be func(gpointer session, gpointer user_data); - * - * @param data The data to be passed to the function. */ -void qof_session_add_close_hook (GFunc fn, gpointer data); - -/** Call all registered session close hooks, informing them that the - * specified session is about to be closed. - * - * @param session A pointer to the session being closed. */ -void qof_session_call_close_hooks (QofSession *session); - gboolean qof_session_export (QofSession *tmp_session, QofSession *real_session, QofPercentageFunc percentage_func); diff --git a/src/libqof/qof/test/CMakeLists.txt b/src/libqof/qof/test/CMakeLists.txt index 252424148b..a16a4bb759 100644 --- a/src/libqof/qof/test/CMakeLists.txt +++ b/src/libqof/qof/test/CMakeLists.txt @@ -1,4 +1,3 @@ - SET(TEST_QOF_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/src # for config.h ${CMAKE_SOURCE_DIR}/src/test-core # for unittest-support.h @@ -17,7 +16,7 @@ SET(test_qof_SOURCES test-qofinstance.cpp # test-kvp-frame.cpp This now use Google Test test-qofobject.c - test-qofsession.c + test-qofsession.cpp test-qof-string-cache.c test-gnc-guid.cpp ${CMAKE_SOURCE_DIR}/src/test-core/unittest-support.c diff --git a/src/libqof/qof/test/Makefile.am b/src/libqof/qof/test/Makefile.am index 1d1b19e75b..1ad569341a 100644 --- a/src/libqof/qof/test/Makefile.am +++ b/src/libqof/qof/test/Makefile.am @@ -14,7 +14,7 @@ test_qof_SOURCES = \ test-qofbook.c \ test-qofinstance.cpp \ test-qofobject.c \ - test-qofsession.c \ + test-qofsession.cpp \ test-qof-string-cache.c \ test-gnc-guid.cpp \ ${top_srcdir}/src/test-core/unittest-support.c diff --git a/src/libqof/qof/test/test-qofsession.c b/src/libqof/qof/test/test-qofsession.cpp similarity index 84% rename from src/libqof/qof/test/test-qofsession.c rename to src/libqof/qof/test/test-qofsession.cpp index 9f4ee521a9..ea5e4f9b2f 100644 --- a/src/libqof/qof/test/test-qofsession.c +++ b/src/libqof/qof/test/test-qofsession.cpp @@ -20,46 +20,33 @@ * Boston, MA 02110-1301, USA gnu@gnu.org * \********************************************************************/ -#ifdef __cplusplus extern "C" { -#endif - #include "config.h" #include #include - -#ifdef __cplusplus } -#endif #include "../qof.h" #include "../qofbackend-p.h" #include "../qofsession-p.h" #include "../qofclass-p.h" +#include "../gnc-backend-prov.hpp" +#include static const gchar *suitename = "/qof/qofsession"; -void test_suite_qofsession ( void ); - -#ifdef __cplusplus -extern "C" -{ -#endif - -extern GHookList* get_session_closed_hooks (void); -extern GSList* get_provider_list (void); -extern gboolean get_qof_providers_initialized (void); -extern void unregister_all_providers (void); +extern "C" void test_suite_qofsession ( void ); extern void (*p_qof_session_load_backend) (QofSession * session, const char * access_method); extern void (*p_qof_session_clear_error) (QofSession * session); extern void (*p_qof_session_destroy_backend) (QofSession * session); -extern void init_static_qofsession_pointers (void); +void init_static_qofsession_pointers (void); -#ifdef __cplusplus -} -#endif +using ProviderVec = std::vector; +extern ProviderVec& get_providers (void); +extern bool get_providers_initialized (void); +extern void unregister_all_providers (void); typedef struct { @@ -136,22 +123,30 @@ test_session_safe_save( Fixture *fixture, gconstpointer pData ) static struct { QofBackend *be; - gboolean data_compatible; - gboolean check_data_type_called; - gboolean backend_new_called; + bool data_compatible; + bool check_data_type_called; + bool backend_new_called; } load_backend_struct; -static gboolean -mock_check_data_type (const char* book_id) +struct QofMockLoadBackendProvider : public QofBackendProvider +{ + QofMockLoadBackendProvider(const char *name, const char* type) : + QofBackendProvider{name, type} {} + QofBackend* create_backend(void); + bool type_check(const char* type); +}; + +bool +QofMockLoadBackendProvider::type_check (const char* book_id) { g_assert (book_id); - g_assert_cmpstr (book_id, == , "my book"); - load_backend_struct.check_data_type_called = TRUE; + g_assert_cmpstr (book_id, ==, "my book"); + load_backend_struct.check_data_type_called = true; return load_backend_struct.data_compatible; } -static QofBackend* -mock_backend_new (void) +QofBackend* +QofMockLoadBackendProvider::create_backend (void) { QofBackend *be = NULL; @@ -165,55 +160,44 @@ mock_backend_new (void) static void test_qof_session_load_backend (Fixture *fixture, gconstpointer pData) { - QofBackendProvider *prov = NULL; QofBook *book = NULL; /* init */ - prov = g_new0 (QofBackendProvider, 1); g_test_message ("Test when no provider is registered"); - g_assert (!get_qof_providers_initialized ()); - g_assert (get_provider_list () == NULL); + g_assert (!get_providers_initialized ()); + g_assert (get_providers ().empty()); p_qof_session_load_backend (fixture->session, "file"); - g_assert (get_qof_providers_initialized ()); + g_assert (!get_providers_initialized ()); g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER); - g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method"); + g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "Failed to load 'file' using access_method"); p_qof_session_clear_error (fixture->session); g_test_message ("Test with provider registered but access method not supported"); - prov->access_method = "unsupported"; - qof_backend_register_provider (prov); - g_assert (get_provider_list ()); - g_assert_cmpint (g_slist_length (get_provider_list ()), == , 1); + auto prov = QofBackendProvider_ptr(new QofMockLoadBackendProvider("Mock Backend", "unsupported")); + qof_backend_register_provider (std::move(prov)); + g_assert (!get_providers().empty()); + g_assert_cmpint (get_providers().size(), == , 1); p_qof_session_load_backend (fixture->session, "file"); g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER); - g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method"); + g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "Failed to load 'file' using access_method"); p_qof_session_clear_error (fixture->session); g_test_message ("Test with access method supported but type incompatible"); - prov->access_method = "file"; - prov->check_data_type = mock_check_data_type; + prov = QofBackendProvider_ptr(new QofMockLoadBackendProvider("Mock Backend", + "file")); + qof_backend_register_provider (std::move(prov)); load_backend_struct.data_compatible = FALSE; load_backend_struct.check_data_type_called = FALSE; fixture->session->book_id = g_strdup ("my book"); p_qof_session_load_backend (fixture->session, "file"); g_assert (load_backend_struct.check_data_type_called); g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER); - g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method"); + g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "Failed to load 'file' using access_method"); p_qof_session_clear_error (fixture->session); - g_test_message ("Test with type compatible but backend_new not set"); - prov->backend_new = NULL; - load_backend_struct.data_compatible = TRUE; - load_backend_struct.check_data_type_called = FALSE; - p_qof_session_load_backend (fixture->session, "file"); - g_assert (load_backend_struct.check_data_type_called); - g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER); - g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method"); - p_qof_session_clear_error (fixture->session); g_test_message ("Test with type compatible backend_new set"); - prov->backend_new = mock_backend_new; load_backend_struct.be = NULL; load_backend_struct.data_compatible = TRUE; load_backend_struct.check_data_type_called = FALSE; @@ -227,12 +211,11 @@ test_qof_session_load_backend (Fixture *fixture, gconstpointer pData) g_assert (load_backend_struct.backend_new_called); g_assert (load_backend_struct.be); g_assert (load_backend_struct.be == fixture->session->backend); - g_assert (prov == fixture->session->backend->provider); g_assert (qof_book_get_backend (book) == load_backend_struct.be); g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR); unregister_all_providers (); - g_assert_cmpint (g_slist_length (get_provider_list ()), == , 0); + g_assert_cmpint (get_providers().size(), == , 0); } static struct @@ -329,9 +312,23 @@ mock_session_begin (QofBackend *be, QofSession *session, const char *book_id, } session_begin_struct.session_begin_called = TRUE; } +struct QofMockSessBackendProvider : public QofBackendProvider +{ + QofMockSessBackendProvider(const char *name, const char* type) : + QofBackendProvider{name, type} {} + QofBackend* create_backend(void); + bool type_check(const char* type); +}; -static QofBackend* -mock_backend_new_for_begin (void) +bool +QofMockSessBackendProvider::type_check (const char* book_id) +{ + g_assert (book_id); + return true; +} + +QofBackend* +QofMockSessBackendProvider::create_backend (void) { QofBackend *be = NULL; @@ -348,7 +345,6 @@ test_qof_session_begin (Fixture *fixture, gconstpointer pData) { gboolean ignore_lock, create, force; QofBackend *be = NULL; - QofBackendProvider *prov = NULL; /* setup */ ignore_lock = TRUE; @@ -357,9 +353,7 @@ test_qof_session_begin (Fixture *fixture, gconstpointer pData) be = g_new0 (QofBackend, 1); g_assert (be); - g_assert_cmpint (g_slist_length (get_provider_list ()), == , 0); - prov = g_new0 (QofBackendProvider, 1); - prov->backend_new = mock_backend_new_for_begin; + g_assert_cmpint (get_providers().size(), == , 0); /* run tests */ g_test_message ("Test when book_id is set backend is not changed"); @@ -383,14 +377,14 @@ test_qof_session_begin (Fixture *fixture, gconstpointer pData) g_assert (fixture->session->backend == NULL); g_assert (fixture->session->book_id == NULL); g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER); - g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method"); + g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "Failed to load 'file' using access_method"); g_test_message ("Test access_method parsing"); qof_session_begin (fixture->session, "postgres://localhost:8080", ignore_lock, create, force); g_assert (fixture->session->backend == NULL); g_assert (fixture->session->book_id == NULL); g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER); - g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'postgres' using access_method"); + g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "Failed to load 'postgres' using access_method"); g_test_message ("Test with valid backend returned and session begin set; error is produced"); session_begin_struct.session = fixture->session; @@ -398,8 +392,10 @@ test_qof_session_begin (Fixture *fixture, gconstpointer pData) session_begin_struct.backend_new_called = FALSE; session_begin_struct.session_begin_called = FALSE; session_begin_struct.produce_error = TRUE; - prov->access_method = "postgres"; - qof_backend_register_provider (prov); + auto prov = QofBackendProvider_ptr(new QofMockSessBackendProvider("Mock Backend", + "postgres")); + qof_backend_register_provider (std::move(prov)); + qof_session_begin (fixture->session, "postgres://localhost:8080", ignore_lock, create, force); g_assert (fixture->session->backend); g_assert (session_begin_struct.be == fixture->session->backend); @@ -768,37 +764,6 @@ test_qof_session_data_loaded (Fixture *fixture, gconstpointer pData) g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , ""); } -static void -test_qof_backend_get_access_method_list (Fixture *fixture, gconstpointer pData) -{ - GList *list = NULL; - const char *access_methods[4] = { "file", "http", "postgres", "sqlite" }; - int i; - - for (i = 0; i < 4; i++) - { - QofBackendProvider *prov = g_new0 (QofBackendProvider, 1); - g_assert (prov); - prov->access_method = access_methods[ i ]; - qof_backend_register_provider (prov); - g_assert_cmpint (g_slist_length (get_provider_list ()), == , (i + 1)); - } - g_assert_cmpint (g_slist_length (get_provider_list ()), == , 4); - - g_test_message ("Test list of access methods is returned"); - list = qof_backend_get_registered_access_method_list (); - g_assert (list); - g_assert_cmpint (g_list_length (list), == , 4); - g_assert_cmpstr (g_list_nth_data (list, 0), == , "file"); - g_assert_cmpstr (g_list_nth_data (list, 1), == , "http"); - g_assert_cmpstr (g_list_nth_data (list, 2), == , "postgres"); - g_assert_cmpstr (g_list_nth_data (list, 3), == , "sqlite"); - - g_list_free (list); - unregister_all_providers (); -} - - static void test_qof_session_get_book (Fixture *fixture, gconstpointer pData) { @@ -890,37 +855,6 @@ mock_hook_fn (gpointer data, gpointer user_data) hooks_struct.call_count++; } -static void -test_qof_session_close_hooks (Fixture *fixture, gconstpointer pData) -{ - gint data1, data2, data3; - - g_test_message ("Test hooks list is initialized and hooks are added"); - g_assert (!get_session_closed_hooks ()); - qof_session_add_close_hook (mock_hook_fn, (gpointer) &data1); - g_assert (get_session_closed_hooks ()); - g_assert (g_hook_find_func_data (get_session_closed_hooks (), FALSE, mock_hook_fn, (gpointer) &data1)); - qof_session_add_close_hook (mock_hook_fn, (gpointer) &data2); - g_assert (g_hook_find_func_data (get_session_closed_hooks (), FALSE, mock_hook_fn, (gpointer) &data2)); - qof_session_add_close_hook (mock_hook_fn, (gpointer) &data3); - g_assert (g_hook_find_func_data (get_session_closed_hooks (), FALSE, mock_hook_fn, (gpointer) &data3)); - - g_test_message ("Test all close hooks are called"); - hooks_struct.session = fixture->session; - hooks_struct.data1 = (gpointer) &data1; - hooks_struct.data2 = (gpointer) &data2; - hooks_struct.data3 = (gpointer) &data3; - hooks_struct.call_count = 0; - qof_session_call_close_hooks (fixture->session); - g_assert_cmpuint (hooks_struct.call_count, == , 3); - - /* currently qofsession does not provide a way to clear hooks list - * g_hook_list_clear is used to destroy list and all of it's elements - * though i' not sure if it frees all the memory allocated - */ - g_hook_list_clear (get_session_closed_hooks ()); -} - void test_suite_qofsession ( void ) { @@ -936,9 +870,7 @@ test_suite_qofsession ( void ) GNC_TEST_ADD (suitename, "qof session swap data", Fixture, NULL, setup, test_qof_session_swap_data, teardown); GNC_TEST_ADD (suitename, "qof session events", Fixture, NULL, setup, test_qof_session_events, teardown); GNC_TEST_ADD (suitename, "qof session data loaded", Fixture, NULL, setup, test_qof_session_data_loaded, teardown); - GNC_TEST_ADD (suitename, "qof backend access method list", Fixture, NULL, setup, test_qof_backend_get_access_method_list, teardown); GNC_TEST_ADD (suitename, "qof session get book", Fixture, NULL, setup, test_qof_session_get_book, teardown); GNC_TEST_ADD (suitename, "qof session get error", Fixture, NULL, setup, test_qof_session_get_error, teardown); GNC_TEST_ADD (suitename, "qof session clear error", Fixture, NULL, setup, test_qof_session_clear_error, teardown); - GNC_TEST_ADD (suitename, "qof session close hooks", Fixture, NULL, setup, test_qof_session_close_hooks, teardown); }