gnucash master: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Thu May 21 15:41:01 EDT 2020


Updated	 via  https://github.com/Gnucash/gnucash/commit/f2a13eca (commit)
	 via  https://github.com/Gnucash/gnucash/commit/98c877a6 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c0ee9b7d (commit)
	 via  https://github.com/Gnucash/gnucash/commit/1858da8a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/0e8a156b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/43d2c801 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/584ccd33 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/22770a3a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/954ce957 (commit)
	from  https://github.com/Gnucash/gnucash/commit/027d1f27 (commit)



commit f2a13ecac783ffe5c9e23f21298a7532e3040bc2
Merge: 027d1f275 98c877a61
Author: John Ralls <jralls at ceridwen.us>
Date:   Wed May 20 17:08:54 2020 -0700

    Merge Christian Gruber's 'test_import_backend' into master.

diff --cc gnucash/import-export/test/CMakeLists.txt
index eab7a7252,3f14f754d..0eae7bffe
--- a/gnucash/import-export/test/CMakeLists.txt
+++ b/gnucash/import-export/test/CMakeLists.txt
@@@ -35,5 -39,51 +35,53 @@@ gnc_add_test(test-import-account-matche
    IMPORT_ACCOUNT_MATCHER_TEST_INCLUDE_DIRS IMPORT_ACCOUNT_MATCHER_TEST_LIBS)
  
  set_dist_list(test_generic_import_DIST CMakeLists.txt
 -  test-link.c test-import-parse.c test-import-pending-matches.cpp
 +  test-import-parse.c test-import-pending-matches.cpp
    gtest-import-account-matcher.cpp)
+ 
+ set(gtest_import_backend_INCLUDE_DIRS
+   ${CMAKE_BINARY_DIR}/common # for config.h
+   ${CMAKE_SOURCE_DIR}/common
+   ${CMAKE_SOURCE_DIR}/gnucash/import-export
+   ${CMAKE_SOURCE_DIR}/libgnucash/app-utils
++  ${CMAKE_SOURCE_DIR}/libgnucash/app-utils/mocks
+   ${CMAKE_SOURCE_DIR}/libgnucash/core-utils
+   ${CMAKE_SOURCE_DIR}/libgnucash/engine
++  ${CMAKE_SOURCE_DIR}/libgnucash/engine/mocks
+   ${GTEST_INCLUDE_DIR}
+   ${GMOCK_INCLUDE_DIR}
+ )
+ 
+ set(gtest_import_backend_LIBS
+   PkgConfig::GTK3
+   ${Boost_LIBRARIES}
+   ${GMODULE_LDFLAGS}
+   ${GTHREAD_LDFLAGS}
+   ${ICU4C_I18N_LDFLAGS}
 -  ${GTEST_LIB}
 -  ${GMOCK_LIB}
++  gmock
++  gtest
+ )
+ 
+ set(gtest_import_backend_SOURCES
+   gtest-import-backend.cpp
+   ${CMAKE_SOURCE_DIR}/gnucash/import-export/import-backend.c
+   ${CMAKE_SOURCE_DIR}/gnucash/import-export/import-settings.c
+   ${CMAKE_SOURCE_DIR}/gnucash/import-export/import-utilities.c
 -  gmock-qofinstance.cpp
 -  gmock-gnc-prefs.cpp
 -  gmock-qofbook.cpp
 -  gmock-Account.cpp
 -  gmock-Transaction.cpp
 -  gmock-Split.cpp
 -  gmock-qofquery.cpp
++  ${CMAKE_SOURCE_DIR}/libgnucash/engine/mocks/gmock-qofinstance.cpp
++  ${CMAKE_SOURCE_DIR}/libgnucash/app-utils/mocks/gmock-gnc-prefs.cpp
++  ${CMAKE_SOURCE_DIR}/libgnucash/engine/mocks/gmock-qofbook.cpp
++  ${CMAKE_SOURCE_DIR}/libgnucash/engine/mocks/gmock-Account.cpp
++  ${CMAKE_SOURCE_DIR}/libgnucash/engine/mocks/gmock-Transaction.cpp
++  ${CMAKE_SOURCE_DIR}/libgnucash/engine/mocks/gmock-Split.cpp
++  ${CMAKE_SOURCE_DIR}/libgnucash/engine/mocks/gmock-qofquery.cpp
+   ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-numeric.cpp
+   ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-rational.cpp
+   ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-int128.cpp
+   ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-date.cpp
+   ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-datetime.cpp
+   ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-timezone.cpp
+   ${CMAKE_SOURCE_DIR}/libgnucash/core-utils/gnc-locale-utils.cpp
+ )
+ 
+ gnc_add_test(test-import-backend "${gtest_import_backend_SOURCES}"
+   gtest_import_backend_INCLUDE_DIRS gtest_import_backend_LIBS)
+ 
diff --cc libgnucash/app-utils/mocks/gmock-gnc-prefs.cpp
index 000000000,d08dc6925..d08dc6925
mode 000000,100644..100644
--- a/libgnucash/app-utils/mocks/gmock-gnc-prefs.cpp
+++ b/libgnucash/app-utils/mocks/gmock-gnc-prefs.cpp
diff --cc libgnucash/app-utils/mocks/gmock-gnc-prefs.h
index 000000000,6382224cd..6382224cd
mode 000000,100644..100644
--- a/libgnucash/app-utils/mocks/gmock-gnc-prefs.h
+++ b/libgnucash/app-utils/mocks/gmock-gnc-prefs.h
diff --cc libgnucash/engine/mocks/gmock-Account.cpp
index 000000000,5152d8866..5152d8866
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-Account.cpp
+++ b/libgnucash/engine/mocks/gmock-Account.cpp
diff --cc libgnucash/engine/mocks/gmock-Account.h
index 000000000,2a39efe6f..2a39efe6f
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-Account.h
+++ b/libgnucash/engine/mocks/gmock-Account.h
diff --cc libgnucash/engine/mocks/gmock-Split.cpp
index 000000000,c6ec5ecb7..c6ec5ecb7
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-Split.cpp
+++ b/libgnucash/engine/mocks/gmock-Split.cpp
diff --cc libgnucash/engine/mocks/gmock-Split.h
index 000000000,569d2fce1..569d2fce1
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-Split.h
+++ b/libgnucash/engine/mocks/gmock-Split.h
diff --cc libgnucash/engine/mocks/gmock-Transaction.cpp
index 000000000,dd02f6ea8..dd02f6ea8
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-Transaction.cpp
+++ b/libgnucash/engine/mocks/gmock-Transaction.cpp
diff --cc libgnucash/engine/mocks/gmock-Transaction.h
index 000000000,0790a7c03..0790a7c03
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-Transaction.h
+++ b/libgnucash/engine/mocks/gmock-Transaction.h
diff --cc libgnucash/engine/mocks/gmock-gobject.h
index 000000000,fa09c8dcf..fa09c8dcf
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-gobject.h
+++ b/libgnucash/engine/mocks/gmock-gobject.h
diff --cc libgnucash/engine/mocks/gmock-qofbook.cpp
index 000000000,7c3c6d7c7..7c3c6d7c7
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-qofbook.cpp
+++ b/libgnucash/engine/mocks/gmock-qofbook.cpp
diff --cc libgnucash/engine/mocks/gmock-qofbook.h
index 000000000,e4d4536b3..e4d4536b3
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-qofbook.h
+++ b/libgnucash/engine/mocks/gmock-qofbook.h
diff --cc libgnucash/engine/mocks/gmock-qofinstance.cpp
index 000000000,9669ef4af..9669ef4af
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-qofinstance.cpp
+++ b/libgnucash/engine/mocks/gmock-qofinstance.cpp
diff --cc libgnucash/engine/mocks/gmock-qofquery.cpp
index 000000000,65a545f14..65a545f14
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-qofquery.cpp
+++ b/libgnucash/engine/mocks/gmock-qofquery.cpp
diff --cc libgnucash/engine/mocks/gmock-qofquery.h
index 000000000,e019ef339..e019ef339
mode 000000,100644..100644
--- a/libgnucash/engine/mocks/gmock-qofquery.h
+++ b/libgnucash/engine/mocks/gmock-qofquery.h

commit 98c877a613be5e2c161b13b8d0d9a1f4f5413c3f
Author: Christian Gruber <christian.gruber at posteo.de>
Date:   Wed Apr 8 23:38:42 2020 +0200

    Add first test using fixture ImportBackendBayesTest

diff --git a/gnucash/import-export/test/gtest-import-backend.cpp b/gnucash/import-export/test/gtest-import-backend.cpp
index 83f33b789..eedcfba92 100644
--- a/gnucash/import-export/test/gtest-import-backend.cpp
+++ b/gnucash/import-export/test/gtest-import-backend.cpp
@@ -4,6 +4,8 @@
 
 #include <config.h>
 
+#include <gnc-datetime.hpp>
+
 extern "C"
 {
 #include <import-backend.h>
@@ -85,6 +87,27 @@ gnc_get_current_book (void)
 
 
 
+/* GMock MATCHERS */
+
+// GMock MATCHER to check for duplicates in containers
+MATCHER(HasDuplicates, std::string("has ") + std::string(negation ? "no " : "") + std::string("duplicated elements"))
+{
+    bool ret = false;
+
+    for (auto e : arg)
+    {
+        if (std::count(arg.begin(), arg.end(), e) > 1)
+        {
+            ret = true;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+
+
 // Test fixture for tests without bayesian matching
 class ImportBackendTest : public testing::Test
 {
@@ -183,3 +206,68 @@ protected:
     };
 };
 
+
+
+/* Tests using fixture ImportBackendBayesTest */
+
+//! Test for function gnc_import_TransInfo_new()
+TEST_F(ImportBackendBayesTest, CreateTransInfo)
+{
+    using namespace testing;
+
+    GncMockImportMatchMap imap(m_import_acc);
+    time64 date(GncDateTime(GncDate(2020, 3, 18)));
+    struct tm *tm_struct;
+    char local_day_of_week[16];
+
+    // get local day of week
+    tm_struct = gnc_gmtime(&date);
+    qof_strftime(local_day_of_week, sizeof(local_day_of_week), "%A", tm_struct);
+    gnc_tm_free(tm_struct);
+
+    // Define first split
+    ON_CALL(*m_trans, getSplit(0))
+        .WillByDefault(Return(m_split));
+    // Transaction has no further splits
+    ON_CALL(*m_trans, getSplit(Gt(0)))
+        .WillByDefault(Return(nullptr));
+    // Define description and memo of first split
+    // This transaction is used for testing tokenization of its content.
+    // Therefore the description text and the memo should contain
+    //   * consecutive separators
+    //   * separators at the beginning and end of string
+    //   * duplicated tokens within and between description text end memo
+    // The token separator is space.
+    ON_CALL(*m_trans, getDescription())
+        .WillByDefault(Return(" test  tokens within   description  tokens  "));
+    ON_CALL(*m_split, getMemo())
+        .WillByDefault(Return("  test   the memo test "));
+    // Define transaction date
+    ON_CALL(*m_trans, getDate())
+        .WillByDefault(Return(date));
+
+    // check tokens created from transaction
+    EXPECT_CALL(imap, findAccountBayes(AllOf(
+            Each(Not(IsEmpty())),                // tokens must not be empty strings
+            Each(Not(HasSubstr(" "))),           // tokens must not contain separator
+            Not(HasDuplicates()),                // tokens must be unique
+            Contains(StrEq(local_day_of_week)),  // tokens must contain local day of week
+            Contains(StrEq("description")),      // spot sample
+            Contains(StrEq("memo"))              // spot sample
+            )))
+        .WillOnce(Return(m_dest_acc));
+
+    // call function to be tested
+    GNCImportTransInfo *trans_info = gnc_import_TransInfo_new(m_trans, &imap);
+
+    // check 'trans_info'
+    EXPECT_EQ(gnc_import_TransInfo_get_fsplit(trans_info),  m_split);
+    EXPECT_EQ(gnc_import_TransInfo_get_destacc(trans_info), m_dest_acc);
+
+    // transaction is not open anymore
+    ON_CALL(*m_trans, isOpen())
+        .WillByDefault(Return(false));
+
+    // delete transaction info
+    gnc_import_TransInfo_delete(trans_info);
+};

commit c0ee9b7d67812fdedc917141cdbf0d07e495d59a
Author: Christian Gruber <christian.gruber at posteo.de>
Date:   Wed Apr 8 23:34:56 2020 +0200

    Add second fixture for testing bayesian import matching

diff --git a/gnucash/import-export/test/gtest-import-backend.cpp b/gnucash/import-export/test/gtest-import-backend.cpp
index dc0407763..83f33b789 100644
--- a/gnucash/import-export/test/gtest-import-backend.cpp
+++ b/gnucash/import-export/test/gtest-import-backend.cpp
@@ -85,6 +85,7 @@ gnc_get_current_book (void)
 
 
 
+// Test fixture for tests without bayesian matching
 class ImportBackendTest : public testing::Test
 {
 protected:
@@ -159,3 +160,26 @@ TEST_F(ImportBackendTest, CreateTransInfo)
     gnc_import_TransInfo_delete(trans_info);
 };
 
+
+
+// Test fixture for tests with bayesian matching
+class ImportBackendBayesTest : public ImportBackendTest
+{
+protected:
+    void SetUp()
+    {
+        ImportBackendTest::SetUp();
+
+        using namespace testing;
+
+        // set bayesian import matching in preferences
+        ON_CALL(*m_prefs, getBool(StrEq(GNC_PREFS_GROUP_IMPORT), StrEq(GNC_PREF_USE_BAYES)))
+            .WillByDefault(Return(true));
+    }
+
+    void TearDown()
+    {
+        ImportBackendTest::TearDown();
+    };
+};
+

commit 1858da8ac39f675639f399190c6e88dd86f4a381
Author: Christian Gruber <christian.gruber at posteo.de>
Date:   Wed Apr 8 23:20:01 2020 +0200

    Add first test for creation of transaction info

diff --git a/gnucash/import-export/test/gtest-import-backend.cpp b/gnucash/import-export/test/gtest-import-backend.cpp
index 53e903584..dc0407763 100644
--- a/gnucash/import-export/test/gtest-import-backend.cpp
+++ b/gnucash/import-export/test/gtest-import-backend.cpp
@@ -119,3 +119,43 @@ protected:
     MockSplit*        m_split;
 };
 
+
+
+/* Tests using fixture ImportBackendTest */
+
+//! Test for function gnc_import_TransInfo_new()
+TEST_F(ImportBackendTest, CreateTransInfo)
+{
+    GncMockImportMatchMap imap(m_import_acc);
+    gchar* online_id;
+
+    using namespace testing;
+
+    //qof_instance_get (QOF_INSTANCE (split), "online-id", &online_id, NULL);
+
+    // Define first split
+    ON_CALL(*m_trans, getSplit(0))
+        .WillByDefault(Return(m_split));
+    // define description of the transaction
+    ON_CALL(*m_trans, getDescription())
+        .WillByDefault(Return("This is the description"));
+
+    // function gnc_import_TransInfo_new() should try to find account using the description from the transaction
+    EXPECT_CALL(imap, findAccount(_, StrEq("This is the description")))
+        .WillOnce(Return(m_dest_acc));
+
+    // call function to be tested
+    GNCImportTransInfo *trans_info = gnc_import_TransInfo_new(m_trans, &imap);
+
+    // check 'trans_info'
+    EXPECT_EQ(gnc_import_TransInfo_get_fsplit(trans_info),  m_split);
+    EXPECT_EQ(gnc_import_TransInfo_get_destacc(trans_info), m_dest_acc);
+
+    // transaction is not open anymore
+    ON_CALL(*m_trans, isOpen())
+        .WillByDefault(Return(false));
+
+    // delete transaction info
+    gnc_import_TransInfo_delete(trans_info);
+};
+

commit 0e8a156b06064b32693cdec7dc79bfea217de470
Author: Christian Gruber <christian.gruber at posteo.de>
Date:   Wed Apr 8 22:51:45 2020 +0200

    Add further required mock functions

diff --git a/gnucash/import-export/test/gtest-import-backend.cpp b/gnucash/import-export/test/gtest-import-backend.cpp
index 1f917d9fa..53e903584 100644
--- a/gnucash/import-export/test/gtest-import-backend.cpp
+++ b/gnucash/import-export/test/gtest-import-backend.cpp
@@ -7,6 +7,8 @@
 extern "C"
 {
 #include <import-backend.h>
+#include <engine-helpers.h>
+#include <gnc-ui-util.h>
 }
 
 #include "gmock-gnc-prefs.h"
@@ -39,6 +41,50 @@ testing::Environment* const env = testing::AddGlobalTestEnvironment(new TestEnvi
 
 
 
+/* mock functions, which can not be mocked by mock classes */
+
+gint
+safe_strcasecmp (const gchar * da, const gchar * db)
+{
+    // use simplified case-sensitive string comparison as mock up
+    return g_strcmp0(da, db);
+}
+
+const char *
+qof_log_prettify (const char *name)
+{
+    // do nothing
+    return name;
+}
+
+// this is a slightly modified version of the function from engine-helpers.c
+const char *
+gnc_get_num_action (const Transaction *trans, const Split *split)
+{
+    gboolean num_action = qof_book_use_split_action_for_num_field(gnc_get_current_book());
+
+    if (trans && !split)
+        return xaccTransGetNum(trans);
+    if (split && !trans)
+        return xaccSplitGetAction(split);
+    if (trans && split)
+    {
+        if (num_action)
+            return xaccSplitGetAction(split);
+        else
+            return xaccTransGetNum(trans);
+    }
+    else return NULL;
+}
+
+QofBook *
+gnc_get_current_book (void)
+{
+    return ((TestEnvironment*)env)->m_book;
+}
+
+
+
 class ImportBackendTest : public testing::Test
 {
 protected:

commit 43d2c80107a5b22e1c6fc0fd192a59a1e8b6fa01
Author: Christian Gruber <christian.gruber at posteo.de>
Date:   Wed Apr 8 22:32:49 2020 +0200

    Add mock classes for prefs and qofquery

diff --git a/gnucash/import-export/test/CMakeLists.txt b/gnucash/import-export/test/CMakeLists.txt
index 4e9d1efae..3f14f754d 100644
--- a/gnucash/import-export/test/CMakeLists.txt
+++ b/gnucash/import-export/test/CMakeLists.txt
@@ -69,10 +69,12 @@ set(gtest_import_backend_SOURCES
   ${CMAKE_SOURCE_DIR}/gnucash/import-export/import-settings.c
   ${CMAKE_SOURCE_DIR}/gnucash/import-export/import-utilities.c
   gmock-qofinstance.cpp
+  gmock-gnc-prefs.cpp
   gmock-qofbook.cpp
   gmock-Account.cpp
   gmock-Transaction.cpp
   gmock-Split.cpp
+  gmock-qofquery.cpp
   ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-numeric.cpp
   ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-rational.cpp
   ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-int128.cpp
diff --git a/gnucash/import-export/test/gmock-gnc-prefs.cpp b/gnucash/import-export/test/gmock-gnc-prefs.cpp
new file mode 100644
index 000000000..d08dc6925
--- /dev/null
+++ b/gnucash/import-export/test/gmock-gnc-prefs.cpp
@@ -0,0 +1,47 @@
+#include <config.h>
+
+#include "gmock-gnc-prefs.h"
+
+PrefsBackend* prefsbackend = NULL;
+
+gboolean
+gnc_prefs_get_bool (const gchar *group, const gchar *pref_name)
+{
+    return ((MockPrefsBackend*)prefsbackend)->getBool(group, pref_name);
+}
+
+gint
+gnc_prefs_get_int (const gchar *group, const gchar *pref_name)
+{
+    return ((MockPrefsBackend*)prefsbackend)->getInt(group, pref_name);
+}
+
+gint64
+gnc_prefs_get_int64 (const gchar *group, const gchar *pref_name)
+{
+    return ((MockPrefsBackend*)prefsbackend)->getInt64(group, pref_name);
+}
+
+gdouble
+gnc_prefs_get_float (const gchar *group, const gchar *pref_name)
+{
+    return ((MockPrefsBackend*)prefsbackend)->getFloat(group, pref_name);
+}
+
+gchar *
+gnc_prefs_get_string (const gchar *group, const gchar *pref_name)
+{
+    return ((MockPrefsBackend*)prefsbackend)->getString(group, pref_name);
+}
+
+gint
+gnc_prefs_get_enum (const gchar *group, const gchar *pref_name)
+{
+    return ((MockPrefsBackend*)prefsbackend)->getEnum(group, pref_name);
+}
+
+void
+gnc_prefs_get_coords (const gchar *group, const gchar *pref_name, gdouble *x, gdouble *y)
+{
+    ((MockPrefsBackend*)prefsbackend)->getCoords(group, pref_name, x, y);
+}
diff --git a/gnucash/import-export/test/gmock-gnc-prefs.h b/gnucash/import-export/test/gmock-gnc-prefs.h
new file mode 100644
index 000000000..6382224cd
--- /dev/null
+++ b/gnucash/import-export/test/gmock-gnc-prefs.h
@@ -0,0 +1,47 @@
+#ifndef GMOCK_GNC_PREFS_H
+#define GMOCK_GNC_PREFS_H
+
+#include <gmock/gmock.h>
+
+extern "C"
+{
+#include <gnc-prefs.h>
+#include <gnc-prefs-p.h>
+}
+
+
+// mock up for PrefsBackend (singleton class)
+class MockPrefsBackend : PrefsBackend
+{
+public:
+    MockPrefsBackend(MockPrefsBackend const&) = delete;
+    MockPrefsBackend& operator=(MockPrefsBackend const&) = delete;
+
+    static MockPrefsBackend* getInstance()
+    {
+        static MockPrefsBackend prefs;  // preferences object
+
+        // register preferences object
+        if (prefsbackend == NULL)
+            prefsbackend = (PrefsBackend*)&prefs;
+
+        // check that preferences object is correctly registered
+        EXPECT_EQ((MockPrefsBackend*)prefsbackend, &prefs);
+
+        return &prefs;
+    }
+
+    MOCK_METHOD2(getBool, gboolean(const gchar *, const gchar *));
+    MOCK_METHOD2(getInt, gint(const gchar *, const gchar *));
+    MOCK_METHOD2(getInt64, gint64(const gchar *, const gchar *));
+    MOCK_METHOD2(getFloat, gdouble(const gchar *, const gchar *));
+    MOCK_METHOD2(getString, gchar*(const gchar *, const gchar *));
+    MOCK_METHOD2(getEnum, gint(const gchar *, const gchar *));
+    MOCK_METHOD4(getCoords, void(const gchar *, const gchar *, gdouble *, gdouble *));
+
+private:
+    MockPrefsBackend() {}
+    ~MockPrefsBackend() {}
+};
+
+#endif
diff --git a/gnucash/import-export/test/gmock-qofquery.cpp b/gnucash/import-export/test/gmock-qofquery.cpp
new file mode 100644
index 000000000..65a545f14
--- /dev/null
+++ b/gnucash/import-export/test/gmock-qofquery.cpp
@@ -0,0 +1,68 @@
+#include <config.h>
+
+#include "gmock-qofquery.h"
+#include "gmock-qofbook.h"
+
+QofQuery *
+qof_query_create_for (QofIdTypeConst obj_type)
+{
+    return (QofQuery*)qof_query_factory.create();
+/*
+    // \todo create typed query objects
+    QofQuery *ret = NULL;
+
+    if (g_strcmp0(obj_type, GNC_ID_SPLIT) == 0)
+        ret = (QofQuery*)qof_query_factory.createForSplit();
+//    else
+//        FAIL();
+
+    return ret;
+*/
+}
+
+void
+qof_query_set_book (QofQuery *query, QofBook *book)
+{
+    g_return_if_fail(QOF_IS_MOCK_BOOK(book));
+    ((QofMockQuery*)query)->setBook(book);
+}
+
+GList *
+qof_query_run (QofQuery *query)
+{
+    GList *matching_objects = NULL;
+
+    // \todo use typed mock objects
+    auto matchingObjects = ((QofMockQuery*)query)->run();
+
+    for (auto object : matchingObjects)
+    {
+        matching_objects = g_list_append(matching_objects, static_cast<gpointer>(object));
+    }
+
+    return matching_objects;
+}
+
+void
+xaccQueryAddDateMatchTT (
+        QofQuery *query,
+        gboolean use_start,
+        time64 stt,
+        gboolean use_end,
+        time64 ett,
+        QofQueryOp op)
+{
+    ((QofMockQuery*)query)->addDateMatchTT(use_start, stt, use_end, ett, op);
+}
+
+void
+xaccQueryAddSingleAccountMatch(QofQuery *query, Account *acc, QofQueryOp op)
+{
+    ((QofMockQuery*)query)->addSingleAccountMatch(acc, op);
+}
+
+void
+qof_query_destroy (QofQuery *query)
+{
+    ((QofMockQuery*)query)->destroy();
+}
diff --git a/gnucash/import-export/test/gmock-qofquery.h b/gnucash/import-export/test/gmock-qofquery.h
new file mode 100644
index 000000000..e019ef339
--- /dev/null
+++ b/gnucash/import-export/test/gmock-qofquery.h
@@ -0,0 +1,46 @@
+#ifndef GMOCK_QOFQUERY_H
+#define GMOCK_QOFQUERY_H
+
+#include <gmock/gmock.h>
+
+#include <qofquery.h>
+#include <qofquery-p.h>
+
+extern "C"
+{
+#include <Query.h>
+}
+
+// mock up for QofQuery
+// hint: class QofMockQuery can not be derived from QofQuery, since struct _QofQuery is not public
+class QofMockQuery
+{
+public:
+    QofMockQuery() {};
+
+    MOCK_METHOD1(setBook, void(QofBook*));
+    MOCK_METHOD0(destroy, void());
+    MOCK_METHOD5(addDateMatchTT, void(gboolean, time64, gboolean, time64, QofQueryOp));
+    MOCK_METHOD2(addSingleAccountMatch, void(Account*, QofQueryOp));
+    MOCK_METHOD0(run, std::vector<void*>());
+};
+
+/*
+// typed mock up for QofQuery
+template <typename T>
+class MockQofQueryWithType : MockQofQuery
+{
+public:
+    // \todo: write constructor
+    MOCK_METHOD0_T(run, std::list<T*>());
+};
+*/
+
+class QofQueryFactory
+{
+public:
+//    MOCK_METHOD0(createForSplit, MockQofQueryWithType<Split>*());
+    MOCK_METHOD0(create, QofMockQuery*());
+} qof_query_factory;
+
+#endif
diff --git a/gnucash/import-export/test/gtest-import-backend.cpp b/gnucash/import-export/test/gtest-import-backend.cpp
index 1ee3e2d4c..1f917d9fa 100644
--- a/gnucash/import-export/test/gtest-import-backend.cpp
+++ b/gnucash/import-export/test/gtest-import-backend.cpp
@@ -9,6 +9,7 @@ extern "C"
 #include <import-backend.h>
 }
 
+#include "gmock-gnc-prefs.h"
 #include "gmock-qofbook.h"
 #include "gmock-Account.h"
 #include "gmock-Transaction.h"
@@ -43,6 +44,8 @@ class ImportBackendTest : public testing::Test
 protected:
     void SetUp()
     {
+        m_prefs = MockPrefsBackend::getInstance();
+        ASSERT_NE(m_prefs, nullptr);
         m_import_acc = new MockAccount();
         m_dest_acc   = new MockAccount();
         m_trans      = new MockTransaction();
@@ -63,6 +66,7 @@ protected:
         m_split->free();
     }
 
+    MockPrefsBackend* m_prefs;
     MockAccount*      m_import_acc;
     MockAccount*      m_dest_acc;
     MockTransaction*  m_trans;

commit 584ccd333d4e1da33e9ce7b0c87856aefd77e2da
Author: Christian Gruber <christian.gruber at posteo.de>
Date:   Wed Apr 8 22:12:58 2020 +0200

    Add test-import-backend to CMakeLists.txt

diff --git a/gnucash/import-export/test/CMakeLists.txt b/gnucash/import-export/test/CMakeLists.txt
index 8d197e57c..4e9d1efae 100644
--- a/gnucash/import-export/test/CMakeLists.txt
+++ b/gnucash/import-export/test/CMakeLists.txt
@@ -41,3 +41,47 @@ gnc_add_test(test-import-account-matcher gtest-import-account-matcher.cpp
 set_dist_list(test_generic_import_DIST CMakeLists.txt
   test-link.c test-import-parse.c test-import-pending-matches.cpp
   gtest-import-account-matcher.cpp)
+
+set(gtest_import_backend_INCLUDE_DIRS
+  ${CMAKE_BINARY_DIR}/common # for config.h
+  ${CMAKE_SOURCE_DIR}/common
+  ${CMAKE_SOURCE_DIR}/gnucash/import-export
+  ${CMAKE_SOURCE_DIR}/libgnucash/app-utils
+  ${CMAKE_SOURCE_DIR}/libgnucash/core-utils
+  ${CMAKE_SOURCE_DIR}/libgnucash/engine
+  ${GTEST_INCLUDE_DIR}
+  ${GMOCK_INCLUDE_DIR}
+)
+
+set(gtest_import_backend_LIBS
+  PkgConfig::GTK3
+  ${Boost_LIBRARIES}
+  ${GMODULE_LDFLAGS}
+  ${GTHREAD_LDFLAGS}
+  ${ICU4C_I18N_LDFLAGS}
+  ${GTEST_LIB}
+  ${GMOCK_LIB}
+)
+
+set(gtest_import_backend_SOURCES
+  gtest-import-backend.cpp
+  ${CMAKE_SOURCE_DIR}/gnucash/import-export/import-backend.c
+  ${CMAKE_SOURCE_DIR}/gnucash/import-export/import-settings.c
+  ${CMAKE_SOURCE_DIR}/gnucash/import-export/import-utilities.c
+  gmock-qofinstance.cpp
+  gmock-qofbook.cpp
+  gmock-Account.cpp
+  gmock-Transaction.cpp
+  gmock-Split.cpp
+  ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-numeric.cpp
+  ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-rational.cpp
+  ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-int128.cpp
+  ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-date.cpp
+  ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-datetime.cpp
+  ${CMAKE_SOURCE_DIR}/libgnucash/engine/gnc-timezone.cpp
+  ${CMAKE_SOURCE_DIR}/libgnucash/core-utils/gnc-locale-utils.cpp
+)
+
+gnc_add_test(test-import-backend "${gtest_import_backend_SOURCES}"
+  gtest_import_backend_INCLUDE_DIRS gtest_import_backend_LIBS)
+

commit 22770a3ac42d8c63bd5f87fbb18a6e33a2cf5944
Author: Christian Gruber <christian.gruber at posteo.de>
Date:   Wed Apr 8 22:08:46 2020 +0200

    Initial test setup

diff --git a/gnucash/import-export/test/gtest-import-backend.cpp b/gnucash/import-export/test/gtest-import-backend.cpp
new file mode 100644
index 000000000..1ee3e2d4c
--- /dev/null
+++ b/gnucash/import-export/test/gtest-import-backend.cpp
@@ -0,0 +1,71 @@
+#include <gtk/gtk.h>
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include <config.h>
+
+extern "C"
+{
+#include <import-backend.h>
+}
+
+#include "gmock-qofbook.h"
+#include "gmock-Account.h"
+#include "gmock-Transaction.h"
+#include "gmock-Split.h"
+
+
+
+/* Global test environment */
+
+class TestEnvironment : public testing::Environment
+{
+public:
+    void SetUp()
+    {
+        m_book = new QofMockBook;
+    };
+
+    void TearDown()
+    {
+        m_book->free();
+    };
+
+    QofMockBook* m_book;
+};
+
+testing::Environment* const env = testing::AddGlobalTestEnvironment(new TestEnvironment);
+
+
+
+class ImportBackendTest : public testing::Test
+{
+protected:
+    void SetUp()
+    {
+        m_import_acc = new MockAccount();
+        m_dest_acc   = new MockAccount();
+        m_trans      = new MockTransaction();
+        m_split      = new MockSplit();
+
+        using namespace testing;
+
+        // define behaviour of m_import_acc
+        ON_CALL(*m_import_acc, getBook())
+            .WillByDefault(Return(((TestEnvironment*)env)->m_book));
+    }
+
+    void TearDown()
+    {
+        m_import_acc->free();
+        m_dest_acc->free();
+        m_trans->free();
+        m_split->free();
+    }
+
+    MockAccount*      m_import_acc;
+    MockAccount*      m_dest_acc;
+    MockTransaction*  m_trans;
+    MockSplit*        m_split;
+};
+

commit 954ce9577f4de5f77956e4cdc1d79d51ef8afb1f
Author: Christian Gruber <christian.gruber at posteo.de>
Date:   Wed Apr 8 22:00:29 2020 +0200

    Add mock classes for book, account, transaction and split

diff --git a/gnucash/import-export/test/gmock-Account.cpp b/gnucash/import-export/test/gmock-Account.cpp
new file mode 100644
index 000000000..5152d8866
--- /dev/null
+++ b/gnucash/import-export/test/gmock-Account.cpp
@@ -0,0 +1,114 @@
+#include <config.h>
+
+#include "gmock-Account.h"
+
+
+struct _MockAccountClass
+{
+    QofInstanceClass parent_class;
+};
+typedef struct _MockAccountClass MockAccountClass;
+
+G_DEFINE_TYPE(MockAccount, gnc_mock_account, QOF_TYPE_INSTANCE);
+
+static void
+gnc_mock_account_init (MockAccount *inst)
+{
+    // function is unused, initialization is done in the MockAccount's constructor
+}
+
+static void
+gnc_mock_account_class_init(MockAccountClass *klass)
+{
+    // function is unused, class functions are defined in C++ code
+}
+
+void
+xaccAccountBeginEdit (Account *account)
+{
+    g_return_if_fail(GNC_IS_MOCK_ACCOUNT(account));
+    ((MockAccount*)account)->beginEdit();
+}
+
+void
+xaccAccountCommitEdit (Account *account)
+{
+    g_return_if_fail(GNC_IS_MOCK_ACCOUNT(account));
+    ((MockAccount*)account)->commitEdit();
+}
+
+QofBook *
+gnc_account_get_book(const Account *account)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_ACCOUNT(account), NULL);
+    return ((MockAccount*)account)->getBook();
+}
+
+gint
+xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc,
+                              void *data)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_ACCOUNT(acc), 0);
+    return ((MockAccount*)acc)->forEachTransaction(proc, data);
+}
+
+GncImportMatchMap *
+gnc_account_imap_create_imap (Account *acc)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_ACCOUNT(acc), NULL);
+    return ((MockAccount*)acc)->imapCreateImap();
+}
+
+Account*
+gnc_account_imap_find_account (
+        GncImportMatchMap *imap,
+        const char* category,
+        const char *key)
+{
+    return ((GncMockImportMatchMap*)imap)->findAccount(category, key);
+}
+
+void
+gnc_account_imap_add_account (
+        GncImportMatchMap *imap,
+        const char *category,
+        const char *key,
+        Account *acc)
+{
+    // not used at the moment
+    ((GncMockImportMatchMap*)imap)->addAccount(category, key, acc);
+}
+
+Account*
+gnc_account_imap_find_account_bayes (
+        GncImportMatchMap *imap,
+        GList *tokens)
+{
+    // \todo use std::list instead of std::vector, since GList is a double-linked list like std::list
+    std::vector<std::string> tokenVec;
+
+    for (auto token = tokens; token; token = token->next)
+    {
+        tokenVec.push_back(static_cast <char const *> (token->data));
+    }
+
+    return ((GncMockImportMatchMap*)imap)->findAccountBayes(tokenVec);
+}
+
+void
+gnc_account_imap_add_account_bayes (
+        GncImportMatchMap *imap,
+        GList *tokens,
+        Account *acc)
+{
+    // \todo use std::list instead of std::vector, since GList is a double-linked list like std::list
+    std::vector<std::string> tokenVec;
+
+    for (auto token = tokens; token; token = token->next)
+    {
+        tokenVec.push_back(static_cast <char const *> (token->data));
+    }
+
+    ((GncMockImportMatchMap*)imap)->addAccountBayes(tokenVec, acc);
+}
+
diff --git a/gnucash/import-export/test/gmock-Account.h b/gnucash/import-export/test/gmock-Account.h
new file mode 100644
index 000000000..2a39efe6f
--- /dev/null
+++ b/gnucash/import-export/test/gmock-Account.h
@@ -0,0 +1,69 @@
+#ifndef GMOCK_ACCOUNT_H
+#define GMOCK_ACCOUNT_H
+
+#include <gmock/gmock.h>
+
+#include <Account.h>
+#include <AccountP.h>
+
+#include "gmock-qofbook.h"
+#include "gmock-gobject.h"
+
+
+GType gnc_mock_account_get_type(void);
+
+#define GNC_TYPE_MOCK_ACCOUNT   (gnc_mock_account_get_type ())
+#define GNC_IS_MOCK_ACCOUNT(o)  (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_MOCK_ACCOUNT))
+
+
+// mock up for Account
+class MockAccount : public Account
+{
+public:
+    MockAccount() {}
+    void* operator new(size_t size)
+    {
+        return mock_g_object_new (GNC_TYPE_MOCK_ACCOUNT, NULL, size);
+    }
+
+    // define separate free() function since destructor is protected
+    void free()
+    {
+        delete this;
+    }
+    void operator delete(void* acc, size_t size)
+    {
+        mock_g_object_unref(acc, size);
+    }
+
+    MOCK_METHOD0(beginEdit, void());
+    MOCK_METHOD0(commitEdit, void());
+    MOCK_METHOD0(getBook, QofMockBook*());
+    MOCK_METHOD2(forEachTransaction, gint(TransactionCallback, void*));
+    MOCK_METHOD0(imapCreateImap, GncImportMatchMap*());
+
+protected:
+    // Protect destructor to avoid MockAccount objects to be created on stack. MockAccount
+    // objects can only be dynamically created, since they are derived from GObject.
+    ~MockAccount() {}
+};
+
+
+class GncMockImportMatchMap : public GncImportMatchMap
+{
+public:
+    GncMockImportMatchMap(MockAccount* account)
+    {
+        g_return_if_fail(GNC_IS_MOCK_ACCOUNT(account));
+
+        acc  = account;
+        book = account->getBook();
+    };
+
+    MOCK_METHOD2(findAccount, Account *(const char*, const char*));
+    MOCK_METHOD3(addAccount, void(const char*, const char*, Account*));
+    MOCK_METHOD1(findAccountBayes, Account *(std::vector<std::string>));
+    MOCK_METHOD2(addAccountBayes, void(std::vector<std::string>, Account*));
+};
+
+#endif
diff --git a/gnucash/import-export/test/gmock-Split.cpp b/gnucash/import-export/test/gmock-Split.cpp
new file mode 100644
index 000000000..c6ec5ecb7
--- /dev/null
+++ b/gnucash/import-export/test/gmock-Split.cpp
@@ -0,0 +1,142 @@
+#include <config.h>
+
+#include "gmock-Split.h"
+#include "gmock-qofbook.h"
+#include "gmock-Account.h"
+#include "gmock-Transaction.h"
+
+
+struct _MockSplitClass
+{
+    QofInstanceClass parent_class;
+};
+typedef struct _MockSplitClass MockSplitClass;
+
+G_DEFINE_TYPE(MockSplit, gnc_mock_split, QOF_TYPE_INSTANCE);
+
+static void
+gnc_mock_split_init (MockSplit *inst)
+{
+    // function is unused since it's overwritten by MockSplit's constructor anyway
+}
+
+static void
+gnc_mock_split_class_init (MockSplitClass *klass)
+{
+    // function is unused, class functions are defined in C++ code
+}
+
+
+Split *
+xaccMallocSplit (QofBook *book)
+{
+    g_return_val_if_fail(QOF_IS_MOCK_BOOK(book), NULL);
+    return ((QofMockBook*)book)->mallocSplit();
+}
+
+QofBook *
+xaccSplitGetBook (const Split *split)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
+    return ((MockSplit*)split)->getBook();
+}
+
+Account *
+xaccSplitGetAccount (const Split *split)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
+    return ((MockSplit*)split)->getAccount();
+}
+
+void
+xaccSplitSetAccount (Split *split, Account *acc)
+{
+    g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
+    g_return_if_fail(GNC_IS_MOCK_ACCOUNT(acc));
+    ((MockSplit*)split)->setAccount(acc);
+}
+
+gnc_numeric
+xaccSplitGetAmount (const Split *split)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), gnc_numeric_zero());
+    return ((MockSplit*)split)->getAmount();
+}
+
+void
+xaccSplitSetAmount (Split *split, gnc_numeric amt)
+{
+    g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
+    ((MockSplit*)split)->setAmount(amt);
+}
+
+gnc_numeric
+xaccSplitGetValue (const Split *split)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), gnc_numeric_zero());
+    return ((MockSplit*)split)->getValue();
+}
+
+void
+xaccSplitSetValue (Split *split, gnc_numeric val)
+{
+    g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
+    ((MockSplit*)split)->setValue(val);
+}
+
+const char *
+xaccSplitGetMemo (const Split *split)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
+    return ((MockSplit*)split)->getMemo();
+}
+
+char
+xaccSplitGetReconcile (const Split *split)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), VREC);
+    return ((MockSplit*)split)->getReconcile();
+}
+
+void
+xaccSplitSetReconcile (Split *split, char recn)
+{
+    g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
+    ((MockSplit*)split)->setReconcile(recn);
+}
+
+void
+xaccSplitSetDateReconciledSecs (Split *split, time64 secs)
+{
+    g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
+    ((MockSplit*)split)->setDateReconciledSecs(secs);
+}
+
+const char *
+xaccSplitGetAction (const Split *split)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
+    return ((MockSplit*)split)->getAction();
+}
+
+Split *
+xaccSplitGetOtherSplit (const Split *split)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
+    return ((MockSplit*)split)->getOtherSplit();
+}
+
+Transaction *
+xaccSplitGetParent (const Split *split)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
+    return ((MockSplit*)split)->getParent();
+}
+
+void
+xaccSplitSetParent(Split *split, Transaction *trans)
+{
+    g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
+    g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
+    ((MockSplit*)split)->setParent(trans);
+}
diff --git a/gnucash/import-export/test/gmock-Split.h b/gnucash/import-export/test/gmock-Split.h
new file mode 100644
index 000000000..569d2fce1
--- /dev/null
+++ b/gnucash/import-export/test/gmock-Split.h
@@ -0,0 +1,85 @@
+#ifndef GMOCK_SPLIT_H
+#define GMOCK_SPLIT_H
+
+#include <gmock/gmock.h>
+
+#include <Split.h>
+#include <SplitP.h>
+
+#include "gmock-qofbook.h"
+#include "gmock-gobject.h"
+
+
+GType gnc_mock_split_get_type(void);
+
+#define GNC_TYPE_MOCK_SPLIT   (gnc_mock_split_get_type ())
+#define GNC_IS_MOCK_SPLIT(o)  (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_MOCK_SPLIT))
+
+
+// mock up for Split
+class MockSplit : public Split
+{
+public:
+    MockSplit()
+    {
+        acc         = nullptr;
+        orig_acc    = nullptr;
+        parent      = nullptr;
+        orig_parent = nullptr;
+        lot         = nullptr;
+
+        action      = nullptr;
+        memo        = nullptr;
+        reconciled  = VREC;
+        amount      = gnc_numeric_zero();
+        value       = gnc_numeric_zero();
+
+        date_reconciled    = 0;
+
+        balance            = gnc_numeric_zero();
+        cleared_balance    = gnc_numeric_zero();
+        reconciled_balance = gnc_numeric_zero();
+        noclosing_balance  = gnc_numeric_zero();
+
+        gains        = GAINS_STATUS_UNKNOWN;
+        gains_split  = nullptr;
+    }
+    void* operator new(size_t size)
+    {
+        return mock_g_object_new (GNC_TYPE_MOCK_SPLIT, NULL, size);
+    }
+
+    // define separate free() function since destructor is protected
+    void free()
+    {
+        delete this;
+    }
+    void operator delete(void* split, size_t size)
+    {
+        mock_g_object_unref(split, size);
+    }
+
+    MOCK_METHOD0(init, void());
+    MOCK_METHOD0(getBook, QofBook *());
+    MOCK_METHOD0(getAccount, Account *());
+    MOCK_METHOD1(setAccount, void(Account*));
+    MOCK_METHOD0(getAmount, gnc_numeric());
+    MOCK_METHOD1(setAmount, void(gnc_numeric));
+    MOCK_METHOD0(getValue, gnc_numeric());
+    MOCK_METHOD1(setValue, void(gnc_numeric));
+    MOCK_METHOD0(getMemo, const char *());
+    MOCK_METHOD0(getReconcile, char());
+    MOCK_METHOD1(setReconcile, void(char));
+    MOCK_METHOD1(setDateReconciledSecs, void(time64));
+    MOCK_METHOD0(getAction, const char *());
+    MOCK_METHOD0(getOtherSplit, Split *());
+    MOCK_METHOD0(getParent, Transaction *());
+    MOCK_METHOD1(setParent, void(Transaction*));
+
+protected:
+    // Protect destructor to avoid MockSplit objects to be created on stack. MockSplit
+    // objects can only be dynamically created, since they are derived from GObject.
+    ~MockSplit() {}
+};
+
+#endif
diff --git a/gnucash/import-export/test/gmock-Transaction.cpp b/gnucash/import-export/test/gmock-Transaction.cpp
new file mode 100644
index 000000000..dd02f6ea8
--- /dev/null
+++ b/gnucash/import-export/test/gmock-Transaction.cpp
@@ -0,0 +1,125 @@
+#include <config.h>
+
+#include "gmock-Transaction.h"
+#include "gmock-Account.h"
+
+
+struct _MockTransactionClass
+{
+    QofInstanceClass parent_class;
+};
+typedef struct _MockTransactionClass MockTransactionClass;
+
+G_DEFINE_TYPE(MockTransaction, gnc_mock_transaction, QOF_TYPE_INSTANCE);
+
+static void
+gnc_mock_transaction_init (MockTransaction *inst)
+{
+    // function is unused, initialization is done in the MockTransaction's constructor
+}
+
+static void
+gnc_mock_transaction_class_init(MockTransactionClass *klass)
+{
+    // function is unused, class functions are defined in C++ code
+}
+
+
+void
+xaccTransBeginEdit (Transaction *trans)
+{
+    g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
+    ((MockTransaction*)trans)->beginEdit();
+}
+
+void
+xaccTransCommitEdit (Transaction *trans)
+{
+    g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
+    ((MockTransaction*)trans)->commitEdit();
+}
+
+Split *
+xaccTransGetSplit (const Transaction *trans, int i)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
+    return ((MockTransaction*)trans)->getSplit(i);
+}
+
+Split *
+xaccTransFindSplitByAccount(const Transaction *trans, const Account *acc)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
+    g_return_val_if_fail(GNC_IS_MOCK_ACCOUNT(acc), NULL);
+    return ((MockTransaction*)trans)->findSplitByAccount(acc);
+}
+
+time64
+xaccTransGetDate (const Transaction *trans)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), 0);
+    return ((MockTransaction*)trans)->getDate();
+}
+
+void
+xaccTransSetDatePostedSecsNormalized (Transaction *trans, time64 time)
+{
+    g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
+    ((MockTransaction*)trans)->setDatePostedSecsNormalized(time);
+}
+
+const char *
+xaccTransGetDescription (const Transaction *trans)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
+    return ((MockTransaction*)trans)->getDescription();
+}
+
+void
+xaccTransSetDescription (Transaction *trans, const char *desc)
+{
+    g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
+    ((MockTransaction*)trans)->setDescription(desc);
+}
+
+const char *
+xaccTransGetNotes (const Transaction *trans)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
+    return ((MockTransaction*)trans)->getNotes();
+}
+
+void
+xaccTransSetNotes (Transaction *trans, const char *notes)
+{
+    g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
+    ((MockTransaction*)trans)->setDescription(notes);
+}
+
+gnc_numeric
+xaccTransGetImbalanceValue (const Transaction * trans)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), gnc_numeric_zero());
+    return ((MockTransaction*)trans)->getImbalanceValue();
+}
+
+const char *
+xaccTransGetNum (const Transaction *trans)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
+    return ((MockTransaction*)trans)->getNum();
+}
+
+gboolean
+xaccTransIsOpen (const Transaction *trans)
+{
+    g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), FALSE);
+    return ((MockTransaction*)trans)->isOpen();
+}
+
+void
+xaccTransDestroy (Transaction *trans)
+{
+    g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
+    ((MockTransaction*)trans)->destroy();
+}
diff --git a/gnucash/import-export/test/gmock-Transaction.h b/gnucash/import-export/test/gmock-Transaction.h
new file mode 100644
index 000000000..0790a7c03
--- /dev/null
+++ b/gnucash/import-export/test/gmock-Transaction.h
@@ -0,0 +1,73 @@
+#ifndef GMOCK_TRANSACTION_H
+#define GMOCK_TRANSACTION_H
+
+#include <gmock/gmock.h>
+
+#include <Transaction.h>
+#include <TransactionP.h>
+
+#include "gmock-qofbook.h"
+#include "gmock-gobject.h"
+
+
+GType gnc_mock_transaction_get_type(void);
+
+#define GNC_TYPE_MOCK_TRANSACTION   (gnc_mock_transaction_get_type ())
+#define GNC_IS_MOCK_TRANSACTION(o)  (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_MOCK_TRANSACTION))
+
+
+// mock up for Transaction
+class MockTransaction : public Transaction
+{
+public:
+    MockTransaction()
+    {
+        num                 = nullptr;
+        description         = nullptr;
+        common_currency     = nullptr;
+        splits              = nullptr;
+        date_entered        = 0;
+        date_posted         = 0;
+        marker              = 0;
+        orig                = nullptr;
+        readonly_reason     = nullptr;
+        reason_cache_valid  = FALSE;
+        isClosingTxn_cached = -1;
+    }
+    void* operator new(size_t size)
+    {
+        return mock_g_object_new (GNC_TYPE_MOCK_TRANSACTION, NULL, size);
+    }
+
+    // define separate free() function since destructor is protected
+    void free()
+    {
+        delete this;
+    }
+    void operator delete(void* trans, size_t size)
+    {
+        mock_g_object_unref(trans, size);
+    }
+
+    MOCK_METHOD0(beginEdit, void());
+    MOCK_METHOD0(commitEdit, void());
+    MOCK_METHOD1(getSplit, Split *(int));
+    MOCK_METHOD1(findSplitByAccount, Split *(const Account*));
+    MOCK_METHOD0(getDate, time64());
+    MOCK_METHOD1(setDatePostedSecsNormalized, void(time64));
+    MOCK_METHOD0(getDescription, const char *());
+    MOCK_METHOD1(setDescription, void(const char*));
+    MOCK_METHOD0(getNotes, const char *());
+    MOCK_METHOD1(setNotes, void(const char*));
+    MOCK_METHOD0(getImbalanceValue, gnc_numeric());
+    MOCK_METHOD0(getNum, const char *());
+    MOCK_METHOD0(isOpen, gboolean());
+    MOCK_METHOD0(destroy, void());
+
+protected:
+    // Protect destructor to avoid MockTransaction objects to be created on stack. MockTransaction
+    // objects can only be dynamically created, since they are derived from GObject.
+    ~MockTransaction() {}
+};
+
+#endif
diff --git a/gnucash/import-export/test/gmock-gobject.h b/gnucash/import-export/test/gmock-gobject.h
new file mode 100644
index 000000000..fa09c8dcf
--- /dev/null
+++ b/gnucash/import-export/test/gmock-gobject.h
@@ -0,0 +1,27 @@
+#ifndef GMOCK_GOBJECT_H
+#define GMOCK_GOBJECT_H
+
+#include <glib.h>
+
+static gpointer
+mock_g_object_new (GType object_type, const gchar *first_property_name, size_t size)
+{
+    GTypeQuery query;
+
+    g_type_query(object_type, &query);
+    g_assert(size == query.instance_size);
+    return g_object_new (object_type, first_property_name);
+}
+
+static void
+mock_g_object_unref (gpointer object, size_t size)
+{
+    GType      object_type = G_OBJECT_TYPE(object);
+    GTypeQuery query;
+
+    g_type_query(object_type, &query);
+    g_assert(size == query.instance_size);
+    g_object_unref(object);
+}
+
+#endif
diff --git a/gnucash/import-export/test/gmock-qofbook.cpp b/gnucash/import-export/test/gmock-qofbook.cpp
new file mode 100644
index 000000000..7c3c6d7c7
--- /dev/null
+++ b/gnucash/import-export/test/gmock-qofbook.cpp
@@ -0,0 +1,29 @@
+#include "gmock-qofbook.h"
+
+struct _QofMockBookClass
+{
+    QofInstanceClass parent_class;
+};
+typedef struct _QofMockBookClass QofMockBookClass;
+
+G_DEFINE_TYPE(QofMockBook, qof_mock_book, QOF_TYPE_INSTANCE);
+
+static void
+qof_mock_book_init (QofMockBook *inst)
+{
+    // function is unused, initialization is done in the QofMockBook's constructor
+}
+
+static void
+qof_mock_book_class_init(QofMockBookClass *klass)
+{
+    // function is unused, class functions are defined in C++ code
+}
+
+gboolean
+qof_book_use_split_action_for_num_field (const QofBook *book)
+{
+    g_return_val_if_fail(QOF_IS_MOCK_BOOK(book), FALSE);
+    return ((QofMockBook*)book)->useSplitActionForNumField();
+}
+
diff --git a/gnucash/import-export/test/gmock-qofbook.h b/gnucash/import-export/test/gmock-qofbook.h
new file mode 100644
index 000000000..e4d4536b3
--- /dev/null
+++ b/gnucash/import-export/test/gmock-qofbook.h
@@ -0,0 +1,62 @@
+#ifndef GMOCK_QOFBOOK_H
+#define GMOCK_QOFBOOK_H
+
+#include <gmock/gmock.h>
+
+#include <qofbook.h>
+#include <qofbook-p.h>
+
+#include "gmock-gobject.h"
+#include "gmock-Split.h"
+
+
+GType qof_mock_book_get_type(void);
+
+#define QOF_TYPE_MOCK_BOOK   (qof_mock_book_get_type ())
+#define QOF_IS_MOCK_BOOK(o)  (G_TYPE_CHECK_INSTANCE_TYPE ((o), QOF_TYPE_MOCK_BOOK))
+
+
+// mock up for QofBook
+class QofMockBook : public QofBook
+{
+public:
+    QofMockBook()
+    {
+        hash_of_collections   = nullptr;
+        data_tables           = nullptr;
+        data_table_finalizers = nullptr;
+
+        book_open     = 'n';
+        read_only     = TRUE;
+        session_dirty = FALSE;
+
+        version = 0;
+
+        cached_num_field_source_isvalid      = FALSE;
+        cached_num_days_autoreadonly_isvalid = FALSE;
+    }
+    void* operator new(size_t size)
+    {
+        return mock_g_object_new (QOF_TYPE_MOCK_BOOK, NULL, size);
+    }
+
+    // define separate free() function since destructor is protected
+    void free()
+    {
+        delete this;
+    }
+    void operator delete(void* book, size_t size)
+    {
+        mock_g_object_unref(book, size);
+    }
+
+    MOCK_METHOD0(mallocSplit, Split *());
+    MOCK_METHOD0(useSplitActionForNumField, gboolean());
+
+protected:
+    // Protect destructor to avoid MockQofBook objects to be created on stack. MockQofBook
+    // objects can only be dynamically created, since they are derived from GObject.
+    ~QofMockBook() {}
+};
+
+#endif
diff --git a/gnucash/import-export/test/gmock-qofinstance.cpp b/gnucash/import-export/test/gmock-qofinstance.cpp
new file mode 100644
index 000000000..9669ef4af
--- /dev/null
+++ b/gnucash/import-export/test/gmock-qofinstance.cpp
@@ -0,0 +1,48 @@
+#include <glib.h>
+
+extern "C"
+{
+#include <qofinstance.h>
+}
+#include <qofinstance-p.h>
+
+
+G_DEFINE_TYPE(QofInstance, qof_instance, G_TYPE_OBJECT);
+
+static void
+qof_instance_init (QofInstance *inst)
+{
+    // function is unused, initialization is done in the constructor of the derived mock class
+}
+
+static void
+qof_instance_class_init(QofInstanceClass *klass)
+{
+    // function is unused, class functions are defined in C++ code
+}
+
+// This is a reimplementation of the function from qofinstance.cpp
+void
+qof_instance_get (const QofInstance *inst, const gchar *first_prop, ...)
+{
+    va_list ap;
+    g_return_if_fail (QOF_IS_INSTANCE (inst));
+
+    va_start (ap, first_prop);
+    g_object_get_valist (G_OBJECT (inst), first_prop, ap);
+    va_end (ap);
+}
+
+// This is a reimplementation of the function from qofinstance.cpp
+// with calling qof_instance_set_dirty()
+void
+qof_instance_set (QofInstance *inst, const gchar *first_prop, ...)
+{
+    va_list ap;
+    g_return_if_fail (QOF_IS_INSTANCE (inst));
+
+    va_start (ap, first_prop);
+    g_object_set_valist (G_OBJECT (inst), first_prop, ap);
+    va_end (ap);
+}
+



Summary of changes:
 gnucash/import-export/test/CMakeLists.txt          |  48 ++++
 .../import-export/test/gtest-import-backend.cpp    | 273 +++++++++++++++++++++
 libgnucash/app-utils/mocks/gmock-gnc-prefs.cpp     |  47 ++++
 libgnucash/app-utils/mocks/gmock-gnc-prefs.h       |  47 ++++
 libgnucash/engine/mocks/gmock-Account.cpp          | 114 +++++++++
 libgnucash/engine/mocks/gmock-Account.h            |  69 ++++++
 libgnucash/engine/mocks/gmock-Split.cpp            | 142 +++++++++++
 libgnucash/engine/mocks/gmock-Split.h              |  85 +++++++
 libgnucash/engine/mocks/gmock-Transaction.cpp      | 125 ++++++++++
 libgnucash/engine/mocks/gmock-Transaction.h        |  73 ++++++
 libgnucash/engine/mocks/gmock-gobject.h            |  27 ++
 libgnucash/engine/mocks/gmock-qofbook.cpp          |  29 +++
 libgnucash/engine/mocks/gmock-qofbook.h            |  62 +++++
 libgnucash/engine/mocks/gmock-qofinstance.cpp      |  48 ++++
 libgnucash/engine/mocks/gmock-qofquery.cpp         |  68 +++++
 libgnucash/engine/mocks/gmock-qofquery.h           |  46 ++++
 16 files changed, 1303 insertions(+)
 create mode 100644 gnucash/import-export/test/gtest-import-backend.cpp
 create mode 100644 libgnucash/app-utils/mocks/gmock-gnc-prefs.cpp
 create mode 100644 libgnucash/app-utils/mocks/gmock-gnc-prefs.h
 create mode 100644 libgnucash/engine/mocks/gmock-Account.cpp
 create mode 100644 libgnucash/engine/mocks/gmock-Account.h
 create mode 100644 libgnucash/engine/mocks/gmock-Split.cpp
 create mode 100644 libgnucash/engine/mocks/gmock-Split.h
 create mode 100644 libgnucash/engine/mocks/gmock-Transaction.cpp
 create mode 100644 libgnucash/engine/mocks/gmock-Transaction.h
 create mode 100644 libgnucash/engine/mocks/gmock-gobject.h
 create mode 100644 libgnucash/engine/mocks/gmock-qofbook.cpp
 create mode 100644 libgnucash/engine/mocks/gmock-qofbook.h
 create mode 100644 libgnucash/engine/mocks/gmock-qofinstance.cpp
 create mode 100644 libgnucash/engine/mocks/gmock-qofquery.cpp
 create mode 100644 libgnucash/engine/mocks/gmock-qofquery.h



More information about the gnucash-changes mailing list