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