1 /***************************************************************************
2 * test-xml-account.c
3 *
4 * Sun Oct 9 15:37:26 2005
5 * Copyright 2005 Neil Williams
6 * linux@codehelp.co.uk
7 ****************************************************************************/
8 /*
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24 #include <glib.h>
25 #include <glib/gstdio.h>
26
27 extern "C"
28 {
29 #include <config.h>
30
31 #include <unistd.h>
32 #include <gnc-engine.h>
33 #include <cashobjects.h>
34
35 #include <test-engine-stuff.h>
36 #include <unittest-support.h>
37
38 #include "Account.h"
39 #include "Scrub.h"
40 }
41
42 #include <cstdlib>
43
44 #include "../gnc-xml-helper.h"
45 #include "../gnc-xml.h"
46 #include "../sixtp-parsers.h"
47 #include "../sixtp-dom-parsers.h"
48 #include "test-file-stuff.h"
49 #include <test-stuff.h>
50
51 static QofBook* sixbook;
52
53 static gchar*
node_and_account_equal(xmlNodePtr node,Account * act)54 node_and_account_equal (xmlNodePtr node, Account* act)
55 {
56 xmlNodePtr mark;
57
58 while (g_strcmp0 ((char*)node->name, "text") == 0)
59 {
60 node = node->next;
61 }
62
63 if (!check_dom_tree_version (node, "2.0.0"))
64 {
65 return g_strdup ("version wrong. Not 2.0.0 or not there");
66 }
67
68 if (!node->name || g_strcmp0 ((char*)node->name, "gnc:account"))
69 {
70 return g_strdup ("Name of toplevel node is bad");
71 }
72
73 for (mark = node->xmlChildrenNode; mark; mark = mark->next)
74 {
75 if (g_strcmp0 ((char*)mark->name, "text") == 0)
76 {
77 }
78 else if (g_strcmp0 ((char*)mark->name, "act:name") == 0)
79 {
80 if (!equals_node_val_vs_string (mark, xaccAccountGetName (act)))
81 {
82 return g_strdup ("names differ");
83 }
84 }
85 else if (g_strcmp0 ((char*)mark->name, "act:id") == 0)
86 {
87 if (!equals_node_val_vs_guid (mark, xaccAccountGetGUID (act)))
88 {
89 return g_strdup ("ids differ");
90 }
91 }
92 else if (g_strcmp0 ((char*)mark->name, "act:type") == 0)
93 {
94 gchar* txt;
95 GNCAccountType type;
96
97 txt = dom_tree_to_text (mark);
98
99 if (!txt)
100 {
101 return g_strdup ("couldn't get type string");
102 }
103 else if (!xaccAccountStringToType (txt, &type))
104 {
105 g_free (txt);
106 return g_strdup ("couldn't convert type string to int");
107 }
108 else if (type != xaccAccountGetType (act))
109 {
110 g_free (txt);
111 return g_strdup ("types differ");
112 }
113 else
114 {
115 g_free (txt);
116 }
117 }
118 else if (g_strcmp0 ((char*)mark->name, "act:commodity") == 0)
119 {
120 /* This is somewhat BS, because if the commodity isn't a
121 currency (and therefore built in) there isn't a
122 corresponding currency in the XML, skip the test. jralls
123 2010-11-02 */
124 if (xaccAccountGetCommodity (act) == NULL) continue;
125 if (!equals_node_val_vs_commodity (
126 mark, xaccAccountGetCommodity (act),
127 gnc_account_get_book (act)))
128 {
129 return g_strdup ("commodities differ");
130 }
131 }
132 else if (g_strcmp0 ((char*)mark->name, "act:code") == 0)
133 {
134 if (!equals_node_val_vs_string (mark, xaccAccountGetCode (act)))
135 {
136 return g_strdup ("codes differ");
137 }
138 }
139 else if (g_strcmp0 ((char*)mark->name, "act:description") == 0)
140 {
141 if (!equals_node_val_vs_string (
142 mark, xaccAccountGetDescription (act)))
143 {
144 return g_strdup ("descriptions differ");
145 }
146 }
147 else if (g_strcmp0 ((char*)mark->name, "act:slots") == 0)
148 {
149 /* xaccAccountDeleteOldData (act); */
150
151 if (!equals_node_val_vs_kvp_frame (mark,
152 qof_instance_get_slots (QOF_INSTANCE (act))))
153 {
154 return g_strdup ("slots differ");
155 }
156 }
157 else if (g_strcmp0 ((char*)mark->name, "act:parent") == 0)
158 {
159 if (!equals_node_val_vs_guid (
160 mark, xaccAccountGetGUID (gnc_account_get_parent (act))))
161 {
162 return g_strdup ("parent ids differ");
163 }
164 }
165 else if (g_strcmp0 ((char*)mark->name, "act:commodity-scu") == 0)
166 {
167 if (!equals_node_val_vs_int (mark, xaccAccountGetCommoditySCU (act)))
168 {
169 return g_strdup ("commodity scus differ");
170 }
171 }
172 else if (g_strcmp0 ((char*)mark->name, "act:hidden") == 0)
173 {
174 if (!equals_node_val_vs_boolean (mark, xaccAccountGetHidden (act)))
175 {
176 return g_strdup ("Hidden flags differ");
177 }
178 }
179 else if (g_strcmp0 ((char*)mark->name, "act:placeholder") == 0)
180 {
181 if (!equals_node_val_vs_boolean (mark, xaccAccountGetPlaceholder (act)))
182 {
183 return g_strdup ("Placeholder flags differ");
184 }
185 }
186 else if (g_strcmp0 ((char*)mark->name, "act:security") == 0)
187 {
188 return NULL; // This tag is ignored.
189 }
190 else
191 {
192 return g_strdup_printf ("unknown node in dom tree: %s", mark->name);
193 }
194 }
195
196 return NULL;
197 }
198
199 static void
delete_random_account(Account * act)200 delete_random_account (Account* act)
201 {
202 xaccAccountBeginEdit (act);
203 xaccAccountDestroy (act);
204 }
205
206 struct act_data_struct
207 {
208 Account* act;
209 int value;
210 };
211 typedef struct act_data_struct act_data;
212
213 static gboolean
test_add_account(const char * tag,gpointer globaldata,gpointer data)214 test_add_account (const char* tag, gpointer globaldata, gpointer data)
215 {
216 Account* account = static_cast<decltype (account)> (data);
217 act_data* gdata = (act_data*)globaldata;
218 gnc_commodity* com;
219 gnc_commodity* new_com;
220 gnc_commodity_table* t;
221
222 com = xaccAccountGetCommodity (account);
223
224 t = gnc_commodity_table_get_table (sixbook);
225
226 new_com = gnc_commodity_table_lookup (t,
227 gnc_commodity_get_namespace (com),
228 gnc_commodity_get_mnemonic (com));
229
230 if (new_com)
231 {
232 xaccAccountSetCommodity (account, new_com);
233 }
234
235 do_test_args (xaccAccountEqual ((Account*)account, (Account*) (gdata->act),
236 TRUE),
237 "gnc_account_sixtp_parser_create",
238 __FILE__, __LINE__, "%d", gdata->value);
239
240 return TRUE;
241 }
242
243 static void
test_account(int i,Account * test_act)244 test_account (int i, Account* test_act)
245 {
246 xmlNodePtr test_node;
247 gchar* filename1;
248 gchar* compare_msg;
249 int fd;
250
251 test_node = gnc_account_dom_tree_create (test_act, FALSE, TRUE);
252
253 if (!test_node)
254 {
255 failure_args ("account_xml", __FILE__, __LINE__,
256 "gnc_account_dom_tree_create returned NULL");
257 return;
258 }
259
260 if ((compare_msg = node_and_account_equal (test_node, test_act)) != NULL)
261 {
262 failure_args ("account_xml", __FILE__, __LINE__,
263 "node and account were not equal: %s", compare_msg);
264 xmlElemDump (stdout, NULL, test_node);
265 fprintf (stdout, "\n");
266 xmlFreeNode (test_node);
267 g_free (compare_msg);
268 return;
269 }
270 else
271 {
272 success ("account_xml");
273 }
274
275 filename1 = g_strdup_printf ("test_file_XXXXXX");
276
277 fd = g_mkstemp (filename1);
278
279 write_dom_node_to_file (test_node, fd);
280
281 close (fd);
282
283 {
284 sixtp* parser;
285 act_data data;
286
287 data.act = test_act;
288 data.value = i;
289
290 parser = gnc_account_sixtp_parser_create ();
291
292 if (!gnc_xml_parse_file (parser, filename1, test_add_account,
293 &data, sixbook))
294 {
295 failure_args ("gnc_xml_parse_file returned FALSE",
296 __FILE__, __LINE__, "%d", i);
297 }
298
299 /* no handling of circular data structures. We'll do that later */
300 /* sixtp_destroy(parser); */
301 }
302
303
304 g_unlink (filename1);
305 g_free (filename1);
306 xmlFreeNode (test_node);
307 }
308
309 static void
test_generation()310 test_generation ()
311 {
312 int i;
313
314 for (i = 0; i < 20; i++)
315 {
316 Account* ran_act;
317
318 ran_act = get_random_account (sixbook);
319
320 test_account (i, ran_act);
321
322 delete_random_account (ran_act);
323 }
324
325 {
326 /* empty some things. */
327 Account* act;
328 const char* msg =
329 "xaccAccountSetCommodity: assertion `GNC_IS_COMMODITY(com)' failed";
330 const char* logdomain = "gnc.engine";
331 GLogLevelFlags loglevel = static_cast<decltype (loglevel)>
332 (G_LOG_LEVEL_CRITICAL);
333 TestErrorStruct check = { loglevel, const_cast<char*> (logdomain),
334 const_cast<char*> (msg)
335 };
336 g_log_set_handler (logdomain, loglevel,
337 (GLogFunc)test_checked_handler, &check);
338
339 act = get_random_account (sixbook);
340
341 xaccAccountSetCode (act, "");
342 xaccAccountSetDescription (act, "");
343
344 xaccAccountSetCommodity (act, NULL);
345
346 test_account (-1, act);
347
348 delete_random_account (act);
349 }
350
351 /* { */
352 /* Account *act1; */
353 /* Account *act2; */
354
355 /* act1 = get_random_account(); */
356 /* act2 = get_random_account(); */
357
358 /* gnc_account_append_child(act1, act2); */
359
360 /* test_account(-1, act2); */
361 /* test_account(-1, act1); */
362
363 /* delete_random_account(act2); */
364 /* delete_random_account(act1); */
365 /* } */
366
367 }
368
369 static gboolean
test_real_account(const char * tag,gpointer global_data,gpointer data)370 test_real_account (const char* tag, gpointer global_data, gpointer data)
371 {
372 char* msg;
373 Account* act = (Account*)data;
374
375 if (!gnc_account_get_parent (act))
376 {
377 gnc_account_append_child (gnc_book_get_root_account (sixbook), act);
378 }
379
380 msg = node_and_account_equal ((xmlNodePtr)global_data, act);
381 do_test_args (msg == NULL, "test_real_account",
382 __FILE__, __LINE__, msg);
383
384 g_free (msg);
385 return TRUE;
386 }
387
388 int
main(int argc,char ** argv)389 main (int argc, char** argv)
390 {
391
392 qof_init ();
393 cashobjects_register ();
394 sixbook = qof_book_new ();
395 auto session = qof_session_new (sixbook);
396 if (argc > 1)
397 {
398 test_files_in_dir (argc, argv, test_real_account,
399 gnc_account_sixtp_parser_create (),
400 "gnc:account", sixbook);
401 }
402 else
403 {
404 test_generation ();
405 }
406
407 qof_session_destroy (session);
408 print_test_results ();
409 qof_close ();
410 exit (get_rv ());
411 }
412