GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
test-qofbook.c
1 /********************************************************************
2  * test_qofbook.c: GLib g_test test suite for qofbook. *
3  * Copyright 2011 John Ralls <[email protected]> *
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 [email protected] *
21 \********************************************************************/
22 #ifdef __cplusplus
23 extern "C"
24 {
25 #endif
26 
27 #include "config.h"
28 #include <string.h>
29 #include <glib.h>
30 #include <unittest-support.h>
31 #ifdef __cplusplus
32 }
33 #endif
34 
35 #include "../qof.h"
36 #include "../qofbook-p.h"
37 #include "../qofbookslots.h"
38 
39 #ifdef HAVE_GLIB_2_38
40 #define _Q "'"
41 #else
42 #define _Q "`"
43 #endif
44 
45 static const gchar *suitename = "/qof/qofbook";
46 void test_suite_qofbook ( void );
47 
48 typedef struct
49 {
50  QofBook *book;
51 } Fixture;
52 
53 static struct
54 {
55  guint param;
56  gpointer data;
57  gboolean called;
58  gchar* msg;
59 } test_struct;
60 
61 static struct
62 {
63  gboolean col1_called;
64  gboolean col2_called;
65  gpointer data;
66 } col_struct;
67 
68 static void
69 setup( Fixture *fixture, gconstpointer pData )
70 {
71  fixture->book = qof_book_new();
72 }
73 
74 static void
75 teardown( Fixture *fixture, gconstpointer pData )
76 {
77  qof_book_destroy( fixture->book );
78 }
79 
80 /* use g_free on test_struct.msg after this function been called */
81 static gboolean
82 handle_faults ( const char * log_domain, GLogLevelFlags log_level, const gchar *msg, gpointer user_data)
83 {
84  test_struct.msg = (gchar *) g_strdup( msg );
85  return FALSE;
86 }
87 
88 /* mock dirty callback function */
89 static void
90 mock_dirty_cb (QofBook *book, gboolean dirty, gpointer user_data)
91 {
92  test_struct.called = TRUE;
93  g_test_message( "Checking if book is valid" );
94  g_assert( book );
95  g_assert( QOF_IS_BOOK( book ) );
96  g_test_message( "Checking parameters" );
97  g_assert( dirty );
98  g_assert( user_data == test_struct.data );
99 }
100 
101 /* mock callback for qof_book_foreach_collection testing */
102 static void
103 mock_foreach_collection (QofCollection *col, gpointer user_data)
104 {
105  g_test_message( "Checking if collection and data passed correctly" );
106  g_assert( col );
107  g_assert( user_data == col_struct.data );
108  if ( g_strcmp0( qof_collection_get_type(col), "my_type" ) == 0 )
109  col_struct.col1_called = TRUE;
110  else if ( g_strcmp0( qof_collection_get_type(col), "my_type2" ) == 0 )
111  col_struct.col2_called = TRUE;
112 }
113 
114 /* mock final callback function */
115 static void
116 mock_final_cb (QofBook *book, gpointer key, gpointer user_data)
117 {
118  test_struct.called = TRUE;
119  g_assert( book );
120  g_assert( QOF_IS_BOOK( book ) );
121  g_test_message( "Checking parameters" );
122  g_assert_cmpstr( (gchar*)key, == , "key" );
123  g_assert_cmpstr( (gchar*)user_data, == , "data" );
124 }
125 
126 static void
127 test_book_readonly( Fixture *fixture, gconstpointer pData )
128 {
129  g_assert( fixture->book != NULL );
130  g_assert( !qof_book_is_readonly( fixture->book ) );
131  qof_book_mark_readonly( fixture->book );
132  g_assert( qof_book_is_readonly( fixture->book ) );
133 }
134 static void
135 test_book_validate_counter( void )
136 {
137  gchar *r;
138  g_test_bug("644036");
139 
140  /* Test for detection of missing format conversion */
141  r = qof_book_validate_counter_format("This string is missing the conversion specifier");
142  g_assert(r);
143  if (r && g_test_verbose())
144  {
145  g_test_message("Counter format validation correctly failed: %s", r);
146  }
147  g_free(r);
148 
149  /* Test the usual Linux/Unix G_GINT64_FORMAT */
150  r = qof_book_validate_counter_format_internal("Test - %li", "li");
151  if (r && g_test_verbose())
152  {
153  g_test_message("Counter format validation erroneously failed: %s", r);
154  }
155  g_assert(r == NULL);
156  g_free(r);
157 
158  /* Test the Windows G_GINT64_FORMAT */
159  r = qof_book_validate_counter_format_internal("Test - %I64i", "I64i");
160  if (r && g_test_verbose())
161  {
162  g_test_message("Counter format validation erroneously failed: %s", r);
163  }
164  g_assert(r == NULL);
165  g_free(r);
166 
167  /* Test the system's GINT64_FORMAT */
168  r = qof_book_validate_counter_format("Test - %" G_GINT64_FORMAT);
169  if (r && g_test_verbose())
170  {
171  g_test_message("Counter format validation erroneously failed: %s", r);
172  }
173  g_assert(r == NULL);
174  g_free(r);
175 
176  /* Test an erroneous Windows G_GINT64_FORMAT */
177  r = qof_book_validate_counter_format_internal("Test - %li", "I64i");
178  if (r && g_test_verbose())
179  {
180  g_test_message("Counter format validation correctly failed: %s", r);
181  }
182  g_assert(r);
183  g_free(r);
184 
185  /* Test an erroneous Linux G_GINT64_FORMAT */
186  r = qof_book_validate_counter_format_internal("Test - %I64i", "li");
187  if (r && g_test_verbose())
188  {
189  g_test_message("Counter format validation correctly failed: %s", r);
190  }
191  g_assert(r);
192  g_free(r);
193 }
194 
195 static void
196 test_book_get_string_option( Fixture *fixture, gconstpointer pData )
197 {
198  const char *opt_name = "Option Name";
199  const char *opt_value = "Option Value";
200  const char *opt_name_notset = "Not Set";
201  g_assert( fixture->book != NULL );
202  qof_book_set_string_option( fixture->book, opt_name, opt_value);
203  g_assert_cmpstr( qof_book_get_string_option( fixture->book, opt_name ), == , opt_value);
204  g_assert_cmpstr( qof_book_get_string_option( fixture->book, opt_name_notset ), == , NULL );
205 }
206 
207 static void
208 test_book_set_string_option( Fixture *fixture, gconstpointer pData )
209 {
210  const char *opt_name = "Option Name";
211  const char *opt_value = "Option Value";
212  g_assert( fixture->book != NULL );
213  qof_book_set_string_option( fixture->book, opt_name, opt_value);
214  g_assert( qof_instance_is_dirty (QOF_INSTANCE (fixture->book)) );
215 }
216 
217 static void
218 test_book_session_not_saved( Fixture *fixture, gconstpointer pData )
219 {
220  g_assert( fixture->book != NULL );
221  g_assert( !qof_book_session_not_saved( fixture->book ) );
222  qof_book_mark_session_saved( fixture->book );
223  g_assert( !qof_book_session_not_saved( fixture->book ) );
224  qof_book_mark_session_dirty( fixture-> book );
225  g_assert( qof_book_session_not_saved( fixture->book ) );
226 }
227 
228 static void
229 test_book_mark_session_saved( Fixture *fixture, gconstpointer pData )
230 {
231  time64 dirty_time, clean_time;
232 
233  qof_book_mark_session_dirty( fixture-> book );
234  g_assert( qof_book_session_not_saved( fixture->book ) );
235  dirty_time = qof_book_get_session_dirty_time( fixture->book );
236  qof_book_mark_session_saved( fixture->book );
237  clean_time = qof_book_get_session_dirty_time( fixture->book );
238  g_assert( !qof_book_session_not_saved( fixture->book ) );
239  g_assert( dirty_time != clean_time );
240  g_assert( clean_time == 0);
241 }
242 
243 static void
244 test_book_get_counter( Fixture *fixture, gconstpointer pData )
245 {
246  const char *counter_name = "Counter name";
247  const char *err_no_book = "No book";
248  const char *err_invalid_cnt = "Invalid counter name";
249  gint64 counter;
250 
251  /* need this as long as we have fatal warnings enabled */
252  g_test_log_set_fatal_handler ( ( GTestLogFatalFunc )handle_faults, NULL );
253 
254  counter = qof_book_get_counter( NULL, counter_name );
255  g_assert_cmpint( counter, == , -1 );
256  g_assert( g_strrstr( test_struct.msg, err_no_book ) != NULL );
257  g_free( test_struct.msg );
258 
259  counter = qof_book_get_counter( fixture->book, NULL );
260  g_assert_cmpint( counter, == , -1 );
261  g_assert( g_strrstr( test_struct.msg, err_invalid_cnt ) != NULL );
262  g_free( test_struct.msg );
263 
264  counter = qof_book_get_counter( fixture->book, NULL );
265  g_assert_cmpint( counter, == , -1 );
266  g_assert( g_strrstr( test_struct.msg, err_invalid_cnt ) != NULL );
267  g_free( test_struct.msg );
268 
269  counter = qof_book_get_counter( fixture->book, counter_name );
270  g_assert_cmpint( counter, == , 0 );
271 
272  qof_book_increment_and_format_counter( fixture->book, counter_name );
273  counter = qof_book_get_counter( fixture->book, counter_name );
274  g_assert_cmpint( counter, == , 1 );
275 }
276 
277 static void
278 test_book_get_counter_format ( Fixture *fixture, gconstpointer pData )
279 {
280  const char *counter_name = "Counter name";
281  const char *err_no_book = "No book";
282  const char *err_invalid_cnt = "Invalid counter name";
283  const char *r;
284 
285  /* need this as long as we have fatal warnings enabled */
286  g_test_log_set_fatal_handler ( ( GTestLogFatalFunc )handle_faults, NULL );
287 
288  g_test_message( "Testing counter format when book is null" );
289  r = qof_book_get_counter_format( NULL, counter_name );
290  g_assert_cmpstr( r, == , NULL );
291  g_assert( g_strrstr( test_struct.msg, err_no_book ) != NULL );
292  g_free( test_struct.msg );
293 
294  g_test_message( "Testing counter format when counter name is null" );
295  r = qof_book_get_counter_format( fixture->book, NULL );
296  g_assert_cmpstr( r, == , NULL );
297  g_assert( g_strrstr( test_struct.msg, err_invalid_cnt ) != NULL );
298  g_free( test_struct.msg );
299 
300  g_test_message( "Testing counter format when counter name is empty string" );
301  r = qof_book_get_counter_format( fixture->book, NULL );
302  g_assert_cmpstr( r, == , NULL );
303  g_assert( g_strrstr( test_struct.msg, err_invalid_cnt ) != NULL );
304  g_free( test_struct.msg );
305 
306  g_test_message( "Testing counter format with existing counter" );
307  r = qof_book_get_counter_format( fixture->book, counter_name );
308  g_assert_cmpstr( r, == , "%.6" G_GINT64_FORMAT);
309 
310  g_test_message( "Testing counter format for default value" );
311  r = qof_book_get_counter_format( fixture->book, counter_name );
312  g_assert_cmpstr( r, == , "%.6" G_GINT64_FORMAT);
313 }
314 
315 static void
316 test_book_increment_and_format_counter ( Fixture *fixture, gconstpointer pData )
317 {
318  const char *counter_name = "Counter name";
319  const char *err_no_book = "No book";
320  const char *err_invalid_cnt = "Invalid counter name";
321  const char *format;
322  char *r;
323  gint64 counter;
324 
325  /* need this as long as we have fatal warnings enabled */
326  g_test_log_set_fatal_handler ( ( GTestLogFatalFunc )handle_faults, NULL );
327 
328  g_test_message( "Testing increment and format when book is null" );
329  r = qof_book_increment_and_format_counter( NULL, counter_name );
330  g_assert_cmpstr( r, == , NULL );
331  g_free( r );
332  g_assert( g_strrstr( test_struct.msg, err_no_book ) != NULL );
333  g_free( test_struct.msg );
334 
335  g_test_message( "Testing increment and format when counter name is null" );
336  r = qof_book_increment_and_format_counter( fixture->book, NULL );
337  g_assert_cmpstr( r, == , NULL );
338  g_free( r );
339  g_assert( g_strrstr( test_struct.msg, err_invalid_cnt ) != NULL );
340  g_free( test_struct.msg );
341 
342  g_test_message( "Testing increment and format when counter name is empty string" );
343  r = qof_book_increment_and_format_counter( fixture->book, NULL );
344  g_assert_cmpstr( r, == , NULL );
345  g_free( r );
346  g_assert( g_strrstr( test_struct.msg, err_invalid_cnt ) != NULL );
347  g_free( test_struct.msg );
348 
349  g_test_message( "Testing increment and format with new counter" );
350  r = qof_book_increment_and_format_counter( fixture->book, counter_name );
351  counter = qof_book_get_counter( fixture->book, counter_name );
352  format = qof_book_get_counter_format( fixture->book, counter_name );
353  g_assert_cmpint( counter, == , 1 );
354  g_assert( qof_instance_is_dirty (QOF_INSTANCE (fixture->book)) );
355  g_assert_cmpstr( r, == , g_strdup_printf( format, counter ));
356  g_free( r );
357 
358  g_test_message( "Testing increment and format with existing counter" );
359  r = qof_book_increment_and_format_counter( fixture->book, counter_name );
360  counter = qof_book_get_counter( fixture->book, counter_name );
361  format = qof_book_get_counter_format( fixture->book, counter_name );
362  g_assert_cmpint( counter, == , 2 );
363  g_assert_cmpstr( r, == , g_strdup_printf( format, counter ));
364  g_free( r );
365 }
366 
367 static void
368 test_book_use_trading_accounts( Fixture *fixture, gconstpointer pData )
369 {
370  g_assert( qof_book_use_trading_accounts( fixture-> book ) == FALSE );
371 
372  g_test_message( "Testing with existing trading accounts set to true - t" );
373  qof_book_begin_edit (fixture->book);
374  qof_instance_set (QOF_INSTANCE (fixture->book),
375  "trading-accts", "t",
376  NULL);
377  g_assert( qof_book_use_trading_accounts( fixture-> book ) == TRUE );
378 
379  g_test_message( "Testing with existing trading accounts and incorrect value - tt" );
380  qof_instance_set (QOF_INSTANCE (fixture->book),
381  "trading-accts", "tt",
382  NULL);
383  g_assert( qof_book_use_trading_accounts( fixture-> book ) == FALSE );
384  qof_book_commit_edit (fixture->book);
385 
386 }
387 
388 static void
389 test_book_get_num_days_autofreeze( Fixture *fixture, gconstpointer pData )
390 {
391  g_test_message( "Testing default: No auto-freeze days are set" );
392  g_assert( qof_book_uses_autoreadonly( fixture-> book ) == FALSE );
393  g_assert( qof_book_get_num_days_autoreadonly( fixture-> book ) == 0 );
394 
395  g_assert( qof_book_uses_autoreadonly( fixture-> book ) == FALSE );
396  g_assert( qof_book_get_num_days_autoreadonly( fixture-> book ) == 0 );
397 
398  qof_book_begin_edit (fixture->book);
399  qof_instance_set (QOF_INSTANCE (fixture->book),
400  "autoreadonly-days", (gdouble)17,
401  NULL);
402  g_assert( qof_book_uses_autoreadonly( fixture-> book ) == TRUE );
403  g_assert( qof_book_get_num_days_autoreadonly( fixture-> book ) == 17 );
404 
405  g_test_message( "Testing when setting this correctly to zero again" );
406 
407  qof_instance_set (QOF_INSTANCE (fixture->book),
408  "autoreadonly-days", (gdouble)0,
409  NULL);
410  g_assert( qof_book_uses_autoreadonly( fixture-> book ) == FALSE );
411  g_assert( qof_book_get_num_days_autoreadonly( fixture-> book ) == 0 );
412 
413  qof_instance_set (QOF_INSTANCE (fixture->book),
414  "autoreadonly-days", (gdouble)32,
415  NULL);
416  g_assert( qof_book_uses_autoreadonly( fixture-> book ) == TRUE );
417  g_assert( qof_book_get_num_days_autoreadonly( fixture-> book ) == 32 );
418 
419  qof_book_commit_edit (fixture->book);
420 }
421 
422 static void
423 test_book_use_split_action_for_num_field( Fixture *fixture, gconstpointer pData )
424 {
425  g_test_message( "Testing default: No selection has been specified" );
426  g_assert( qof_book_use_split_action_for_num_field( fixture-> book ) == FALSE );
427 
428  g_test_message( "Testing with existing use split action for num set to true - t" );
429 
430  qof_book_begin_edit (fixture->book);
431  qof_instance_set (QOF_INSTANCE (fixture->book),
432  "split-action-num-field", "t",
433  NULL);
434  g_assert( qof_book_use_split_action_for_num_field( fixture-> book ) == TRUE );
435 
436  g_test_message( "Testing with existing use split action for num and incorrect value - tt" );
437  qof_instance_set (QOF_INSTANCE (fixture->book),
438  "split-action-num-field", "tt",
439  NULL);
440  g_assert( qof_book_use_split_action_for_num_field( fixture-> book ) == FALSE );
441  qof_book_commit_edit (fixture->book);
442 }
443 
444 static void
445 test_book_mark_session_dirty( Fixture *fixture, gconstpointer pData )
446 {
447  QofBook *_empty = NULL;
448  time64 before, after;
449  guint param = (guint) g_test_rand_int();
450 
451  g_test_message( "Testing when book is NULL" );
452  qof_book_mark_session_dirty( _empty );
453  g_assert( _empty == NULL );
454 
455  g_test_message( "Testing when book is not dirty and dirty_cb is null" );
456  g_assert_cmpint( qof_book_get_session_dirty_time( fixture->book ), == , 0);
457  g_assert( fixture->book->dirty_cb == NULL );
458  g_assert( qof_book_session_not_saved( fixture->book ) == FALSE );
459  before = gnc_time (NULL);
460  qof_book_mark_session_dirty( fixture->book );
461  after = gnc_time (NULL);
462  g_assert_cmpint( qof_book_get_session_dirty_time( fixture->book ), >= , before);
463  g_assert_cmpint( qof_book_get_session_dirty_time( fixture->book ), <= , after);
464  g_assert( qof_book_session_not_saved( fixture->book ) == TRUE );
465 
466  g_test_message( "Testing when book is not dirty and dirty_cb is not null" );
467  /* prepare conditions */
468  qof_book_mark_session_saved( fixture->book );
469  qof_book_set_dirty_cb( fixture->book, mock_dirty_cb, (gpointer) (&param) );
470  test_struct.data = (gpointer) (&param);
471  test_struct.called = FALSE;
472  g_assert( fixture->book->dirty_cb != NULL );
473  g_assert_cmpint( qof_book_get_session_dirty_time( fixture->book ), == , 0);
474  g_assert( qof_book_session_not_saved( fixture->book ) == FALSE );
475  /* run FUT */
476  before = gnc_time (NULL);
477  qof_book_mark_session_dirty( fixture->book );
478  after = gnc_time (NULL);
479  /* test output */
480  g_assert_cmpint( qof_book_get_session_dirty_time( fixture->book ), >= , before);
481  g_assert_cmpint( qof_book_get_session_dirty_time( fixture->book ), <= , after);
482  g_assert( qof_book_session_not_saved( fixture->book ) == TRUE );
483  g_assert( test_struct.called );
484 
485  g_test_message( "Testing when book is dirty" );
486  g_assert( qof_book_session_not_saved( fixture->book ) == TRUE );
487  before = qof_book_get_session_dirty_time( fixture->book );
488  qof_book_mark_session_dirty( fixture->book );
489  g_assert( qof_book_session_not_saved( fixture->book ) == TRUE );
490  after = qof_book_get_session_dirty_time( fixture->book );
491  g_assert_cmpint( before, == , after );
492 }
493 
494 static void
495 test_book_get_session_dirty_time( Fixture *fixture, gconstpointer pData )
496 {
497  time64 before, after;
498 
499  g_test_message( "Testing time on saved book = 0" );
500  g_assert( qof_book_session_not_saved( fixture->book ) == FALSE );
501  g_assert_cmpint( qof_book_get_session_dirty_time( fixture->book ), == , 0);
502 
503  g_test_message( "Testing time on dirty book is correct" );
504  before = gnc_time (NULL);
505  qof_book_mark_session_dirty( fixture->book );
506  after = gnc_time (NULL);
507  g_assert_cmpint( qof_book_get_session_dirty_time( fixture->book ), >= , before);
508  g_assert_cmpint( qof_book_get_session_dirty_time( fixture->book ), <= , after);
509 
510 }
511 
512 static void
513 test_book_set_dirty_cb( Fixture *fixture, gconstpointer pData )
514 {
515  const char * error_msg = "Already existing callback";
516 
517  g_test_message( "Testing when callback is previously not set" );
518  g_assert( fixture->book->dirty_cb == NULL );
519  qof_book_set_dirty_cb( fixture->book, mock_dirty_cb, (gpointer) (&test_struct) );
520  g_assert( fixture->book->dirty_cb == mock_dirty_cb );
521  g_assert( fixture->book->dirty_data == &test_struct );
522 
523  /* need this as long as we have fatal warnings enabled */
524  g_test_log_set_fatal_handler ( ( GTestLogFatalFunc )handle_faults, NULL );
525 
526  g_test_message( "Testing when callback was previously set" );
527  g_assert( fixture->book->dirty_cb != NULL );
528  qof_book_set_dirty_cb( fixture->book, NULL, NULL );
529  g_assert( g_strrstr( test_struct.msg, error_msg ) != NULL );
530  g_assert( fixture->book->dirty_cb == NULL );
531  g_assert( fixture->book->dirty_data == NULL );
532  g_free( test_struct.msg );
533 }
534 
535 static void
536 test_book_shutting_down( Fixture *fixture, gconstpointer pData )
537 {
538  g_test_message( "Testing when book is null" );
539  g_assert( qof_book_shutting_down( NULL ) == FALSE );
540  g_test_message( "Testing when shutting down is true" );
541  fixture->book->shutting_down = TRUE;
542  g_assert( qof_book_shutting_down( fixture->book ) == TRUE );
543  g_test_message( "Testing when shutting down is false" );
544  fixture->book->shutting_down = FALSE;
545  g_assert( qof_book_shutting_down( fixture->book ) == FALSE );
546 }
547 
548 static void
549 test_book_set_get_data( Fixture *fixture, gconstpointer pData )
550 {
551  const char *key = "key";
552  const char *data = "data";
553 
554  g_assert( fixture->book->data_tables != NULL );
555  g_test_message( "Testing when book is null" );
556  qof_book_set_data( NULL, key, (gpointer) data );
557  g_assert( qof_book_get_data( NULL, key ) == NULL );
558 
559  g_test_message( "Testing when key is null" );
560  qof_book_set_data( fixture->book, NULL, (gpointer) data );
561  g_assert( qof_book_get_data( fixture->book, NULL) == NULL );
562 
563  g_test_message( "Testing with book key not null, data null" );
564  qof_book_set_data( fixture->book, key, NULL );
565  g_assert( qof_book_get_data( fixture->book, key ) == NULL );
566 
567  g_test_message( "Testing with book key data not null" );
568  qof_book_set_data( fixture->book, key, (gpointer) data );
569  g_assert_cmpstr( (const char *)qof_book_get_data( fixture->book, key ), == , data );
570 }
571 
572 static void
573 test_book_get_collection( Fixture *fixture, gconstpointer pData )
574 {
575  QofIdType my_type = "my type";
576  QofCollection *m_col, *m_col2;
577 
578  g_test_message( "Testing when book is null" );
579  g_assert( qof_book_get_collection( NULL, my_type ) == NULL );
580 
581  g_test_message( "Testing when entity type is null" );
582  g_assert( qof_book_get_collection( fixture->book, NULL ) == NULL );
583 
584  g_test_message( "Testing when collection does not exist" );
585  g_assert( fixture->book->hash_of_collections != NULL );
586  g_assert( g_hash_table_lookup ( fixture->book->hash_of_collections, my_type ) == NULL );
587  m_col = qof_book_get_collection( fixture->book, my_type );
588  g_assert( m_col != NULL );
589 
590  g_test_message( "Testing with existing collection" );
591  g_assert( g_hash_table_lookup ( fixture->book->hash_of_collections, my_type ) != NULL );
592  m_col2 = qof_book_get_collection( fixture->book, my_type );
593  g_assert( m_col2 != NULL );
594  g_assert( m_col == m_col2 );
595 }
596 
597 static void
598 test_book_foreach_collection( Fixture *fixture, gconstpointer pData )
599 {
600  G_GNUC_UNUSED QofCollection *m_col, *m_col2;
601  QofIdType my_type = "my_type", my_type2 = "my_type2";
602  guint param = (guint) g_test_rand_int();
603  /* GLib assertion messages which aren't filtered to make clang's output like gcc's */
604 #if defined(__clang__)
605 #define _func "void qof_book_foreach_collection(const QofBook *, QofCollectionForeachCB, gpointer)"
606 #else
607 #define _func "void qof_book_foreach_collection(const QofBook*, QofCollectionForeachCB, gpointer)"
608 //#define _func "qof_book_foreach_collection"
609 #endif
610  gchar *msg1 = _func ": assertion " _Q "book' failed";
611  gchar *msg2 = _func ": assertion " _Q "cb' failed";
612 #undef _func
613  gchar *log_domain = "qof";
614  guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL, hdlr;
615  TestErrorStruct check1 = { loglevel, log_domain, msg1 };
616  TestErrorStruct check2 = { loglevel, log_domain, msg2 };
617 
618  /* need this as long as we have fatal warnings enabled */
619  g_test_log_set_fatal_handler ( ( GTestLogFatalFunc )handle_faults, NULL );
620  test_add_error (&check1);
621  test_add_error (&check2);
622  hdlr = g_log_set_handler (log_domain, loglevel,
623  (GLogFunc)test_list_handler, NULL);
624 
625  g_test_message( "Testing when book is null" );
626  m_col = qof_book_get_collection( fixture->book, my_type );
627  m_col2 = qof_book_get_collection( fixture->book, my_type2 );
628  col_struct.col1_called = FALSE;
629  col_struct.col2_called = FALSE;
630  col_struct.data = (gpointer) (&param);
631  /* launch foreach make sure callback was not called and check warning msg */
632  qof_book_foreach_collection( NULL, mock_foreach_collection, (gpointer)(&param) );
633  g_assert( !col_struct.col1_called );
634  g_assert( !col_struct.col2_called );
635  g_assert_cmpstr( test_struct.msg, == , msg1);
636  g_free( test_struct.msg );
637 
638  g_test_message( "Testing when cb is null" );
639  /* launching with empty cb should still fail and produce warning */
640  qof_book_foreach_collection( fixture->book, NULL, (gpointer)(&param) );
641  g_assert( !col_struct.col1_called );
642  g_assert( !col_struct.col2_called );
643  g_assert_cmpstr( test_struct.msg, == , msg2);
644  g_free( test_struct.msg );
645  g_log_remove_handler (log_domain, hdlr);
646  test_clear_error_list ();
647 
648  g_test_message( "Testing when book and cb not null, user_data provided" );
649  /* both cols have to be called */
650  qof_book_foreach_collection( fixture->book, mock_foreach_collection, (gpointer)(&param) );
651  g_assert( col_struct.col1_called );
652  g_assert( col_struct.col2_called );
653 }
654 
655 static void
656 test_book_set_data_fin( void )
657 {
658  QofBook *book;
659  const char *key = "key";
660  const char *data = "data";
661 
662  /* init */
663  book = qof_book_new();
664  g_assert_cmpint( g_hash_table_size( book->data_tables ), == , 0 );
665  g_assert_cmpint( g_hash_table_size( book->data_table_finalizers ), == , 0 );
666 
667  g_test_message( "Testing when book is null" );
668  qof_book_set_data_fin( NULL, key, (gpointer) data, mock_final_cb );
669  /* assert nothing was set */
670  g_assert_cmpint( g_hash_table_size( book->data_tables ), == , 0 );
671  g_assert_cmpint( g_hash_table_size( book->data_table_finalizers ), == , 0 );
672 
673  g_test_message( "Testing when key is null" );
674  qof_book_set_data_fin( book, NULL, (gpointer) data, mock_final_cb );
675  /* nothing set as well */
676  g_assert_cmpint( g_hash_table_size( book->data_tables ), == , 0 );
677  g_assert_cmpint( g_hash_table_size( book->data_table_finalizers ), == , 0 );
678 
679  g_test_message( "Testing with book key not null, cb null" );
680  qof_book_set_data_fin( book, key, (gpointer) data, NULL );
681  /* now data is set cb not set */
682  g_assert_cmpint( g_hash_table_size( book->data_tables ), == , 1 );
683  g_assert_cmpint( g_hash_table_size( book->data_table_finalizers ), == , 0 );
684  g_assert_cmpstr( (const char *)qof_book_get_data( book, key ), == , data );
685 
686  g_test_message( "Testing with all data set" );
687  qof_book_set_data_fin( book, key, (gpointer) data, mock_final_cb );
688  /* now we have all set */
689  g_assert_cmpint( g_hash_table_size( book->data_tables ), == , 1 );
690  g_assert_cmpint( g_hash_table_size( book->data_table_finalizers ), == , 1 );
691  g_assert_cmpstr( (const char *)qof_book_get_data( book, key ), == , data );
692  g_assert( g_hash_table_lookup ( book->data_table_finalizers, (gpointer)key ) == mock_final_cb );
693 
694  /* get rid of book make sure final cb is called */
695  test_struct.called = FALSE;
696  qof_book_destroy( book );
697  g_assert( test_struct.called );
698 }
699 
700 static void
701 test_book_mark_closed( Fixture *fixture, gconstpointer pData )
702 {
703  g_test_message( "Testing when book is null" );
704  g_assert_cmpstr( &fixture->book->book_open, == , "y" );
705  qof_book_mark_closed( NULL );
706  g_assert_cmpstr( &fixture->book->book_open, == , "y" );
707 
708  g_test_message( "Testing when book is not null" );
709  qof_book_mark_closed( fixture->book );
710  g_assert_cmpstr( &fixture->book->book_open, == , "n" );
711 }
712 
713 static void
714 test_book_new_destroy( void )
715 {
716  QofBook *book;
717  const char *key = "key";
718  const char *data = "data";
719 
720  g_test_message( "Testing book creation and initial setup" );
721  book = qof_book_new();
722  g_assert( book );
723  g_assert( QOF_IS_BOOK( book ) );
724 
725  g_test_message( "Testing book initial setup" );
726  g_assert( book->hash_of_collections );
727  g_assert( book->data_tables );
728  g_assert( book->data_table_finalizers );
729  g_assert_cmpint( g_hash_table_size( book->hash_of_collections ), == , 1 );
730  g_assert( g_hash_table_lookup ( book->hash_of_collections, QOF_ID_BOOK ) != NULL );
731  g_assert_cmpint( g_hash_table_size( book->data_tables ), == , 0 );
732  g_assert_cmpint( g_hash_table_size( book->data_table_finalizers ), == , 0 );
733  g_assert_cmpstr( &book->book_open, == , "y");
734  g_assert( !book->read_only );
735  g_assert_cmpint( book->version, == , 0 );
736 
737  /* set finalizer */
738  qof_book_set_data_fin( book, key, (gpointer) data, mock_final_cb );
739  test_struct.called = FALSE;
740 
741  g_test_message( "Testing book destroy" );
742  qof_book_destroy( book );
743  g_assert( qof_book_shutting_down( book ) );
744  g_assert( test_struct.called );
745 }
746 
747 void
748 test_suite_qofbook ( void )
749 {
750  GNC_TEST_ADD( suitename, "readonly", Fixture, NULL, setup, test_book_readonly, teardown );
751  GNC_TEST_ADD_FUNC( suitename, "validate counter", test_book_validate_counter );
752  GNC_TEST_ADD( suitename, "get string option", Fixture, NULL, setup, test_book_get_string_option, teardown );
753  GNC_TEST_ADD( suitename, "set string option", Fixture, NULL, setup, test_book_set_string_option, teardown );
754  GNC_TEST_ADD( suitename, "session not saved", Fixture, NULL, setup, test_book_session_not_saved, teardown );
755  GNC_TEST_ADD( suitename, "session mark saved", Fixture, NULL, setup, test_book_mark_session_saved, teardown );
756  GNC_TEST_ADD( suitename, "get counter", Fixture, NULL, setup, test_book_get_counter, teardown );
757  GNC_TEST_ADD( suitename, "get counter format", Fixture, NULL, setup, test_book_get_counter_format, teardown );
758  GNC_TEST_ADD( suitename, "increment and format counter", Fixture, NULL, setup, test_book_increment_and_format_counter, teardown );
759  GNC_TEST_ADD( suitename, "use trading accounts", Fixture, NULL, setup, test_book_use_trading_accounts, teardown );
760  GNC_TEST_ADD( suitename, "get autofreeze days", Fixture, NULL, setup, test_book_get_num_days_autofreeze, teardown );
761  GNC_TEST_ADD( suitename, "use split action for num field", Fixture, NULL, setup, test_book_use_split_action_for_num_field, teardown );
762  GNC_TEST_ADD( suitename, "mark session dirty", Fixture, NULL, setup, test_book_mark_session_dirty, teardown );
763  GNC_TEST_ADD( suitename, "session dirty time", Fixture, NULL, setup, test_book_get_session_dirty_time, teardown );
764  GNC_TEST_ADD( suitename, "set dirty callback", Fixture, NULL, setup, test_book_set_dirty_cb, teardown );
765  GNC_TEST_ADD( suitename, "shutting down", Fixture, NULL, setup, test_book_shutting_down, teardown );
766  GNC_TEST_ADD( suitename, "set get data", Fixture, NULL, setup, test_book_set_get_data, teardown );
767  GNC_TEST_ADD( suitename, "get collection", Fixture, NULL, setup, test_book_get_collection, teardown );
768  GNC_TEST_ADD( suitename, "foreach collection", Fixture, NULL, setup, test_book_foreach_collection, teardown );
769  GNC_TEST_ADD_FUNC( suitename, "set data finalizers", test_book_set_data_fin );
770  GNC_TEST_ADD( suitename, "mark closed", Fixture, NULL, setup, test_book_mark_closed, teardown );
771  GNC_TEST_ADD_FUNC( suitename, "book new and destroy", test_book_new_destroy );
772 }
void qof_book_set_dirty_cb(QofBook *book, QofBookDirtyCB cb, gpointer user_data)
#define qof_instance_is_dirty
Definition: qofinstance.h:165
time64 qof_book_get_session_dirty_time(const QofBook *book)
gchar * qof_book_increment_and_format_counter(QofBook *book, const char *counter_name)
gint qof_book_get_num_days_autoreadonly(const QofBook *book)
void qof_instance_set(QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
gboolean qof_book_use_split_action_for_num_field(const QofBook *book)
QofBook * qof_book_new(void)
const char * qof_book_get_counter_format(const QofBook *book, const char *counter_name)
void qof_book_mark_closed(QofBook *book)
void qof_book_mark_readonly(QofBook *book)
gchar * qof_book_validate_counter_format_internal(const gchar *p, const gchar *gint64_format)
gint64 qof_book_get_counter(QofBook *book, const char *counter_name)
const gchar * QofIdType
Definition: qofid.h:85
void qof_book_mark_session_saved(QofBook *book)
void qof_book_set_data_fin(QofBook *book, const gchar *key, gpointer data, QofBookFinalCB)
void qof_book_set_data(QofBook *book, const gchar *key, gpointer data)
gboolean qof_book_session_not_saved(const QofBook *book)
void qof_book_mark_session_dirty(QofBook *book)
QofIdType qof_collection_get_type(const QofCollection *)
gboolean qof_book_is_readonly(const QofBook *book)
time64 gnc_time(time64 *tbuf)
get the current local time
QofCollection * qof_book_get_collection(const QofBook *, QofIdType)
gint64 time64
Definition: gnc-date.h:83
gboolean qof_book_uses_autoreadonly(const QofBook *book)
gboolean qof_book_shutting_down(const QofBook *book)
gpointer qof_book_get_data(const QofBook *book, const gchar *key)
gboolean qof_book_use_trading_accounts(const QofBook *book)
void qof_book_destroy(QofBook *book)
gchar * qof_book_validate_counter_format(const gchar *format)