mirror of
https://github.com/Gnucash/gnucash.git
synced 2026-09-03 20:53:02 -05:00
Update dbi tests - more object types are now saved and loaded
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18958 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include "test-dbi-stuff.h"
|
||||
|
||||
#include "Account.h"
|
||||
#include "Transaction.h"
|
||||
#include "Split.h"
|
||||
#include "gnc-commodity.h"
|
||||
|
||||
@@ -43,16 +44,26 @@ create_session(void)
|
||||
QofSession* session = qof_session_new();
|
||||
QofBook* book = qof_session_get_book( session );
|
||||
Account* root = gnc_book_get_root_account( book );
|
||||
Account* a;
|
||||
Account* acct1;
|
||||
Account* acct2;
|
||||
KvpFrame* frame;
|
||||
Transaction* tx;
|
||||
Split* spl1;
|
||||
Split* spl2;
|
||||
Timespec ts;
|
||||
struct timeval tv;
|
||||
gnc_commodity_table* table;
|
||||
gnc_commodity* currency;
|
||||
|
||||
table = gnc_commodity_table_get_table( book );
|
||||
currency = gnc_commodity_table_lookup( table, GNC_COMMODITY_NS_CURRENCY, "CAD" );
|
||||
|
||||
a = xaccMallocAccount( book );
|
||||
xaccAccountSetType( a, ACCT_TYPE_BANK );
|
||||
xaccAccountSetName( a, "Bank" );
|
||||
acct1 = xaccMallocAccount( book );
|
||||
xaccAccountSetType( acct1, ACCT_TYPE_BANK );
|
||||
xaccAccountSetName( acct1, "Bank 1" );
|
||||
xaccAccountSetCommodity( acct1, currency );
|
||||
|
||||
frame = qof_instance_get_slots( QOF_INSTANCE(a) );
|
||||
frame = qof_instance_get_slots( QOF_INSTANCE(acct1) );
|
||||
kvp_frame_set_gint64( frame, "int64-val", 100 );
|
||||
kvp_frame_set_double( frame, "double-val", 3.14159 );
|
||||
kvp_frame_set_numeric( frame, "numeric-val", gnc_numeric_zero() );
|
||||
@@ -64,9 +75,23 @@ create_session(void)
|
||||
kvp_frame_set_timespec( frame, "timespec-val", ts );
|
||||
|
||||
kvp_frame_set_string( frame, "string-val", "abcdefghijklmnop" );
|
||||
kvp_frame_set_guid( frame, "guid-val", qof_instance_get_guid( QOF_INSTANCE(a) ) );
|
||||
kvp_frame_set_guid( frame, "guid-val", qof_instance_get_guid( QOF_INSTANCE(acct1) ) );
|
||||
|
||||
gnc_account_append_child( root, acct1 );
|
||||
|
||||
acct2 = xaccMallocAccount( book );
|
||||
xaccAccountSetType( acct2, ACCT_TYPE_BANK );
|
||||
xaccAccountSetName( acct2, "Bank 1" );
|
||||
|
||||
tx = xaccMallocTransaction( book );
|
||||
xaccTransBeginEdit( tx );
|
||||
xaccTransSetCurrency( tx, currency );
|
||||
spl1 = xaccMallocSplit( book );
|
||||
xaccTransAppendSplit( tx, spl1 );
|
||||
spl2 = xaccMallocSplit( book );
|
||||
xaccTransAppendSplit( tx, spl2 );
|
||||
xaccTransCommitEdit( tx );
|
||||
|
||||
gnc_account_append_child( root, a );
|
||||
|
||||
return session;
|
||||
}
|
||||
@@ -85,6 +110,7 @@ int main (int argc, char ** argv)
|
||||
filename = tempnam( "/tmp", "test-sqlite3-" );
|
||||
printf( "Using filename: %s\n", filename );
|
||||
test_dbi_store_and_reload( "sqlite3", session_1, filename );
|
||||
#if 0
|
||||
printf( "TEST_MYSQL_URL='%s'\n", TEST_MYSQL_URL );
|
||||
if ( strlen( TEST_MYSQL_URL ) > 0 )
|
||||
{
|
||||
@@ -97,6 +123,7 @@ int main (int argc, char ** argv)
|
||||
session_1 = create_session();
|
||||
test_dbi_store_and_reload( "pgsql", session_1, TEST_PGSQL_URL );
|
||||
}
|
||||
#endif
|
||||
print_test_results();
|
||||
qof_close();
|
||||
exit(get_rv());
|
||||
|
||||
@@ -32,11 +32,340 @@
|
||||
|
||||
#include "Account.h"
|
||||
#include "Split.h"
|
||||
#include "Transaction.h"
|
||||
#include "gnc-commodity.h"
|
||||
|
||||
static gboolean testAccountEqual(const Account *aa, const Account *ab, gboolean check_guids);
|
||||
static QofLogModule log_module = "test-dbi";
|
||||
|
||||
static gboolean testTransEqual(const Transaction *ta, const Transaction *tb,
|
||||
gboolean check_guids, gboolean check_splits,
|
||||
gboolean check_balances, gboolean assume_ordered);
|
||||
static gboolean test_commodity_equal(const gnc_commodity * a, const gnc_commodity * b);
|
||||
|
||||
/*
|
||||
* Helper routine for testSplitEqual.
|
||||
*/
|
||||
static gboolean
|
||||
testSplitEqualCheckBal (const char *tag, gnc_numeric a, gnc_numeric b)
|
||||
{
|
||||
char *str_a, *str_b;
|
||||
|
||||
if (gnc_numeric_equal (a, b))
|
||||
return TRUE;
|
||||
|
||||
str_a = gnc_numeric_to_string (a);
|
||||
str_b = gnc_numeric_to_string (b);
|
||||
|
||||
PWARN ("%sbalances differ: %s vs %s", tag, str_a, str_b);
|
||||
|
||||
g_free (str_a);
|
||||
g_free (str_b);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
testSplitEqual(const Split *sa, const Split *sb,
|
||||
gboolean check_guids,
|
||||
gboolean check_balances,
|
||||
gboolean check_txn_splits)
|
||||
{
|
||||
Timespec ts1, ts2;
|
||||
|
||||
if (!sa && !sb) return TRUE; /* Arguable. FALSE is better, methinks */
|
||||
|
||||
if (!sa || !sb)
|
||||
{
|
||||
PWARN ("one is NULL");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sa == sb) return TRUE;
|
||||
|
||||
if (check_guids)
|
||||
{
|
||||
if (qof_instance_guid_compare(sa, sb) != 0)
|
||||
{
|
||||
PWARN ("GUIDs differ");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Since these strings are cached we can just use pointer equality */
|
||||
if (strcmp(xaccSplitGetMemo(sa), xaccSplitGetMemo(sb)) != 0)
|
||||
{
|
||||
const gchar* memo_a = xaccSplitGetMemo(sa);
|
||||
const gchar* memo_b = xaccSplitGetMemo(sb);
|
||||
|
||||
PWARN ("memos differ: (%p)%s vs (%p)%s",
|
||||
memo_a, memo_a, memo_b, memo_b);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (strcmp(xaccSplitGetAction(sa), xaccSplitGetAction(sb)) != 0)
|
||||
{
|
||||
PWARN ("actions differ: %s vs %s", xaccSplitGetAction(sa), xaccSplitGetAction(sb));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (kvp_frame_compare(qof_instance_get_slots(QOF_INSTANCE(sa)), qof_instance_get_slots(QOF_INSTANCE(sb))) != 0)
|
||||
{
|
||||
char *frame_a;
|
||||
char *frame_b;
|
||||
|
||||
frame_a = kvp_frame_to_string (qof_instance_get_slots(QOF_INSTANCE(sa)));
|
||||
frame_b = kvp_frame_to_string (qof_instance_get_slots(QOF_INSTANCE(sb)));
|
||||
|
||||
PWARN ("kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
|
||||
|
||||
g_free (frame_a);
|
||||
g_free (frame_b);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (xaccSplitGetReconcile(sa) != xaccSplitGetReconcile(sb))
|
||||
{
|
||||
PWARN ("reconcile flags differ: %c vs %c", xaccSplitGetReconcile(sa), xaccSplitGetReconcile(sb));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ts1 = xaccSplitRetDateReconciledTS(sa);
|
||||
ts2 = xaccSplitRetDateReconciledTS(sb);
|
||||
if (timespec_cmp(&ts1, &ts2))
|
||||
{
|
||||
PWARN ("reconciled date differs");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gnc_numeric_eq(xaccSplitGetAmount (sa), xaccSplitGetAmount (sb)))
|
||||
{
|
||||
char *str_a;
|
||||
char *str_b;
|
||||
|
||||
str_a = gnc_numeric_to_string (xaccSplitGetAmount (sa));
|
||||
str_b = gnc_numeric_to_string (xaccSplitGetAmount (sb));
|
||||
|
||||
PWARN ("amounts differ: %s vs %s", str_a, str_b);
|
||||
|
||||
g_free (str_a);
|
||||
g_free (str_b);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gnc_numeric_eq(xaccSplitGetValue (sa), xaccSplitGetValue (sb)))
|
||||
{
|
||||
char *str_a;
|
||||
char *str_b;
|
||||
|
||||
str_a = gnc_numeric_to_string (xaccSplitGetValue (sa));
|
||||
str_b = gnc_numeric_to_string (xaccSplitGetValue (sb));
|
||||
|
||||
PWARN ("values differ: %s vs %s", str_a, str_b);
|
||||
|
||||
g_free (str_a);
|
||||
g_free (str_b);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (check_balances)
|
||||
{
|
||||
gnc_numeric bal1, bal2;
|
||||
|
||||
bal1 = xaccSplitGetBalance(sa);
|
||||
bal2 = xaccSplitGetBalance(sb);
|
||||
if (!testSplitEqualCheckBal ("", bal1, bal2))
|
||||
return FALSE;
|
||||
bal1 = xaccSplitGetClearedBalance(sa);
|
||||
bal2 = xaccSplitGetClearedBalance(sb);
|
||||
if (!testSplitEqualCheckBal ("cleared ", bal1, bal2))
|
||||
return FALSE;
|
||||
bal1 = xaccSplitGetReconciledBalance(sa);
|
||||
bal2 = xaccSplitGetReconciledBalance(sb);
|
||||
if (!testSplitEqualCheckBal ("reconciled ", bal1, bal2))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!testTransEqual(xaccSplitGetParent(sa), xaccSplitGetParent(sb), check_guids, check_txn_splits,
|
||||
check_balances, FALSE))
|
||||
{
|
||||
PWARN ("transactions differ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_split_guids (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const Split *sa = a;
|
||||
const Split *sb = b;
|
||||
|
||||
if (sa == sb) return 0;
|
||||
if (!sa || !sb) return 1;
|
||||
|
||||
return guid_compare (xaccSplitGetGUID (sa), xaccSplitGetGUID (sb));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
testTransEqual(const Transaction *ta, const Transaction *tb,
|
||||
gboolean check_guids,
|
||||
gboolean check_splits,
|
||||
gboolean check_balances,
|
||||
gboolean assume_ordered)
|
||||
{
|
||||
Timespec ts1, ts2;
|
||||
|
||||
if (!ta && !tb) return TRUE; /* Arguable. FALSE may be better. */
|
||||
|
||||
if (!ta || !tb)
|
||||
{
|
||||
PWARN ("one is NULL");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ta == tb) return TRUE;
|
||||
|
||||
if (check_guids)
|
||||
{
|
||||
if (qof_instance_guid_compare(ta, tb) != 0)
|
||||
{
|
||||
PWARN ("GUIDs differ");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_commodity_equal(xaccTransGetCurrency(ta), xaccTransGetCurrency(tb)))
|
||||
{
|
||||
PWARN ("commodities differ %s vs %s",
|
||||
gnc_commodity_get_unique_name (xaccTransGetCurrency(ta)),
|
||||
gnc_commodity_get_unique_name (xaccTransGetCurrency(tb)));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ts1 = xaccTransRetDateEnteredTS(ta);
|
||||
ts2 = xaccTransRetDateEnteredTS(tb);
|
||||
ts1.tv_nsec = ts2.tv_nsec = 0;
|
||||
if (timespec_cmp(&ts1, &ts2))
|
||||
{
|
||||
char buf1[100];
|
||||
char buf2[100];
|
||||
|
||||
(void)gnc_timespec_to_iso8601_buff(ts1, buf1);
|
||||
(void)gnc_timespec_to_iso8601_buff(ts2, buf2);
|
||||
PWARN ("date entered differs: '%s' vs '%s'", buf1, buf2);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ts1 = xaccTransRetDatePostedTS(ta);
|
||||
ts2 = xaccTransRetDatePostedTS(tb);
|
||||
ts1.tv_nsec = ts2.tv_nsec = 0;
|
||||
if (timespec_cmp(&ts1, &ts2))
|
||||
{
|
||||
char buf1[100];
|
||||
char buf2[100];
|
||||
|
||||
(void)gnc_timespec_to_iso8601_buff(ts1, buf1);
|
||||
(void)gnc_timespec_to_iso8601_buff(ts2, buf2);
|
||||
PWARN ("date posted differs: '%s' vs '%s'", buf1, buf2);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (strcmp(xaccTransGetNum(ta), xaccTransGetNum(tb)) != 0)
|
||||
{
|
||||
PWARN ("num differs: %s vs %s", xaccTransGetNum(ta), xaccTransGetNum(tb));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (strcmp(xaccTransGetDescription(ta), xaccTransGetDescription(tb)) != 0)
|
||||
{
|
||||
PWARN ("descriptions differ: %s vs %s", xaccTransGetDescription(ta), xaccTransGetDescription(tb));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (kvp_frame_compare(qof_instance_get_slots(QOF_INSTANCE(ta)), qof_instance_get_slots(QOF_INSTANCE(tb))) != 0)
|
||||
{
|
||||
char *frame_a;
|
||||
char *frame_b;
|
||||
|
||||
frame_a = kvp_frame_to_string (qof_instance_get_slots(QOF_INSTANCE(ta)));
|
||||
frame_b = kvp_frame_to_string (qof_instance_get_slots(QOF_INSTANCE(tb)));
|
||||
|
||||
PWARN ("kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
|
||||
|
||||
g_free (frame_a);
|
||||
g_free (frame_b);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (check_splits)
|
||||
{
|
||||
GList* splits1;
|
||||
GList* splits2;
|
||||
|
||||
splits1 = xaccTransGetSplitList(ta);
|
||||
splits2 = xaccTransGetSplitList(tb);
|
||||
if ((!splits1 && splits2) || (!splits2 && splits1))
|
||||
{
|
||||
PWARN ("only one has splits");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (splits1 && splits2)
|
||||
{
|
||||
GList *node_a, *node_b;
|
||||
|
||||
for (node_a = splits1, node_b = splits2;
|
||||
node_a;
|
||||
node_a = node_a->next, node_b = node_b->next)
|
||||
{
|
||||
Split *split_a = node_a->data;
|
||||
Split *split_b;
|
||||
|
||||
/* don't presume that the splits are in the same order */
|
||||
if (!assume_ordered)
|
||||
node_b = g_list_find_custom (splits2, split_a,
|
||||
compare_split_guids);
|
||||
|
||||
if (!node_b)
|
||||
{
|
||||
PWARN ("first has split %s and second does not",
|
||||
guid_to_string (xaccSplitGetGUID (split_a)));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
split_b = node_b->data;
|
||||
|
||||
if (!testSplitEqual (split_a, split_b, check_guids, check_balances,
|
||||
FALSE))
|
||||
{
|
||||
char str_a[GUID_ENCODING_LENGTH+1];
|
||||
char str_b[GUID_ENCODING_LENGTH+1];
|
||||
|
||||
guid_to_string_buff (xaccSplitGetGUID (split_a), str_a);
|
||||
guid_to_string_buff (xaccSplitGetGUID (split_b), str_b);
|
||||
|
||||
PWARN ("splits %s and %s differ", str_a, str_b);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_list_length (splits1) != g_list_length (splits2))
|
||||
{
|
||||
PWARN ("different number of splits");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test_commodity_equal(const gnc_commodity * a, const gnc_commodity * b)
|
||||
{
|
||||
@@ -318,7 +647,7 @@ testAccountEqual(const Account *aa, const Account *ab, gboolean check_guids)
|
||||
Split *sa = (Split *) la->data;
|
||||
Split *sb = (Split *) lb->data;
|
||||
|
||||
if (!xaccSplitEqual(sa, sb, check_guids, TRUE, FALSE))
|
||||
if (!testSplitEqual(sa, sb, check_guids, TRUE, FALSE))
|
||||
{
|
||||
PWARN ("splits differ");
|
||||
return(FALSE);
|
||||
@@ -354,19 +683,104 @@ compare_accounts( QofBook* book_1, QofBook* book_2 )
|
||||
do_test( testAccountEqual( root_1, root_2, TRUE ), "Accounts trees match" );
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
QofBook* book_1;
|
||||
QofBook* book_2;
|
||||
gboolean result;
|
||||
} CompareInfoStruct;
|
||||
|
||||
static void
|
||||
compare_pricedbs( QofBook* book_1, QofBook* book_2 )
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
compare_single_tx( QofInstance* inst, gpointer user_data )
|
||||
{
|
||||
CompareInfoStruct* info = (CompareInfoStruct*)user_data;
|
||||
Transaction* tx_1 = GNC_TRANS(inst);
|
||||
Transaction* tx_2 = xaccTransLookup( qof_instance_get_guid(inst), info->book_2 );
|
||||
|
||||
if (!testTransEqual( tx_1, tx_2, TRUE, TRUE, TRUE, FALSE ))
|
||||
{
|
||||
info->result = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
compare_txs( QofBook* book_1, QofBook* book_2 )
|
||||
{
|
||||
CompareInfoStruct info;
|
||||
QofCollection* coll;
|
||||
|
||||
coll = qof_book_get_collection( book_1, GNC_ID_TRANS );
|
||||
info.book_1 = book_1;
|
||||
info.book_2 = book_2;
|
||||
info.result = TRUE;
|
||||
qof_collection_foreach(coll, compare_single_tx, &info);
|
||||
|
||||
do_test( info.result, "Transaction lists match" );
|
||||
}
|
||||
|
||||
static void
|
||||
compare_single_sx( QofInstance* inst, gpointer user_data )
|
||||
{
|
||||
#if 0
|
||||
CompareInfoStruct* info = (CompareInfoStruct*)user_data;
|
||||
Transaction* tx_1 = GNC_TRANS(inst);
|
||||
Transaction* tx_2 = xaccTransLookup( qof_instance_get_guid(inst), info->book_2 );
|
||||
|
||||
if (!testTransEqual( tx_1, tx_2, TRUE, TRUE, TRUE, FALSE ))
|
||||
{
|
||||
info->result = FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
compare_sxs( QofBook* book_1, QofBook* book_2 )
|
||||
{
|
||||
QofCollection* coll;
|
||||
CompareInfoStruct info;
|
||||
|
||||
coll = qof_book_get_collection( book_1, GNC_ID_SCHEDXACTION );
|
||||
info.book_1 = book_1;
|
||||
info.book_2 = book_2;
|
||||
info.result = TRUE;
|
||||
qof_collection_foreach(coll, compare_single_sx, &info);
|
||||
|
||||
do_test( info.result, "Scheduled transaction lists match" );
|
||||
}
|
||||
|
||||
static void
|
||||
compare_single_lot( QofInstance* inst, gpointer user_data )
|
||||
{
|
||||
#if 0
|
||||
CompareInfoStruct* info = (CompareInfoStruct*)user_data;
|
||||
Transaction* tx_1 = GNC_TRANS(inst);
|
||||
Transaction* tx_2 = xaccTransLookup( qof_instance_get_guid(inst), info->book_2 );
|
||||
|
||||
if (!testTransEqual( tx_1, tx_2, TRUE, TRUE, TRUE, FALSE ))
|
||||
{
|
||||
info->result = FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
compare_lots( QofBook* book_1, QofBook* book_2 )
|
||||
{
|
||||
QofCollection* coll;
|
||||
CompareInfoStruct info;
|
||||
|
||||
coll = qof_book_get_collection( book_1, GNC_ID_LOT );
|
||||
info.book_1 = book_1;
|
||||
info.book_2 = book_2;
|
||||
info.result = TRUE;
|
||||
qof_collection_foreach(coll, compare_single_sx, &info);
|
||||
|
||||
do_test( info.result, "Lot lists match" );
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -376,6 +790,7 @@ compare_books( QofBook* book_1, QofBook* book_2 )
|
||||
compare_pricedbs( book_1, book_2 );
|
||||
compare_txs( book_1, book_2 );
|
||||
compare_sxs( book_1, book_2 );
|
||||
compare_lots( book_1, book_2 );
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/***************************************************************************
|
||||
* test-dbi.c
|
||||
*
|
||||
* Tests saving and loading to a dbi/sqlite3 db
|
||||
* Tests saving and loading to a dbi/sqlite3 db. The contents of an XML
|
||||
* file are read and saved to sqlite3, then the results read back and compared.
|
||||
*
|
||||
* Copyright (C) 2009 Phil Longstaff <plongstaff@rogers.com>
|
||||
****************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user