39 #include <kvp-frame.hpp> 45 #define __STDC_FORMAT_MACROS 47 #include <sys/types.h> 62 #include "gnc-session.h" 64 #include "TransactionP.h" 65 #include "Recurrence.h" 70 #include "test-stuff.h" 71 #include "test-engine-strings.h" 73 #include <qofinstance-p.h> 75 static gboolean glist_strings_only = FALSE;
77 static GHashTable *exclude_kvp_types = NULL;
78 static gint kvp_max_depth = 5;
79 static gint kvp_frame_max_elements = 10;
81 static gint max_tree_depth = 1;
82 static gint max_level_accounts = 3;
83 static gint max_total_accounts = 10;
84 static gint max_trans_num = 1000;
85 static gint total_num_accounts = 0;
87 static gint max_scu = 100;
88 static gint min_scu = 100;
89 static const int64_t num_limit = INT64_MAX;
90 static const int64_t max_denom_mult = 1000000000LL;
99 static gint borked = 80;
101 gboolean gnc_engine_debug_random = FALSE;
107 set_max_account_tree_depth (gint max_tree_depth_in)
109 max_tree_depth = MAX (max_tree_depth_in, 1);
113 set_max_accounts_per_level (gint max_level_accounts_in)
115 max_level_accounts = MAX (max_level_accounts_in, 1);
119 set_max_kvp_depth (gint max_kvp_depth)
121 kvp_max_depth = MAX (max_kvp_depth, 1);
125 set_max_kvp_frame_elements (gint max_kvp_frame_elements)
127 kvp_frame_max_elements = MAX (max_kvp_frame_elements, 1);
131 kvp_exclude_type (KvpValue::Type kvp_type)
135 if (!exclude_kvp_types)
136 exclude_kvp_types = g_hash_table_new (g_int_hash, g_int_equal);
138 key = g_new (gint, 1);
141 g_hash_table_insert (exclude_kvp_types, key, exclude_kvp_types);
145 kvp_type_excluded (KvpValue::Type kvp_type)
149 if (!exclude_kvp_types)
152 if (g_hash_table_lookup (exclude_kvp_types, &key))
158 static gboolean zero_nsec = FALSE;
162 static inline gboolean
165 if (1 == get_random_int_in_range (0, borked))
176 get_random_list_element (GList *list)
178 g_return_val_if_fail (list, NULL);
180 return g_list_nth_data (list,
181 get_random_int_in_range (0,
182 g_list_length (list) - 1));
185 static KvpValue* get_random_kvp_value_depth (
int type, gint depth);
188 get_random_glist_depth (gint depth)
191 int count = get_random_int_in_range(1, 5);
194 if (depth >= kvp_max_depth)
197 for (i = 0; i < count; i++)
199 KvpValue *value =
nullptr;
203 value = get_random_kvp_value_depth (-2, depth + 1);
207 ret = g_list_prepend(ret, value);
217 get_random_time (
void)
226 get_random_guid(
void)
239 static KvpFrame* get_random_kvp_frame_depth (gint depth);
242 get_random_kvp_value_depth (
int type, gint depth)
244 KvpValue::Type datype;
249 datype =
static_cast<KvpValue::Type
>(get_random_int_in_range(KvpValue::Type::INT64, KvpValue::Type::FRAME));
254 datype =
static_cast<KvpValue::Type
>(get_random_int_in_range(KvpValue::Type::INT64, KvpValue::Type::FRAME - 1));
257 datype =
static_cast<KvpValue::Type
>(type);
259 if (datype == KvpValue::Type::FRAME && depth >= kvp_max_depth)
262 if (datype == KvpValue::Type::GLIST && depth >= kvp_max_depth)
265 if (kvp_type_excluded (datype))
270 case KvpValue::Type::INT64:
271 ret =
new KvpValue(get_random_gint64());
274 case KvpValue::Type::DOUBLE:
278 case KvpValue::Type::NUMERIC:
282 case KvpValue::Type::STRING:
285 tmp_str = get_random_string();
289 ret =
new KvpValue(tmp_str);
293 case KvpValue::Type::GUID:
295 return new KvpValue(get_random_guid());
299 case KvpValue::Type::TIME64:
301 time64 t = get_random_time();
302 ret =
new KvpValue(t);
306 case KvpValue::Type::GLIST:
307 ret =
new KvpValue(get_random_glist_depth (depth + 1));
310 case KvpValue::Type::FRAME:
312 return new KvpValue(get_random_kvp_frame_depth(depth + 1));
324 get_random_kvp_frame_depth (gint depth)
329 if (depth >= kvp_max_depth)
332 auto ret =
new KvpFrame;
334 vals_to_add = get_random_int_in_range(1, kvp_frame_max_elements);
337 for (; vals_to_add > 0; vals_to_add--)
345 key = get_random_string_without(
"/");
353 val = get_random_kvp_value_depth (-1, depth + 1);
364 ret->set_path({key}, val);
373 get_random_kvp_frame (
void)
375 return get_random_kvp_frame_depth (0);
379 get_random_kvp_value(
int type)
381 return get_random_kvp_value_depth (type, 0);
387 #define RAND_IN_RANGE(X) (((X)*((gint64) (rand()+1)))/RAND_MAX) 390 get_random_gnc_numeric(int64_t deno)
396 if (RAND_MAX / 8 > rand())
399 deno = RAND_IN_RANGE(6000ULL);
403 gint64 norm = RAND_IN_RANGE (11ULL);
415 if (0 == deno) deno = 1;
423 limit = num_limit / (max_denom_mult / deno == 0 ? max_denom_mult : max_denom_mult / deno);
424 numer = get_random_gint64 ();
427 int64_t num = numer % limit;
433 if (0 == numer) numer = 1;
434 g_log(
"test.engine.suff", G_LOG_LEVEL_INFO,
"New GncNumeric %" PRIu64
" / %" PRIu64
" !\n", numer, deno);
435 return gnc_numeric_create(numer, deno);
442 get_random_rate (
void)
446 gint64 numer = get_random_gint64 () % (2ULL << 24);
447 gint64 denom = 100LL;
448 return gnc_numeric_create (numer, denom);
454 const char *types[] =
465 get_random_commodity_namespace(
void)
467 return get_random_string_in_array(types);
470 static gnc_commodity *
471 get_random_commodity_from_table (gnc_commodity_table *
table)
474 gnc_commodity *com = NULL;
476 g_return_val_if_fail (
table, NULL);
485 name_space =
static_cast<char*
>(get_random_list_element (namespaces));
491 com =
static_cast<gnc_commodity*
>(get_random_list_element (commodities));
493 g_list_free (commodities);
499 g_list_free (namespaces);
505 get_random_commodity (QofBook *book)
513 gnc_commodity_table *
table;
520 get_random_int_in_range (1, 5) < 5)
521 return get_random_commodity_from_table (
table);
524 mn = get_random_string_length_in_range(1, 3);
525 space = get_random_commodity_namespace();
529 ret = gnc_commodity_table_lookup (
table, space, mn);
538 name = get_random_string();
539 cusip = get_random_string();
541 ran_int = get_random_int_in_range(min_scu, max_scu);
556 make_random_changes_to_commodity (gnc_commodity *com)
560 g_return_if_fail (com);
562 str = get_random_string ();
566 str = get_random_string ();
570 str = get_random_string ();
574 str = get_random_string ();
582 make_random_changes_to_commodity_table (gnc_commodity_table *
table)
587 g_return_if_fail (
table);
591 for (node = namespaces; node; node = node->next)
593 auto ns =
static_cast<const char *
>(node->data);
602 for (com_node = commodities; com_node; com_node = com_node->next)
604 auto com =
static_cast<gnc_commodity *
>(com_node->data);
607 make_random_changes_to_commodity (com);
611 g_list_free (commodities);
614 g_list_free (namespaces);
620 make_random_changes_to_price (QofBook *book, GNCPrice *p)
627 g_return_if_fail (book && p);
629 gnc_price_begin_edit (p);
631 c = get_random_commodity (book);
632 gnc_price_set_commodity (p, c);
634 c = get_random_commodity (book);
635 gnc_price_set_currency (p, c);
637 time = get_random_time ();
638 gnc_price_set_time64 (p, time);
640 ps = (
PriceSource)get_random_int_in_range((
int)PRICE_SOURCE_EDIT_DLG,
641 (int)PRICE_SOURCE_INVALID);
642 gnc_price_set_source (p, ps);
644 string = get_random_string ();
645 gnc_price_set_typestr (p,
string);
650 gnc_price_commit_edit (p);
654 get_random_price(QofBook *book)
661 failure_args(
"engine-stuff", __FILE__, __LINE__,
662 "get_random_price failed");
666 make_random_changes_to_price (book, p);
669 failure_args(
"engine-stuff", __FILE__, __LINE__,
670 "make_random_changes_to_price failed");
678 make_random_pricedb (QofBook *book, GNCPriceDB *db)
682 num_prices = get_random_int_in_range (1, 41);
685 failure_args(
"engine-stuff", __FILE__, __LINE__,
686 "get_random_int_in_range failed");
690 while (num_prices-- > 0)
694 p = get_random_price (book);
697 failure_args(
"engine-stuff", __FILE__, __LINE__,
698 "get_random_price failed");
712 get_random_pricedb(QofBook *book)
719 failure_args(
"engine-stuff", __FILE__, __LINE__,
720 "gnc_pricedb_get_db failed");
723 if (!make_random_pricedb (book, db))
732 price_accumulator (GNCPrice *p, gpointer data)
734 auto list =
static_cast<GList**
>(data);
736 *list = g_list_prepend (*list, p);
742 make_random_changes_to_pricedb (QofBook *book, GNCPriceDB *pdb)
747 g_return_if_fail (pdb);
751 for (node = list; node; node = node->next)
753 auto p =
static_cast<GNCPrice *
>(node->data);
755 switch (get_random_int_in_range (0, 5))
763 make_random_changes_to_price (book, p);
775 int i = get_random_int_in_range (1, 5);
779 GNCPrice *p = get_random_price (book);
792 set_account_random_string(
Account* act,
793 void(*func)(
Account *act,
const gchar*str))
795 gchar *tmp_str = get_random_string();
798 (func)(act, tmp_str);
804 set_account_random_string_from_array(
808 const gchar *tmp_str = get_random_string_in_array(list);
810 (func)(act, tmp_str);
815 account_add_subaccounts (QofBook *book,
Account *account,
int depth)
822 num_accounts = get_random_int_in_range (1, 10);
823 while (num_accounts-- > 0)
825 Account *sub = get_random_account (book);
829 total_num_accounts ++;
830 if (total_num_accounts > max_total_accounts)
return;
832 account_add_subaccounts (book, sub, depth - 1);
837 make_random_account_tree (QofBook *book,
Account *root)
841 g_return_if_fail (book);
842 g_return_if_fail (root);
844 total_num_accounts = 0;
845 depth = get_random_int_in_range (1, max_tree_depth);
847 account_add_subaccounts (book, root, depth);
850 if (total_num_accounts <= 1)
851 account_add_subaccounts (book, root, 1);
855 get_random_account_tree (QofBook *book)
859 g_return_val_if_fail (book, NULL);
861 root = gnc_book_get_root_account (book);
865 gnc_book_set_root_account (book, root);
868 make_random_account_tree (book, root);
882 add_random_splits(QofBook *book, Transaction *trn, GList *account_list)
889 if (1 >= g_list_length (account_list))
return;
891 auto acc =
static_cast<Account*
>(get_random_list_element (account_list));
893 s1 = get_random_split(book, acc, trn);
895 auto bcc =
static_cast<Account*
>(get_random_list_element (account_list));
896 if ((bcc == acc) && (!do_bork()))
904 bcc =
static_cast<Account*
>(get_random_list_element (account_list));
910 s2 = get_random_split(book, bcc, trn);
916 val = get_random_gnc_numeric(s2_scu);
917 g_log (
"test.engine.suff", G_LOG_LEVEL_DEBUG,
"Borking second %" PRIu64
918 " / %" PRIu64
", scu %d\n", val.num, val.denom, s2_scu);
922 if (val.denom != s2_scu)
924 if (val.denom > s2_scu)
925 val.num /= val.denom / s2_scu;
938 make_random_changes_to_transaction_and_splits (QofBook *book,
946 g_return_if_fail (book);
947 g_return_if_fail (trans);
948 g_return_if_fail (accounts);
952 make_random_changes_to_transaction (book, trans);
954 switch (get_random_int_in_range (0, 3))
968 add_random_splits (book, trans, accounts);
977 for (node = splits; node; node = node->next)
979 auto split =
static_cast<Split *
>(node->data);
980 auto account =
static_cast<Account*
>(get_random_list_element (accounts));
1003 for (node = splits; node; node = node->next)
1005 auto split =
static_cast<Split *
>(node->data);
1007 if (get_random_boolean ())
1008 make_random_changes_to_split (split);
1011 if (get_random_boolean ())
1018 add_trans_helper (Transaction *trans, gpointer data)
1021 auto list =
static_cast<GList **
>(data);
1027 *list = g_list_prepend (*list, ti);
1032 make_random_changes_to_level (QofBook *book,
Account *parent)
1041 g_return_if_fail (parent && book);
1046 new_account = get_random_account (book);
1048 if (get_random_boolean () || !accounts)
1052 account =
static_cast<Account*
>(get_random_list_element (accounts));
1057 g_list_free (accounts);
1061 add_random_transactions_to_book (book, get_random_int_in_range (1, 6));
1064 for (node = accounts; node; node = node->next)
1066 auto account =
static_cast<Account *
>(node->data);
1068 if (get_random_boolean ())
1069 make_random_changes_to_account (book, account);
1076 for (node = transes; node; node = node->next)
1078 auto ti =
static_cast<TransInfo *
>(node->data);
1084 make_random_changes_to_transaction_and_splits (book, trans, accounts);
1087 for (node = transes; node; node = node->next)
1089 auto ti =
static_cast<TransInfo *
>(node->data);
1093 g_list_free (transes);
1097 account =
static_cast<Account*
>(get_random_list_element (accounts));
1100 splits = g_list_copy (splits);
1102 for (node = splits; node; node = node->next)
1104 auto split =
static_cast<Split *
>(node->data);
1108 new_account =
static_cast<Account*
>(get_random_list_element (accounts));
1110 while (new_account == account);
1118 g_list_free (splits);
1119 g_list_free (accounts);
1124 if (accounts && (g_list_length (accounts) > 1))
1126 int i = get_random_int_in_range (1, 4);
1132 auto a1 =
static_cast<Account*
>(get_random_list_element (accounts));
1134 if (get_random_boolean ())
1135 a2 = static_cast<Account*>(get_random_list_element (accounts));
1157 g_list_free (accounts);
1161 get_random_account(QofBook *book)
1171 sane_account_names);
1181 qof_instance_set_slots(QOF_INSTANCE(ret), get_random_kvp_frame());
1183 root = gnc_book_get_root_account (book);
1187 gnc_book_set_root_account (book, root);
1196 make_random_changes_to_account (QofBook *book,
Account *account)
1200 g_return_if_fail (account);
1214 qof_instance_set_slots(QOF_INSTANCE(account), get_random_kvp_frame());
1220 set_split_random_string(Split *spl,
1221 void(*func)(Split *act,
const gchar*str))
1223 gchar *tmp_str = get_random_string();
1226 (func)(spl, tmp_str);
1235 get_random_split(QofBook *book,
Account *acct, Transaction *trn)
1238 gnc_numeric amt = {0, 1}, val = {0, 1}, rate = {0, 0};
1249 str = get_random_string_in_array(sane_descriptions);
1251 str = get_random_string_in_array(sane_actions);
1256 time = get_random_time();
1262 xaccSplitSetParent(ret, trn);
1263 xaccSplitSetAccount(ret, acct);
1267 val = get_random_gnc_numeric (scu);
1269 fprintf(stderr,
"get_random_split: Created split with zero value: %p\n", ret);
1276 if (val.denom > scu && val.num > num_limit / (max_denom_mult / scu))
1278 int64_t new_num = val.num / (val.denom / scu);
1279 g_log(
"test.engine.suff", G_LOG_LEVEL_DEBUG,
1280 "Adjusting val.denom from %" PRIu64
" to %" PRIu64
"\n",
1288 g_log (
"test.engine.suff", G_LOG_LEVEL_DEBUG,
1289 "Random split value: %" PRIu64
" / %" PRIu64
", scu %d\n",
1290 val.num, val.denom, scu);
1307 rate = get_random_rate ();
1312 g_log (
"test.engine.suff", G_LOG_LEVEL_DEBUG,
"Random split amount: %" 1313 PRIu64
" / %" PRIu64
", rate %" PRIu64
" / %" PRIu64
"\n",
1314 amt.num, amt.denom, rate.num, rate.denom);
1328 qof_instance_set_slots(QOF_INSTANCE (ret), get_random_kvp_frame());
1335 make_random_changes_to_split (Split *split)
1340 g_return_if_fail (split);
1351 time = get_random_time();
1354 qof_instance_set_slots (QOF_INSTANCE (split), get_random_kvp_frame());
1364 set_tran_random_string(Transaction* trn,
1365 void(*func)(Transaction *act,
const gchar*str))
1367 gchar *tmp_str = get_random_string();
1375 (func)(trn, tmp_str);
1382 set_tran_random_string_from_array(
1383 Transaction* trn,
void(*func)(Transaction *trn,
const gchar*str),
1384 const gchar *list[])
1386 const gchar *tmp_str = get_random_string_in_array(list);
1388 (func)(trn, tmp_str);
1392 trn_add_ran_time (Transaction *trn,
void (*func)(Transaction*,
time64))
1394 func(trn, get_random_time());
1399 get_random_transaction_with_currency(QofBook *book,
1400 gnc_commodity *currency,
1401 GList *account_list)
1414 if (1 >= g_list_length (account_list))
1416 failure_args(
"engine-stuff", __FILE__, __LINE__,
1417 "get_random_transaction_with_currency: account_list too short");
1421 numstr = g_new0(gchar, 10);
1428 currency ? currency :
1429 get_random_commodity (book));
1431 num = get_random_int_in_range (1, max_trans_num);
1432 g_snprintf(numstr, 10,
"%d", num);
1439 f = get_random_kvp_frame();
1440 qof_instance_set_slots (QOF_INSTANCE (trans), f);
1442 add_random_splits(book, trans, account_list);
1444 if (get_random_int_in_range (1, 10) == 1)
1446 char *reason = get_random_string ();
1454 failure_args(
"engine-stuff", __FILE__, __LINE__,
1455 "get_random_transaction_with_currency failed");
1463 get_random_transaction (QofBook *book)
1467 g_return_val_if_fail(book, NULL);
1468 ret = get_random_transaction_with_currency (book, NULL, NULL);
1471 failure_args(
"engine-stuff", __FILE__, __LINE__,
1472 "get_random_transaction failed");
1479 make_random_changes_to_transaction (QofBook *book, Transaction *trans)
1481 g_return_if_fail (trans && book);
1485 if (get_random_int_in_range (1, 2) == 1)
1501 qof_instance_set_slots (QOF_INSTANCE (trans), get_random_kvp_frame());
1510 get_random_guids(
int max)
1512 GList *guids = NULL;
1515 if (max < 1)
return NULL;
1517 num_guids = get_random_int_in_range (1, max);
1519 while (num_guids-- > 0)
1520 guids = g_list_prepend (guids, get_random_guid ());
1526 free_random_guids(GList *guids)
1530 for (node = guids; node; node = node->next)
1531 g_free (node->data);
1533 g_list_free (guids);
1537 get_random_queryop(
void)
1539 int op_num = get_random_int_in_range(1, 11);
1559 op = QOF_QUERY_NAND;
1568 g_assert_not_reached();
1571 if (gnc_engine_debug_random) printf (
"op = %d (int was %d), ", op, op_num);
1576 get_random_kvp_path (
void)
1582 len = get_random_int_in_range (1, kvp_max_depth);
1585 path = g_slist_prepend (path, get_random_string_without (
"\n\\"));
1587 return g_slist_reverse (path);
1591 free_random_kvp_path (GSList *path)
1595 for (node = path; node; node = node->next)
1596 g_free (node->data);
1598 g_slist_free (path);
1602 get_random_id_type (
void)
1604 switch (get_random_int_in_range (1, 3))
1607 return GNC_ID_SPLIT;
1609 return GNC_ID_TRANS;
1611 return GNC_ID_ACCOUNT;
1613 return get_random_string ();
1631 set_query_sort (QofQuery *q, sort_type_t sort_code)
1633 GSList *p1 = NULL, *p2 = NULL, *p3 = NULL, *standard;
1643 p1 = g_slist_prepend (p1, const_cast<char*>(TRANS_DATE_POSTED));
1644 p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_TRANS));
1647 case BY_DATE_ENTERED:
1648 p1 = g_slist_prepend (p1, const_cast<char*>(TRANS_DATE_ENTERED));
1649 p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_TRANS));
1652 case BY_DATE_RECONCILED:
1653 p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_RECONCILE));
1654 p2 = g_slist_prepend (p2, const_cast<char*>(SPLIT_DATE_RECONCILED));
1658 p1 = g_slist_prepend (p1, const_cast<char*>(TRANS_NUM));
1659 p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_TRANS));
1663 p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_VALUE));
1667 p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_MEMO));
1671 p1 = g_slist_prepend (p1, const_cast<char*>(TRANS_DESCRIPTION));
1672 p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_TRANS));
1676 g_slist_free (standard);
1679 g_slist_free (standard);
1680 g_return_if_fail (FALSE);
1687 template <
typename T>
inline T
1688 compare_param(
int max)
1690 auto ret = get_random_int_in_range (max == 1 ? 0 : 1, max);
1691 return static_cast<T
>(ret);
1695 get_random_query(
void)
1700 num_terms = get_random_int_in_range (1, 3);
1701 if (gnc_engine_debug_random) printf(
"num_terms = %d", num_terms);
1703 q = qof_query_create_for(GNC_ID_SPLIT);
1705 while (num_terms-- > 0)
1716 pr_type = get_random_int_in_range (1, 20);
1717 if (gnc_engine_debug_random) printf(
"\n pr_type = %d ", pr_type);
1722 guids = get_random_guids (10);
1723 xaccQueryAddAccountGUIDMatch
1726 compare_param<QofGuidMatch>(QOF_GUID_MATCH_NONE),
1727 get_random_queryop ());
1728 free_random_guids (guids);
1732 string = get_random_string_without (
"\\");
1733 xaccQueryAddActionMatch (q,
1735 get_random_boolean (),
1736 get_random_boolean (),
1737 compare_param<QofQueryCompare>(QOF_COMPARE_CONTAINS),
1738 get_random_queryop ());
1743 xaccQueryAddBalanceMatch
1745 compare_param<QofQueryCompare> (1),
1746 get_random_queryop ());
1750 xaccQueryAddClearedMatch
1752 static_cast<cleared_match_t>(get_random_int_in_range (1,
1755 CLEARED_RECONCILED |
1758 get_random_queryop ());
1762 start = get_random_time ();
1763 end = get_random_time ();
1764 xaccQueryAddDateMatchTT (q,
1765 get_random_boolean (),
1767 get_random_boolean (),
1769 get_random_queryop ());
1773 string = get_random_string_without (
"\\");
1774 xaccQueryAddDescriptionMatch (q,
1776 get_random_boolean (),
1777 get_random_boolean (),
1778 compare_param<QofQueryCompare>(QOF_COMPARE_CONTAINS),
1779 get_random_queryop ());
1784 guid = get_random_guid ();
1785 xaccQueryAddGUIDMatch (q,
1787 get_random_id_type (),
1788 get_random_queryop ());
1796 string = get_random_string_without (
"\\");
1797 xaccQueryAddMemoMatch (q,
1799 get_random_boolean (),
1800 get_random_boolean (),
1801 compare_param<QofQueryCompare>(QOF_COMPARE_CONTAINS),
1802 get_random_queryop ());
1807 string = get_random_string_without (
"\\");
1808 xaccQueryAddNumberMatch (q,
1810 get_random_boolean (),
1811 get_random_boolean (),
1812 compare_param<QofQueryCompare>(QOF_COMPARE_CONTAINS),
1813 get_random_queryop ());
1818 xaccQueryAddSharePriceMatch
1821 compare_param<QofQueryCompare> (QOF_COMPARE_NEQ),
1822 get_random_queryop ());
1826 xaccQueryAddSharesMatch
1829 compare_param<QofQueryCompare> (QOF_COMPARE_NEQ),
1830 get_random_queryop ());
1834 xaccQueryAddValueMatch
1837 compare_param<QofNumericMatch> (QOF_NUMERIC_MATCH_ANY),
1838 compare_param<QofQueryCompare> (QOF_COMPARE_NEQ),
1839 get_random_queryop ());
1843 if (gnc_engine_debug_random) printf(
"ignored..");
1849 if (gnc_engine_debug_random) printf (
"\n");
1850 set_query_sort (q, compare_param<sort_type_t>(BY_NONE));
1853 get_random_boolean (),
1854 get_random_boolean (),
1855 get_random_boolean ());
1863 get_random_book (
void)
1869 get_random_account_tree (book);
1870 get_random_pricedb (book);
1876 get_random_session (
void)
1879 auto session = qof_session_new (book);
1881 get_random_account_tree (book);
1882 get_random_pricedb (book);
1888 add_random_transactions_to_book (QofBook *book, gint num_transactions)
1890 gnc_commodity_table *
table;
1893 if (num_transactions <= 0)
return;
1895 g_return_if_fail (book);
1898 g_return_if_fail (accounts);
1902 while (num_transactions--)
1906 com = get_random_commodity_from_table (
table);
1907 get_random_transaction_with_currency (book, com, accounts);
1909 g_list_free (accounts);
1913 make_random_changes_to_book (QofBook *book)
1915 g_return_if_fail (book);
1917 make_random_changes_to_level (book, gnc_book_get_root_account (book));
1926 make_random_changes_to_session (QofSession *session)
1928 g_return_if_fail (session);
1940 static gboolean include_price = TRUE;
1943 trans_query_include_price (gboolean include_price_in)
1945 include_price = include_price_in;
1949 get_random_query_type (
void)
1951 switch (get_random_int_in_range (0, 1))
1963 make_trans_query (Transaction *trans, TestQueryTypes query_types)
1970 if (query_types == RANDOM_QT)
1971 query_types = get_random_query_type ();
1973 q = qof_query_create_for(GNC_ID_SPLIT);
1978 if (query_types & SIMPLE_QT)
1985 TRUE, FALSE, QOF_COMPARE_CONTAINS, QOF_QUERY_AND);
1991 TRUE, FALSE, QOF_COMPARE_CONTAINS, QOF_QUERY_AND);
1997 TRUE, FALSE, QOF_COMPARE_CONTAINS, QOF_QUERY_AND);
2001 xaccQueryAddValueMatch (q, n, QOF_NUMERIC_MATCH_ANY,
2002 QOF_COMPARE_EQUAL, QOF_QUERY_AND);
2005 xaccQueryAddSharesMatch (q, n, QOF_COMPARE_EQUAL, QOF_QUERY_AND);
2010 xaccQueryAddSharePriceMatch (q, n, QOF_COMPARE_EQUAL, QOF_QUERY_AND);
2015 xaccQueryAddDateMatchTT (q, TRUE, time, TRUE, time, QOF_QUERY_AND);
2020 xaccQueryAddMemoMatch (q,
xaccSplitGetMemo (s), TRUE, FALSE, QOF_COMPARE_CONTAINS, QOF_QUERY_AND);
2024 cleared_match_t how;
2032 how = CLEARED_CLEARED;
2035 how = CLEARED_RECONCILED;
2038 how = CLEARED_FROZEN;
2041 how = CLEARED_VOIDED;
2044 failure (
"bad reconcile flag");
2049 xaccQueryAddClearedMatch (q, how, QOF_QUERY_AND);
2053 if (query_types & ACCOUNT_QT)
2062 auto split =
static_cast<Split *
>(node->data);
2070 list = g_list_prepend (list, get_random_guid ());
2071 list = g_list_prepend (list, get_random_guid ());
2072 list = g_list_prepend (list, get_random_guid ());
2073 xaccQueryAddAccountGUIDMatch (q, list, QOF_GUID_MATCH_NONE, QOF_QUERY_AND);
2077 GncGUID * guid = get_random_guid ();
2079 list = g_list_prepend (list, guid);
2083 for (node = list; node; node = node->next)
2084 g_free (node->data);
2088 if (query_types & GUID_QT)
2091 GNC_ID_SPLIT, QOF_QUERY_AND);
2094 GNC_ID_TRANS, QOF_QUERY_AND);
2097 GNC_ID_ACCOUNT, QOF_QUERY_AND);
2104 daily_freq(
const GDate* start,
int multiplier)
2107 recurrenceSet(r, multiplier, PERIOD_DAY, start, WEEKEND_ADJ_NONE);
2112 once_freq(
const GDate *when)
2115 recurrenceSet(r, 1, PERIOD_ONCE, when, WEEKEND_ADJ_NONE);
2119 static SchedXaction*
2120 add_sx(
const gchar *name,
const GDate *start,
const GDate *end,
2126 xaccSchedXactionSetStartDate(sx, start);
2129 if (last_occur != NULL)
2130 xaccSchedXactionSetLastOccurDate(sx, last_occur);
2132 GList *recurrences = NULL;
2133 recurrences = g_list_append(recurrences, r);
2137 gnc_sxes_add_sx(gnc_book_get_schedxactions(book), sx);
2143 add_daily_sx(
const gchar *name,
const GDate *start,
2144 const GDate *end,
const GDate *last_occur)
2146 return add_sx(name, start, end, last_occur, daily_freq(start, 1));
2150 add_once_sx(
const gchar *name,
const GDate *when)
2152 return add_sx(name, when, NULL, NULL, once_freq(when));
2156 remove_sx(SchedXaction *sx)
2159 SchedXactions *sxes = gnc_book_get_schedxactions(book);
2160 gnc_sxes_del_sx(sxes, sx);
void xaccAccountSetType(Account *acc, GNCAccountType tip)
Set the account's type.
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.
gnc_commodity * gnc_commodity_table_insert(gnc_commodity_table *table, gnc_commodity *comm)
Add a new commodity to the commodity table.
GNCPrice * gnc_price_create(QofBook *book)
gnc_price_create - returns a newly allocated and initialized price with a reference count of 1...
int xaccAccountTreeForEachTransaction(Account *acc, TransactionCallback proc, void *data)
Traverse all of the transactions in the given account group.
void guid_replace(GncGUID *guid)
Generate a new guid.
void gnc_sx_set_schedule(SchedXaction *sx, GList *schedule)
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
Transaction * xaccMallocTransaction(QofBook *book)
The xaccMallocTransaction() will malloc memory and initialize it.
void xaccSplitSetAction(Split *split, const char *actn)
The Action is an arbitrary user-assigned string.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
void gnc_account_append_child(Account *new_parent, Account *child)
This function will remove from the child account any pre-existing parent relationship, and will then add the account as a child of the new parent.
Split * xaccTransGetSplit(const Transaction *trans, int i)
Return a pointer to the indexed split in this transaction's split list.
SplitList * xaccAccountGetSplitList(const Account *acc)
The xaccAccountGetSplitList() routine returns a pointer to a GList of the splits in the account...
void qof_query_set_sort_order(QofQuery *q, QofQueryParamList *params1, QofQueryParamList *params2, QofQueryParamList *params3)
When a query is run, the results are sorted before being returned.
gboolean xaccSplitDestroy(Split *split)
Destructor.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value...
void gnc_price_unref(GNCPrice *p)
gnc_price_unref - indicate you're finished with a price (i.e.
gboolean gnc_pricedb_add_price(GNCPriceDB *db, GNCPrice *p)
Add a price to the pricedb.
void gnc_commodity_set_fraction(gnc_commodity *cm, int fraction)
Set the fraction for the specified commodity.
char xaccSplitGetReconcile(const Split *split)
Returns the value of the reconcile flag.
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
void xaccAccountSetCode(Account *acc, const char *str)
Set the account's accounting code.
QofBook * qof_book_new(void)
Allocate, initialise and return a new QofBook.
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
void xaccTransSetNum(Transaction *trans, const char *xnum)
Sets the transaction Number (or ID) field; rather than use this function directly, see 'gnc_set_num_action' in engine/engine-helpers.c & .h which takes a user-set book option for selecting the source for the num-cell (the transaction-number or the split-action field) in registers/reports into account automatically.
stop here; the following types just aren't ready for prime time
void xaccSplitSetReconcile(Split *split, char recn)
Set the reconcile flag.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
void qof_query_set_sort_increasing(QofQuery *q, gboolean prim_inc, gboolean sec_inc, gboolean tert_inc)
When a query is run, the results are sorted before being returned.
$brief This file declares testing functions for the engine.
const char * xaccTransGetNum(const Transaction *trans)
Gets the transaction Number (or ID) field; rather than use this function directly, see 'gnc_get_num_action' and 'gnc_get_action_num' in engine/engine-helpers.c & .h which takes a user-set book option for selecting the source for the num-cell (the transaction-number or the split-action field) in registers/reports into account automatically.
These expect a single object and expect the QofAccessFunc returns GncGUID*.
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Return the pricedb associated with the book.
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
#define VREC
split is void
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
void qof_query_set_max_results(QofQuery *q, int n)
Set the maximum number of results that should be returned.
void xaccTransDestroy(Transaction *trans)
Destroys a transaction.
void xaccAccountDestroy(Account *acc)
The xaccAccountDestroy() routine can be used to get rid of an account.
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
The xaccTransLookup() subroutine will return the transaction associated with the given id...
const gchar * QofIdType
QofIdType declaration.
#define xaccAccountGetGUID(X)
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
Account handling public routines.
void qof_query_destroy(QofQuery *query)
Frees the resources associate with a Query object.
void xaccTransVoid(Transaction *trans, const char *reason)
xaccTransVoid voids a transaction.
#define YREC
The Split has been reconciled.
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
GList * gnc_commodity_table_get_namespaces(const gnc_commodity_table *table)
Return a list of all namespaces in the commodity table.
void gnc_commodity_set_cusip(gnc_commodity *cm, const char *cusip)
Set the 'exchange code' for the specified commodity.
#define FREC
frozen into accounting period
gnc_commodity * gnc_commodity_new(QofBook *book, const char *fullname, const char *name_space, const char *mnemonic, const char *cusip, int fraction)
Create a new commodity.
time64 xaccTransRetDatePosted(const Transaction *trans)
Retrieve the posted date of the transaction.
Anchor Scheduled Transaction info in a book.
The bank account type denotes a savings or checking account held at a bank.
gboolean gnc_commodity_namespace_is_iso(const char *name_space)
Checks to see if the specified commodity namespace is the namespace for ISO 4217 currencies.
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
gnc_numeric gnc_numeric_div(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Division.
#define xaccSplitGetGUID(X)
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
gnc_numeric xaccSplitGetSharePrice(const Split *split)
Returns the price of the split, that is, the value divided by the amount.
void xaccTransUnvoid(Transaction *trans)
xaccTransUnvoid restores a voided transaction to its original state.
All type declarations for the whole Gnucash engine.
These expect a GList* of objects and calls the QofAccessFunc routine on each item in the list to obta...
#define CREC
The Split has been cleared.
gboolean gnc_numeric_positive_p(gnc_numeric a)
Returns 1 if a > 0, otherwise returns 0.
gboolean gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p)
Remove a price from the pricedb and unref the price.
Split * xaccMallocSplit(QofBook *book)
Constructor.
#define xaccTransGetGUID(X)
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
CommodityList * gnc_commodity_table_get_commodities(const gnc_commodity_table *table, const char *name_space)
Return a list of all commodities in the commodity table that are in the given namespace.
void xaccSplitSetDateReconciledSecs(Split *split, time64 secs)
Set the date on which this split was reconciled by specifying the time as time64. ...
void xaccSchedXactionSetName(SchedXaction *sx, const gchar *newName)
A copy of the name is made.
QofQueryOp
Query Term Operators, for combining Query Terms.
void xaccTransSetDatePostedSecs(Transaction *trans, time64 secs)
The xaccTransSetDatePostedSecs() method will modify the posted date of the transaction, specified by a time64 (see ctime(3)).
gboolean xaccTransGetVoidStatus(const Transaction *trans)
Retrieve information on whether or not a transaction has been voided.
void gnc_commodity_set_fullname(gnc_commodity *cm, const char *fullname)
Set the full name for the specified commodity.
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction's commodity.
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
gboolean xaccAccountHasAncestor(const Account *acc, const Account *ancestor)
Returns true if the account is 'ancestor' or has 'ancestor' as an ancestor.
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
void gnc_commodity_set_mnemonic(gnc_commodity *cm, const char *mnemonic)
Set the mnemonic for the specified commodity.
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account...
This is the private header for the account structure.
PriceSource
Price source enum.
#define QUERY_DEFAULT_SORT
Default sort object type.
Account * xaccMallocAccount(QofBook *book)
Constructor.
void gnc_commodity_table_remove(gnc_commodity_table *table, gnc_commodity *comm)
Remove a commodity from the commodity table.
void gnc_commodity_set_namespace(gnc_commodity *cm, const char *name_space)
Set the namespace for the specified commodity.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
const char * xaccSplitGetAction(const Split *split)
Returns the action string.
SchedXaction * xaccSchedXactionMalloc(QofBook *book)
Creates and initializes a scheduled transaction.
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
guint gnc_commodity_table_get_size(const gnc_commodity_table *tbl)
Returns the number of commodities in the commodity table.
gboolean gnc_pricedb_foreach_price(GNCPriceDB *db, GncPriceForeachFunc f, gpointer user_data, gboolean stable_order)
Call a GncPriceForeachFunction once for each price in db, until the function returns FALSE...
void xaccAccountSetDescription(Account *acc, const char *str)
Set the account's description.
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Modify the date of when the transaction was entered.
Scheduled Transactions public handling routines.
void xaccSchedXactionSetEndDate(SchedXaction *sx, const GDate *newEnd)
Set to an invalid GDate to turn off 'end-date' definition.
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
API for Transactions and Splits (journal entries)
The type used to store guids in C.
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
void xaccAccountSetName(Account *acc, const char *str)
Set the account's name.
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
void xaccTransRollbackEdit(Transaction *trans)
The xaccTransRollbackEdit() routine rejects all edits made, and sets the transaction back to where it...
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
Set the account's commodity.
#define NREC
not reconciled or cleared
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.