Merge Christian Gruber's 'test_import_backend' into maint.

This commit is contained in:
John Ralls
2020-11-08 14:04:29 -08:00
18 changed files with 622 additions and 347 deletions

View File

@@ -2,46 +2,68 @@
#include "gmock-gnc-prefs.h"
PrefsBackend* prefsbackend = NULL;
static MockPrefsBackend* prefsbackend = nullptr;
void
gmock_gnc_prefs_set_backend(MockPrefsBackend *backend)
{
prefsbackend = backend;
}
extern "C"
{
gboolean
gnc_prefs_get_bool (const gchar *group, const gchar *pref_name)
{
return ((MockPrefsBackend*)prefsbackend)->getBool(group, pref_name);
EXPECT_NE(prefsbackend, nullptr);
return prefsbackend ? prefsbackend->get_bool(group, pref_name) : FALSE;
}
gint
gnc_prefs_get_int (const gchar *group, const gchar *pref_name)
{
return ((MockPrefsBackend*)prefsbackend)->getInt(group, pref_name);
EXPECT_NE(prefsbackend, nullptr);
return prefsbackend ? prefsbackend->get_int(group, pref_name) : 0;
}
gint64
gnc_prefs_get_int64 (const gchar *group, const gchar *pref_name)
{
return ((MockPrefsBackend*)prefsbackend)->getInt64(group, pref_name);
EXPECT_NE(prefsbackend, nullptr);
return prefsbackend ? prefsbackend->get_int64(group, pref_name) : 0;
}
gdouble
gnc_prefs_get_float (const gchar *group, const gchar *pref_name)
{
return ((MockPrefsBackend*)prefsbackend)->getFloat(group, pref_name);
EXPECT_NE(prefsbackend, nullptr);
return prefsbackend ? prefsbackend->get_float(group, pref_name) : 0.0;
}
gchar *
gnc_prefs_get_string (const gchar *group, const gchar *pref_name)
{
return ((MockPrefsBackend*)prefsbackend)->getString(group, pref_name);
EXPECT_NE(prefsbackend, nullptr);
return prefsbackend ? prefsbackend->get_string(group, pref_name) : NULL;
}
gint
gnc_prefs_get_enum (const gchar *group, const gchar *pref_name)
{
return ((MockPrefsBackend*)prefsbackend)->getEnum(group, pref_name);
EXPECT_NE(prefsbackend, nullptr);
return prefsbackend ? prefsbackend->get_enum(group, pref_name) : 0;
}
void
gnc_prefs_get_coords (const gchar *group, const gchar *pref_name, gdouble *x, gdouble *y)
{
((MockPrefsBackend*)prefsbackend)->getCoords(group, pref_name, x, y);
EXPECT_NE(prefsbackend, nullptr);
*x = 0.0;
*y = 0.0;
if (prefsbackend != nullptr)
prefsbackend->get_coords(group, pref_name, x, y);
}
} // extern "C"

View File

@@ -6,42 +6,26 @@
extern "C"
{
#include <gnc-prefs.h>
#include <gnc-prefs-p.h>
}
// mock up for PrefsBackend (singleton class)
class MockPrefsBackend : PrefsBackend
// mock up class implementing preferences backend (see struct PrefBackend in gnc-prefs-p.h)
class MockPrefsBackend
{
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() {}
MOCK_METHOD2(get_bool, gboolean(const gchar *, const gchar *));
MOCK_METHOD2(get_int, gint(const gchar *, const gchar *));
MOCK_METHOD2(get_int64, gint64(const gchar *, const gchar *));
MOCK_METHOD2(get_float, gdouble(const gchar *, const gchar *));
MOCK_METHOD2(get_string, gchar*(const gchar *, const gchar *));
MOCK_METHOD2(get_enum, gint(const gchar *, const gchar *));
MOCK_METHOD4(get_coords, void(const gchar *, const gchar *, gdouble *, gdouble *));
};
/** Define a preferences backend.
*
* \attention Each call to this function overwrites a previously set backend.
*/
void gmock_gnc_prefs_set_backend(MockPrefsBackend *backend);
#endif

View File

@@ -0,0 +1,169 @@
/**
* @file fake-qofquery.cpp
*/
#include <config.h>
#include <qofbook.h>
#include <list>
#include "fake-qofquery.h"
/* class QofFakeQueryPool */
static class QofFakeQueryPool
{
public:
/* Add QofFakeQuery object to the pool */
void add_query(QofFakeQuery *query)
{
m_queriesNew.push_back(query);
}
/* Request to use a QofFakeQuery object */
QofFakeQuery* request_query(QofIdTypeConst obj_type)
{
QofFakeQuery* query = nullptr;
auto it = std::find_if(m_queriesNew.begin(), m_queriesNew.end(),
[obj_type](QofFakeQuery const* query) {
return (g_strcmp0(query->m_obj_type, obj_type) == 0);
});
if (it != m_queriesNew.end())
{
query = *it;
m_queriesNew.erase(it);
m_queriesUsed.push_back(query);
}
EXPECT_NE(query, nullptr);
return query;
}
/* Check if a QofFakeQuery object is currently used, i.e. it has been
* requested before */
bool query_used(QofQuery *query)
{
auto it = std::find(m_queriesUsed.begin(), m_queriesUsed.end(), (QofFakeQuery*)query);
return (it != m_queriesUsed.end());
}
/* Release a formerly requested QofFakeQuery object, which is not used
* anymore */
void release_query(QofFakeQuery *query)
{
ASSERT_TRUE(query_used((QofQuery*)query));
auto it = std::find(m_queriesUsed.begin(), m_queriesUsed.end(), query);
m_queriesUsed.erase(it);
m_queriesConsumed.push_back(*it);
}
/* Remove a formerly added QofFakeQueryObject from the pool */
void remove_query(QofFakeQuery *query)
{
ASSERT_FALSE(query_used((QofQuery*)query));
auto it = std::find(m_queriesConsumed.begin(), m_queriesConsumed.end(), (QofFakeQuery*)query);
if (it != m_queriesConsumed.end())
m_queriesConsumed.erase(it);
else
{
it = std::find(m_queriesNew.begin(), m_queriesNew.end(), (QofFakeQuery*)query);
bool query_found = (it != m_queriesNew.end());
ASSERT_TRUE(query_found);
m_queriesNew.erase(it);
}
}
private:
std::list<QofFakeQuery*> m_queriesNew {};
std::list<QofFakeQuery*> m_queriesUsed {};
std::list<QofFakeQuery*> m_queriesConsumed {};
} queryPool;
/* class QofFakeQuery */
QofFakeQuery::QofFakeQuery(QofIdTypeConst obj_type) :
m_obj_type(obj_type)
{
queryPool.add_query(this);
}
QofFakeQuery::~QofFakeQuery()
{
queryPool.remove_query(this);
}
/* mock functions */
QofQuery *
qof_query_create_for (QofIdTypeConst obj_type)
{
return (QofQuery*)queryPool.request_query(obj_type);
}
void
qof_query_destroy (QofQuery *query)
{
queryPool.release_query((QofFakeQuery*)query);
}
void
qof_query_set_book (QofQuery *query, QofBook *book)
{
ASSERT_TRUE(queryPool.query_used(query));
ASSERT_TRUE(QOF_IS_BOOK(book));
((QofFakeQuery*)query)->set_book(book);
}
extern "C"
{
void
xaccQueryAddDateMatchTT (
QofQuery *query,
gboolean use_start,
time64 stt,
gboolean use_end,
time64 ett,
QofQueryOp op)
{
ASSERT_TRUE(queryPool.query_used(query));
((QofFakeQuery*)query)->add_date_match_tt(use_start, stt, use_end, ett, op);
}
void
xaccQueryAddSingleAccountMatch(QofQuery *query, Account *acc, QofQueryOp op)
{
ASSERT_TRUE(queryPool.query_used(query));
((QofFakeQuery*)query)->add_single_account_match(acc, op);
}
} // extern "C"
GList *
qof_query_run (QofQuery *query)
{
GList *matching_objects = NULL;
bool query_used = queryPool.query_used(query);
EXPECT_TRUE(query_used);
if (query_used)
{
auto matchingObjects = ((QofFakeQuery*)query)->run();
for (auto object : matchingObjects)
{
matching_objects = g_list_append(matching_objects, static_cast<gpointer>(object));
}
}
return matching_objects;
}

View File

@@ -0,0 +1,71 @@
/**
* @file fake-qofquery.h
*
* @brief Mocking qof queries
*/
#ifndef FAKE_QOFQUERY_H
#define FAKE_QOFQUERY_H
#include <gmock/gmock.h>
#include <qofquery.h>
extern "C"
{
#include <Query.h>
}
/** Fake object providing functionality similar to QofQuery
*
* @note QofQuery is a @c typedef for @c struct _QofQuery, which is not
* public. Therefore class QofFakeQuery is not derived from QofQuery.
*
* To use a QofFakeQuery object simply create it before the GnuCash code
* performs a query. Check that the QofFakeQuery object is created with the
* correct object type. Also define all expectations and return values on the
* created QofFakeQuery object before the GnuCash code performs the query.
*
* After the query is finished, the QofFakeQuery object can be destroyed. A
* QofFakeQuery object can only be used once.
*
* Internally each created QofFakeQuery object is registered at a
* QofFakeQueryPool, which provides it to the GnuCash code on request. This
* pool observes the life-cycle of each QofFakeQuery object. The following
* steps are expected to be done on each QofFakeQuery object in the
* specified order:
* -# create QofFakeQuery object (test application)
* -# call qof_query_create_for() (GnuCash code)
* -# call qof_query_run() (GnuCash code)
* -# call qof_query_destroy() (GnuCash code)
* -# destroy QofFakeQuery object (test application)
*
* The calls to qof_query_create_for(), qof_query_run() and qof_query_destroy()
* are optional, but
* - qof_query_create_for() and qof_query_destroy() have to be called in
* pairs
* - if qof_query_run() is called, qof_query_create_for() has to be called
* before as well
*
* Several GTest assertions are implemented to signal violations of the
* QofFakeQuery object life-cycle.
*
* @note If you want to check, that a certain query is run by the GnuCash code,
* then define the appropriate expectations on the QofFakeQuery object in your
* test application.
*/
class QofFakeQuery
{
public:
QofFakeQuery(QofIdTypeConst obj_type);
~QofFakeQuery();
MOCK_METHOD1(set_book, void(QofBook*));
MOCK_METHOD5(add_date_match_tt, void(gboolean, time64, gboolean, time64, QofQueryOp));
MOCK_METHOD2(add_single_account_match, void(Account*, QofQueryOp));
MOCK_METHOD0(run, std::vector<void*>());
QofIdTypeConst m_obj_type;
};
#endif

View File

@@ -9,54 +9,63 @@ struct _MockAccountClass
};
typedef struct _MockAccountClass MockAccountClass;
G_DEFINE_TYPE(MockAccount, gnc_mock_account, QOF_TYPE_INSTANCE);
G_DEFINE_TYPE(MockAccount, gnc_mockaccount, QOF_TYPE_INSTANCE);
static void
gnc_mock_account_init (MockAccount *inst)
gnc_mockaccount_init (MockAccount *inst)
{
// function is unused, initialization is done in the MockAccount's constructor
// function is unused, initialization is done in the MockAccount's C++ constructor
}
static void
gnc_mock_account_class_init(MockAccountClass *klass)
gnc_mockaccount_class_init(MockAccountClass *klass)
{
// function is unused, class functions are defined in C++ code
}
GType gnc_account_get_type(void)
{
return gnc_mockaccount_get_type();
}
void
xaccAccountBeginEdit (Account *account)
{
g_return_if_fail(GNC_IS_MOCK_ACCOUNT(account));
((MockAccount*)account)->beginEdit();
ASSERT_TRUE(GNC_IS_MOCKACCOUNT(account));
gnc_mockaccount(account)->begin_edit();
}
void
xaccAccountCommitEdit (Account *account)
{
g_return_if_fail(GNC_IS_MOCK_ACCOUNT(account));
((MockAccount*)account)->commitEdit();
ASSERT_TRUE(GNC_IS_MOCKACCOUNT(account));
gnc_mockaccount(account)->commit_edit();
}
QofBook *
gnc_account_get_book(const Account *account)
{
g_return_val_if_fail(GNC_IS_MOCK_ACCOUNT(account), NULL);
return ((MockAccount*)account)->getBook();
SCOPED_TRACE("");
auto mockaccount = gnc_mockaccount(account);
return mockaccount ? mockaccount->get_book() : nullptr;
}
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);
SCOPED_TRACE("");
auto mockaccount = gnc_mockaccount(acc);
return mockaccount ? mockaccount->for_each_transaction(proc, data) : 0;
}
GncImportMatchMap *
gnc_account_imap_create_imap (Account *acc)
{
g_return_val_if_fail(GNC_IS_MOCK_ACCOUNT(acc), NULL);
return ((MockAccount*)acc)->imapCreateImap();
SCOPED_TRACE("");
auto mockaccount = gnc_mockaccount(acc);
return mockaccount ? mockaccount->create_imap() : nullptr;
}
Account*
@@ -65,7 +74,7 @@ gnc_account_imap_find_account (
const char* category,
const char *key)
{
return ((GncMockImportMatchMap*)imap)->findAccount(category, key);
return ((GncMockImportMatchMap*)imap)->find_account(category, key);
}
void
@@ -75,8 +84,7 @@ gnc_account_imap_add_account (
const char *key,
Account *acc)
{
// not used at the moment
((GncMockImportMatchMap*)imap)->addAccount(category, key, acc);
((GncMockImportMatchMap*)imap)->add_account(category, key, acc);
}
Account*
@@ -84,15 +92,14 @@ 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;
std::vector<const char*> tokenVec;
for (auto token = tokens; token; token = token->next)
{
tokenVec.push_back(static_cast <char const *> (token->data));
}
return ((GncMockImportMatchMap*)imap)->findAccountBayes(tokenVec);
return ((GncMockImportMatchMap*)imap)->find_account_bayes(tokenVec);
}
void
@@ -101,14 +108,13 @@ gnc_account_imap_add_account_bayes (
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;
std::vector<const char*> tokenVec;
for (auto token = tokens; token; token = token->next)
{
tokenVec.push_back(static_cast <char const *> (token->data));
}
((GncMockImportMatchMap*)imap)->addAccountBayes(tokenVec, acc);
((GncMockImportMatchMap*)imap)->add_account_bayes(tokenVec, acc);
}

View File

@@ -5,25 +5,28 @@
#include <Account.h>
#include <AccountP.h>
#include <qofbook.h>
#include "gmock-qofbook.h"
#include "gmock-gobject.h"
GType gnc_mock_account_get_type(void);
GType gnc_mockaccount_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))
#define GNC_TYPE_MOCKACCOUNT (gnc_mockaccount_get_type ())
#define GNC_IS_MOCKACCOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_MOCKACCOUNT))
// mock up for Account
class MockAccount : public Account
{
public:
/* note: don't use default constructor instead of empty constructor, since
* it does zero initialization, which would overwrite GObject
* initialization, which is already done in the new operator. */
MockAccount() {}
void* operator new(size_t size)
{
return mock_g_object_new (GNC_TYPE_MOCK_ACCOUNT, NULL, size);
return mock_g_object_new (GNC_TYPE_MOCKACCOUNT, NULL, size);
}
// define separate free() function since destructor is protected
@@ -36,34 +39,53 @@ public:
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*());
MOCK_METHOD0(begin_edit, void());
MOCK_METHOD0(commit_edit, void());
MOCK_CONST_METHOD0(get_book, QofBook*());
MOCK_CONST_METHOD2(for_each_transaction, gint(TransactionCallback, void*));
MOCK_METHOD0(create_imap, 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.
/* 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() {}
};
// mock up for GncImportMatchMap
class GncMockImportMatchMap : public GncImportMatchMap
{
public:
GncMockImportMatchMap(MockAccount* account)
{
g_return_if_fail(GNC_IS_MOCK_ACCOUNT(account));
acc = account;
book = account->getBook();
book = account->get_book();
};
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*));
MOCK_METHOD2(find_account, Account *(const char*, const char*));
MOCK_METHOD3(add_account, void(const char*, const char*, Account*));
MOCK_METHOD1(find_account_bayes, Account *(std::vector<const char*>&));
MOCK_METHOD2(add_account_bayes, void(std::vector<const char*>&, Account*));
};
// type conversion functions
static inline MockAccount*
gnc_mockaccount (Account *account)
{
if (GNC_IS_MOCKACCOUNT(account))
return static_cast<MockAccount*>(account);
ADD_FAILURE() << "Expected 'account' to be of type 'MockAccount'";
return nullptr;
}
static inline const MockAccount*
gnc_mockaccount (const Account *account)
{
if (GNC_IS_MOCKACCOUNT(account))
return static_cast<const MockAccount*>(account);
ADD_FAILURE() << "Expected 'account' to be of type 'MockAccount'";
return nullptr;
}
#endif

View File

@@ -1,9 +1,10 @@
#include <config.h>
#include <Transaction.h>
#include <Account.h>
#include "gmock-Split.h"
#include "gmock-qofbook.h"
#include "gmock-Account.h"
#include "gmock-Transaction.h"
struct _MockSplitClass
@@ -12,131 +13,146 @@ struct _MockSplitClass
};
typedef struct _MockSplitClass MockSplitClass;
G_DEFINE_TYPE(MockSplit, gnc_mock_split, QOF_TYPE_INSTANCE);
G_DEFINE_TYPE(MockSplit, gnc_mocksplit, QOF_TYPE_INSTANCE);
static void
gnc_mock_split_init (MockSplit *inst)
gnc_mocksplit_init (MockSplit *inst)
{
// function is unused since it's overwritten by MockSplit's constructor anyway
// function is unused, initialization is done in the MockSplit's C++ constructor
}
static void
gnc_mock_split_class_init (MockSplitClass *klass)
gnc_mocksplit_class_init (MockSplitClass *klass)
{
// function is unused, class functions are defined in C++ code
}
GType gnc_split_get_type(void)
{
return gnc_mocksplit_get_type();
}
Split *
xaccMallocSplit (QofBook *book)
{
g_return_val_if_fail(QOF_IS_MOCK_BOOK(book), NULL);
return ((QofMockBook*)book)->mallocSplit();
SCOPED_TRACE("");
QofMockBook* mockbook = qof_mockbook(book);
return mockbook ? mockbook->malloc_split() : nullptr;
}
QofBook *
xaccSplitGetBook (const Split *split)
{
g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
return ((MockSplit*)split)->getBook();
SCOPED_TRACE("");
auto mocksplit = gnc_mocksplit(split);
return mocksplit ? mocksplit->get_book() : nullptr;
}
Account *
xaccSplitGetAccount (const Split *split)
{
g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
return ((MockSplit*)split)->getAccount();
SCOPED_TRACE("");
auto mocksplit = gnc_mocksplit(split);
return mocksplit ? mocksplit->get_account() : nullptr;
}
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);
ASSERT_TRUE(GNC_IS_MOCKSPLIT(split));
ASSERT_TRUE(GNC_IS_ACCOUNT(acc));
gnc_mocksplit(split)->set_account(acc);
}
gnc_numeric
xaccSplitGetAmount (const Split *split)
{
g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), gnc_numeric_zero());
return ((MockSplit*)split)->getAmount();
SCOPED_TRACE("");
auto mocksplit = gnc_mocksplit(split);
return mocksplit ? mocksplit->get_amount() : gnc_numeric_zero();
}
void
xaccSplitSetAmount (Split *split, gnc_numeric amt)
{
g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
((MockSplit*)split)->setAmount(amt);
ASSERT_TRUE(GNC_IS_MOCKSPLIT(split));
gnc_mocksplit(split)->set_amount(amt);
}
gnc_numeric
xaccSplitGetValue (const Split *split)
{
g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), gnc_numeric_zero());
return ((MockSplit*)split)->getValue();
SCOPED_TRACE("");
auto mocksplit = gnc_mocksplit(split);
return mocksplit ? mocksplit->get_value() : gnc_numeric_zero();
}
void
xaccSplitSetValue (Split *split, gnc_numeric val)
{
g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
((MockSplit*)split)->setValue(val);
ASSERT_TRUE(GNC_IS_MOCKSPLIT(split));
gnc_mocksplit(split)->set_value(val);
}
const char *
xaccSplitGetMemo (const Split *split)
{
g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
return ((MockSplit*)split)->getMemo();
SCOPED_TRACE("");
auto mocksplit = gnc_mocksplit(split);
return mocksplit ? mocksplit->get_memo() : "";
}
char
xaccSplitGetReconcile (const Split *split)
{
g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), VREC);
return ((MockSplit*)split)->getReconcile();
SCOPED_TRACE("");
auto mocksplit = gnc_mocksplit(split);
return mocksplit ? mocksplit->get_reconcile() : VREC;
}
void
xaccSplitSetReconcile (Split *split, char recn)
{
g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
((MockSplit*)split)->setReconcile(recn);
ASSERT_TRUE(GNC_IS_MOCKSPLIT(split));
gnc_mocksplit(split)->set_reconcile(recn);
}
void
xaccSplitSetDateReconciledSecs (Split *split, time64 secs)
{
g_return_if_fail(GNC_IS_MOCK_SPLIT(split));
((MockSplit*)split)->setDateReconciledSecs(secs);
ASSERT_TRUE(GNC_IS_MOCKSPLIT(split));
gnc_mocksplit(split)->set_date_reconciled_secs(secs);
}
const char *
xaccSplitGetAction (const Split *split)
{
g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
return ((MockSplit*)split)->getAction();
SCOPED_TRACE("");
auto mocksplit = gnc_mocksplit(split);
return mocksplit ? mocksplit->get_action() : "";
}
Split *
xaccSplitGetOtherSplit (const Split *split)
{
g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
return ((MockSplit*)split)->getOtherSplit();
SCOPED_TRACE("");
auto mocksplit = gnc_mocksplit(split);
return mocksplit ? mocksplit->get_other_split() : nullptr;
}
Transaction *
xaccSplitGetParent (const Split *split)
{
g_return_val_if_fail(GNC_IS_MOCK_SPLIT(split), NULL);
return ((MockSplit*)split)->getParent();
SCOPED_TRACE("");
auto mocksplit = gnc_mocksplit(split);
return mocksplit ? mocksplit->get_parent() : nullptr;
}
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);
ASSERT_TRUE(GNC_IS_MOCKSPLIT(split));
ASSERT_TRUE(GNC_IS_TRANSACTION(trans));
gnc_mocksplit(split)->set_parent(trans);
}

View File

@@ -4,16 +4,19 @@
#include <gmock/gmock.h>
#include <Split.h>
extern "C"
{
#include <SplitP.h>
}
#include "gmock-qofbook.h"
#include "gmock-gobject.h"
GType gnc_mock_split_get_type(void);
GType gnc_mocksplit_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))
#define GNC_TYPE_MOCKSPLIT (gnc_mocksplit_get_type ())
#define GNC_IS_MOCKSPLIT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_MOCKSPLIT))
// mock up for Split
@@ -46,7 +49,7 @@ public:
}
void* operator new(size_t size)
{
return mock_g_object_new (GNC_TYPE_MOCK_SPLIT, NULL, size);
return mock_g_object_new (GNC_TYPE_MOCKSPLIT, NULL, size);
}
// define separate free() function since destructor is protected
@@ -60,21 +63,21 @@ public:
}
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*));
MOCK_CONST_METHOD0(get_book, QofBook *());
MOCK_CONST_METHOD0(get_account, Account *());
MOCK_METHOD1(set_account, void(Account*));
MOCK_CONST_METHOD0(get_amount, gnc_numeric());
MOCK_METHOD1(set_amount, void(gnc_numeric));
MOCK_CONST_METHOD0(get_value, gnc_numeric());
MOCK_METHOD1(set_value, void(gnc_numeric));
MOCK_CONST_METHOD0(get_memo, const char *());
MOCK_CONST_METHOD0(get_reconcile, char());
MOCK_METHOD1(set_reconcile, void(char));
MOCK_METHOD1(set_date_reconciled_secs, void(time64));
MOCK_CONST_METHOD0(get_action, const char *());
MOCK_CONST_METHOD0(get_other_split, Split *());
MOCK_CONST_METHOD0(get_parent, Transaction *());
MOCK_METHOD1(set_parent, void(Transaction*));
protected:
// Protect destructor to avoid MockSplit objects to be created on stack. MockSplit
@@ -82,4 +85,24 @@ protected:
~MockSplit() {}
};
// type conversion functions
static inline MockSplit*
gnc_mocksplit (Split *split)
{
if (GNC_IS_MOCKSPLIT(split))
return static_cast<MockSplit*>(split);
ADD_FAILURE() << "Expected 'split' to be of type 'MockSplit'";
return nullptr;
}
static inline const MockSplit*
gnc_mocksplit (const Split *split)
{
if (GNC_IS_MOCKSPLIT(split))
return static_cast<const MockSplit*>(split);
ADD_FAILURE() << "Expected 'split' to be of type 'MockSplit'";
return nullptr;
}
#endif

View File

@@ -1,7 +1,8 @@
#include <config.h>
#include <Account.h>
#include "gmock-Transaction.h"
#include "gmock-Account.h"
struct _MockTransactionClass
@@ -10,123 +11,136 @@ struct _MockTransactionClass
};
typedef struct _MockTransactionClass MockTransactionClass;
G_DEFINE_TYPE(MockTransaction, gnc_mock_transaction, QOF_TYPE_INSTANCE);
G_DEFINE_TYPE(MockTransaction, gnc_mocktransaction, QOF_TYPE_INSTANCE);
static void
gnc_mock_transaction_init (MockTransaction *inst)
gnc_mocktransaction_init (MockTransaction *inst)
{
// function is unused, initialization is done in the MockTransaction's constructor
// function is unused, initialization is done in the MockTransaction's C++ constructor
}
static void
gnc_mock_transaction_class_init(MockTransactionClass *klass)
gnc_mocktransaction_class_init(MockTransactionClass *klass)
{
// function is unused, class functions are defined in C++ code
}
GType gnc_transaction_get_type(void)
{
return gnc_mocktransaction_get_type();
}
void
xaccTransBeginEdit (Transaction *trans)
{
g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
((MockTransaction*)trans)->beginEdit();
ASSERT_TRUE(GNC_IS_MOCKTRANSACTION(trans));
gnc_mocktransaction(trans)->begin_edit();
}
void
xaccTransCommitEdit (Transaction *trans)
{
g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
((MockTransaction*)trans)->commitEdit();
ASSERT_TRUE(GNC_IS_MOCKTRANSACTION(trans));
gnc_mocktransaction(trans)->commit_edit();
}
Split *
xaccTransGetSplit (const Transaction *trans, int i)
{
g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
return ((MockTransaction*)trans)->getSplit(i);
SCOPED_TRACE("");
auto mocktrans = gnc_mocktransaction(trans);
return mocktrans ? mocktrans->get_split(i) : nullptr;
}
SplitList *
xaccTransGetSplitList (const Transaction *trans)
{
g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
return trans ? ((MockTransaction*)trans)->getSplitList() : NULL;
g_return_val_if_fail(GNC_IS_MOCKTRANSACTION(trans), NULL);
return trans ? ((MockTransaction*)trans)->get_split_list() : NULL;
}
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);
SCOPED_TRACE("");
auto mocktrans = gnc_mocktransaction(trans);
EXPECT_TRUE(GNC_IS_ACCOUNT(acc));
return mocktrans ? mocktrans->find_split_by_account(acc) : nullptr;
}
time64
xaccTransGetDate (const Transaction *trans)
{
g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), 0);
return ((MockTransaction*)trans)->getDate();
SCOPED_TRACE("");
auto mocktrans = gnc_mocktransaction(trans);
return mocktrans ? mocktrans->get_date() : 0;
}
void
xaccTransSetDatePostedSecsNormalized (Transaction *trans, time64 time)
{
g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
((MockTransaction*)trans)->setDatePostedSecsNormalized(time);
ASSERT_TRUE(GNC_IS_MOCKTRANSACTION(trans));
gnc_mocktransaction(trans)->set_date_posted_secs_normalized(time);
}
const char *
xaccTransGetDescription (const Transaction *trans)
{
g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
return ((MockTransaction*)trans)->getDescription();
SCOPED_TRACE("");
auto mocktrans = gnc_mocktransaction(trans);
return mocktrans ? mocktrans->get_description() : "";
}
void
xaccTransSetDescription (Transaction *trans, const char *desc)
{
g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
((MockTransaction*)trans)->setDescription(desc);
ASSERT_TRUE(GNC_IS_MOCKTRANSACTION(trans));
gnc_mocktransaction(trans)->set_description(desc);
}
const char *
xaccTransGetNotes (const Transaction *trans)
{
g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
return ((MockTransaction*)trans)->getNotes();
SCOPED_TRACE("");
auto mocktrans = gnc_mocktransaction(trans);
return mocktrans ? mocktrans->get_notes() : "";
}
void
xaccTransSetNotes (Transaction *trans, const char *notes)
{
g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
((MockTransaction*)trans)->setDescription(notes);
ASSERT_TRUE(GNC_IS_MOCKTRANSACTION(trans));
gnc_mocktransaction(trans)->set_notes(notes);
}
gnc_numeric
xaccTransGetImbalanceValue (const Transaction * trans)
{
g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), gnc_numeric_zero());
return ((MockTransaction*)trans)->getImbalanceValue();
SCOPED_TRACE("");
auto mocktrans = gnc_mocktransaction(trans);
return mocktrans ? mocktrans->get_imbalance_value() : gnc_numeric_zero();
}
const char *
xaccTransGetNum (const Transaction *trans)
{
g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), NULL);
return ((MockTransaction*)trans)->getNum();
SCOPED_TRACE("");
auto mocktrans = gnc_mocktransaction(trans);
return mocktrans ? mocktrans->get_num() : "";
}
gboolean
xaccTransIsOpen (const Transaction *trans)
{
g_return_val_if_fail(GNC_IS_MOCK_TRANSACTION(trans), FALSE);
return ((MockTransaction*)trans)->isOpen();
SCOPED_TRACE("");
auto mocktrans = gnc_mocktransaction(trans);
return mocktrans ? mocktrans->is_open() : FALSE;
}
void
xaccTransDestroy (Transaction *trans)
{
g_return_if_fail(GNC_IS_MOCK_TRANSACTION(trans));
((MockTransaction*)trans)->destroy();
ASSERT_TRUE(GNC_IS_MOCKTRANSACTION(trans));
gnc_mocktransaction(trans)->destroy();
}

View File

@@ -4,16 +4,18 @@
#include <gmock/gmock.h>
#include <Transaction.h>
extern "C"
{
#include <TransactionP.h>
}
#include "gmock-qofbook.h"
#include "gmock-gobject.h"
GType gnc_mock_transaction_get_type(void);
GType gnc_mocktransaction_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))
#define GNC_TYPE_MOCKTRANSACTION (gnc_mocktransaction_get_type ())
#define GNC_IS_MOCKTRANSACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_MOCKTRANSACTION))
// mock up for Transaction
@@ -36,7 +38,7 @@ public:
}
void* operator new(size_t size)
{
return mock_g_object_new (GNC_TYPE_MOCK_TRANSACTION, NULL, size);
return mock_g_object_new (GNC_TYPE_MOCKTRANSACTION, NULL, size);
}
// define separate free() function since destructor is protected
@@ -49,20 +51,20 @@ public:
mock_g_object_unref(trans, size);
}
MOCK_METHOD0(beginEdit, void());
MOCK_METHOD0(commitEdit, void());
MOCK_METHOD1(getSplit, Split *(int));
MOCK_METHOD0(getSplitList, SplitList *());
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(begin_edit, void());
MOCK_METHOD0(commit_edit, void());
MOCK_CONST_METHOD1(get_split, Split *(int));
MOCK_CONST_METHOD0(get_split_list, GList*());
MOCK_CONST_METHOD1(find_split_by_account, Split *(const Account*));
MOCK_CONST_METHOD0(get_date, time64());
MOCK_METHOD1(set_date_posted_secs_normalized, void(time64));
MOCK_CONST_METHOD0(get_description, const char *());
MOCK_METHOD1(set_description, void(const char*));
MOCK_CONST_METHOD0(get_notes, const char *());
MOCK_METHOD1(set_notes, void(const char*));
MOCK_CONST_METHOD0(get_imbalance_value, gnc_numeric());
MOCK_CONST_METHOD0(get_num, const char *());
MOCK_CONST_METHOD0(is_open, gboolean());
MOCK_METHOD0(destroy, void());
protected:
@@ -71,4 +73,24 @@ protected:
~MockTransaction() {}
};
// type conversion functions
static inline MockTransaction*
gnc_mocktransaction (Transaction *trans)
{
if (GNC_IS_MOCKTRANSACTION(trans))
return static_cast<MockTransaction*>(trans);
ADD_FAILURE() << "Expected 'trans' to be of type 'MockTransaction'";
return nullptr;
}
static inline const MockTransaction*
gnc_mocktransaction (const Transaction *trans)
{
if (GNC_IS_MOCKTRANSACTION(trans))
return static_cast<const MockTransaction*>(trans);
ADD_FAILURE() << "Expected 'trans' to be of type 'MockTransaction'";
return nullptr;
}
#endif

View File

@@ -2,6 +2,7 @@
#define GMOCK_GOBJECT_H
#include <glib.h>
#include <glib-object.h>
static gpointer
mock_g_object_new (GType object_type, const gchar *first_property_name, size_t size)

View File

@@ -6,24 +6,31 @@ struct _QofMockBookClass
};
typedef struct _QofMockBookClass QofMockBookClass;
G_DEFINE_TYPE(QofMockBook, qof_mock_book, QOF_TYPE_INSTANCE);
G_DEFINE_TYPE(QofMockBook, qof_mockbook, QOF_TYPE_INSTANCE);
static void
qof_mock_book_init (QofMockBook *inst)
qof_mockbook_init (QofMockBook *inst)
{
// function is unused, initialization is done in the QofMockBook's constructor
// function is unused, initialization is done in the QofMockBook's C++ constructor
}
static void
qof_mock_book_class_init(QofMockBookClass *klass)
qof_mockbook_class_init(QofMockBookClass *klass)
{
// function is unused, class functions are defined in C++ code
}
GType qof_book_get_type(void)
{
return qof_mockbook_get_type();
}
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();
SCOPED_TRACE("");
auto mockbook = qof_mockbook(book);
return mockbook ? mockbook->use_split_action_for_num_field() : FALSE;
}

View File

@@ -5,15 +5,15 @@
#include <qofbook.h>
#include <qofbook-p.h>
#include <Split.h>
#include "gmock-gobject.h"
#include "gmock-Split.h"
GType qof_mock_book_get_type(void);
GType qof_mockbook_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))
#define QOF_TYPE_MOCKBOOK (qof_mockbook_get_type ())
#define QOF_IS_MOCKBOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), QOF_TYPE_MOCKBOOK))
// mock up for QofBook
@@ -37,7 +37,7 @@ public:
}
void* operator new(size_t size)
{
return mock_g_object_new (QOF_TYPE_MOCK_BOOK, NULL, size);
return mock_g_object_new (QOF_TYPE_MOCKBOOK, NULL, size);
}
// define separate free() function since destructor is protected
@@ -50,8 +50,8 @@ public:
mock_g_object_unref(book, size);
}
MOCK_METHOD0(mallocSplit, Split *());
MOCK_METHOD0(useSplitActionForNumField, gboolean());
MOCK_METHOD0(malloc_split, Split *());
MOCK_CONST_METHOD0(use_split_action_for_num_field, gboolean());
protected:
// Protect destructor to avoid MockQofBook objects to be created on stack. MockQofBook
@@ -59,4 +59,25 @@ protected:
~QofMockBook() {}
};
// type conversion functions
static inline QofMockBook*
qof_mockbook (QofBook *book)
{
if (QOF_IS_MOCKBOOK(book))
return static_cast<QofMockBook*>(book);
ADD_FAILURE() << "Expected 'book' to be of type 'QofMockBook'";
return nullptr;
}
static inline const QofMockBook*
qof_mockbook (const QofBook *book)
{
if (QOF_IS_MOCKBOOK(book))
return static_cast<const QofMockBook*>(book);
ADD_FAILURE() << "Expected 'book' to be of type 'QofMockBook'";
return nullptr;
}
#endif

View File

@@ -1,5 +1,7 @@
#include <glib.h>
#include <gmock/gmock.h>
extern "C"
{
#include <qofinstance.h>
@@ -21,12 +23,14 @@ qof_instance_class_init(QofInstanceClass *klass)
// function is unused, class functions are defined in C++ code
}
extern "C"
{
// 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));
ASSERT_TRUE (QOF_IS_INSTANCE (inst));
va_start (ap, first_prop);
g_object_get_valist (G_OBJECT (inst), first_prop, ap);
@@ -34,15 +38,16 @@ qof_instance_get (const QofInstance *inst, const gchar *first_prop, ...)
}
// This is a reimplementation of the function from qofinstance.cpp
// with calling qof_instance_set_dirty()
// without 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));
ASSERT_TRUE (QOF_IS_INSTANCE (inst));
va_start (ap, first_prop);
g_object_set_valist (G_OBJECT (inst), first_prop, ap);
va_end (ap);
}
} // extern "C"

View File

@@ -1,68 +0,0 @@
#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();
}

View File

@@ -1,46 +0,0 @@
#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