1 /********************************************************************
2  * utest-Account.c: GLib g_test test suite for Account.c.	    *
3  * Copyright 2011 John Ralls <jralls@ceridwen.us>		    *
4  *                                                                  *
5  * This program is free software; you can redistribute it and/or    *
6  * modify it under the terms of the GNU General Public License as   *
7  * published by the Free Software Foundation; either version 2 of   *
8  * the License, or (at your option) any later version.              *
9  *                                                                  *
10  * This program is distributed in the hope that it will be useful,  *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
13  * GNU General Public License for more details.                     *
14  *                                                                  *
15  * You should have received a copy of the GNU General Public License*
16  * along with this program; if not, contact:                        *
17  *                                                                  *
18  * Free Software Foundation           Voice:  +1-617-542-5942       *
19  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
20  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
21  ********************************************************************/
22 #include <glib.h>
23 
24 extern "C"
25 {
26 #include <config.h>
27 #include <string.h>
28 #include <unittest-support.h>
29 #include <gnc-event.h>
30 #include <gnc-date.h>
31 /* Add specific headers for this class */
32 #include "gnc-glib-utils.h"
33 #include "../Account.h"
34 #include "../AccountP.h"
35 #include "../Split.h"
36 #include "../Transaction.h"
37 #include "../gnc-lot.h"
38 
39 #if defined(__clang__) && (__clang_major__ == 5 || (__clang_major__ == 3 && __clang_minor__ < 5))
40 #define USE_CLANG_FUNC_SIG 1
41 #endif
42 static const gchar *suitename = "/engine/Account";
43 void test_suite_account (void);
44 }
45 
46 #include <qofinstance-p.h>
47 #include <kvp-frame.hpp>
48 
49 typedef struct
50 {
51     Account *acct;
52     AccountTestFunctions *func;
53 } Fixture;
54 
55 typedef struct
56 {
57     GNCAccountType type;
58     const char *name;
59     const char *parent;
60     const char *code;
61     const char *desc;
62     const char *color;
63     const char *notes;
64     const char *num;
65     GNCPolicy *policy;
66 } AccountParms;
67 
68 typedef struct
69 {
70     const char *memo;
71     const char *account;
72     char reconciled;
73     gnc_numeric amount;
74     gnc_numeric value;
75     guint lotnum;
76 } SplitParms;
77 
78 typedef struct
79 {
80     const char *desc;
81     gint date_offset;
82     SplitParms splits[2];
83 } TxnParms;
84 
85 typedef struct
86 {
87     guint num_accounts;
88     AccountParms **accounts;
89     guint num_txns;
90     TxnParms **txns;
91 } SetupData;
92 
93 static AccountParms bad_names[] =
94 {
95     {ACCT_TYPE_NONE, "foo:bar", "", "", "", "", "", "", NULL},
96     {ACCT_TYPE_NONE, "baz", "", "", "", "", "", "", NULL},
97     {ACCT_TYPE_NONE, "waldo:pepper", "", "", "", "", "", "", NULL}
98 };
99 
100 static AccountParms good_names[] =
101 {
102     {ACCT_TYPE_NONE, "foo", "", "", "", "", "", "", NULL},
103     {ACCT_TYPE_NONE, "baz", "foo", "", "", "", "", "", NULL},
104     {ACCT_TYPE_NONE, "waldo", "baz", "", "", "", "", "", NULL}
105 };
106 
107 static SetupData bad_data = {3, (AccountParms**)(&bad_names), 0, NULL};
108 static SetupData good_data = {3, (AccountParms**)(&good_names), 0, NULL};
109 
110 static AccountParms some_names[] =
111 {
112     {ACCT_TYPE_NONE, "foo", "root", "", "", "", "", "", NULL},
113     {ACCT_TYPE_NONE, "baz", "foo", "", "", "", "", "", NULL},
114     {ACCT_TYPE_NONE, "bar", "root", "", "", "", "", "", NULL},
115     {ACCT_TYPE_NONE, "meh", "bar", "", "", "", "", "", NULL},
116 
117 };
118 
119 static TxnParms some_txns[] =
120 {
121     {
122         "waldo", -9, {
123             {"waldo_baz", "baz", NREC, { -150000, 100}, {0, 1}, 0},
124             {"waldo_meh", "meh", NREC, {150000, 100}, {0, 1}, 0}
125         }
126     },
127     {
128         "pepper", -7, {
129             {"pepper_baz", "baz", CREC, { -12345, 100}, {0, 1}, 0},
130             {"pepper_meh", "meh", CREC, {12345, 100}, {0, 1}, 0}
131         }
132     },
133     {
134         "salt", -2, {
135             {"salt_baz", "baz", YREC, { -31415, 100}, {0, 1}, 0},
136             {"salt_meh", "meh", YREC, {31415, 100}, {0, 1}, 0}
137         }
138     },
139     {
140         "pork", 3, {
141             {"pork_baz", "baz", YREC, {23746, 100}, {0, 1}, 0},
142             {"pork_meh", "meh", YREC, { -23746, 100}, {0, 1}, 0}
143         }
144     },
145     {
146         "sausage", 5, {
147             {"sausage_baz", "baz", NREC, { -1143, 100}, {0, 1}, 0},
148             {"sausage_meh", "meh", NREC, {1143, 100}, {0, 1}, 0}
149         }
150     }
151 };
152 
153 static SetupData some_data = {4, (AccountParms**)(&some_names),
154                               5, (TxnParms**)(&some_txns)
155                              };
156 
157 static AccountParms complex_accts[] =
158 {
159     {ACCT_TYPE_EXPENSE, "expense", "root", "3000", "", "", "", "", NULL},
160     {ACCT_TYPE_EXPENSE, "ordinary", "expense", "3100", "", "", "", NULL},
161     {ACCT_TYPE_EXPENSE, "deductible", "expense", "3200", "", "", "", NULL},
162     {ACCT_TYPE_INCOME, "income", "root", "4000", "", "", "", "", NULL},
163     {ACCT_TYPE_INCOME, "taxable", "income", "4100", "", "", "", "", NULL},
164     {ACCT_TYPE_INCOME, "exempt", "income", "4200", "", "", "", "", NULL},
165     {ACCT_TYPE_INCOME, "wage", "taxable", "4150", "", "", "", "", NULL},
166     {ACCT_TYPE_INCOME, "div", "taxable", "4140", "", "", "", "", NULL},
167     {ACCT_TYPE_INCOME, "div1", "taxable", "4140", "", "", "", "", NULL},
168     {ACCT_TYPE_INCOME, "qdiv", "div1", "4141", "", "", "", "", NULL},
169     {ACCT_TYPE_INCOME, "odiv", "div1", "4142", "", "", "", "", NULL},
170     {ACCT_TYPE_INCOME, "int", "taxable", "4160", "", "", "", "", NULL},
171     {ACCT_TYPE_INCOME, "ltcg", "taxable", "4120", "", "", "", "", NULL},
172     {ACCT_TYPE_INCOME, "stcg", "taxable", "4110", "", "", "", "", NULL},
173     {ACCT_TYPE_INCOME, "int", "exempt", "4210", "", "", "", "", NULL},
174     {ACCT_TYPE_INCOME, "div", "exempt", "4230", "", "", "", "", NULL},
175     {ACCT_TYPE_INCOME, "gift", "exempt", "4220", "", "", "", "", NULL},
176     {ACCT_TYPE_ASSET, "assets", "root", "2000", "", "", "", "", NULL},
177     {ACCT_TYPE_BANK, "bank", "assets", "2300", "", "", "", "", NULL},
178     {ACCT_TYPE_ASSET, "broker", "assets", "2200", "", "", NULL},
179     {ACCT_TYPE_BANK, "money", "broker", "2210", "", "", NULL},
180     {ACCT_TYPE_STOCK, "stocks", "broker", "2220", "", "", NULL},
181     {ACCT_TYPE_EXPENSE, "food", "ordinary", "3110", "", "", "", NULL},
182     {ACCT_TYPE_EXPENSE, "utilities", "ordinary", "3150", "", "", "", NULL},
183     {ACCT_TYPE_EXPENSE, "auto", "ordinary", "3120", "", "", "", NULL},
184     {ACCT_TYPE_EXPENSE, "mortgage-int", "deductible", "3230", "", "", "", NULL},
185     {ACCT_TYPE_EXPENSE, "medical", "deductible", "3220", "", "", "", NULL},
186     {ACCT_TYPE_STOCK, "foo", "stocks", "2221", "", "", NULL},
187     {ACCT_TYPE_STOCK, "bar", "stocks", "2222", "", "", NULL},
188     /* Note the repetition of the stock account "baz". The variations are
189      * used to test gnc_account_merge_children. */
190     {ACCT_TYPE_STOCK, "baz", "stocks", "2223", "baz", "", NULL},
191     {ACCT_TYPE_STOCK, "baz2", "stocks", "2223", "baz", "", NULL},
192     {ACCT_TYPE_MUTUAL, "baz", "stocks", "2223", "baz", "", NULL},
193     {ACCT_TYPE_STOCK, "baz", "stocks", "2223", "baz company", "", NULL},
194     {ACCT_TYPE_STOCK, "baz", "stocks", "2224", "baz", "", NULL},
195 
196 };
197 
198 static TxnParms lot_txns[] =
199 {
200     {
201         "funding", -12, {
202             {"funding_money", "money", NREC, {1000000, 100}, {0, 1}, 0},
203             {"funding_gift", "gift", NREC, {1000000, 100}, {0, 1}, 0}
204         }
205     },
206     {
207         "waldo", -9, {
208             {"waldo_baz", "baz", NREC, {1500, 1}, {150899, 100}, 1},
209             {"waldo_money", "money", NREC, { -150899, 100}, {0, 1}, 0}
210         }
211     },
212     {
213         "pepper", -7, {
214             {"pepper_baz", "baz", CREC, { -500, 1}, { -69101, 100}, 1},
215             {"pepper_money", "money", CREC, {69101, 100}, {0, 1}, 0}
216         }
217     },
218     {
219         "salt", -2, {
220             {"salt_baz", "baz", YREC, {1000, 1}, {120899, 10}, 2},
221             {"salt_money", "money", YREC, { -120899, 100}, {0, 1}, 0}
222         }
223     },
224     {
225         "pork", 3, {
226             {"pork_baz", "baz", YREC, { -1000, 1}, { -79101, 100}, 1},
227             {"pork_money", "money", YREC, {79101, 100}, {0, 1}, 0}
228         }
229     },
230     {
231         "sausage", 5, {
232             {"sausage_baz", "baz", NREC, { -500, 1}, { -74101, 100}, 2},
233             {"sausage_mmoney", "money", NREC, {74101, 100}, {0, 1}, 0}
234         }
235     },
236     {
237         "pork", 3, {
238             {"pork_baz2", "baz2", YREC, { -1000, 1}, { -79101, 100}, 1},
239             {"pork_money", "money", YREC, {79101, 100}, {0, 1}, 0}
240         }
241     },
242     {
243         "sausage", 5, {
244             {"sausage_baz2", "baz2", NREC, { -500, 1}, { -74101, 100}, 2},
245             {"sausage_mmoney", "money", NREC, {74101, 100}, {0, 1}, 0}
246         }
247     },
248     {
249         "links", 1, {
250             {"links_baz", "baz", NREC, {500, 1}, {60899, 100}, 3},
251             {"links_mmoney", "money", NREC, { -60899, 100}, {0, 1}, 0}
252         }
253     }
254 };
255 
256 static SetupData complex = {G_N_ELEMENTS (complex_accts),
257                             (AccountParms**)(&complex_accts), 0, NULL
258                            };
259 
260 static SetupData complex_data = {G_N_ELEMENTS (complex_accts),
261                                  (AccountParms**)(&complex_accts),
262                                  G_N_ELEMENTS (lot_txns),
263                                  (TxnParms**)(&lot_txns)
264                                 };
265 
266 static Split*
insert_split(Account * parent,Transaction * txn,SplitParms * p)267 insert_split (Account *parent, Transaction *txn, SplitParms *p)
268 {
269     auto book = gnc_account_get_book (parent);
270     auto split = xaccMallocSplit (book);
271     auto acct = gnc_account_lookup_by_name (parent, p->account);
272     auto lotlist = xaccAccountGetLotList (acct);
273     GNCLot* lot = NULL;
274     g_assert (acct != NULL);
275     xaccSplitSetParent (split, txn);
276     xaccSplitSetMemo (split, p->memo);
277     xaccSplitSetReconcile (split, (p->reconciled ? p->reconciled : NREC));
278     g_object_set (split,
279                   "account", acct,
280                   "memo", p->memo,
281                   "amount", &(p->amount),
282                   "value", &(p->value),
283                   NULL);
284 
285     gnc_account_insert_split (acct, split);
286     if (p->lotnum == 0)
287         return split;
288 
289     if (p->lotnum > g_list_length (lotlist))
290         lot = gnc_lot_new (book);
291     else
292         lot = GNC_LOT (g_list_nth_data (lotlist, p->lotnum - 1));
293 
294     gnc_lot_add_split (lot, split);
295     return split;
296 }
297 
298 static void
setup(Fixture * fixture,gconstpointer pData)299 setup (Fixture *fixture, gconstpointer pData)
300 {
301     auto book = qof_book_new ();
302     auto root = gnc_account_create_root (book);
303     auto parms = static_cast<const SetupData*>(pData);
304     TxnParms *t_arr;
305     AccountParms *p_arr;
306     auto accts = g_hash_table_new (g_str_hash, g_str_equal);
307     guint ind;
308 
309     auto root_str = CACHE_INSERT("root");
310     g_hash_table_insert (accts, (gpointer)root_str, root);
311     fixture->func = _utest_account_fill_functions ();
312     if (parms == NULL)
313     {
314         fixture->acct = root;
315         return;
316     }
317     auto acct = root;
318 
319     p_arr  = (AccountParms*)parms->accounts;
320     for (ind = 0; ind < parms->num_accounts; ind++)
321     {
322         auto child = xaccMallocAccount (book);
323         AccountParms p = p_arr[ind];
324         if (p.parent && strlen (p.parent) > 0)
325         {
326             auto parent = static_cast<Account*>(g_hash_table_lookup (accts, p.parent));
327             g_assert (parent != NULL);
328             gnc_account_append_child (parent, child);
329         }
330         else
331             gnc_account_append_child (acct, child);
332         acct = child;
333         xaccAccountSetType (acct, p.type);
334         if (p.name)
335         {
336             xaccAccountSetName (acct, p.name);
337             g_hash_table_insert (accts, const_cast<char*>(p.name), acct);
338         }
339         if (p.code)
340             xaccAccountSetCode (acct, p.code);
341         if (p.desc)
342             xaccAccountSetDescription (acct, p.desc);
343         if (p.color)
344             xaccAccountSetColor (acct, p.color);
345         if (p.notes)
346             xaccAccountSetNotes (acct, p.notes);
347         if (p.num)
348             xaccAccountSetLastNum (acct, p.num);
349         if (p.policy)
350             gnc_account_set_policy (acct, p.policy);
351     }
352 
353     t_arr  = (TxnParms*)parms->txns;
354     for (ind = 0; ind < parms->num_txns; ind++)
355     {
356         Transaction *txn = xaccMallocTransaction (book);
357         TxnParms p = t_arr[ind];
358         GDate *date = g_date_new ();
359         gnc_gdate_set_time64 (date, gnc_time (NULL));
360         xaccTransBeginEdit (txn);
361         if (p.desc)
362             xaccTransSetDescription (txn, p.desc);
363         if (p.date_offset < 0)
364             g_date_subtract_days (date, (guint)(-p.date_offset));
365         else
366             g_date_add_days (date, (guint)(p.date_offset));
367         xaccTransSetDatePostedGDate (txn, *date);
368         insert_split (root, txn, &p.splits[0]);
369         insert_split (root, txn, &p.splits[1]);
370         /* xaccTransCommitEdit () does a bunch of scrubbing that we don't need */
371         qof_commit_edit (QOF_INSTANCE (txn));
372     }
373     fixture->acct = acct;
374     g_hash_table_destroy (accts);
375     gnc_set_account_separator (":");
376 }
377 
378 static void
teardown(Fixture * fixture,gconstpointer pData)379 teardown ( Fixture *fixture, gconstpointer pData)
380 {
381     Account *child = fixture->acct;
382     qof_book_destroy (gnc_account_get_book (child));
383     /* No need to free the last account, qof_book_destroy did that */
384     g_free (fixture->func);
385 }
386 
387 
388 /* gnc_get_account_separator_string
389 const gchar *
390 gnc_get_account_separator_string (void)// C: 31 in 7 SCM: 64 in 6*/
391 //Simple Getter. No Test.
392 /* static void
393 test_gnc_get_account_separator_string (Fixture *fixture, gconstpointer pData)
394 {
395 }*/
396 /* gnc_get_account_separator
397 gunichar
398 gnc_get_account_separator (void)// C: 8 in 4 */
399 //Simple Getter. No Test.
400 /* gnc_set_account_separator
401 void
402 gnc_set_account_separator (const gchar *separator)// C: 5 in 3 */
403 static void
test_gnc_set_account_separator()404 test_gnc_set_account_separator ()
405 {
406     gchar sep_str[6];
407     const gunichar pass_sep = 0xE5A;
408     const gunichar fail_sep = 0x92A;
409     const gunichar default_sep = ':';
410     gunichar sep = gnc_get_account_separator ();
411 
412     g_assert (sep == default_sep);
413     memset (sep_str, 0, sizeof (sep_str));
414     g_unichar_to_utf8 (fail_sep, sep_str);
415     gnc_set_account_separator (sep_str);
416     sep = gnc_get_account_separator ();
417     g_assert (sep != fail_sep);
418     g_assert (sep == default_sep);
419     memset (sep_str, 0, sizeof (sep_str));
420     g_unichar_to_utf8 (pass_sep, sep_str);
421     gnc_set_account_separator (sep_str);
422     sep = gnc_get_account_separator ();
423     g_assert (sep == pass_sep);
424 }
425 /* Note: gnc_account_name_violations and gnc_account_list_name_violations should work with unicode. Change the functions and the tests accordingly. */
426 /* gnc_account_name_violations_errmsg
427 gchar *gnc_account_name_violations_errmsg (const gchar *separator, GList* invalid_account_names)// C: 6 in 4 */
428 static void
test_gnc_account_name_violations_errmsg()429 test_gnc_account_name_violations_errmsg ()
430 {
431     GList *badnames = NULL, *nonames = NULL, *node = NULL;
432     auto separator = ":";
433     /* FUT wants to free the strings, so we alloc them */
434     badnames = g_list_prepend (badnames, g_strdup ("Foo:bar"));
435     badnames = g_list_prepend (badnames, g_strdup ("baz"));
436     badnames = g_list_prepend (badnames, g_strdup ("waldo:pepper"));
437     auto message = gnc_account_name_violations_errmsg (separator, nonames);
438     auto account_list = gnc_g_list_stringjoin (badnames, "\n");
439     message = gnc_account_name_violations_errmsg (separator, nonames);
440     g_assert (message == NULL);
441     auto validation_message = g_strdup_printf (
442         "The separator character \"%s\" is used in one or more account "
443         "names.\n\nThis will result in unexpected behaviour. "
444         "Either change the account names or choose another separator "
445         "character.\n\nBelow you will find the list of invalid account names:\n"
446         "%s", separator, account_list);
447     g_free (account_list);
448     message = gnc_account_name_violations_errmsg (separator, badnames);
449     g_assert_cmpstr ( message, == , validation_message);
450     g_free (validation_message);
451     g_free (message);
452 }
453 /* This should be qof_BOOK_list_name_violations */
454 /* gnc_account_list_name_violations
455 GList *gnc_account_list_name_violations (QofBook *book, const gchar *separator)// C: 6 in 4 */
456 static void
test_gnc_account_list_name_violations(Fixture * fixture,gconstpointer pData)457 test_gnc_account_list_name_violations (Fixture *fixture, gconstpointer pData)
458 {
459     auto log_level = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
460     auto log_domain = "gnc.engine";
461     auto msg = ": assertion 'separator != NULL' failed";
462     auto check = test_error_struct_new(log_domain, log_level, msg);
463     GList *results, *res_iter;
464     auto sep = ":";
465     QofBook *book = gnc_account_get_book (fixture->acct);
466     /* Because of GLib bug 653052, we have to set the logging user_data to
467      * affect the test_log_fatal_handler
468      */
469     GLogFunc oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler, check);
470     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_substring_handler, check);
471     g_assert (gnc_account_list_name_violations (NULL, NULL) == NULL);
472     g_assert_cmpint (check->hits, ==, 1);
473     g_assert (gnc_account_list_name_violations (book, NULL) == NULL);
474     g_assert_cmpint (check->hits, ==, 2);
475     g_assert (gnc_account_list_name_violations (NULL, sep) == NULL);
476     g_log_set_default_handler (oldlogger, NULL);
477     results = gnc_account_list_name_violations (book, sep);
478     g_assert_cmpuint (g_list_length (results), == , 2);
479     g_assert_cmpint (check->hits, ==, 2);
480     for (res_iter = results; res_iter; res_iter = g_list_next (res_iter))
481         test_free (res_iter->data);
482     g_list_free (results);
483 }
484 /* mark_account
485 void
486 mark_account (Account *acc)// C: 2 in 1 */
487 /*Simple passthrough of qof_instance_set_dirty; Don't test.*/
488 // Not Used
489 /* gnc_account_init
490 G_DEFINE_TYPE (Account, gnc_account, QOF_TYPE_INSTANCE)
491 static void
492 gnc_account_init (Account* acc)// 1
493 */
494 /* test_gnc_account_create_and_destroy (void):
495  * Tests the following functions:
496  * gnc_account_init ()
497  * gnc_account_class_init ()
498  * gnc_account_get_property ()
499  * gnc_account_set_property ()
500  * xaccAccountGetColor ()
501  * xaccAccountGetNotes ()
502  *
503  * Exercises the following functions, may not thoroughly test them:
504  * xaccAccountSetName ()
505  * xaccAccountSetCode ()
506  * xaccAccountSetDescription ()
507  * xaccAccountSetColor ()
508  * xaccAccountSetNotes ()
509  * xaccAccountSetType ()
510  * xaccAccountSetCommodity ()
511  * xaccAccountSetCommoditySCU ()
512  * xaccAccountSetNotStdSCU ()
513  * gnc_account_set_sort_dirty ()
514  * gnc_account_set_balance ()
515  * gnc_account_set_start_balance ()
516  * gnc_account_set_start_cleared_balance ()
517  * gnc_account_set_start_reconciled_balance ()
518  * gnc_account_set_policy ()
519  * xaccAccountSetMark () *** Not Used ***
520  * xaccAccountSetTaxRelated ()
521  * xaccAccountSetTaxUSCode ()
522  * xaccAccountSetTaxUSPayerNameSource ()
523  * xaccAccountSetTaxUSCopyNumber ()
524  * xaccAccountSetHidden ()
525  * xaccAccountSetPlaceholder ()
526 
527  * Note very well that this is only the GObject portion of creating
528  * and destroying Account objects. There are other parts (which is a
529  * major problem), see in particular the note at test_xaccFreeAccount.
530  */
531 
532 static void
test_gnc_account_create_and_destroy(void)533 test_gnc_account_create_and_destroy (void)
534 {
535     auto acc = static_cast<Account*>(g_object_new (GNC_TYPE_ACCOUNT, NULL));
536     char *name, *fname, *code, *desc, *color, *notes, *tax_code, *tax_src;
537     GNCAccountType type;
538     gnc_commodity *commo;
539     gint commo_scu, mark;
540     gboolean non_std_scu, sort_dirty, bal_dirty, opening_balance, tax_rel, hide, hold;
541     gint64 copy_num;
542     gnc_numeric *start_bal, *start_clr_bal, *start_rec_bal;
543     gnc_numeric *end_bal, *end_clr_bal, *end_rec_bal;
544     GNCPolicy *pol;
545 
546     g_object_get (acc,
547                   "name", &name,
548                   "fullname", &fname,
549                   "code", &code,
550                   "description", &desc,
551                   "color", &color,
552                   "notes", &notes,
553                   "type", &type,
554                   "commodity", &commo,
555                   "commodity_scu", &commo_scu,
556                   "non-std-scu", &non_std_scu,
557                   "sort-dirty", &sort_dirty,
558                   "balance-dirty", &bal_dirty,
559                   "start-balance", &start_bal,
560                   "start-cleared-balance", &start_clr_bal,
561                   "start-reconciled-balance", &start_rec_bal,
562                   "end-balance", &end_bal,
563                   "end-cleared-balance", &end_clr_bal,
564                   "end-reconciled-balance", &end_rec_bal,
565                   "opening-balance", &opening_balance,
566                   "policy", &pol,
567                   "acct-mark", &mark,
568                   "tax-related", &tax_rel,
569                   "tax-code", &tax_code,
570                   "tax-source", &tax_src,
571                   "tax-copy-number", &copy_num,
572                   "hidden", &hide,
573                   "placeholder", &hold,
574                   NULL);
575 
576     g_assert_cmpstr (name, == , "");
577     g_assert_cmpstr (fname, == , "");
578     g_assert_cmpstr (code, == , "");
579     g_assert_cmpstr (desc, == , "");
580     g_assert (!color);
581     g_assert (!notes);
582     g_assert (type == ACCT_TYPE_NONE);
583     g_assert (!commo);
584     g_assert (!commo_scu);
585     g_assert (!non_std_scu);
586     g_assert (!sort_dirty);
587     g_assert (!bal_dirty);
588     g_assert (gnc_numeric_zero_p (*end_bal));
589     g_assert (gnc_numeric_zero_p (*end_clr_bal));
590     g_assert (gnc_numeric_zero_p (*end_rec_bal));
591     g_assert (gnc_numeric_zero_p (*start_bal));
592     g_assert (gnc_numeric_zero_p (*start_clr_bal));
593     g_assert (gnc_numeric_zero_p (*start_rec_bal));
594     g_assert (!opening_balance);
595     g_assert (pol == xaccGetFIFOPolicy ());
596     g_assert (!mark);
597     g_assert (!tax_rel);
598     g_assert (!tax_code);
599     g_assert (!tax_src);
600     g_assert (copy_num == 1);
601     g_assert (!hide);
602     g_assert (!hold);
603     g_assert (gnc_account_get_parent (acc) == NULL);
604     g_assert (gnc_account_get_children (acc) == NULL);
605     g_assert (xaccAccountGetLotList (acc) == NULL);
606     g_assert (xaccAccountGetSplitList (acc) == NULL);
607     g_free (name);
608     g_free (fname);
609     g_free (code);
610     g_free (desc);
611     g_free (color);
612     g_free (notes);
613     g_free (tax_code);
614     g_free (tax_src);
615     g_free (start_bal);
616     g_free (start_clr_bal);
617     g_free (start_rec_bal);
618     g_free (end_bal);
619     g_free (end_clr_bal);
620     g_free (end_rec_bal);
621 
622     g_object_unref (acc);
623     /* There's no good way to test that the object has been properly
624      * destroyed; on the other hand, that's GObject's job.
625      */
626 
627 }
628 /* xaccInitAccount
629 static void
630 xaccInitAccount (Account * acc, QofBook *book)// 3
631 Simple pass-through for qof_instance_init_data ()
632 */
633 /* gnc_account_get_book
634 QofBook *
635 gnc_account_get_book (const Account *account)// C: 30 in 21 SCM: 8 in 4
636 Simple pass-through for qof_instance_get_book ()
637 */
638 /* gnc_coll_get_root_account
639 static Account *
640 gnc_coll_get_root_account (QofCollection *col)// 3
641 Simple pass-through for qof_collection_get_data ()
642 */
643 
644 /* test_gnc_book_set_get_root_account:
645  * Tests the following:
646  * gnc_coll_set_root_account ()
647  * gnc_coll_get_root_account ()
648  * gnc_book_set_root_account ()
649  * gnc_book_get_root_account ()
650  * Note that the first two are static helper functions which
651  * generalize the second pair -- but in vain, because they're used
652  * only in one place.
653  */
654 static void
test_gnc_book_set_get_root_account(Fixture * fixture,gconstpointer pData)655 test_gnc_book_set_get_root_account (Fixture *fixture, gconstpointer pData)
656 {
657     auto log_level = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
658     auto log_domain = "gnc.account";
659     auto msg = "[gnc_book_set_root_account()] cannot mix and match books freely!";
660     auto check = test_error_struct_new(log_domain, log_level, msg);
661     Account *acc1, *acc2;
662     QofBook* book1 = qof_book_new ();
663     GLogFunc oldlogger;
664     QofBook *book2 = gnc_account_get_book (fixture->acct);
665     acc1 = gnc_book_get_root_account (NULL);
666     g_assert (!acc1);
667     /* Check that an account is created, and that it isn't the same as the
668      * one in fixture.
669      */
670     acc1 = gnc_book_get_root_account (book1);
671     g_assert (acc1);
672     g_assert (acc1 != fixture->acct);
673     /* Now try to set the book's root account to the fixture
674      * account. Should throw an error.
675      */
676     oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler, check);
677     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler,
678                                   check);
679     gnc_book_set_root_account (book1, fixture->acct);
680     g_assert (gnc_book_get_root_account (book1) == acc1);
681     g_assert_cmpint (check->hits, ==, 1);
682     g_log_set_default_handler (oldlogger, NULL);
683     /* Check that if we set the same root, it stays set */
684     gnc_book_set_root_account (book2, fixture->acct);
685     g_assert (gnc_book_get_root_account (book2) == fixture->acct);
686     /* Create a new account in book1 and check that we can set it to root */
687     acc2 = xaccMallocAccount (book1);
688     gnc_book_set_root_account (book1, acc2);
689     g_assert (gnc_book_get_root_account (book1) != acc1);
690     g_assert (gnc_book_get_root_account (book1) == acc2);
691     /* Clean up */
692     /* acc1 gets freed by setting the root account to acc2
693         g_object_unref (acc1);
694     */
695     qof_book_destroy (book1);
696 }
697 
698 /* xaccMallocAccount
699 Account *
700 xaccMallocAccount (QofBook *book)// C: 24 in 17 SCM: 9 in 6*/
701 static void
test_xaccMallocAccount(void)702 test_xaccMallocAccount (void)
703 {
704     QofBook *book = qof_book_new ();
705     Account *acc;
706     TestSignal signal = test_signal_new (NULL, QOF_EVENT_CREATE, NULL);
707     acc = xaccMallocAccount (book);
708     g_assert (acc != NULL);
709     test_signal_assert_hits (signal, 1);
710     test_signal_free (signal);
711     g_object_unref (acc);
712     qof_book_destroy (book);
713 }
714 
715 /* gnc_account_create_root
716 Account *
717 gnc_account_create_root (QofBook *book)// C: 5 in 3 */
718 static void
test_gnc_account_create_root(void)719 test_gnc_account_create_root (void)
720 {
721     QofBook *book = qof_book_new ();
722     QofCollection *coll = qof_book_get_collection (book, GNC_ID_ROOT_ACCOUNT);
723     Account *acc;
724     char *name;
725     AccountTestFunctions *func = _utest_account_fill_functions ();
726     /* Can't use gnc_book_get_root_account, it creates one if it doesn't
727      * yet exist */
728     g_assert (func->coll_get_root_account (coll) == NULL);
729     acc = gnc_account_create_root (book);
730     g_assert (acc);
731     g_object_get (acc, "name", &name, NULL);
732     g_assert_cmpstr (name, == , "Root Account");
733     g_assert (gnc_book_get_root_account (book) == acc);
734     g_object_unref (acc);
735     qof_book_destroy (book);
736     g_free (func);
737     g_free (name);
738 }
739 /* xaccCloneAccountCommon
740 static Account *
741 xaccCloneAccountCommon (const Account *from, QofBook *book)// 3
742 */
743 static void
test_xaccCloneAccount(Fixture * fixture,gconstpointer pData)744 test_xaccCloneAccount (Fixture *fixture, gconstpointer pData)
745 {
746     Account *clone;
747     QofBook *book = gnc_account_get_book (fixture->acct);
748     auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
749     auto msg1 = ": assertion 'GNC_IS_ACCOUNT(from)' failed";
750     auto msg2 = ": assertion 'QOF_IS_BOOK(book)' failed";
751     auto check = test_error_struct_new("gnc.engine", loglevel, msg1);
752     AccountPrivate *acct_p, *clone_p;
753     auto oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler,
754                                                 check);
755     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_substring_handler, check);
756     clone = xaccCloneAccount (NULL, book);
757     g_assert (clone == NULL);
758     g_assert_cmpint (check->hits, ==, 1);
759     g_free(check->msg);
760     check->msg = g_strdup(msg2);
761     clone = xaccCloneAccount (fixture->acct, NULL);
762     g_assert (clone == NULL);
763     g_assert_cmpint (check->hits, ==, 2);
764     g_log_set_default_handler (oldlogger, NULL);
765     /* Now test the real clone */
766     clone = xaccCloneAccount (fixture->acct, book);
767     g_assert (clone);
768     acct_p = fixture->func->get_private (fixture->acct);
769     clone_p = fixture->func->get_private (clone);
770     g_assert (clone_p->type == acct_p->type);
771     g_assert (clone_p->accountName == acct_p->accountName);
772     g_assert (clone_p->accountCode == acct_p->accountCode);
773     g_assert (clone_p->description == acct_p->description);
774     g_assert (compare (clone->inst.kvp_data,
775                        fixture->acct->inst.kvp_data) == 0);
776     g_assert (gnc_commodity_equal (clone_p->commodity, acct_p->commodity));
777     g_assert (clone_p->commodity_scu == acct_p->commodity_scu);
778     g_assert (clone_p->non_standard_scu == acct_p->non_standard_scu);
779     /* Clean Up */
780     test_error_struct_free(check);
781     g_object_unref (clone);
782 
783 }
784 /* xaccFreeOneChildAccount
785 static void
786 xaccFreeOneChildAccount (Account *acc, gpointer dummy)// 2
787 No need to test, it's a passthrough for xaccAccountDestroy
788 */
789 /* xaccFreeAccountChildren
790 static void
791 xaccFreeAccountChildren (Account *acc)// 3
792 */
793 static void
test_xaccFreeAccountChildren(Fixture * fixture,gconstpointer pData)794 test_xaccFreeAccountChildren (Fixture *fixture, gconstpointer pData)
795 {
796     Account *root = gnc_account_get_root (fixture->acct);
797     AccountPrivate *priv = fixture->func->get_private (root);
798     g_assert_cmpuint (g_list_length (priv->children), > , 0);
799     fixture->func->xaccFreeAccountChildren (root);
800     /* We'd like to check for the child actually having been freed, but
801      * there's not good way to do that. */
802     g_assert_cmpuint (g_list_length (priv->children), == , 0);
803     qof_book_destroy (gnc_account_get_book (root));
804     /* No need to unref the root account, qof_book_destroy did that. */
805     g_free (fixture->func);
806 }
807 /* xaccFreeAccount
808 static void
809 xaccFreeAccount (Account *acc)//
810 The approved way to call this is via xaccAccountDestroy-->xaccAccountCommitEdit-->qof_instance_commit_edit2-->acc_free-->xaccFreeAccount
811 
812 Note that none of this is called by gnc_account_dispose, and xaccFreeAccount calls unref on itself. (Not run dispose, unref.)
813 
814 This "works" as follows:
815 xaccAccountDestroy sets a "destroying" flag in qof_instance and calls xaccAccountCommitEdit.
816 xaccAccountCommitEdit checks the flag and finding it true:
817    calls xaccFreeACcountChildren
818    tests qof_book_shutting_down and either deletes the split list for the account (trusting the Transaction code to delete the splits if it is shutting down) or deletes the actual splits while it's clearing the list. (What happens to the references in the transactions then? It's calling xaccSplitDestroy, not g_oject_unref!)
819    Again checking that the book isn't shutting down:
820       run destroy_pending_splits_for_account
821       destroy all of the lots in the lots list (again, destroy, not unref or even dispose)
822   free the lot list (regardless of whether the book is shutting down) and NULL the pointer
823   set the instance dirty
824 unconditionally calls qof_commit_edit_part2 with acc_free
825 qof_commit_edit_part2:
826    calls the backend's commit if there is one
827    calls acc_free
828    calls acc_done (which only fires off a qof_event, so we'll ignore it)
829 acc_free removes the account from the parent if there is one and calls xaccFreeAccount, then calls xaccFreeAccount
830 xaccFreeAccount calls:
831     xaccFreeAccountChildren
832     destroys the lots (unless commitEdit did so already) and NULLs the pointer
833     destroys the splits unless commitEdit did so already
834     removes the name, code, and description strings from the string cache
835     zeroes out the priv structure variables
836     unrefs the account (should call run_dispose).
837 dispose calls parent->dispose.
838 
839 acc_free
840 */
841 /* Aside from being broken (the assert at the end of freeing the splits fails),
842    Account deallocation is implemented wrong. We don't run this test, and the function will be replaced when the time comes. */
843 static void
test_xaccFreeAccount(Fixture * fixture,gconstpointer pData)844 test_xaccFreeAccount (Fixture *fixture, gconstpointer pData)
845 {
846     auto msg1 = "[xaccFreeAccount()]  instead of calling xaccFreeAccount(), please call\n"
847                   " xaccAccountBeginEdit(); xaccAccountDestroy();\n";
848 #ifdef USE_CLANG_FUNC_SIG
849 #define _func "int xaccTransGetSplitIndex(const Transaction *, const Split *)"
850 #else
851 #define _func "xaccTransGetSplitIndex"
852 #endif
853     auto msg2 = _func ": assertion 'trans && split' failed";
854 #undef _func
855     auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
856     auto check1 = test_error_struct_new("gnc.account", loglevel, msg1);
857     auto check2 = test_error_struct_new("gnc.engine", loglevel, msg2);
858     QofBook *book = gnc_account_get_book (fixture->acct);
859     Account *parent = gnc_account_get_parent (fixture->acct);
860     AccountPrivate *p_priv = fixture->func->get_private (parent);
861     const guint numItems = 3;
862     guint i = 0;
863     guint hdlr1, hdlr2;
864     gnc_commodity *commodity = gnc_commodity_new (book, "US Dollar", "CURRENCY", "USD", "0", 100);
865     test_add_error (check1);
866     test_add_error (check2);
867     hdlr1 = g_log_set_handler ("gnc.account", loglevel,
868                                (GLogFunc)test_checked_handler, check1);
869     hdlr2 = g_log_set_handler ("gnc.engine", loglevel,
870                                (GLogFunc)test_checked_handler, check2);
871     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_handler, NULL);
872     for (i = 0; i < numItems; i++)
873     {
874         Split *split = xaccMallocSplit (book);
875         xaccSplitSetAccount (split, parent);
876         gnc_account_insert_split (parent, split);
877         xaccAccountInsertLot (parent, gnc_lot_new (book));
878     }
879     xaccAccountSetCommodity (parent, commodity);
880     /* Check that we've got children, lots, and splits to remove */
881     g_assert (p_priv->children != NULL);
882     g_assert (p_priv->lots != NULL);
883     g_assert (p_priv->splits != NULL);
884     g_assert (p_priv->parent != NULL);
885     g_assert (p_priv->commodity != NULL);
886     g_assert_cmpint (check1->hits, ==, 0);
887     g_assert_cmpint (check2->hits, ==, 0);
888     /* Now set the other private parts to something so that they can be set back */
889     p_priv->cleared_balance = gnc_numeric_create ( 5, 12);
890     p_priv->reconciled_balance = gnc_numeric_create ( 5, 12);
891     p_priv->balance = gnc_numeric_create ( 5, 12);
892     p_priv->balance_dirty = TRUE;
893     p_priv->sort_dirty = TRUE;
894     fixture->func->xaccFreeAccount (parent);
895     g_assert_cmpint (check1->hits, ==, 6);
896     g_assert_cmpint (check2->hits, ==, 6);
897     /* cleanup what's left */
898     g_log_remove_handler ("gnc.account", hdlr1);
899     g_log_remove_handler ("gnc.engine", hdlr2);
900     test_clear_error_list ();
901     qof_book_destroy (book);
902     g_free (fixture->func);
903 }
904 /* xaccAccountBeginEdit
905 void
906 xaccAccountBeginEdit (Account *acc)// C: 80 in 29 SCM: 15 in 9
907 
908 No test, just a passthrough.
909 */
910 /* static void
911 test_xaccAccountBeginEdit (Fixture *fixture, gconstpointer pData)
912 {
913 }*/
914 /* on_done
915 static void on_done (QofInstance *inst)// 2
916 ***Callback for qof_commit_edit_part2
917 No test, just queues a qof event.
918 */
919 /* static void
920 test_on_done (Fixture *fixture, gconstpointer pData)
921 {
922 }*/
923 /* on_err
924 static void on_err (QofInstance *inst, QofBackendError errcode)// 2
925 ***Callback for qof_commit_edit_part2
926 */
927 /* static void
928 test_on_err (Fixture *fixture, gconstpointer pData)
929 No test, just a pass-through.
930 {
931 }*/
932 /* acc_free
933 static void acc_free (QofInstance *inst)// 2
934 ***Callback for qof_commit_edit_part2
935 No test, just a passthrough -- plus see comment at test_xaccFreeAccount, which is what this is a passthrough of.
936 */
937 /* static void
938 test_acc_free (Fixture *fixture, gconstpointer pData)
939 {
940 }*/
941 /* destroy_pending_splits_for_account
942 static void
943 destroy_pending_splits_for_account (QofInstance *ent, gpointer acc)// 2
944 
945 Pass-through, no test.
946 */
947 /* static void
948 test_destroy_pending_splits_for_account (Fixture *fixture, gconstpointer pData)
949 {
950 }*/
951 /* xaccAccountCommitEdit
952 void
953 xaccAccountCommitEdit (Account *acc)// C: 65 in 26 SCM: 11 in 7
954 Also tests:
955   xaccAccountDestroy
956 */
957 static void
test_xaccAccountCommitEdit(Fixture * fixture,gconstpointer pData)958 test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData)
959 {
960     auto msg1 = "[xaccFreeAccount()]  instead of calling xaccFreeAccount(), please call\n"
961                   " xaccAccountBeginEdit(); xaccAccountDestroy();\n";
962 #ifdef USE_CLANG_FUNC_SIG
963 #define _func "int xaccTransGetSplitIndex(const Transaction *, const Split *)"
964 #else
965 #define _func "xaccTransGetSplitIndex"
966 #endif
967     auto msg2 = _func ": assertion 'trans && split' failed";
968 #undef _func
969     auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
970     auto check1 = test_error_struct_new("gnc.account", loglevel, msg1);
971     auto check2 = test_error_struct_new("gnc.engine", loglevel, msg2);
972     guint hdlr1, hdlr2;
973     TestSignal sig1, sig2;
974     QofBook *book = gnc_account_get_book (fixture->acct);
975     Account *parent = gnc_account_get_parent (fixture->acct);
976     AccountPrivate *p_priv = fixture->func->get_private (parent);
977     const guint numItems = 3;
978     guint i = 0;
979     gnc_commodity *commodity = gnc_commodity_new (book, "US Dollar", "CURRENCY", "USD", "0", 100);
980     test_add_error (check1);
981     test_add_error (check2);
982     hdlr1 = g_log_set_handler ("gnc.account", loglevel,
983                                (GLogFunc)test_checked_handler, check1);
984     hdlr2 = g_log_set_handler ("gnc.engine", loglevel,
985                                (GLogFunc)test_checked_handler, check2);
986     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_handler, NULL);
987     for (i = 0; i < numItems; i++)
988     {
989         Split *split = xaccMallocSplit (book);
990         xaccSplitSetAccount (split, parent);
991         gnc_account_insert_split (parent, split);
992         xaccAccountInsertLot (parent, gnc_lot_new (book));
993     }
994     xaccAccountSetCommodity (parent, commodity);
995     /* Check that we've got children, lots, and splits to remove */
996     g_assert (p_priv->children != NULL);
997     g_assert (p_priv->lots != NULL);
998     g_assert (p_priv->splits != NULL);
999     g_assert (p_priv->parent != NULL);
1000     g_assert (p_priv->commodity != NULL);
1001     g_assert_cmpint (check1->hits, ==, 0);
1002     g_assert_cmpint (check2->hits, ==, 0);
1003 
1004     sig1 = test_signal_new (&parent->inst, QOF_EVENT_MODIFY, NULL);
1005     sig2 = test_signal_new (&parent->inst, QOF_EVENT_DESTROY, NULL);
1006     /* Now we're ready to start testing. */
1007     xaccAccountBeginEdit (parent);
1008     xaccAccountCommitEdit (parent);
1009     /* Make sure that the account didn't get destroyed */
1010     test_signal_assert_hits (sig1, 1);
1011     test_signal_assert_hits (sig2, 0);
1012     g_assert (p_priv->children != NULL);
1013     g_assert (p_priv->lots != NULL);
1014     g_assert (p_priv->splits != NULL);
1015     g_assert (p_priv->parent != NULL);
1016     g_assert (p_priv->commodity != NULL);
1017     g_assert_cmpint (check1->hits, ==, 0);
1018     g_assert_cmpint (check2->hits, ==, 0);
1019     /* xaccAccountDestroy destroys the account by calling
1020      * qof_instance_set_destroying (), then xaccAccountCommitEdit ();
1021      */
1022     xaccAccountBeginEdit (parent);
1023     xaccAccountDestroy (parent);
1024     /* So this time we make sure that the account is destroyed */
1025     test_signal_assert_hits (sig1, 2);
1026     test_signal_assert_hits (sig2, 1);
1027     g_assert_cmpint (check1->hits, ==, 2);
1028     g_assert_cmpint (check2->hits, ==, 12);
1029     /* And clean up */
1030     test_signal_free (sig1);
1031     test_signal_free (sig2);
1032     g_log_remove_handler ("gnc.account", hdlr1);
1033     g_log_remove_handler ("gnc.engine", hdlr2);
1034     test_clear_error_list ();
1035     qof_book_destroy (book);
1036     g_free (fixture->func);
1037 }
1038 /* xaccAcctChildrenEqual
1039 static gboolean
1040 xaccAcctChildrenEqual (const GList *na,// 2
1041 */
1042 /* static void
1043 test_xaccAcctChildrenEqual (Fixture *fixture, gconstpointer pData)
1044 {
1045 }*/
1046 /* xaccAccountEqual
1047 gboolean
1048 xaccAccountEqual (const Account *aa, const Account *ab, gboolean check_guids)// C: 8 in 6
1049 Test support only; don't test for now.
1050 */
1051 /* static void
1052 test_xaccAccountEqual (Fixture *fixture, gconstpointer pData)
1053 {
1054 }*/
1055 /*
1056   The following are getters and setters, unworthy of testing:
1057   gnc_account_get_sort_dirty *** Test Only ***
1058   gnc_account_set_sort_dirty
1059   gnc_account_get_balance_dirty *** Test Only ***
1060   gnc_account_set_balance_dirty
1061 */
1062 /* gnc_account_find_split *** Test Only ***
1063  */
1064 /* gnc_account_insert_split
1065 gboolean
1066 gnc_account_insert_split (Account *acc, Split *s)// C: 5 in 3
1067 
1068 Also tests gnc_account_remove_split ()
1069 */
1070 
1071 
1072 static void
test_gnc_account_kvp_setters_getters(Fixture * fixture,gconstpointer pData)1073 test_gnc_account_kvp_setters_getters (Fixture *fixture, gconstpointer pData)
1074 {
1075     Account *account = xaccMallocAccount (gnc_account_get_book (fixture->acct));
1076     xaccAccountSetType (account, ACCT_TYPE_EQUITY);
1077 
1078     // equity_type getter/setter
1079     g_assert (xaccAccountGetIsOpeningBalance (account) == FALSE);
1080 
1081     xaccAccountSetIsOpeningBalance (account, TRUE);
1082     g_assert (xaccAccountGetIsOpeningBalance (account) == TRUE);
1083 
1084     xaccAccountSetIsOpeningBalance (account, FALSE);
1085     g_assert (xaccAccountGetIsOpeningBalance (account) == FALSE);
1086 
1087     // sortreversed getter/setter
1088     g_assert (xaccAccountGetSortReversed (account) == FALSE);
1089 
1090     xaccAccountSetSortReversed (account, TRUE);
1091     g_assert (xaccAccountGetSortReversed (account) == TRUE);
1092 
1093     xaccAccountSetSortReversed (account, FALSE);
1094     g_assert (xaccAccountGetSortReversed (account) == FALSE);
1095 
1096     // color getter/setter
1097     g_assert_cmpstr (xaccAccountGetColor (account), ==, nullptr);
1098 
1099     xaccAccountSetColor (account, "red");
1100     g_assert_cmpstr (xaccAccountGetColor (account), ==, "red");
1101 
1102     xaccAccountSetColor (account, "unset");
1103     g_assert_cmpstr (xaccAccountGetColor (account), ==, "unset");
1104 
1105     xaccAccountSetColor (account, "");
1106     g_assert_cmpstr (xaccAccountGetColor (account), ==, nullptr);
1107 
1108     xaccAccountSetColor (account, nullptr);
1109     g_assert_cmpstr (xaccAccountGetColor (account), ==, nullptr);
1110 
1111     // last_num getter/setter
1112     g_assert_cmpstr (xaccAccountGetLastNum (account), ==, nullptr);
1113 
1114     xaccAccountSetLastNum (account, "red");
1115     g_assert_cmpstr (xaccAccountGetLastNum (account), ==, "red");
1116 
1117     xaccAccountSetLastNum (account, "");
1118     g_assert_cmpstr (xaccAccountGetLastNum (account), ==, "");
1119 
1120     xaccAccountSetLastNum (account, "  ");
1121     g_assert_cmpstr (xaccAccountGetLastNum (account), ==, "  ");
1122 
1123     xaccAccountSetLastNum (account, "unset");
1124     g_assert_cmpstr (xaccAccountGetLastNum (account), ==, "unset");
1125 
1126     xaccAccountSetLastNum (account, nullptr);
1127     g_assert_cmpstr (xaccAccountGetLastNum (account), ==, nullptr);
1128 
1129     // tax_us_code getter/setter
1130     g_assert_cmpstr (xaccAccountGetTaxUSCode (account), ==, nullptr);
1131 
1132     xaccAccountSetTaxUSCode (account, "red");
1133     g_assert_cmpstr (xaccAccountGetTaxUSCode (account), ==, "red");
1134 
1135     xaccAccountSetTaxUSCode (account, "");
1136     g_assert_cmpstr (xaccAccountGetTaxUSCode (account), ==, "");
1137 
1138     xaccAccountSetTaxUSCode (account, "  ");
1139     g_assert_cmpstr (xaccAccountGetTaxUSCode (account), ==, "  ");
1140 
1141     xaccAccountSetTaxUSCode (account, "unset");
1142     g_assert_cmpstr (xaccAccountGetTaxUSCode (account), ==, "unset");
1143 
1144     xaccAccountSetTaxUSCode (account, nullptr);
1145     g_assert_cmpstr (xaccAccountGetTaxUSCode (account), ==, nullptr);
1146 
1147     // tax_us_pns getter/setter
1148     g_assert_cmpstr (xaccAccountGetTaxUSPayerNameSource (account), ==, nullptr);
1149 
1150     xaccAccountSetTaxUSPayerNameSource (account, "red");
1151     g_assert_cmpstr (xaccAccountGetTaxUSPayerNameSource (account), ==, "red");
1152 
1153     xaccAccountSetTaxUSPayerNameSource (account, "");
1154     g_assert_cmpstr (xaccAccountGetTaxUSPayerNameSource (account), ==, "");
1155 
1156     xaccAccountSetTaxUSPayerNameSource (account, "  ");
1157     g_assert_cmpstr (xaccAccountGetTaxUSPayerNameSource (account), ==, "  ");
1158 
1159     xaccAccountSetTaxUSPayerNameSource (account, "unset");
1160     g_assert_cmpstr (xaccAccountGetTaxUSPayerNameSource (account), ==, "unset");
1161 
1162     xaccAccountSetTaxUSPayerNameSource (account, nullptr);
1163     g_assert_cmpstr (xaccAccountGetTaxUSPayerNameSource (account), ==, nullptr);
1164 
1165     // filter getter/setter
1166     g_assert_cmpstr (xaccAccountGetFilter (account), ==, nullptr);
1167 
1168     xaccAccountSetFilter (account, "bla");
1169     g_assert_cmpstr (xaccAccountGetFilter (account), ==, "bla");
1170 
1171     xaccAccountSetFilter (account, "unset");
1172     g_assert_cmpstr (xaccAccountGetFilter (account), ==, "unset");
1173 
1174     xaccAccountSetFilter (account, "   unset ");
1175     g_assert_cmpstr (xaccAccountGetFilter (account), ==, "unset");
1176 
1177     xaccAccountSetFilter (account, "");
1178     g_assert_cmpstr (xaccAccountGetFilter (account), ==, nullptr);
1179 
1180     xaccAccountSetFilter (account, nullptr);
1181     g_assert_cmpstr (xaccAccountGetFilter (account), ==, nullptr);
1182 
1183     // sortOrder getter/setter
1184     g_assert_cmpstr (xaccAccountGetSortOrder (account), ==, nullptr);
1185 
1186     xaccAccountSetSortOrder (account, "boo");
1187     g_assert_cmpstr (xaccAccountGetSortOrder (account), ==, "boo");
1188 
1189     xaccAccountSetSortOrder (account, "unset");
1190     g_assert_cmpstr (xaccAccountGetSortOrder (account), ==, "unset");
1191 
1192     xaccAccountSetSortOrder (account, "  unset ");
1193     g_assert_cmpstr (xaccAccountGetSortOrder (account), ==, "unset");
1194 
1195     xaccAccountSetSortOrder (account, "");
1196     g_assert_cmpstr (xaccAccountGetSortOrder (account), ==, nullptr);
1197 
1198     xaccAccountSetSortOrder (account, nullptr);
1199     g_assert_cmpstr (xaccAccountGetSortOrder (account), ==, nullptr);
1200 
1201     // Notes getter/setter
1202     g_assert_cmpstr (xaccAccountGetNotes (account), ==, nullptr);
1203 
1204     xaccAccountSetNotes (account, "boo");
1205     g_assert_cmpstr (xaccAccountGetNotes (account), ==, "boo");
1206 
1207     xaccAccountSetNotes (account, "unset");
1208     g_assert_cmpstr (xaccAccountGetNotes (account), ==, "unset");
1209 
1210     xaccAccountSetNotes (account, "    unset ");
1211     g_assert_cmpstr (xaccAccountGetNotes (account), ==, "unset");
1212 
1213     xaccAccountSetNotes (account, "");
1214     g_assert_cmpstr (xaccAccountGetNotes (account), ==, nullptr);
1215 
1216     xaccAccountSetNotes (account, nullptr);
1217     g_assert_cmpstr (xaccAccountGetNotes (account), ==, nullptr);
1218 
1219     // STOCK_ACCOUNT tests from now on
1220     xaccAccountSetType (account, ACCT_TYPE_STOCK);
1221 
1222     // dxaccAccountGetPriceSrc getter/setter
1223     g_assert_cmpstr (dxaccAccountGetPriceSrc (account), ==, nullptr);
1224 
1225     dxaccAccountSetPriceSrc (account, "boo");
1226     g_assert_cmpstr (dxaccAccountGetPriceSrc (account), ==, "boo");
1227 
1228     dxaccAccountSetPriceSrc (account, "");
1229     g_assert_cmpstr (dxaccAccountGetPriceSrc (account), ==, "");
1230 
1231     dxaccAccountSetPriceSrc (account, nullptr);
1232     g_assert_cmpstr (dxaccAccountGetPriceSrc (account), ==, nullptr);
1233 
1234     // dxaccAccountGetQuoteTZ getter/setter
1235     g_assert_cmpstr (dxaccAccountGetQuoteTZ (account), ==, nullptr);
1236 
1237     dxaccAccountSetQuoteTZ (account, "boo");
1238     g_assert_cmpstr (dxaccAccountGetQuoteTZ (account), ==, "boo");
1239 
1240     dxaccAccountSetQuoteTZ (account, "");
1241     g_assert_cmpstr (dxaccAccountGetQuoteTZ (account), ==, "");
1242 
1243     dxaccAccountSetQuoteTZ (account, nullptr);
1244     g_assert_cmpstr (dxaccAccountGetQuoteTZ (account), ==, nullptr);
1245 
1246     xaccAccountBeginEdit (account);
1247     xaccAccountDestroy (account);
1248 }
1249 
1250 static void
set_kvp_string_path(Account * acc,std::vector<std::string> const & path,const char * value)1251 set_kvp_string_path (Account *acc, std::vector<std::string> const & path,
1252                      const char *value)
1253 {
1254     xaccAccountBeginEdit(acc);
1255     if (value)
1256     {
1257         GValue v = G_VALUE_INIT;
1258         g_value_init (&v, G_TYPE_STRING);
1259         g_value_set_string (&v, value);
1260         qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, path);
1261         g_value_unset (&v);
1262     }
1263     else
1264         qof_instance_set_path_kvp (QOF_INSTANCE (acc), NULL, path);
1265 
1266     xaccAccountCommitEdit(acc);
1267 }
1268 
1269 static void
test_gnc_account_get_map_entry(Fixture * fixture,gconstpointer pData)1270 test_gnc_account_get_map_entry (Fixture *fixture, gconstpointer pData)
1271 {
1272     Account *account = xaccMallocAccount (gnc_account_get_book (fixture->acct));
1273 
1274     g_assert_cmpstr (gnc_account_get_map_entry (account, "one", NULL), ==, nullptr);
1275     g_assert_cmpstr (gnc_account_get_map_entry (account, "one", "two"), ==, nullptr);
1276 
1277     set_kvp_string_path (account, {"one"}, "uno");
1278     g_assert_cmpstr (gnc_account_get_map_entry (account, "one", NULL), ==, "uno");
1279     g_assert_cmpstr (gnc_account_get_map_entry (account, "one", "two"), ==, nullptr);
1280 
1281     set_kvp_string_path (account, {"one", "two"}, "dos");
1282     g_assert_cmpstr (gnc_account_get_map_entry (account, "one", "tw0"), ==, nullptr);
1283     g_assert_cmpstr (gnc_account_get_map_entry (account, "one", "two"), ==, "dos");
1284 
1285     set_kvp_string_path (account, {"one"}, nullptr);
1286     g_assert_cmpstr (gnc_account_get_map_entry (account, "one", NULL), ==, nullptr);
1287     g_assert_cmpstr (gnc_account_get_map_entry (account, "one", "two"), ==, nullptr);
1288 
1289     set_kvp_string_path (account, {"one", "two"}, "dos");
1290     g_assert_cmpstr (gnc_account_get_map_entry (account, "one", "two"), ==, "dos");
1291 
1292     xaccAccountBeginEdit (account);
1293     xaccAccountDestroy (account);
1294 }
1295 
1296 static void
test_gnc_account_insert_remove_split(Fixture * fixture,gconstpointer pData)1297 test_gnc_account_insert_remove_split (Fixture *fixture, gconstpointer pData)
1298 {
1299     QofBook *book = gnc_account_get_book (fixture->acct);
1300     Split *split1 = xaccMallocSplit (book);
1301     Split *split2 = xaccMallocSplit (book);
1302     Split *split3 = xaccMallocSplit (book);
1303     TestSignal sig1, sig2, sig3;
1304     AccountPrivate *priv = fixture->func->get_private (fixture->acct);
1305     auto msg1 = ": assertion 'GNC_IS_ACCOUNT(acc)' failed";
1306     auto msg2 = ": assertion 'GNC_IS_SPLIT(s)' failed";
1307     auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
1308 //    auto log_domain = "gnc.engine";
1309     auto check1 = test_error_struct_new("gnc.engine", loglevel, msg1);
1310     auto check2 = test_error_struct_new("gnc.engine", loglevel, msg2);
1311     auto check3 = test_error_struct_new("gnc.engine", loglevel, NULL);
1312     guint logger;
1313     sig1 = test_signal_new (&fixture->acct->inst, QOF_EVENT_MODIFY, NULL);
1314     sig2 = test_signal_new (&fixture->acct->inst, GNC_EVENT_ITEM_ADDED, split1);
1315 
1316     test_add_error (check1);
1317     test_add_error (check2);
1318     logger = g_log_set_handler ("gnc.engine", loglevel,
1319                                 (GLogFunc)test_null_handler, check3);
1320     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_substring_handler, NULL);
1321 
1322     /* Check that the call fails with invalid account and split (throws) */
1323     g_assert (!gnc_account_insert_split (NULL, split1));
1324     g_assert_cmpuint (g_list_length (priv->splits), == , 0);
1325     g_assert (!priv->sort_dirty);
1326     g_assert (!priv->balance_dirty);
1327     test_signal_assert_hits (sig1, 0);
1328     test_signal_assert_hits (sig2, 0);
1329     g_assert (!gnc_account_insert_split (fixture->acct, NULL));
1330     g_assert_cmpuint (g_list_length (priv->splits), == , 0);
1331     g_assert (!priv->sort_dirty);
1332     g_assert (!priv->balance_dirty);
1333     test_signal_assert_hits (sig1, 0);
1334     test_signal_assert_hits (sig2, 0);
1335     /* g_assert (!gnc_account_insert_split (fixture->acct, (Split*)priv)); */
1336     /* g_assert_cmpuint (g_list_length (priv->splits), == , 0); */
1337     /* g_assert (!priv->sort_dirty); */
1338     /* g_assert (!priv->balance_dirty); */
1339     /* test_signal_assert_hits (sig1, 0); */
1340     /* test_signal_assert_hits (sig2, 0); */
1341     g_assert_cmpint (check1->hits, ==, 1);
1342     g_assert_cmpint (check2->hits, ==, 1);
1343     g_assert_cmpint (check3->hits, ==, 0);
1344     g_log_remove_handler ("gnc.engine", logger);
1345     test_clear_error_list ();
1346 
1347     /* Check that it works the first time */
1348     g_assert (gnc_account_insert_split (fixture->acct, split1));
1349     g_assert_cmpuint (g_list_length (priv->splits), == , 1);
1350     g_assert (!priv->sort_dirty);
1351     g_assert (priv->balance_dirty);
1352     test_signal_assert_hits (sig1, 1);
1353     test_signal_assert_hits (sig2, 1);
1354     /* Check that it fails if the split has already been added once */
1355     g_assert (!gnc_account_insert_split (fixture->acct, split1));
1356     /* Free up hdlr2 and set up hdlr2 */
1357     test_signal_free (sig2);
1358     sig3 = test_signal_new (&fixture->acct->inst, GNC_EVENT_ITEM_ADDED, split2);
1359     /* Now add a second split to the account and check that sort_dirty isn't set. We have to bump the editlevel to force this. */
1360     g_assert (gnc_account_insert_split (fixture->acct, split2));
1361     g_assert_cmpuint (g_list_length (priv->splits), == , 2);
1362     g_assert (!priv->sort_dirty);
1363     g_assert (priv->balance_dirty);
1364     test_signal_assert_hits (sig1, 2);
1365     test_signal_assert_hits (sig3, 1);
1366     /* One more add, incrementing the editlevel to get sort_dirty set. */
1367     test_signal_free (sig3);
1368     sig3 = test_signal_new (&fixture->acct->inst, GNC_EVENT_ITEM_ADDED, split3);
1369     qof_instance_increase_editlevel (fixture->acct);
1370     g_assert (gnc_account_insert_split (fixture->acct, split3));
1371     qof_instance_decrease_editlevel (fixture->acct);
1372     g_assert_cmpuint (g_list_length (priv->splits), == , 3);
1373     g_assert (priv->sort_dirty);
1374     g_assert (priv->balance_dirty);
1375     test_signal_assert_hits (sig1, 3);
1376     test_signal_assert_hits (sig3, 1);
1377     /* Finally delete a split. It's going to recompute the balance, so
1378      * balance_dirty will be false. */
1379     test_signal_free (sig3);
1380     sig3 = test_signal_new (&fixture->acct->inst, GNC_EVENT_ITEM_REMOVED,
1381                             split3);
1382     g_assert (gnc_account_remove_split (fixture->acct, split3));
1383     g_assert_cmpuint (g_list_length (priv->splits), == , 2);
1384     g_assert (priv->sort_dirty);
1385     g_assert (!priv->balance_dirty);
1386     test_signal_assert_hits (sig1, 4);
1387     test_signal_assert_hits (sig3, 1);
1388     /* And do it again to make sure that it fails when the split has
1389      * already been removed */
1390     g_assert (!gnc_account_remove_split (fixture->acct, split3));
1391     g_assert_cmpuint (g_list_length (priv->splits), == , 2);
1392     g_assert (priv->sort_dirty);
1393     g_assert (!priv->balance_dirty);
1394     test_signal_assert_hits (sig1, 4);
1395     test_signal_assert_hits (sig3, 1);
1396 
1397     /* Clean up the handlers */
1398     test_signal_free (sig3);
1399     test_signal_free (sig1);
1400 }
1401 /* xaccAccountSortSplits
1402 void
1403 xaccAccountSortSplits (Account *acc, gboolean force)// C: 4 in 2
1404 Make static?
1405 Passthrough, no test.
1406 */
1407 /* xaccAccountBringUpToDate
1408 static void
1409 xaccAccountBringUpToDate (Account *acc)// 3
1410 Passthrough, no test.
1411 */
1412 /* xaccAccountSetGUID
1413 void
1414 xaccAccountSetGUID (Account *acc, const GncGUID *guid)// C: 5 in 4
1415 Getter/Setter, no test.
1416 * Naughty function: GUID should be set at object construction and be invariant thereafter.
1417  */
1418 /* xaccAccountLookup
1419 Account *
1420 xaccAccountLookup (const GncGUID *guid, QofBook *book)// C: 37 in 28 SCM: 2 in 1
1421 Passthrough, no test.
1422 */
1423 /* More getters/setters:
1424 	xaccAccountGetMark *** Test Only ***
1425 	xaccAccountSetMark *** Not Used ***
1426 	xaccClearMark *** Not Used ***
1427 	xaccClearMarkDown
1428 	gnc_account_get_policy
1429 	gnc_account_set_policy
1430 */
1431 /* xaccAccountRemoveLot
1432 void
1433 xaccAccountRemoveLot (Account *acc, GNCLot *lot)// C: 6 in 4 */
1434 static void
test_xaccAccountInsertRemoveLot(Fixture * fixture,gconstpointer pData)1435 test_xaccAccountInsertRemoveLot (Fixture *fixture, gconstpointer pData)
1436 {
1437     QofBook *book = gnc_account_get_book (fixture->acct);
1438     GNCLot *lot = gnc_lot_new (book);
1439     Account *parent = gnc_account_get_parent (fixture->acct);
1440     TestSignal sig1 = test_signal_new (QOF_INSTANCE (lot),
1441                                        QOF_EVENT_ADD, NULL);
1442     TestSignal sig2 = test_signal_new (&fixture->acct->inst,
1443                                        QOF_EVENT_MODIFY, NULL);
1444     TestSignal sig3 = test_signal_new (QOF_INSTANCE (lot),
1445                                        QOF_EVENT_REMOVE, NULL);
1446     TestSignal sig4 = test_signal_new (&parent->inst, QOF_EVENT_MODIFY, NULL);
1447 
1448     AccountPrivate *a_priv = fixture->func->get_private (fixture->acct);
1449     AccountPrivate *p_priv = fixture->func->get_private (parent);
1450 
1451     g_assert_cmpuint (g_list_length (a_priv->lots), == , 0);
1452     g_assert_cmpuint (g_list_length (p_priv->lots), == , 0);
1453     xaccAccountInsertLot (fixture->acct, lot);
1454     g_assert (gnc_lot_get_account (lot) == fixture->acct);
1455     g_assert_cmpuint (g_list_length (a_priv->lots), == , 1);
1456     test_signal_assert_hits (sig1, 1);
1457     test_signal_assert_hits (sig2, 1);
1458     /* Make sure that inserting again doesn't do anything */
1459     xaccAccountInsertLot (fixture->acct, lot);
1460     g_assert (gnc_lot_get_account (lot) == fixture->acct);
1461     g_assert_cmpuint (g_list_length (a_priv->lots), == , 1);
1462     test_signal_assert_hits (sig1, 1);
1463     test_signal_assert_hits (sig2, 1);
1464     /* Check that inserting the lot into a different account changes the lot */
1465     xaccAccountInsertLot (parent, lot);
1466     g_assert (gnc_lot_get_account (lot) == parent);
1467     g_assert_cmpuint (g_list_length (a_priv->lots), == , 0);
1468     g_assert_cmpuint (g_list_length (p_priv->lots), == , 1);
1469     test_signal_assert_hits (sig1, 2);
1470     test_signal_assert_hits (sig4, 1);
1471     test_signal_assert_hits (sig2, 1);
1472     /* Check that removing the lot works */
1473     xaccAccountRemoveLot (parent, lot);
1474     /* The following test should fail, but it doesn't because of an
1475      * error in the routine: When removing a lot from an account, the
1476      * account reference in the lot object should be NULLed. */
1477     g_assert (gnc_lot_get_account (lot) != NULL);
1478     g_assert_cmpuint (g_list_length (a_priv->lots), == , 0);
1479     g_assert_cmpuint (g_list_length (p_priv->lots), == , 0);
1480     test_signal_assert_hits (sig3, 1);
1481     test_signal_assert_hits (sig4, 2);
1482     test_signal_assert_hits (sig2, 1);
1483     /* Check that destroying the lot removes its reference */
1484     /* Because the lot's account pointer doesn't get nulled when the lot
1485      * is removed, we have to do that for the next test to work: */
1486     gnc_lot_set_account (lot, NULL);
1487     xaccAccountInsertLot (parent, lot);
1488     g_assert_cmpuint (g_list_length (p_priv->lots), == , 1);
1489     g_assert (gnc_lot_get_account (lot) == parent);
1490     gnc_lot_destroy (lot);
1491     /* Destroying the lot should remove it from the account. */
1492     g_assert_cmpuint (g_list_length (p_priv->lots), == , 0);
1493     test_signal_assert_hits (sig1, 3);
1494     test_signal_assert_hits (sig3, 2);
1495     test_signal_assert_hits (sig4, 4);
1496     test_signal_free (sig1);
1497     test_signal_free (sig2);
1498     test_signal_free (sig3);
1499     test_signal_free (sig4);
1500 
1501 }
1502 /*
1503 static void
1504 xaccPreSplitMove (Split *split, gpointer dummy)// 2
1505 static void
1506 xaccPostSplitMove (Split *split, Account *accto)// 2
1507 void
1508 xaccAccountMoveAllSplits (Account *accfrom, Account *accto)// C: 5 in 3
1509 
1510 * All of the work is done in other classes which in turn call other
1511 * Account functions (gnc_account_add_split and
1512 * gnc_account_remove_split). Mock classes with the functions that call
1513 * those wouldn't really achieve anything, since the actual functions
1514 * could break by failing to call gnc_account_*_split and the test
1515 * wouldn't know.
1516 */
1517 
1518 /* xaccAccountRecomputeBalance
1519 void
1520 xaccAccountRecomputeBalance (Account * acc)// C: 9 in 5 */
1521 static void
test_xaccAccountRecomputeBalance(Fixture * fixture,gconstpointer pData)1522 test_xaccAccountRecomputeBalance (Fixture *fixture, gconstpointer pData)
1523 {
1524     AccountPrivate *priv = fixture->func->get_private (fixture->acct);
1525     gnc_numeric bal = gnc_numeric_zero (), rec_bal = gnc_numeric_zero (),
1526                 clr_bal = gnc_numeric_zero ();
1527     SetupData *sdata = (SetupData*)pData;
1528     TxnParms* t_arr;
1529     g_assert (sdata != NULL);
1530     t_arr = (TxnParms*)sdata->txns;
1531     for (unsigned int ind = 0; ind < sdata->num_txns; ind++)
1532     {
1533         SplitParms p = t_arr[ind].splits[1];
1534         bal = gnc_numeric_add_fixed (bal, p.amount);
1535         if (p.reconciled != NREC)
1536             clr_bal = gnc_numeric_add_fixed (clr_bal, p.amount);
1537         if (p.reconciled == YREC || p.reconciled == FREC)
1538             rec_bal = gnc_numeric_add_fixed (rec_bal, p.amount);
1539     }
1540     g_assert (gnc_numeric_zero_p (priv->starting_balance));
1541     g_assert (gnc_numeric_zero_p (priv->balance));
1542     priv->balance_dirty = TRUE;
1543     xaccAccountRecomputeBalance (fixture->acct);
1544     g_assert (gnc_numeric_zero_p (priv->starting_balance));
1545     g_assert (gnc_numeric_eq (priv->balance, bal));
1546     g_assert (gnc_numeric_eq (priv->cleared_balance, clr_bal));
1547     g_assert (gnc_numeric_eq (priv->reconciled_balance, rec_bal));
1548     g_assert (!priv->balance_dirty);
1549 }
1550 
1551 /* xaccAccountOrder
1552 int
1553 xaccAccountOrder (const Account *aa, const Account *ab)// C: 11 in 3 */
1554 static void
test_xaccAccountOrder()1555 test_xaccAccountOrder ( )
1556 {
1557     Account *aa = NULL, *ab = NULL;
1558     QofBook *book = qof_book_new ();
1559 
1560 
1561     g_assert (xaccAccountOrder (aa, ab) == 0);
1562     aa = xaccMallocAccount (book);
1563     g_assert (xaccAccountOrder (aa, ab) == -1);
1564     g_assert (xaccAccountOrder (ab, aa) == 1);
1565 
1566     ab = xaccMallocAccount (book);
1567     qof_instance_increase_editlevel (aa);
1568     qof_instance_increase_editlevel (ab);
1569     g_object_set (G_OBJECT (aa),
1570                   "code", "3333",
1571                   "type", ACCT_TYPE_ASSET,
1572                   "name", "foo",
1573                   NULL);
1574     g_object_set (G_OBJECT (ab),
1575                   "code", "3333",
1576                   "type", ACCT_TYPE_ASSET,
1577                   "name", "foo",
1578                   NULL);
1579 
1580     g_assert_cmpint (xaccAccountOrder (aa, aa), == , 0);
1581     g_assert_cmpint (xaccAccountOrder (aa, ab), == ,
1582                      qof_instance_guid_compare (aa, ab));
1583     g_object_set (G_OBJECT (ab), "name", "bar", NULL);
1584     g_assert_cmpint (xaccAccountOrder (aa, ab), > , 0);
1585     g_object_set (G_OBJECT (ab), "name", "waldo", NULL);
1586     g_assert_cmpint (xaccAccountOrder (aa, ab), < , 0);
1587 
1588     g_object_set (G_OBJECT (ab), "type", ACCT_TYPE_BANK, NULL);
1589     g_test_message ("The next test should fail: There's an error in the sort"
1590                     " sequence that causes ACCT_TYPE_BANK to sort last"
1591                     " instead of first\n");
1592     g_assert_cmpint (xaccAccountOrder (aa, ab), < , 0);
1593     g_object_set (G_OBJECT (ab), "type", ACCT_TYPE_STOCK, NULL);
1594     g_assert_cmpint (xaccAccountOrder (aa, ab), > , 0);
1595     g_object_set (G_OBJECT (ab),
1596                   "type", ACCT_TYPE_INCOME,
1597                   "name", "bar",
1598                   NULL);
1599     g_assert_cmpint (xaccAccountOrder (aa, ab), < , 0);
1600 
1601     g_object_set (G_OBJECT (ab), "code", "2222",
1602                   "name", "waldo",
1603                   NULL);
1604     g_assert_cmpint (xaccAccountOrder (aa, ab), > , 0);
1605     g_object_set (G_OBJECT (ab),
1606                   "code", "4444",
1607                   "type", ACCT_TYPE_STOCK,
1608                   "name", "bar",
1609                   NULL);
1610     g_assert_cmpint (xaccAccountOrder (aa, ab), < , 0);
1611     qof_instance_decrease_editlevel (aa);
1612     qof_instance_decrease_editlevel (ab);
1613 
1614     xaccAccountBeginEdit (aa);
1615     xaccAccountDestroy (aa);
1616     xaccAccountBeginEdit (ab);
1617     xaccAccountDestroy (ab);
1618     qof_book_destroy (book);
1619 }
1620 /* qof_xaccAccountOrder
1621 static int
1622 qof_xaccAccountOrder (const Account **aa, const Account **ab)// 2
1623 Pass-through
1624 */
1625 /*
1626  * The following functions are tested in get/set above:
1627  * xaccAccountSetType
1628  * xaccAccountSetName
1629  * xaccAccountSetCode
1630  * xaccAccountSetDescription
1631  * xaccAccountSetColor
1632  * xaccAccountSetNotes
1633  * xaccAccountSetCommodity
1634  * xaccAccountSetCommoditySCU
1635  * xaccAccountGetCommoditySCUi
1636  * xaccAccountGetCommoditySCU
1637  * xaccAccountSetNonStdSCU
1638  * xaccAccountGetNonStdSCU
1639  */
1640 /* DxaccAccountSetCurrency
1641 void
1642 DxaccAccountSetCurrency (Account * acc, gnc_commodity * currency)// C: 7 in 5
1643 Deprecated, don't test
1644 
1645 */
1646 
1647 /* qofAccountSetParent
1648 static void
1649 qofAccountSetParent (Account *acc, QofInstance *parent)// 2
1650 */
1651 static void
test_qofAccountSetParent(Fixture * fixture,gconstpointer pData)1652 test_qofAccountSetParent (Fixture *fixture, gconstpointer pData)
1653 {
1654     Account *root = gnc_account_get_root (fixture->acct);
1655     Account *old_parent = gnc_account_get_parent (fixture->acct);
1656     AccountTestFunctions *func = _utest_account_fill_functions ();
1657     g_assert (root != old_parent);
1658     /* qofAccountSetParent doesn't check to see if the parent is already
1659      * set, nor does gnc_account_append_child, which is the passed-through
1660      * function.
1661      */
1662     func->qofAccountSetParent (fixture->acct, QOF_INSTANCE (root));
1663     g_assert (root == gnc_account_get_parent (fixture->acct));
1664     g_assert (qof_instance_get_dirty (QOF_INSTANCE (fixture->acct)));
1665     g_assert (qof_instance_get_dirty (QOF_INSTANCE (root)));
1666     g_assert (qof_instance_get_dirty (QOF_INSTANCE (old_parent)));
1667 }
1668 /* gnc_account_append_child
1669 void
1670 gnc_account_append_child (Account *new_parent, Account *child)// C: 29 in 18 SCM: 7 in 4*/
1671 /* gnc_account_remove_child
1672 void
1673 gnc_account_remove_child (Account *parent, Account *child)// C: 4 in 2 */
1674 static void
test_gnc_account_append_remove_child(Fixture * fixture,gconstpointer pData)1675 test_gnc_account_append_remove_child (Fixture *fixture, gconstpointer pData)
1676 {
1677     QofBook *book = gnc_account_get_book (fixture->acct);
1678     QofBook *fbook = qof_book_new ();
1679     Account *froot = gnc_account_create_root (fbook);
1680     Account *account = xaccMallocAccount (fbook);
1681     auto logdomain = "gnc.account";
1682     auto msg1 = "[gnc_account_append_child()] reparenting accounts across books is not correctly supported\n";
1683     auto msg2 = "[gnc_account_remove_child()] account not a child of parent";
1684     guint log_handler = 0;
1685     auto loglevelc = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
1686     auto loglevelw = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL);
1687     auto check_warn = test_error_struct_new("gnc.account", loglevelw, msg1);
1688     auto check_err = test_error_struct_new("gnc.account", loglevelc, msg2);
1689     TestSignal sig1, sig2, sig3;
1690     AccountTestFunctions *func = _utest_account_fill_functions ();
1691     AccountPrivate *frpriv = func->get_private (froot),
1692                     *apriv = func->get_private (fixture->acct);
1693     const GncGUID *acct_guid = qof_instance_get_guid (QOF_INSTANCE (account));
1694     sig1 = test_signal_new (QOF_INSTANCE (account), QOF_EVENT_ADD, NULL);
1695     sig2 = test_signal_new (QOF_INSTANCE (account), QOF_EVENT_DESTROY, NULL);
1696     sig3 = test_signal_new (QOF_INSTANCE (account), QOF_EVENT_CREATE, NULL);
1697 
1698     gnc_account_append_child (froot, account);
1699     g_assert (gnc_account_get_parent (account) == froot);
1700     test_signal_assert_hits (sig1, 1);
1701     test_signal_assert_hits (sig2, 0);
1702     test_signal_assert_hits (sig3, 0);
1703     g_assert_cmpint (check_warn->hits, ==, 0);
1704     g_assert_cmpint (check_err->hits, ==, 0);
1705     g_assert (qof_instance_get_dirty (QOF_INSTANCE (froot)));
1706     g_assert (qof_instance_get_dirty (QOF_INSTANCE (account)));
1707     g_assert (g_list_find (frpriv->children, account));
1708     g_assert (qof_collection_lookup_entity (
1709                   qof_book_get_collection (fbook, GNC_ID_ACCOUNT),
1710                   acct_guid));
1711     auto loglevelr = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING |
1712                                                  G_LOG_FLAG_FATAL |
1713                                                  G_LOG_FLAG_RECURSION);
1714     log_handler = g_log_set_handler (logdomain, loglevelr,
1715                                      (GLogFunc)test_null_handler, check_warn);
1716     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check_warn);
1717     gnc_account_append_child (fixture->acct, account);
1718     g_log_remove_handler (logdomain, log_handler);
1719     g_assert_cmpstr (msg1, == , check_warn->msg);
1720     g_assert (gnc_account_get_parent (account) == fixture->acct);
1721     test_signal_assert_hits (sig1, 2);
1722     test_signal_assert_hits (sig2, 1);
1723     test_signal_assert_hits (sig3, 1);
1724     g_assert_cmpint (check_warn->hits, ==, 1);
1725     g_assert_cmpint (check_err->hits, ==, 0);
1726     g_assert (!qof_collection_lookup_entity (
1727                   qof_book_get_collection (fbook, GNC_ID_ACCOUNT),
1728                   acct_guid));
1729     g_assert (qof_collection_lookup_entity (
1730                   qof_book_get_collection (book, GNC_ID_ACCOUNT),
1731                   acct_guid));
1732     g_assert (qof_instance_get_dirty (QOF_INSTANCE (fixture->acct)));
1733     g_assert (g_list_find (frpriv->children, account) == NULL);
1734     g_assert (g_list_find (apriv->children, account));
1735 
1736     test_signal_free (sig1);
1737     test_signal_free (sig2);
1738     test_signal_free (sig3);
1739     sig1 = test_signal_new (&account->inst, QOF_EVENT_REMOVE, NULL);
1740     sig2 = test_signal_new (&(fixture->acct)->inst, QOF_EVENT_MODIFY, NULL);
1741     log_handler = g_log_set_handler (logdomain, loglevelc,
1742                                      (GLogFunc)test_null_handler, check_err);
1743     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check_err);
1744     gnc_account_remove_child (froot, account);
1745     g_log_remove_handler (logdomain, log_handler);
1746 
1747     test_signal_assert_hits (sig1, 0);
1748     test_signal_assert_hits (sig2, 0);
1749     g_assert_cmpint (check_err->hits, ==, 1);
1750     g_assert_cmpint (check_warn->hits, ==, 1);
1751 
1752     gnc_account_remove_child (fixture->acct, account);
1753     g_assert (gnc_account_get_parent (account) == NULL);
1754     g_assert (g_list_find (apriv->children, account) == NULL);
1755     test_signal_assert_hits (sig1, 1);
1756     test_signal_assert_hits (sig2, 1);
1757     g_assert_cmpint (check_warn->hits, ==, 1);
1758     g_assert_cmpint (check_err->hits, ==, 1);
1759     test_signal_free (sig1);
1760     test_signal_free (sig2);
1761     xaccAccountBeginEdit (account);
1762     xaccAccountDestroy (account);
1763     xaccAccountBeginEdit (froot);
1764     xaccAccountDestroy (froot);
1765     qof_book_destroy (fbook);
1766 
1767 }
1768 /* Simple Getters or passthroughs, no tests:
1769  * gnc_account_get_parent
1770  * gnc_account_get_root
1771  * gnc_account_is_root
1772  * gnc_account_get_children
1773  * gnc_account_get_children_sorted
1774  * gnc_account_n_children
1775  * gnc_account_child_index
1776  * gnc_account_nth_child
1777  */
1778 /* gnc_account_n_descendants
1779 gint
1780 gnc_account_n_descendants (const Account *account)// C: 12 in 6 */
1781 static void
test_gnc_account_n_descendants(Fixture * fixture,gconstpointer pData)1782 test_gnc_account_n_descendants (Fixture *fixture, gconstpointer pData)
1783 {
1784     g_assert_cmpint (
1785         gnc_account_n_descendants (
1786             gnc_account_get_root (fixture->acct)), == , 4);
1787 }
1788 /* gnc_account_get_current_depth
1789 gint
1790 gnc_account_get_current_depth (const Account *account)// C: 4 in 2 SCM: 12 in 4*/
1791 static void
test_gnc_account_get_current_depth(Fixture * fixture,gconstpointer pData)1792 test_gnc_account_get_current_depth (Fixture *fixture, gconstpointer pData)
1793 {
1794     g_assert_cmpint (
1795         gnc_account_get_current_depth (fixture->acct), == , 2);
1796 }
1797 /* gnc_account_get_tree_depth
1798 gint
1799 gnc_account_get_tree_depth (const Account *account)// C: 4 in 2 SCM: 3 in 3*/
1800 static void
test_gnc_account_get_tree_depth(Fixture * fixture,gconstpointer pData)1801 test_gnc_account_get_tree_depth (Fixture *fixture, gconstpointer pData)
1802 {
1803     /* Magic result value based on depth of the "complex" AccountParms array. */
1804     g_assert_cmpint (
1805         gnc_account_get_tree_depth (
1806             gnc_account_get_root (fixture->acct)), == , 5);
1807     g_assert_cmpint (
1808         gnc_account_get_tree_depth (fixture->acct), == , 1);
1809 }
1810 /* gnc_account_get_descendants
1811 GList *
1812 gnc_account_get_descendants (const Account *account)// C: 24 in 17 SCM: 6 in 6*/
1813 static void
print_account(gpointer item,gpointer data)1814 print_account (gpointer item, gpointer data)
1815 {
1816     Account *account = (Account *)item;
1817     gchar *name, *code, *desc;
1818     GNCAccountType type;
1819     const gchar *typestr;
1820     g_object_get (account,
1821                   "type", &type,
1822                   "name", &name,
1823                   "code", &code,
1824                   "description", &desc,
1825                   NULL);
1826     typestr = xaccAccountGetTypeStr (type);
1827     g_test_message ("%s: %s, %s %s", typestr, code, name, desc);
1828     g_free (code);
1829     g_free (name);
1830     g_free (desc);
1831 }
1832 
1833 static void
test_gnc_account_get_descendants(Fixture * fixture,gconstpointer pData)1834 test_gnc_account_get_descendants (Fixture *fixture, gconstpointer pData)
1835 {
1836 
1837     GList *list = gnc_account_get_descendants (
1838                       gnc_account_get_root (fixture->acct));
1839     g_assert (list != NULL);
1840     g_assert_cmpuint (g_list_length (list), == , 34);
1841     g_assert_cmpint (g_list_index (list, fixture->acct), == , 33);
1842     g_list_free (list);
1843     list = gnc_account_get_descendants (fixture->acct);
1844     g_assert (list == NULL);
1845 }
1846 /* gnc_account_get_descendants_sorted
1847 GList *
1848 gnc_account_get_descendants_sorted (const Account *account)// C: 6 in 4 SCM: 62 in 46*/
1849 static void
test_gnc_account_get_descendants_sorted(Fixture * fixture,gconstpointer pData)1850 test_gnc_account_get_descendants_sorted (Fixture *fixture, gconstpointer pData)
1851 {
1852     GList *list = gnc_account_get_descendants_sorted (
1853                       gnc_account_get_root (fixture->acct));
1854     g_assert (list != NULL);
1855     g_list_foreach (list, print_account, NULL);
1856     g_assert_cmpuint (g_list_length (list), == , 34);
1857     g_assert_cmpint (g_list_index (list, fixture->acct), == , 10);
1858     g_list_free (list);
1859 }
1860 /* gnc_account_lookup_by_name
1861 Account *
1862 gnc_account_lookup_by_name (const Account *parent, const char * name)// C: 22 in 12 */
1863 static void
test_gnc_account_lookup_by_name(Fixture * fixture,gconstpointer pData)1864 test_gnc_account_lookup_by_name (Fixture *fixture, gconstpointer pData)
1865 {
1866     Account *root, *target;
1867     gchar *code;
1868     root = gnc_account_get_root (fixture->acct);
1869     target = gnc_account_lookup_by_name (root, "income");
1870     g_assert (target != NULL);
1871     g_object_get (target, "code", &code, NULL);
1872     g_assert_cmpstr (code, == , "4000");
1873     target = gnc_account_lookup_by_name (target, "int");
1874     g_assert (target != NULL);
1875     g_free (code);
1876     g_object_get (target, "code", &code, NULL);
1877     g_assert_cmpstr (code, == , "4160");
1878     target = gnc_account_lookup_by_name (root, "bank");
1879     g_assert (target != NULL);
1880     g_free (code);
1881     g_object_get (target, "code", &code, NULL);
1882     g_assert_cmpstr (code, == , "2300");
1883     target = gnc_account_lookup_by_name (target, "int");
1884     g_assert (target == NULL);
1885     g_free (code);
1886 
1887 }
1888 /* gnc_account_lookup_by_code
1889 Account *
1890 gnc_account_lookup_by_code (const Account *parent, const char * code)// C: 5 in 3 */
1891 static void
test_gnc_account_lookup_by_code(Fixture * fixture,gconstpointer pData)1892 test_gnc_account_lookup_by_code (Fixture *fixture, gconstpointer pData)
1893 {
1894     Account *root, *target;
1895     gchar *name;
1896     root = gnc_account_get_root (fixture->acct);
1897     target = gnc_account_lookup_by_code (root, "3100");
1898     g_assert (target != NULL);
1899     g_object_get (target, "name", &name, NULL);
1900     g_assert_cmpstr (name, == , "ordinary");
1901     g_free (name);
1902     target = gnc_account_lookup_by_code (target, "3150");
1903     g_assert (target != NULL);
1904     g_object_get (target, "name", &name, NULL);
1905     g_assert_cmpstr (name, == , "utilities");
1906     target = gnc_account_lookup_by_code (target, "2100");
1907     g_assert (target == NULL);
1908     g_free (name);
1909 }
1910 /* gnc_account_lookup_by_full_name_helper
1911 static Account *
1912 gnc_account_lookup_by_full_name_helper (const Account *parent,// 3
1913 */
1914 static void
test_gnc_account_lookup_by_full_name_helper(Fixture * fixture,gconstpointer pData)1915 test_gnc_account_lookup_by_full_name_helper ( Fixture *fixture,
1916         gconstpointer pData )
1917 {
1918     Account *root, *target;
1919     const char *names1[] = {"income", "taxable", "int", NULL};
1920     const char *names2[] =  {"income", "exempt", "int", NULL};
1921     const char *names3[] = {"expense", "taxable", "int", NULL};
1922     char *code;
1923     AccountTestFunctions *func = _utest_account_fill_functions ();
1924 
1925     root = gnc_account_get_root (fixture->acct);
1926     target = func->gnc_account_lookup_by_full_name_helper (root, const_cast<char**>(names1));
1927     g_assert (target != NULL);
1928     g_object_get (target, "code", &code, NULL);
1929     g_assert_cmpstr (code, == , "4160");
1930     g_free (code);
1931     target = func->gnc_account_lookup_by_full_name_helper (root, const_cast<char**>(names2));
1932     g_assert (target != NULL);
1933     g_object_get (target, "code", &code, NULL);
1934     g_assert_cmpstr (code, == , "4210");
1935     target = func->gnc_account_lookup_by_full_name_helper (root, const_cast<char**>(names3));
1936     g_assert (target == NULL);
1937     g_free (code);
1938 }
1939 /* gnc_account_lookup_by_full_name
1940 Account *
1941 gnc_account_lookup_by_full_name (const Account *any_acc,// C: 15 in 11 SCM: 8 in 4*/
1942 static void
test_gnc_account_lookup_by_full_name(Fixture * fixture,gconstpointer pData)1943 test_gnc_account_lookup_by_full_name (Fixture *fixture, gconstpointer pData)
1944 {
1945     Account *root, *target;
1946     auto names1 = "income:taxable:int";
1947     auto names2 =  "income:exempt:int";
1948     auto names3 = "expense:taxable:int";
1949     gchar *code;
1950 
1951     root = gnc_account_get_root (fixture->acct);
1952     target = gnc_account_lookup_by_full_name (root, names1);
1953     g_assert (target != NULL);
1954     g_object_get (target, "code", &code, NULL);
1955     g_assert_cmpstr (code, == , "4160");
1956     g_free (code);
1957     target = gnc_account_lookup_by_full_name (root, names2);
1958     g_assert (target != NULL);
1959     g_object_get (target, "code", &code, NULL);
1960     g_assert_cmpstr (code, == , "4210");
1961     target = gnc_account_lookup_by_full_name (root, names3);
1962     g_assert (target == NULL);
1963     g_free (code);
1964 }
1965 
1966 static void
thunk(Account * s,gpointer data)1967 thunk (Account *s, gpointer data)
1968 {
1969     guint *counter = (guint*)data;
1970     g_assert (GNC_IS_ACCOUNT (s));
1971     ++(*counter);
1972 }
1973 
1974 static gpointer
thunk2(Account * s,gpointer data)1975 thunk2 (Account *s, gpointer data)
1976 {
1977     guint *counter = (guint*)data;
1978     gchar *name;
1979     g_assert (GNC_IS_ACCOUNT (s));
1980     g_object_get (G_OBJECT (s), "name", &name, NULL);
1981     if (!g_strcmp0 (name, "int"))
1982     {
1983         g_free (name);
1984         return s;
1985     }
1986     g_free (name);
1987     ++(*counter);
1988     return NULL;
1989 }
1990 /* gnc_account_foreach_child
1991 void
1992 gnc_account_foreach_child (const Account *acc,// C: 6 in 3 */
1993 static void
test_gnc_account_foreach_child(Fixture * fixture,gconstpointer pData)1994 test_gnc_account_foreach_child (Fixture *fixture, gconstpointer pData)
1995 {
1996     Account *root = gnc_account_get_root (fixture->acct);
1997     Account *begin = gnc_account_lookup_by_code (root, "4000");
1998     guint counter = 0;
1999     gnc_account_foreach_child (begin, thunk, &counter);
2000     g_assert_cmpint (counter, == , 2);
2001 }
2002 /* gnc_account_foreach_child_until  *** Not Used ***
2003 gpointer
2004 gnc_account_foreach_child_until (const Account *acc,// C: 4 in 2 */
2005 /*static void
2006 test_gnc_account_foreach_child_until (Fixture *fixture, gconstpointer pData)
2007 {
2008     Account *root = gnc_account_get_root (fixture->acct);
2009     Account *first = gnc_account_lookup_by_code (root, "4000");
2010     Account *second = gnc_account_lookup_by_code (root, "4100");
2011     Account *expected = gnc_account_lookup_by_code (root, "4160");
2012     Account *result;
2013     guint counter = 0;
2014     result = gnc_account_foreach_child_until (first, thunk2, &counter);
2015     g_assert_cmpint (counter, ==, 2);
2016     g_assert (result == NULL);
2017     counter = 0;
2018     result = gnc_account_foreach_child_until (second, thunk2, &counter);
2019     g_assert (result == expected);
2020     g_assert_cmpint (counter, ==, 3);
2021     }*/
2022 /* gnc_account_foreach_descendant
2023 void
2024 gnc_account_foreach_descendant (const Account *acc,// C: 23 in 14 */
2025 static void
test_gnc_account_foreach_descendant(Fixture * fixture,gconstpointer pData)2026 test_gnc_account_foreach_descendant (Fixture *fixture, gconstpointer pData)
2027 {
2028     Account *root = gnc_account_get_root (fixture->acct);
2029     Account *begin = gnc_account_lookup_by_code (root, "4000");
2030     guint counter = 0;
2031     gnc_account_foreach_descendant (begin, thunk, &counter);
2032     g_assert_cmpint (counter, == , 13);
2033 }
2034 /* gnc_account_foreach_descendant_until
2035 gpointer
2036 gnc_account_foreach_descendant_until (const Account *acc,// C: 8 in 6 */
2037 static void
test_gnc_account_foreach_descendant_until(Fixture * fixture,gconstpointer pData)2038 test_gnc_account_foreach_descendant_until (Fixture *fixture, gconstpointer pData)
2039 {
2040     Account *root = gnc_account_get_root (fixture->acct);
2041     Account *first = gnc_account_lookup_by_code (root, "2000");
2042     Account *second = gnc_account_lookup_by_code (root, "4000");
2043     Account *expected = gnc_account_lookup_by_code (root, "4160");
2044     unsigned int counter = 0;
2045     auto result = static_cast<Account*>(gnc_account_foreach_descendant_until (first, thunk2, &counter));
2046     g_assert_cmpint (counter, == , 11);
2047     g_assert (result == NULL);
2048     counter = 0;
2049     result = static_cast<Account*>(gnc_account_foreach_descendant_until (second, thunk2, &counter));
2050     g_assert (result == expected);
2051     g_assert_cmpint (counter, == , 6);
2052 }
2053 /* More getter/setters:
2054  * xaccAccountGetType
2055  * qofAccountGetTypeString
2056  * qofAccountSetType
2057  * xaccAccountGetName
2058  * xaccAccountGetCode
2059  * xaccAccountGetDescription
2060  * xaccAccountGetColor
2061  * xaccAccountGetNotes
2062  * xaccAccountGetCommodity
2063  * gnc_account_set_start_balance
2064  * gnc_account_set_start_cleared_balance
2065  * gnc_account_set_start_reconciled_balance
2066  * xaccAccountGetBalance
2067  * xaccAccountGetClearedBalance C: 1
2068  * xaccAccountGetReconciledBalance
2069  */
2070 /* gnc_account_get_full_name
2071 gchar *
2072 gnc_account_get_full_name (const Account *account)// C: 38 in 21 SCM: 29 in 19*/
2073 static void
test_gnc_account_get_full_name(Fixture * fixture,gconstpointer pData)2074 test_gnc_account_get_full_name (Fixture *fixture, gconstpointer pData)
2075 {
2076     gchar *result;
2077     result = gnc_account_get_full_name (NULL);
2078     g_assert (result != NULL);
2079     g_assert_cmpstr (result, == , "");
2080     g_free (result);
2081     result = gnc_account_get_full_name (gnc_account_get_root (fixture->acct));
2082     g_assert (result != NULL);
2083     g_assert_cmpstr (result, == , "");
2084     g_free (result);
2085     result = gnc_account_get_full_name (fixture->acct);
2086     g_assert (result != NULL);
2087     g_assert_cmpstr (result, == , "foo:baz:waldo");
2088     g_free (result);
2089 
2090 }
2091 
2092 /* DxaccAccountGetCurrency
2093 gnc_commodity *
2094 DxaccAccountGetCurrency (const Account *acc)// C: 9 in 5
2095 Deprecated, Don't test.
2096 */
2097 /* xaccAccountGetProjectedMinimumBalance
2098 gnc_numeric
2099 xaccAccountGetProjectedMinimumBalance (const Account *acc)// C: 4 in 2 */
2100 static void
test_xaccAccountGetProjectedMinimumBalance(Fixture * fixture,gconstpointer pData)2101 test_xaccAccountGetProjectedMinimumBalance (Fixture *fixture, gconstpointer pData)
2102 {
2103     gnc_numeric val, bal = gnc_numeric_zero ();
2104     gfloat dval;
2105     gfloat dbal = 0.0;
2106     SetupData *sdata = (SetupData*)pData;
2107     TxnParms* t_arr;
2108     int ind;
2109     gint min_ind = 4;
2110     g_assert (sdata != NULL);
2111     t_arr = (TxnParms*)sdata->txns;
2112     for (ind = 0; ind < min_ind; ind++)
2113     {
2114         SplitParms p = t_arr[ind].splits[1];
2115         bal = gnc_numeric_add_fixed (bal, p.amount);
2116     }
2117     dbal = gnc_numeric_to_double (bal);
2118     val = xaccAccountGetProjectedMinimumBalance (fixture->acct);
2119     dval = gnc_numeric_to_double (val);
2120     g_assert_cmpfloat (dval, == , 0.0);
2121     xaccAccountRecomputeBalance (fixture->acct);
2122     val = xaccAccountGetProjectedMinimumBalance (fixture->acct);
2123     dval = gnc_numeric_to_double (val);
2124     g_assert_cmpfloat (dval, == , dbal);
2125 }
2126 /* xaccAccountGetBalanceAsOfDate
2127 gnc_numeric
2128 xaccAccountGetBalanceAsOfDate (Account *acc, time64 date)// C: 12 in 7 SCM: 4 in 4*/
2129 static void
test_xaccAccountGetBalanceAsOfDate(Fixture * fixture,gconstpointer pData)2130 test_xaccAccountGetBalanceAsOfDate (Fixture *fixture, gconstpointer pData)
2131 {
2132     gnc_numeric val, bal = gnc_numeric_zero ();
2133     gfloat dval;
2134     gfloat dbal = 0.0;
2135     SetupData *sdata = (SetupData*)pData;
2136     TxnParms* t_arr;
2137     int ind;
2138     gint min_ind = 2;
2139     gint offset = 24 * 3600 * 3; /* 3 days in seconds */
2140     g_assert (sdata != NULL);
2141     t_arr = (TxnParms*)sdata->txns;
2142     for (ind = 0; ind < min_ind; ind++)
2143     {
2144         SplitParms p = t_arr[ind].splits[1];
2145         bal = gnc_numeric_add_fixed (bal, p.amount);
2146     }
2147     dbal = gnc_numeric_to_double (bal);
2148     xaccAccountRecomputeBalance (fixture->acct);
2149     val = xaccAccountGetBalanceAsOfDate (fixture->acct,
2150                                          (gnc_time (NULL) - offset));
2151     dval = gnc_numeric_to_double (val);
2152     g_assert_cmpfloat (dval, == , dbal);
2153 }
2154 /* xaccAccountGetPresentBalance
2155 gnc_numeric
2156 xaccAccountGetPresentBalance (const Account *acc)// C: 4 in 2 */
2157 static void
test_xaccAccountGetPresentBalance(Fixture * fixture,gconstpointer pData)2158 test_xaccAccountGetPresentBalance (Fixture *fixture, gconstpointer pData)
2159 {
2160     gnc_numeric val, bal = gnc_numeric_zero ();
2161     gfloat dval;
2162     gfloat dbal = 0.0;
2163     SetupData *sdata = (SetupData*)pData;
2164     TxnParms* t_arr;
2165     int ind;
2166     gint min_ind = 3;
2167     g_assert (sdata != NULL);
2168     t_arr = (TxnParms*)sdata->txns;
2169     for (ind = 0; ind < min_ind; ind++)
2170     {
2171         SplitParms p = t_arr[ind].splits[1];
2172         bal = gnc_numeric_add_fixed (bal, p.amount);
2173     }
2174     dbal = gnc_numeric_to_double (bal);
2175     xaccAccountRecomputeBalance (fixture->acct);
2176     val = xaccAccountGetPresentBalance (fixture->acct);
2177     dval = gnc_numeric_to_double (val);
2178     g_assert_cmpfloat (dval, == , dbal);
2179 }
2180 /*
2181  * xaccAccountConvertBalanceToCurrency
2182  * xaccAccountConvertBalanceToCurrencyAsOfDate are wrappers around
2183  * gnc_pricedb_convert_balance_latest_price and
2184  * gnc_pricedb_convert_balance_nearest_price_t64. Don't test.
2185  *
2186  * The rest of these are convenience functions that wrap
2187  * xaccAccountConvertBalanceToCurrency* with one of the balance getter
2188  * functions tested immediately above and one of the recursion
2189  * functions, tested above those. There's no point in testing them.
2190  *
2191  * xaccAccountGetXxxBalanceInCurrency
2192  * xaccAccountGetXxxBalanceAsOfDateInCurrency
2193  * xaccAccountBalanceHelper
2194  * xaccAccountBalanceAsOfDateHelper
2195  * xaccAccountGetXxxBalanceInCurrencyRecursive
2196  * xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive
2197  * xaccAccountGetBalanceInCurrency
2198  * xaccAccountGetClearedBalanceInCurrency
2199  * xaccAccountGetReconciledBalanceInCurrency
2200  * xaccAccountGetPresentBalanceInCurrency
2201  * xaccAccountGetProjectedMinimumBalanceInCurrency
2202  * xaccAccountGetBalanceAsOfDateInCurrency
2203  * xaccAccountGetBalanceChangeForPeriod
2204  */
2205 /*
2206  * Yet more getters & setters:
2207  * xaccAccountGetSplitList
2208  * xaccAccountGetLotList
2209  */
2210 /* xaccAccountFindOpenLots
2211 LotList *
2212 xaccAccountFindOpenLots (const Account *acc,// C: 24 in 13 */
2213 
2214 static gboolean
bogus_lot_match_func_true(GNCLot * lot,gpointer p_data)2215 bogus_lot_match_func_true (GNCLot *lot, gpointer p_data)
2216 {
2217     return TRUE;
2218 }
2219 
2220 static gboolean
bogus_lot_match_func_false(GNCLot * lot,gpointer p_data)2221 bogus_lot_match_func_false (GNCLot *lot, gpointer p_data)
2222 {
2223     return FALSE;
2224 }
2225 
2226 static guint count_sorts = 0;
2227 static gint
bogus_lot_sort_func(gconstpointer a,gconstpointer b)2228 bogus_lot_sort_func (gconstpointer a, gconstpointer b)
2229 {
2230     ++count_sorts;
2231     return 0;
2232 }
2233 
2234 static void
test_xaccAccountFindOpenLots(Fixture * fixture,gconstpointer pData)2235 test_xaccAccountFindOpenLots (Fixture *fixture, gconstpointer pData)
2236 {
2237     Account *root = gnc_account_get_root (fixture->acct);
2238     Account *acct = gnc_account_lookup_by_name (root, "baz");
2239     LotList* lots;
2240 
2241     g_assert (acct);
2242     lots = xaccAccountFindOpenLots (acct, NULL, NULL, NULL);
2243     g_assert (g_list_length (lots) == 2);
2244     if (lots) g_list_free (lots);
2245     lots = xaccAccountFindOpenLots (acct, bogus_lot_match_func_true,
2246                                     NULL, NULL);
2247     g_assert (g_list_length (lots) == 2);
2248     if (lots) g_list_free (lots);
2249     lots = xaccAccountFindOpenLots (acct, bogus_lot_match_func_false,
2250                                     NULL, NULL);
2251     g_assert (g_list_length (lots) == 0);
2252     if (lots) g_list_free (lots);
2253     lots = xaccAccountFindOpenLots (acct, NULL, NULL, bogus_lot_sort_func);
2254     g_assert_cmpint (count_sorts, == , 1);
2255     g_assert (g_list_length (lots) == 2);
2256     if (lots) g_list_free (lots);
2257     count_sorts = 0;
2258 }
2259 
2260 static gpointer
bogus_for_each_lot_func(GNCLot * lot,gpointer data)2261 bogus_for_each_lot_func (GNCLot *lot, gpointer data)
2262 {
2263     auto count = static_cast<unsigned int *>(data);
2264     ++*count;
2265     return (*count > 4 ? lot : NULL);
2266 }
2267 
2268 /* xaccAccountForEachLot
2269 gpointer
2270 xaccAccountForEachLot (const Account *acc,// C: 2 in 2 */
2271 static void
test_xaccAccountForEachLot(Fixture * fixture,gconstpointer pData)2272 test_xaccAccountForEachLot (Fixture *fixture, gconstpointer pData)
2273 {
2274     Account *root = gnc_account_get_root (fixture->acct);
2275     Account *acct = gnc_account_lookup_by_name (root, "baz");
2276     guint count_calls = 0;
2277 
2278     g_assert (acct);
2279     xaccAccountForEachLot (acct, bogus_for_each_lot_func, &count_calls);
2280     g_assert_cmpint (count_calls, == , 3);
2281     xaccAccountForEachLot (acct, bogus_for_each_lot_func, &count_calls);
2282     g_assert_cmpint (count_calls, == , 5);
2283 }
2284 /* These getters and setters look in KVP, so I guess their delegators instead:
2285  * xaccAccountGetTaxRelated
2286  * xaccAccountSetTaxRelated
2287  * xaccAccountGetTaxUSCode
2288  * xaccAccountSetTaxUSCode
2289  * xaccAccountGetTaxUSPayerNameSource
2290  * xaccAccountSetTaxUSPayerNameSource
2291  * xaccAccountGetTaxUSCopyNumber
2292  * xaccAccountSetTaxUSCopyNumber
2293  * xaccAccountGetPlaceholder
2294  * xaccAccountSetPlaceholder
2295  * xaccAccountGetDescendantPlaceholder
2296  * xaccAccountGetHidden
2297  * xaccAccountSetHidden
2298  * xaccAccountIsHidden
2299 */
2300 /* xaccAccountHasAncestor
2301 gboolean
2302 xaccAccountHasAncestor (const Account *acc, const Account * ancestor)// C: 5 in 3 */
2303 static void
test_xaccAccountHasAncestor(Fixture * fixture,gconstpointer pData)2304 test_xaccAccountHasAncestor (Fixture *fixture, gconstpointer pData)
2305 {
2306     Account *root = gnc_account_get_root (fixture->acct);
2307     Account *ltcg = gnc_account_lookup_by_name (root, "ltcg");
2308     Account *income = gnc_account_lookup_by_name (root, "income");
2309     Account *expense = gnc_account_lookup_by_name (root, "expense");
2310 
2311     g_assert (root);
2312     g_assert (ltcg);
2313     g_assert (income);
2314     g_assert (expense);
2315     g_assert (xaccAccountHasAncestor (fixture->acct, root));
2316     g_assert (xaccAccountHasAncestor (ltcg, income));
2317     g_assert (!xaccAccountHasAncestor (ltcg, expense));
2318 
2319 }
operator ++(GNCAccountType & x)2320 inline GNCAccountType& operator++(GNCAccountType& x)
2321 {
2322     using AcctTypeType = std::underlying_type<GNCAccountType>;
2323     if (x < ACCT_TYPE_LAST)
2324         x = static_cast<GNCAccountType>(x + 1);
2325     return x;
2326 }
2327 
2328 /* xaccAccountTypeEnumAsString
2329  * xaccAccountStringToType
2330  * xaccAccountStringToEnum
2331  * xaccAccountGetTypeStr
2332  * xaccAccountIsPriced
2333 const char *
2334 xaccAccountTypeEnumAsString (GNCAccountType type)// C: 5 in 3 */
2335 static void
test_xaccAccountType_Stuff(void)2336 test_xaccAccountType_Stuff (void)
2337 {
2338     auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
2339     auto logdomain = "gnc.account";
2340     auto msg1 = g_strdup_printf ("[xaccAccountTypeEnumAsString()] asked to translate unknown account type %d.\n", ACCT_TYPE_LAST);
2341     auto msg2 = "[xaccAccountStringToType()] asked to translate unknown account type string (null).\n";
2342     auto msg3 = "[xaccAccountStringToType()] asked to translate unknown account type string LAST.\n";
2343     guint loghandler = 0;
2344     auto check1 = test_error_struct_new(logdomain, loglevel, msg1);
2345     auto check2 = test_error_struct_new(logdomain, loglevel, msg2);
2346     auto check3 = test_error_struct_new(logdomain, loglevel, msg3);
2347     auto acc = static_cast<Account*>(g_object_new (GNC_TYPE_ACCOUNT, NULL));
2348     GNCAccountType type;
2349 
2350     for (type = ACCT_TYPE_NONE; type < ACCT_TYPE_LAST; ++type)
2351     {
2352         const gchar *type_name = xaccAccountTypeEnumAsString (type);
2353         const gchar *typestr;
2354         gchar *typestr_uc;
2355 
2356         g_assert (type_name);
2357         g_assert_cmpint (xaccAccountStringToEnum (type_name), == , type);
2358         if (type < 0 || type >= NUM_ACCOUNT_TYPES)
2359             continue;
2360 
2361         typestr = xaccAccountGetTypeStr (type);
2362         typestr_uc = g_ascii_strup (typestr, strlen (typestr));
2363         if (type == ACCT_TYPE_PAYABLE || type == ACCT_TYPE_RECEIVABLE)
2364         {
2365             auto cmpstr = g_strconcat ("A/", type_name, NULL);
2366             g_assert_cmpstr (typestr_uc, == , cmpstr);
2367             g_free (cmpstr);
2368         }
2369         else if (type == ACCT_TYPE_CREDIT)
2370         {
2371             auto cmpstr = g_strconcat (type_name, " CARD", NULL);
2372             g_assert_cmpstr (typestr_uc, == , cmpstr);
2373             g_free (cmpstr);
2374         }
2375         else if (type == ACCT_TYPE_MUTUAL)
2376         {
2377             auto cmpstr = g_strconcat (type_name, " FUND", NULL);
2378             g_assert_cmpstr (typestr_uc, == , cmpstr);
2379             g_free (cmpstr);
2380         }
2381         else
2382             g_assert_cmpstr (typestr_uc, == , type_name);
2383         g_free (typestr_uc);
2384 
2385 	qof_instance_increase_editlevel (acc);
2386         g_object_set (acc, "type", type, NULL);
2387 	qof_instance_decrease_editlevel (acc);
2388         if (type == ACCT_TYPE_STOCK || type == ACCT_TYPE_MUTUAL ||
2389                 type == ACCT_TYPE_CURRENCY)
2390             g_assert (xaccAccountIsPriced (acc));
2391         else
2392             g_assert (!xaccAccountIsPriced (acc));
2393 
2394     }
2395     g_object_unref (acc);
2396 
2397     loghandler = g_log_set_handler (logdomain, loglevel,
2398                                     (GLogFunc)test_null_handler, check1);
2399     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check1);
2400     g_assert (!xaccAccountTypeEnumAsString (ACCT_TYPE_LAST));
2401     g_assert_cmpint (check1->hits, ==, 1);
2402 
2403     g_log_remove_handler (logdomain, loghandler);
2404     g_free (msg1);
2405     loghandler = g_log_set_handler (logdomain, loglevel,
2406                                     (GLogFunc)test_null_handler, check2);
2407     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check2);
2408     g_assert (!xaccAccountStringToType (NULL, &type));
2409     g_assert_cmpint (check2->hits, ==, 1);
2410 
2411     g_log_remove_handler (logdomain, loghandler);
2412     loghandler = g_log_set_handler (logdomain, loglevel,
2413                                     (GLogFunc)test_null_handler, check3);
2414     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check3);
2415     g_assert (!xaccAccountStringToType ("LAST", &type));
2416     g_assert_cmpint (check3->hits, ==, 1);
2417 
2418     g_log_remove_handler (logdomain, loghandler);
2419 
2420 
2421 }
2422 /* xaccParentAccountTypesCompatibleWith
2423  * xaccAccountTypesCompatible
2424  * xaccAccountTypesCompatibleWith
2425 guint32
2426 xaccParentAccountTypesCompatibleWith (GNCAccountType type)// C: 5 in 3 */
2427 static void
test_xaccAccountType_Compatibility(void)2428 test_xaccAccountType_Compatibility (void)
2429 {
2430     guint32 bank_compat = ((1 << ACCT_TYPE_BANK)       |
2431                            (1 << ACCT_TYPE_CASH)       |
2432                            (1 << ACCT_TYPE_ASSET)      |
2433                            (1 << ACCT_TYPE_STOCK)      |
2434                            (1 << ACCT_TYPE_MUTUAL)     |
2435                            (1 << ACCT_TYPE_CURRENCY)   |
2436                            (1 << ACCT_TYPE_CREDIT)     |
2437                            (1 << ACCT_TYPE_LIABILITY)  |
2438                            (1 << ACCT_TYPE_RECEIVABLE) |
2439                            (1 << ACCT_TYPE_PAYABLE)    |
2440                            (1 << ACCT_TYPE_ROOT));
2441     guint32 expense_compat = ((1 << ACCT_TYPE_INCOME)     |
2442                               (1 << ACCT_TYPE_EXPENSE)    |
2443                               (1 << ACCT_TYPE_ROOT));
2444     guint32 equity_compat = ((1 << ACCT_TYPE_EQUITY) | (1 << ACCT_TYPE_ROOT));
2445     guint32 trading_compat = ((1 << ACCT_TYPE_TRADING) | (1 << ACCT_TYPE_ROOT));
2446     guint32 currency_compat = ((1 << ACCT_TYPE_BANK)       |
2447                                (1 << ACCT_TYPE_CASH)       |
2448                                (1 << ACCT_TYPE_ASSET)      |
2449                                (1 << ACCT_TYPE_CREDIT)     |
2450                                (1 << ACCT_TYPE_LIABILITY)  |
2451                                (1 << ACCT_TYPE_INCOME)     |
2452                                (1 << ACCT_TYPE_EXPENSE)    |
2453                                (1 << ACCT_TYPE_EQUITY));
2454     guint32 stock_compat = ((1 << ACCT_TYPE_STOCK)      |
2455                             (1 << ACCT_TYPE_MUTUAL)     |
2456                             (1 << ACCT_TYPE_CURRENCY));
2457     guint32 immutable_ar_compat = (1 << ACCT_TYPE_RECEIVABLE);
2458     guint32 immutable_ap_compat = (1 << ACCT_TYPE_PAYABLE);
2459     guint32 immutable_trading_compat = (1 << ACCT_TYPE_TRADING);
2460     guint32 compat;
2461     GNCAccountType  type;
2462     auto msg1 = g_strdup_printf ("[xaccParentAccountTypesCompatibleWith()] bad account type: %d", ACCT_TYPE_ROOT);
2463     auto msg2 = g_strdup_printf ("[xaccParentAccountTypesCompatibleWith()] bad account type: %d", ACCT_TYPE_SAVINGS);
2464     auto logdomain = "gnc.account";
2465     auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
2466     auto check1 = test_error_struct_new(logdomain, loglevel, msg1);
2467     auto check2 = test_error_struct_new(logdomain, loglevel, msg2);
2468     gint loghandler;
2469 
2470     for (type = ACCT_TYPE_BANK; type < NUM_ACCOUNT_TYPES; ++type)
2471     {
2472         if (type == ACCT_TYPE_ROOT)
2473         {
2474             loghandler = g_log_set_handler (logdomain, loglevel,
2475                                             (GLogFunc)test_null_handler, check1);
2476             g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler,
2477                                           check1);
2478             compat = xaccParentAccountTypesCompatibleWith (type);
2479             g_log_remove_handler (logdomain, loghandler);
2480             g_assert_cmpint (compat, == , 0);
2481             g_assert_cmpint (check1->hits, ==, 1);
2482             g_free (msg1);
2483             continue;
2484         }
2485         compat = xaccParentAccountTypesCompatibleWith (type);
2486 
2487         if (type <= ACCT_TYPE_CURRENCY || type == ACCT_TYPE_PAYABLE
2488                 || type == ACCT_TYPE_RECEIVABLE)
2489             g_assert_cmpint (compat, == , bank_compat);
2490         else if (type == ACCT_TYPE_INCOME || type == ACCT_TYPE_EXPENSE)
2491             g_assert_cmpint (compat, == , expense_compat);
2492         else if (type == ACCT_TYPE_EQUITY)
2493             g_assert_cmpint (compat, == , equity_compat);
2494         else if (type == ACCT_TYPE_TRADING)
2495             g_assert_cmpint (compat, == , trading_compat);
2496         for (auto parent = ACCT_TYPE_NONE; parent < ACCT_TYPE_LAST; ++parent)
2497             if (1 << parent & compat)
2498                 g_assert (xaccAccountTypesCompatible (parent, type));
2499             else
2500                 g_assert (!xaccAccountTypesCompatible (parent, type));
2501 
2502         compat = xaccAccountTypesCompatibleWith (type);
2503         if (type <= ACCT_TYPE_LIABILITY ||
2504             (type >= ACCT_TYPE_INCOME && type <= ACCT_TYPE_EQUITY))
2505             g_assert_cmpint (compat, == , currency_compat);
2506         else if (type >= ACCT_TYPE_STOCK && type <= ACCT_TYPE_CURRENCY)
2507             g_assert_cmpint (compat, == , stock_compat);
2508         else if (type == ACCT_TYPE_RECEIVABLE)
2509             g_assert_cmpint (compat, == , immutable_ar_compat);
2510         else if (type == ACCT_TYPE_PAYABLE)
2511             g_assert_cmpint (compat, == , immutable_ap_compat);
2512         else if (type == ACCT_TYPE_TRADING)
2513             g_assert_cmpint (compat, == , immutable_trading_compat);
2514     }
2515 
2516     loghandler = g_log_set_handler (logdomain, loglevel,
2517                                     (GLogFunc)test_null_handler, check2);
2518     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check2);
2519     compat = xaccParentAccountTypesCompatibleWith (++type);
2520     g_log_remove_handler (logdomain, loghandler);
2521     g_assert_cmpint (compat, == , 0);
2522     g_assert_cmpint (check2->hits, ==, 1);
2523     g_free (msg2);
2524 }
2525 /* More KVP getters & setters
2526  * xaccAccountGetReconcileLastDate
2527  * xaccAccountSetReconcileLastDate
2528  * xaccAccountGetReconcilePostponeDate
2529  * xaccAccountSetReconcilePostponeDate
2530  * xaccAccountGetReconcilePostponeBalance
2531  * xaccAccountSetReconcilePostponeBalance
2532  * xaccAccountClearReconcilePostpone
2533  * xaccAccountGetAutoInterestXfer
2534  * xaccAccountSetAutoInterestXfer
2535  * xaccAccountGetLastNum
2536  * xaccAccountSetLastNum
2537  * xaccAccountSetReconcileChildrenStatus
2538  * xaccAccountGetReconcileChildrenStatus
2539  * xaccAccountGetReconcileLastInterval
2540  * xaccAccountSetReconcileLastInterval
2541  * dxaccAccountSetPriceSrc
2542  * dxaccAccountSetQuoteTZ
2543  * dxaccAccountGetQuoteTZ
2544  */
2545 /* finder_help_function
2546 static void
2547 finder_help_function (const Account *acc, const char *description,// 3
2548 Helper function, fully exercised by the following two public functions
2549 */
2550 /* xaccAccountFindSplitByDesc
2551 Split *
2552 xaccAccountFindSplitByDesc (const Account *acc, const char *description)// C: 5 in 3 */
2553 
2554 static void
test_xaccAccountFindSplitByDesc(Fixture * fixture,gconstpointer pData)2555 test_xaccAccountFindSplitByDesc (Fixture *fixture, gconstpointer pData)
2556 {
2557     Account *root = gnc_account_get_root (fixture->acct);
2558     Account *baz = gnc_account_lookup_by_name (root, "baz");
2559     gchar *memo;
2560     Split *split = xaccAccountFindSplitByDesc (baz, "pepper");
2561     g_assert (split);
2562     g_object_get (split, "memo", &memo, NULL);
2563     g_assert_cmpstr (memo, == , "pepper_baz");
2564     g_free (memo);
2565 }
2566 /* xaccAccountFindTransByDesc
2567 Transaction *
2568 xaccAccountFindTransByDesc (const Account *acc, const char *description)// C: 5 in 3 */
2569 static void
test_xaccAccountFindTransByDesc(Fixture * fixture,gconstpointer pData)2570 test_xaccAccountFindTransByDesc (Fixture *fixture, gconstpointer pData)
2571 {
2572     Account *root = gnc_account_get_root (fixture->acct);
2573     Account *baz = gnc_account_lookup_by_name (root, "baz");
2574     gchar *desc;
2575     Transaction *txn = xaccAccountFindTransByDesc (baz, "pepper");
2576     g_assert (txn);
2577     g_object_get (txn, "description", &desc, NULL);
2578     g_assert_cmpstr (desc, == , "pepper");
2579     g_free (desc);
2580 }
2581 /* gnc_account_join_children
2582 void
2583 gnc_account_join_children (Account *to_parent, Account *from_parent)// C: 4 in 2 SCM: 3 in 3*/
2584 static void
test_gnc_account_join_children(Fixture * fixture,gconstpointer pData)2585 test_gnc_account_join_children (Fixture *fixture, gconstpointer pData)
2586 {
2587     Account *root = gnc_account_get_root (fixture->acct);
2588     Account *broker = gnc_account_lookup_by_name (root, "broker");
2589     Account *income = gnc_account_lookup_by_name (root, "income");
2590     gint broker_desc = gnc_account_n_descendants (broker);
2591     gint income_desc = gnc_account_n_descendants (income);
2592 
2593     g_test_message ("The following should fail because of account type incompatibility. It doesn't, which is a bug.");
2594     gnc_account_join_children (income, broker);
2595     g_assert_cmpint (gnc_account_n_descendants (income), == ,
2596                      broker_desc + income_desc);
2597 
2598 
2599 }
2600 /* gnc_account_merge_children
2601 void
2602 gnc_account_merge_children (Account *parent)// C: 4 in 2 SCM: 2 in 2*/
2603 static void
test_gnc_account_merge_children(Fixture * fixture,gconstpointer pData)2604 test_gnc_account_merge_children (Fixture *fixture, gconstpointer pData)
2605 {
2606     Account *root = gnc_account_get_root (fixture->acct);
2607     Account *taxable = gnc_account_lookup_by_name (root, "taxable");
2608     Account *expense = gnc_account_lookup_by_name (root, "expense");
2609     Account *div = gnc_account_lookup_by_name (root, "div");
2610     Account *div1 = gnc_account_lookup_by_name (root, "div1");
2611     gint taxable_desc = gnc_account_n_descendants (taxable);
2612     gint expense_desc = gnc_account_n_descendants (expense);
2613     TestSignal sig4, sig5;
2614     /* This segment doesn't test because of problems with resetting
2615      * the accounts on the splits. It will have to be rewritten with a
2616      * mock Split object
2617     Account *stocks = gnc_account_lookup_by_name (root, "stocks");
2618     Account *baz = gnc_account_lookup_by_name (root, "baz");
2619     Account *baz2 = gnc_account_lookup_by_name (root, "baz2");
2620     gint stocks_desc = gnc_account_n_descendants (stocks);
2621     gfloat stocks_balance = gnc_numeric_to_double (
2622                                 xaccAccountGetBalance (stocks));
2623     gfloat baz_balance = gnc_numeric_to_double (xaccAccountGetBalance (baz));
2624     gfloat baz2_balance = gnc_numeric_to_double (xaccAccountGetBalance (baz2));
2625     TestSignal sig1, sig2, sig3;
2626     auto logdomain = "gnc.engine";
2627     auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
2628     auto msg = "[xaccSplitCommitEdit ()] Account grabbed split prematurely.";
2629     auto check = test_error_struct_new(logdomain, loglevel, msg);
2630     guint hdlr = g_log_set_handler (logdomain, loglevel,
2631     			   (GLogFunc)test_null_handler, check);
2632     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check);
2633 
2634     sig1 = test_signal_new (QOF_INSTANCE (baz), QOF_EVENT_MODIFY, NULL);
2635     sig2 = test_signal_new (QOF_INSTANCE (baz2), QOF_EVENT_MODIFY, NULL);
2636     sig3 = test_signal_new (QOF_INSTANCE (baz2), QOF_EVENT_DESTROY, NULL);
2637 
2638     gnc_account_foreach_descendant (stocks, (AccountCb)print_account, NULL);
2639     g_object_set (baz2, "name", "baz", NULL);
2640     gnc_account_merge_children (stocks);
2641     gnc_account_foreach_descendant (stocks, (AccountCb)print_account, NULL);
2642     g_assert_cmpint (gnc_account_n_descendants (stocks), ==, stocks_desc - 1);
2643     g_assert_cmpfloat (gnc_numeric_to_double (xaccAccountGetBalance (stocks)),
2644     	       ==, stocks_balance);
2645     g_assert_cmpfloat (gnc_numeric_to_double (xaccAccountGetBalance (baz)),
2646     	       ==, baz_balance + baz2_balance);
2647     test_signal_assert_hits (sig1, 0);
2648     test_signal_assert_hits (sig2, 0);
2649     test_signal_assert_hits (sig3, 1);
2650     test_signal_free (sig1);
2651     test_signal_free (sig2);
2652     test_signal_free (sig3);
2653     g_log_remove_handler (logdomain, hdlr);
2654     g_free (msg);
2655     */
2656     sig4 = test_signal_new (QOF_INSTANCE (div), QOF_EVENT_MODIFY, NULL);
2657     sig5 = test_signal_new (QOF_INSTANCE (div1), QOF_EVENT_MODIFY, NULL);
2658     qof_instance_increase_editlevel (div1);
2659     g_object_set (div1, "name", "div", NULL);
2660     qof_instance_decrease_editlevel (div1);
2661     gnc_account_merge_children (taxable);
2662     g_assert_cmpint (gnc_account_n_descendants (taxable), == , taxable_desc - 1);
2663     test_signal_assert_hits (sig4, 1);
2664     test_signal_assert_hits (sig5, 3);
2665     test_signal_free (sig4);
2666     test_signal_free (sig5);
2667     gnc_account_merge_children (expense);
2668     g_assert_cmpint (gnc_account_n_descendants (expense), == , expense_desc);
2669 }
2670 /* xaccSplitsBeginStagedTransactionTraversals
2671  * xaccAccountBeginStagedTransactionTraversals
2672  * gnc_account_tree_begin_staged_transaction_traversals
2673  * xaccAccountStagedTransactionTraversal
2674  * gnc_account_tree_staged_transaction_traversal
2675  * Static helper functions for xaccAccount (Tree)?ForEach ()
2676  */
2677 /* xaccTransactionTraverse
2678 gboolean
2679 xaccTransactionTraverse (Transaction *trans, int stage)// Used only by xaccSplitTransactionTraverses (not used) delete.
2680 */
2681 /* xaccSplitTransactionTraverse
2682 gboolean
2683 xaccSplitTransactionTraverse (Split *split, int stage)// Not used, delete.
2684 */
2685 /* do_one_split
2686  * do_one_account
2687  Trivial helper functions
2688 */
2689 typedef struct
2690 {
2691     guint count;
2692     gchar *name;
2693 } Thunkdata;
2694 
2695 static gint
thunk3(Transaction * txn,gpointer data)2696 thunk3 (Transaction *txn, gpointer data)
2697 {
2698     Thunkdata *td = (Thunkdata*)data;
2699     ++(td->count);
2700     if (td->name)
2701     {
2702         gchar *txn_desc;
2703         gboolean result;
2704         g_object_get (txn, "description", &txn_desc, NULL);
2705         result = g_strcmp0 (td->name, txn_desc) == 0;
2706         g_free (txn_desc);
2707         if (result)
2708             return td->count;
2709     }
2710     return 0;
2711 }
2712 
2713 /* xaccAccountTreeForEachTransaction
2714 int
2715 xaccAccountTreeForEachTransaction (Account *acc, TransactionCallback proc,
2716                                    void *data);// C: 302 in 89 SCM: 1158 in 142*/
2717 static void
test_xaccAccountTreeForEachTransaction(Fixture * fixture,gconstpointer pData)2718 test_xaccAccountTreeForEachTransaction (Fixture *fixture, gconstpointer pData )
2719 {
2720     Thunkdata td = {0, NULL};
2721     Account *root = gnc_account_get_root (fixture->acct);
2722     gint result;
2723     result = xaccAccountTreeForEachTransaction (root, thunk3, &td);
2724     g_assert_cmpint (td.count, == , 9);
2725     g_assert_cmpint (result, == , 0);
2726     td.count = 0;
2727     td.name = g_strdup("pepper");
2728     result = xaccAccountTreeForEachTransaction (root, thunk3, &td);
2729     g_assert_cmpint (td.count, == , result);
2730     g_assert_cmpint (result, < , 9);
2731     g_free(td.name);
2732 }
2733 /* xaccAccountForEachTransaction
2734 gint
2735 xaccAccountForEachTransaction (const Account *acc, TransactionCallback proc,// C: 8 in 4 */
2736 static void
test_xaccAccountForEachTransaction(Fixture * fixture,gconstpointer pData)2737 test_xaccAccountForEachTransaction (Fixture *fixture, gconstpointer pData )
2738 {
2739     Thunkdata td = {0, NULL};
2740     Account *root = gnc_account_get_root (fixture->acct);
2741     Account *money = gnc_account_lookup_by_name (root, "money");
2742     gint result;
2743     result = xaccAccountForEachTransaction (root, thunk3, &td);
2744     g_assert_cmpint (td.count, == , 0);
2745     g_assert (money);
2746     result = xaccAccountForEachTransaction (money, thunk3, &td);
2747     g_assert_cmpint (td.count, == , 9);
2748     g_assert_cmpint (result, == , 0);
2749     td.count = 0;
2750     td.name = g_strdup("pepper");
2751     result = xaccAccountForEachTransaction (money, thunk3, &td);
2752     g_assert_cmpint (td.count, == , result);
2753     g_assert_cmpint (result, < , 9);
2754     g_free(td.name);
2755 }
2756 
2757 
2758 void
test_suite_account(void)2759 test_suite_account (void)
2760 {
2761 
2762     GNC_TEST_ADD_FUNC (suitename, "gnc set account separator", test_gnc_set_account_separator);
2763     GNC_TEST_ADD_FUNC (suitename, "gnc account name violations errmsg", test_gnc_account_name_violations_errmsg);
2764     GNC_TEST_ADD (suitename, "gnc account list name violations", Fixture, &bad_data, setup, test_gnc_account_list_name_violations,  teardown);
2765     GNC_TEST_ADD_FUNC (suitename, "account create and destroy", test_gnc_account_create_and_destroy);
2766     GNC_TEST_ADD (suitename, "book set/get root account", Fixture, NULL, setup, test_gnc_book_set_get_root_account, teardown);
2767     GNC_TEST_ADD_FUNC (suitename, "xaccMallocAccount", test_xaccMallocAccount);
2768 
2769     GNC_TEST_ADD_FUNC (suitename, "gnc account create root", test_gnc_account_create_root);
2770     GNC_TEST_ADD (suitename, "xaccCloneAccount", Fixture, NULL, setup, test_xaccCloneAccount,  teardown );
2771     /*Destroys the account, so we have to do the tear down in the test function */
2772     GNC_TEST_ADD (suitename, "xaccFreeAccountChildren", Fixture,  &good_data, setup, test_xaccFreeAccountChildren,  NULL);
2773     /* See comment at the beginning of test_xaccFreeAccount */
2774     GNC_TEST_ADD (suitename, "xaccFreeAccount", Fixture, &good_data, setup, test_xaccFreeAccount,  NULL );
2775     GNC_TEST_ADD (suitename, "xaccAccountCommitEdit", Fixture, &good_data, setup, test_xaccAccountCommitEdit,  NULL );
2776 // GNC_TEST_ADD (suitename, "xaccAcctChildrenEqual", Fixture, NULL, setup, test_xaccAcctChildrenEqual,  teardown );
2777 // GNC_TEST_ADD (suitename, "xaccAccountEqual", Fixture, NULL, setup, test_xaccAccountEqual,  teardown );
2778     GNC_TEST_ADD (suitename, "gnc account kvp getters & setters", Fixture, NULL, setup, test_gnc_account_kvp_setters_getters,  teardown );
2779     GNC_TEST_ADD (suitename, "test_gnc_account_get_map_entry", Fixture, NULL, setup, test_gnc_account_get_map_entry,  teardown );
2780     GNC_TEST_ADD (suitename, "gnc account insert & remove split", Fixture, NULL, setup, test_gnc_account_insert_remove_split,  teardown );
2781     GNC_TEST_ADD (suitename, "xaccAccount Insert and Remove Lot", Fixture, &good_data, setup, test_xaccAccountInsertRemoveLot,  teardown );
2782     GNC_TEST_ADD (suitename, "xaccAccountRecomputeBalance", Fixture, &some_data, setup, test_xaccAccountRecomputeBalance,  teardown );
2783     GNC_TEST_ADD_FUNC (suitename, "xaccAccountOrder", test_xaccAccountOrder );
2784     GNC_TEST_ADD (suitename, "qofAccountSetParent", Fixture, &some_data, setup, test_qofAccountSetParent,  teardown );
2785     GNC_TEST_ADD (suitename, "gnc account append/remove child", Fixture, NULL, setup, test_gnc_account_append_remove_child,  teardown );
2786     GNC_TEST_ADD (suitename, "gnc account n descendants", Fixture, &some_data, setup, test_gnc_account_n_descendants,  teardown );
2787     GNC_TEST_ADD (suitename, "gnc account get current depth", Fixture, &some_data, setup, test_gnc_account_get_current_depth,  teardown );
2788     GNC_TEST_ADD (suitename, "gnc account get tree depth", Fixture, &complex, setup, test_gnc_account_get_tree_depth,  teardown );
2789     GNC_TEST_ADD (suitename, "gnc account get descendants", Fixture, &complex, setup, test_gnc_account_get_descendants,  teardown );
2790     GNC_TEST_ADD (suitename, "gnc account get descendants sorted", Fixture, &complex, setup, test_gnc_account_get_descendants_sorted,  teardown );
2791     GNC_TEST_ADD (suitename, "gnc account lookup by name", Fixture, &complex, setup, test_gnc_account_lookup_by_name,  teardown );
2792     GNC_TEST_ADD (suitename, "gnc account lookup by code", Fixture, &complex, setup, test_gnc_account_lookup_by_code,  teardown );
2793     GNC_TEST_ADD (suitename, "gnc account lookup by full name helper", Fixture, &complex, setup, test_gnc_account_lookup_by_full_name_helper,  teardown );
2794     GNC_TEST_ADD (suitename, "gnc account lookup by full name", Fixture, &complex, setup, test_gnc_account_lookup_by_full_name,  teardown );
2795     GNC_TEST_ADD (suitename, "gnc account foreach child", Fixture, &complex, setup, test_gnc_account_foreach_child,  teardown );
2796     GNC_TEST_ADD (suitename, "gnc account foreach descendant", Fixture, &complex, setup, test_gnc_account_foreach_descendant,  teardown );
2797     GNC_TEST_ADD (suitename, "gnc account foreach descendant until", Fixture, &complex, setup, test_gnc_account_foreach_descendant_until,  teardown );
2798     GNC_TEST_ADD (suitename, "gnc account get full name", Fixture, &good_data, setup, test_gnc_account_get_full_name,  teardown );
2799     GNC_TEST_ADD (suitename, "xaccAccountGetProjectedMinimumBalance", Fixture, &some_data, setup, test_xaccAccountGetProjectedMinimumBalance,  teardown );
2800     GNC_TEST_ADD (suitename, "xaccAccountGetBalanceAsOfDate", Fixture, &some_data, setup, test_xaccAccountGetBalanceAsOfDate,  teardown );
2801     GNC_TEST_ADD (suitename, "xaccAccountGetPresentBalance", Fixture, &some_data, setup, test_xaccAccountGetPresentBalance,  teardown );
2802     GNC_TEST_ADD (suitename, "xaccAccountFindOpenLots", Fixture, &complex_data, setup, test_xaccAccountFindOpenLots,  teardown );
2803     GNC_TEST_ADD (suitename, "xaccAccountForEachLot", Fixture, &complex_data, setup, test_xaccAccountForEachLot,  teardown );
2804 
2805     GNC_TEST_ADD (suitename, "xaccAccountHasAncestor", Fixture, &complex, setup, test_xaccAccountHasAncestor,  teardown );
2806     GNC_TEST_ADD_FUNC (suitename, "AccountType Stuff", test_xaccAccountType_Stuff );
2807     GNC_TEST_ADD_FUNC (suitename, "AccountType Compatibility", test_xaccAccountType_Compatibility);
2808     GNC_TEST_ADD (suitename, "xaccAccountFindSplitByDesc", Fixture, &complex_data, setup, test_xaccAccountFindSplitByDesc,  teardown );
2809     GNC_TEST_ADD (suitename, "xaccAccountFindTransByDesc", Fixture, &complex_data, setup, test_xaccAccountFindTransByDesc,  teardown );
2810     GNC_TEST_ADD (suitename, "gnc account join children", Fixture, &complex, setup, test_gnc_account_join_children,  teardown );
2811     GNC_TEST_ADD (suitename, "gnc account merge children", Fixture, &complex_data, setup, test_gnc_account_merge_children,  teardown );
2812     GNC_TEST_ADD (suitename, "xaccAccountForEachTransaction", Fixture, &complex_data, setup, test_xaccAccountForEachTransaction,  teardown );
2813     GNC_TEST_ADD (suitename, "xaccAccountTreeForEachTransaction", Fixture, &complex_data, setup, test_xaccAccountTreeForEachTransaction,  teardown );
2814 
2815 
2816 }
2817