GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
test-qofsession.c
1 /********************************************************************
2  * test_qofsession.c: GLib g_test test suite for qofsession. *
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 
23 #ifdef __cplusplus
24 extern "C"
25 {
26 #endif
27 
28 #include "config.h"
29 #include <glib.h>
30 #include <unittest-support.h>
31 
32 #ifdef __cplusplus
33 }
34 #endif
35 
36 #include "../qof.h"
37 #include "../qofbackend-p.h"
38 #include "../qofsession-p.h"
39 #include "../qofclass-p.h"
40 
41 static const gchar *suitename = "/qof/qofsession";
42 void test_suite_qofsession ( void );
43 
44 #ifdef __cplusplus
45 extern "C"
46 {
47 #endif
48 
49 extern GHookList* get_session_closed_hooks (void);
50 extern GSList* get_provider_list (void);
51 extern gboolean get_qof_providers_initialized (void);
52 extern void unregister_all_providers (void);
53 
54 extern void (*p_qof_session_load_backend) (QofSession * session, const char * access_method);
55 extern void (*p_qof_session_clear_error) (QofSession * session);
56 extern void (*p_qof_session_destroy_backend) (QofSession * session);
57 
58 extern void init_static_qofsession_pointers (void);
59 
60 #ifdef __cplusplus
61 }
62 #endif
63 
64 typedef struct
65 {
66  QofSession *session;
67 } Fixture;
68 
69 static void
70 safe_sync( QofBackend *be, QofBook *book )
71 {
73  qof_backend_set_message( be, "Just Kidding!" );
74 }
75 
76 static void
77 percentage_fn ( const char* message, double percent )
78 {
79  g_print( "%s %f complete", message, percent );
80 }
81 
82 static void
83 setup( Fixture *fixture, gconstpointer pData )
84 {
85  fixture->session = qof_session_new();
86  init_static_qofsession_pointers ();
87  g_assert (p_qof_session_clear_error && p_qof_session_destroy_backend && p_qof_session_load_backend);
88 }
89 
90 static void
91 teardown( Fixture *fixture, gconstpointer pData )
92 {
93  qof_session_destroy( fixture->session );
94  p_qof_session_clear_error = NULL;
95  p_qof_session_destroy_backend = NULL;
96  p_qof_session_load_backend = NULL;
97 }
98 
99 static void
100 test_qof_session_new_destroy (void)
101 {
102  QofSession *session = NULL;
103  QofBook *book = NULL;
104 
105  g_test_message ("Test session initialization");
106  session = qof_session_new ();
107  g_assert (session);
108  g_assert_cmpstr (session->entity.e_type, == , QOF_ID_SESSION);
109  g_assert (session->book);
110  book = (QofBook*) session->book;
111  g_assert (book);
112  g_assert (QOF_IS_BOOK (book));
113  g_assert (!session->book_id);
114  g_assert (!session->backend);
115  g_assert_cmpint (session->lock, == , 1);
116  g_assert_cmpint (qof_session_get_error (session), == , ERR_BACKEND_NO_ERR);
117 
118  g_test_message ("Test session destroy");
119  qof_session_destroy (session);
120  /* all data structures of session get deallocated so we can't really test this place
121  * instead qof_session_destroy_backend and qof_session_end are tested
122  */
123 }
124 
125 static void
126 test_session_safe_save( Fixture *fixture, gconstpointer pData )
127 {
128  fixture->session->backend = g_new0 (QofBackend, 1);
129  fixture->session->backend->safe_sync = safe_sync;
130  qof_session_safe_save( fixture->session, percentage_fn );
131  g_assert_cmpint( ERR_BACKEND_DATA_CORRUPT, == ,
132  qof_session_get_error( fixture->session ));
133  g_assert( NULL == qof_session_get_url( fixture->session ));
134 }
135 
136 static struct
137 {
138  QofBackend *be;
139  gboolean data_compatible;
140  gboolean check_data_type_called;
141  gboolean backend_new_called;
142 } load_backend_struct;
143 
144 static gboolean
145 mock_check_data_type (const char* book_id)
146 {
147  g_assert (book_id);
148  g_assert_cmpstr (book_id, == , "my book");
149  load_backend_struct.check_data_type_called = TRUE;
150  return load_backend_struct.data_compatible;
151 }
152 
153 static QofBackend*
154 mock_backend_new (void)
155 {
156  QofBackend *be = NULL;
157 
158  be = g_new0 (QofBackend, 1);
159  g_assert (be);
160  load_backend_struct.be = be;
161  load_backend_struct.backend_new_called = TRUE;
162  return be;
163 }
164 
165 static void
166 test_qof_session_load_backend (Fixture *fixture, gconstpointer pData)
167 {
168  QofBackendProvider *prov = NULL;
169  QofBook *book = NULL;
170 
171  /* init */
172  prov = g_new0 (QofBackendProvider, 1);
173 
174  g_test_message ("Test when no provider is registered");
175  g_assert (!get_qof_providers_initialized ());
176  g_assert (get_provider_list () == NULL);
177  p_qof_session_load_backend (fixture->session, "file");
178  g_assert (get_qof_providers_initialized ());
179  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
180  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
181  p_qof_session_clear_error (fixture->session);
182 
183  g_test_message ("Test with provider registered but access method not supported");
184  prov->access_method = "unsupported";
186  g_assert (get_provider_list ());
187  g_assert_cmpint (g_slist_length (get_provider_list ()), == , 1);
188  p_qof_session_load_backend (fixture->session, "file");
189  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
190  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
191  p_qof_session_clear_error (fixture->session);
192 
193  g_test_message ("Test with access method supported but type incompatible");
194  prov->access_method = "file";
195  prov->check_data_type = mock_check_data_type;
196  load_backend_struct.data_compatible = FALSE;
197  load_backend_struct.check_data_type_called = FALSE;
198  fixture->session->book_id = g_strdup ("my book");
199  p_qof_session_load_backend (fixture->session, "file");
200  g_assert (load_backend_struct.check_data_type_called);
201  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
202  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
203  p_qof_session_clear_error (fixture->session);
204 
205  g_test_message ("Test with type compatible but backend_new not set");
206  prov->backend_new = NULL;
207  load_backend_struct.data_compatible = TRUE;
208  load_backend_struct.check_data_type_called = FALSE;
209  p_qof_session_load_backend (fixture->session, "file");
210  g_assert (load_backend_struct.check_data_type_called);
211  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
212  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
213  p_qof_session_clear_error (fixture->session);
214 
215  g_test_message ("Test with type compatible backend_new set");
216  prov->backend_new = mock_backend_new;
217  load_backend_struct.be = NULL;
218  load_backend_struct.data_compatible = TRUE;
219  load_backend_struct.check_data_type_called = FALSE;
220  load_backend_struct.backend_new_called = FALSE;
221  g_assert (fixture->session->backend == NULL);
222  book = qof_session_get_book (fixture->session);
223  g_assert (book);
224  g_assert (qof_book_get_backend (book) == NULL);
225  p_qof_session_load_backend (fixture->session, "file");
226  g_assert (load_backend_struct.check_data_type_called);
227  g_assert (load_backend_struct.backend_new_called);
228  g_assert (load_backend_struct.be);
229  g_assert (load_backend_struct.be == fixture->session->backend);
230  g_assert (prov == fixture->session->backend->provider);
231  g_assert (qof_book_get_backend (book) == load_backend_struct.be);
232  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
233 
234  unregister_all_providers ();
235  g_assert_cmpint (g_slist_length (get_provider_list ()), == , 0);
236 }
237 
238 static struct
239 {
240  QofBackend *be;
241  QofBook *oldbook;
242  gboolean error;
243  gboolean load_called;
244 } load_session_struct;
245 
246 static void
247 mock_load (QofBackend *be, QofBook *book, QofBackendLoadType type)
248 {
249  g_assert (be);
250  g_assert (book);
251  g_assert (be == load_session_struct.be);
252  g_assert (book != load_session_struct.oldbook);
253  g_assert (qof_book_get_backend (book) == be);
254  if (load_session_struct.error)
255  qof_backend_set_error (be, ERR_BACKEND_DATA_CORRUPT); /* just any valid error */
256  load_session_struct.load_called = TRUE;
257 }
258 
259 static void
260 test_qof_session_load (Fixture *fixture, gconstpointer pData)
261 {
262  /* Method initializes a new book and loads data into it
263  * if load fails old books are restored
264  */
265  QofBackend *be = NULL;
266  QofBook *newbook = NULL;
267 
268  /* init */
269  fixture->session->book_id = g_strdup ("my book");
270  be = g_new0 (QofBackend, 1);
271  g_assert (be);
272  fixture->session->backend = be;
273  be->load = mock_load;
274 
275  g_test_message ("Test when no error is produced");
276  g_assert (be->percentage == NULL);
277  load_session_struct.be = be;
278  load_session_struct.oldbook = qof_session_get_book (fixture->session);
279  g_assert (fixture->session->book);
280  load_session_struct.error = FALSE;
281  load_session_struct.load_called = FALSE;
282  qof_session_load (fixture->session, percentage_fn);
283  newbook = qof_session_get_book (fixture->session);
284  g_assert (newbook);
285  g_assert (load_session_struct.oldbook != newbook);
286  g_assert (fixture->session->book);
287  g_assert (load_session_struct.load_called);
288 
289  g_test_message ("Test when no is produced");
290  load_session_struct.oldbook = qof_session_get_book (fixture->session);
291  g_assert (fixture->session->book);
292  load_session_struct.error = TRUE;
293  load_session_struct.load_called = FALSE;
294  qof_session_load (fixture->session, percentage_fn);
295  newbook = qof_session_get_book (fixture->session);
296  g_assert (newbook);
297  g_assert (load_session_struct.oldbook == newbook);
298  g_assert (fixture->session->book);
299  g_assert (load_session_struct.load_called);
300 }
301 
302 static struct
303 {
304  QofBackend *be;
305  QofSession *session;
306  const char *book_id;
307  gboolean backend_new_called;
308  gboolean session_begin_called;
309  gboolean produce_error;
310 } session_begin_struct;
311 
312 static void
313 mock_session_begin (QofBackend *be, QofSession *session, const char *book_id,
314  gboolean ignore_lock, gboolean create, gboolean force)
315 {
316  g_assert (be);
317  g_assert (be == session_begin_struct.be);
318  g_assert (session);
319  g_assert (session == session_begin_struct.session);
320  g_assert (book_id);
321  g_assert_cmpstr (book_id, == , session_begin_struct.book_id);
322  g_assert (ignore_lock);
323  g_assert (!create);
324  g_assert (force);
325  if (session_begin_struct.produce_error)
326  {
328  qof_backend_set_message (be, "push any error");
329  }
330  session_begin_struct.session_begin_called = TRUE;
331 }
332 
333 static QofBackend*
334 mock_backend_new_for_begin (void)
335 {
336  QofBackend *be = NULL;
337 
338  be = g_new0 (QofBackend, 1);
339  g_assert (be);
340  be->session_begin = mock_session_begin;
341  session_begin_struct.be = be;
342  session_begin_struct.backend_new_called = TRUE;
343  return be;
344 }
345 
346 static void
347 test_qof_session_begin (Fixture *fixture, gconstpointer pData)
348 {
349  gboolean ignore_lock, create, force;
350  QofBackend *be = NULL;
351  QofBackendProvider *prov = NULL;
352 
353  /* setup */
354  ignore_lock = TRUE;
355  create = FALSE;
356  force = TRUE;
357 
358  be = g_new0 (QofBackend, 1);
359  g_assert (be);
360  g_assert_cmpint (g_slist_length (get_provider_list ()), == , 0);
361  prov = g_new0 (QofBackendProvider, 1);
362  prov->backend_new = mock_backend_new_for_begin;
363 
364  /* run tests */
365  g_test_message ("Test when book_id is set backend is not changed");
366  fixture->session->backend = be;
367  fixture->session->book_id = g_strdup ("my book");
368  qof_session_begin (fixture->session, "my book", ignore_lock, create, force);
369  g_assert (fixture->session->backend == be);
370 
371  g_test_message ("Test when session book_id is not set and book_id passed is null backend is not changed");
372  g_free (fixture->session->book_id);
373  fixture->session->book_id = NULL;
374  qof_session_begin (fixture->session, NULL, ignore_lock, create, force);
375  g_assert (fixture->session->backend == be);
376 
377  g_test_message ("Test default access_method parsing");
378  /* routine will destroy old backend
379  * parse access_method as 'file' and try to find backend
380  * as there is no backend registered error will be raised
381  */
382  qof_session_begin (fixture->session, "default_should_be_file", ignore_lock, create, force);
383  g_assert (fixture->session->backend == NULL);
384  g_assert (fixture->session->book_id == NULL);
385  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
386  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
387 
388  g_test_message ("Test access_method parsing");
389  qof_session_begin (fixture->session, "postgres://localhost:8080", ignore_lock, create, force);
390  g_assert (fixture->session->backend == NULL);
391  g_assert (fixture->session->book_id == NULL);
392  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
393  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'postgres' using access_method");
394 
395  g_test_message ("Test with valid backend returned and session begin set; error is produced");
396  session_begin_struct.session = fixture->session;
397  session_begin_struct.book_id = "postgres://localhost:8080";
398  session_begin_struct.backend_new_called = FALSE;
399  session_begin_struct.session_begin_called = FALSE;
400  session_begin_struct.produce_error = TRUE;
401  prov->access_method = "postgres";
403  qof_session_begin (fixture->session, "postgres://localhost:8080", ignore_lock, create, force);
404  g_assert (fixture->session->backend);
405  g_assert (session_begin_struct.be == fixture->session->backend);
406  g_assert (session_begin_struct.backend_new_called == TRUE);
407  g_assert (session_begin_struct.session_begin_called == TRUE);
408  g_assert (fixture->session->book_id == NULL);
409  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_DATA_CORRUPT);
410  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "push any error");
411 
412  g_test_message ("Test normal session_begin execution");
413  session_begin_struct.backend_new_called = FALSE;
414  session_begin_struct.session_begin_called = FALSE;
415  session_begin_struct.produce_error = FALSE;
416  qof_session_begin (fixture->session, "postgres://localhost:8080", ignore_lock, create, force);
417  g_assert (fixture->session->backend);
418  g_assert (session_begin_struct.be == fixture->session->backend);
419  g_assert (session_begin_struct.backend_new_called == TRUE);
420  g_assert (session_begin_struct.session_begin_called == TRUE);
421  g_assert (fixture->session->book_id);
422  g_assert_cmpstr (fixture->session->book_id, == , "postgres://localhost:8080");
423  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
424 
425  unregister_all_providers ();
426 }
427 
428 static struct
429 {
430  QofBackend *be;
431  QofBook *book;
432  QofSession *session;
433  const char *book_id;
434  gboolean sync_called;
435  gboolean backend_new_called;
436  gboolean session_begin_called;
437 } session_save_struct;
438 
439 static void
440 mock_sync (QofBackend *be, QofBook *book)
441 {
442  g_assert (be);
443  g_assert (book);
444  g_assert (be == session_save_struct.be);
445  g_assert (book == session_save_struct.book);
446  session_save_struct.sync_called = TRUE;
447 }
448 
449 static void
450 test_qof_session_save (Fixture *fixture, gconstpointer pData)
451 {
452  QofBook *book = NULL;
453  QofBackend *be = NULL;
454  QofBackendProvider *prov = NULL;
455 
456  g_test_message ("Test when backend not set");
457  g_assert (fixture->session->backend == NULL);
458  book = qof_session_get_book (fixture->session);
459  g_assert (book);
460  qof_session_push_error (fixture->session, ERR_BACKEND_DATA_CORRUPT, "push any error");
461  g_assert_cmpint (fixture->session->lock, == , 1);
462  qof_session_save (fixture->session, NULL);
463  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
464  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load backend");
465  g_assert_cmpint (fixture->session->lock, == , 1);
466 
467  g_test_message ("Test when backend set; imitate error");
468  be = g_new0 (QofBackend, 1);
469  g_assert (be);
470  be->sync = mock_sync;
471  fixture->session->backend = be;
472  g_assert_cmpint (fixture->session->lock, == , 1);
473  session_save_struct.sync_called = FALSE;
474  session_save_struct.be = be;
475  session_save_struct.book = book;
477  qof_backend_set_message (be, "push any error");
478  qof_session_save (fixture->session, percentage_fn);
479  g_assert (qof_book_get_backend (book) == be);
480  g_assert (be->percentage == percentage_fn);
481  g_assert (session_save_struct.sync_called);
482  g_assert_cmpint (fixture->session->lock, == , 1);
483  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_DATA_CORRUPT);
484  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "");
485 
486  g_test_message ("Test when backend set; successful save");
487  g_assert_cmpint (fixture->session->lock, == , 1);
488  session_save_struct.sync_called = FALSE;
489  qof_session_save (fixture->session, percentage_fn);
490  g_assert (qof_book_get_backend (book) == be);
491  g_assert (be->percentage == percentage_fn);
492  g_assert (session_save_struct.sync_called);
493  g_assert_cmpint (fixture->session->lock, == , 1);
494  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
495 
496  /* change backend testing
497  * code probably should be moved to separate routine or some existing code can be reused
498  * for example: qof_session_load_backend
499  */
500 
501  unregister_all_providers ();
502  g_free (prov);
503 }
504 
505 static struct
506 {
507  QofBackend *be;
508  gboolean called;
509 } destroy_backend_struct;
510 
511 static void
512 mock_destroy_backend (QofBackend *be)
513 {
514  g_assert (be);
515  g_assert (destroy_backend_struct.be == be);
516  destroy_backend_struct.called = TRUE;
517 }
518 
519 static void
520 test_qof_session_destroy_backend (Fixture *fixture, gconstpointer pData)
521 {
522  QofBackend *be = NULL;
523 
524  g_test_message ("Test with destroy backend callback not set");
525  be = g_new0 (QofBackend, 1);
526  g_assert (be);
527  fixture->session->backend = be;
528  p_qof_session_destroy_backend (fixture->session);
529  g_assert (!fixture->session->backend);
530 
531  g_test_message ("Test with destroy backend callback set");
532  be = g_new0 (QofBackend, 1);
533  g_assert (be);
534  be->destroy_backend = mock_destroy_backend;
535  fixture->session->backend = be;
536  destroy_backend_struct.called = FALSE;
537  destroy_backend_struct.be = be;
538  p_qof_session_destroy_backend (fixture->session);
539  g_assert (!fixture->session->backend);
540  g_assert (destroy_backend_struct.called);
541 }
542 
543 static struct
544 {
545  QofBackend *be;
546  gboolean called;
547 } session_end_struct;
548 
549 static void
550 mock_session_end (QofBackend *be)
551 {
552  g_assert (be);
553  g_assert (session_end_struct.be == be);
554  session_end_struct.called = TRUE;
555 }
556 
557 static void
558 test_qof_session_end (Fixture *fixture, gconstpointer pData)
559 {
560  QofBackend *be = NULL;
561 
562  g_test_message ("Test backend is closed, errors cleared and book_id removed");
563  be = g_new0 (QofBackend, 1);
564  g_assert (be);
565  be->session_end = mock_session_end;
566  fixture->session->backend = be;
567  qof_session_push_error (fixture->session, ERR_BACKEND_DATA_CORRUPT, "push any error");
568  fixture->session->book_id = g_strdup ("my book");
569  session_end_struct.called = FALSE;
570  session_end_struct.be = be;
571  qof_session_end (fixture->session);
572  g_assert (session_end_struct.called);
573  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
574  g_assert (!fixture->session->book_id);
575 }
576 
577 static struct
578 {
579  QofBackend *be;
580  QofBook *book;
581  gboolean called;
582 } session_export_struct;
583 
584 static void
585 mock_export (QofBackend *be, QofBook *book)
586 {
587  g_assert (be);
588  g_assert (session_export_struct.be == be);
589  g_assert (book);
590  g_assert (session_export_struct.book == book);
591  session_export_struct.called = TRUE;
592 }
593 
594 static void
595 test_qof_session_export (Fixture *fixture, gconstpointer pData)
596 {
597  QofSession *real_session = NULL;
598  QofBook *tmp_book = NULL, *real_book = NULL;
599  QofBackend *be = NULL;
600 
601  real_session = qof_session_new ();
602  g_assert (real_session);
603 
604  g_test_message ("Test null checks");
605  g_assert (!qof_session_export (NULL, real_session, percentage_fn));
606  g_assert (!qof_session_export (fixture->session, NULL, percentage_fn));
607 
608  g_test_message ("Test with backend not set");
609  tmp_book = qof_session_get_book (fixture->session);
610  g_assert (tmp_book);
611  be = qof_book_get_backend (tmp_book);
612  g_assert (!be);
613  g_assert (!qof_session_export (fixture->session, real_session, percentage_fn));
614 
615  g_test_message ("Test with backend set");
616  be = g_new0 (QofBackend, 1);
617  g_assert (be);
618  fixture->session->backend = be;
619  qof_book_set_backend (tmp_book, be);
620  g_assert (!be->percentage);
621  g_assert (qof_session_export (fixture->session, real_session, percentage_fn));
622  g_assert (be->percentage == percentage_fn);
623 
624  g_test_message ("Test with backend export function set and error is produced");
625  be->export_fn = mock_export;
627  qof_backend_set_message (be, "push any error");
628  session_export_struct.called = FALSE;
629  real_book = qof_session_get_book (real_session);
630  g_assert (real_book);
631  session_export_struct.be = be;
632  session_export_struct.book = real_book;
633  g_assert (!qof_session_export (fixture->session, real_session, percentage_fn));
634  g_assert (session_export_struct.called);
635 
636  g_test_message ("Test with backend export function set and no error produced");
637  p_qof_session_clear_error (fixture->session);
638  session_export_struct.called = FALSE;
639  g_assert (qof_session_export (fixture->session, real_session, percentage_fn));
640  g_assert (session_export_struct.called);
641 
642  qof_session_destroy (real_session);
643 }
644 
645 static void
646 test_qof_session_swap_data (Fixture *fixture, gconstpointer pData)
647 {
648  QofSession *session2 = NULL;
649  QofBackend *be1 = NULL, *be2 = NULL;
650  QofBook *book1 = NULL, *book2 = NULL;
651 
652  /* init */
653  g_assert (fixture->session);
654  session2 = qof_session_new ();
655  g_assert (session2);
656  g_assert (fixture->session != session2);
657  be1 = g_new0 (QofBackend, 1);
658  g_assert (be1);
659  be2 = g_new0 (QofBackend, 1);
660  g_assert (be2);
661  fixture->session->backend = be1;
662  session2->backend = be2;
663  book1 = fixture->session->book;
664  book2 = session2->book;
665  g_assert (book1);
666  g_assert (book2);
667  qof_book_set_backend (book1, fixture->session->backend);
668  qof_book_set_backend (book2, session2->backend);
669 
670 
671  g_test_message ("Test book lists are swapped and backend for each book is swapped");
672  qof_session_swap_data (fixture->session, session2);
673  g_assert (fixture->session->book == book2);
674  g_assert (session2->book == book1);
675 
676  qof_session_destroy (session2);
677 }
678 
679 static struct
680 {
681  QofBackend *be;
682  gboolean called;
683 } events_struct;
684 
685 static gboolean
686 mock_events_fn (QofBackend *be)
687 {
688  g_assert (be);
689  g_assert (be == events_struct.be);
690  events_struct.called = TRUE;
691  return TRUE;
692 }
693 
694 static void
695 test_qof_session_events (Fixture *fixture, gconstpointer pData)
696 {
697  QofBackend *be = NULL;
698 
699  g_test_message ("Test pending events null checks");
700  g_assert (!qof_session_events_pending (NULL));
701  g_assert (!fixture->session->backend);
702  g_assert (!qof_session_events_pending (fixture->session));
703  be = g_new0 (QofBackend, 1);
704  g_assert (be);
705  be->events_pending = NULL;
706  fixture->session->backend = be;
707  g_assert (!qof_session_events_pending (fixture->session));
708 
709  g_test_message ("Test pending events callback");
710  be->events_pending = mock_events_fn;
711  events_struct.called = FALSE;
712  events_struct.be = be;
713  g_assert (qof_session_events_pending (fixture->session));
714  g_assert (events_struct.called);
715 
716  g_test_message ("Test process events null checks");
717  g_assert (!qof_session_process_events (NULL));
718  fixture->session->backend = NULL;
719  g_assert (!qof_session_process_events (fixture->session));
720  be->process_events = NULL;
721  fixture->session->backend = be;
722  g_assert (!qof_session_process_events (fixture->session));
723 
724  g_test_message ("Test process events callback");
725  be->process_events = mock_events_fn;
726  events_struct.called = FALSE;
727  events_struct.be = be;
728  g_assert (qof_session_process_events (fixture->session));
729  g_assert (events_struct.called);
730 }
731 
732 static struct
733 {
734  QofBackend *be;
735  QofBook *book;
736  gboolean called;
737 } data_load_struct;
738 
739 static void
740 mock_all_data_load (QofBackend *be, QofBook *book, QofBackendLoadType type)
741 {
742  g_assert (be);
743  g_assert (book);
744  g_assert (be == data_load_struct.be);
745  g_assert (book == data_load_struct.book);
746  g_assert_cmpint (type, == , LOAD_TYPE_LOAD_ALL);
748  data_load_struct.called = TRUE;
749 }
750 
751 static void
752 test_qof_session_data_loaded (Fixture *fixture, gconstpointer pData)
753 {
754  QofBackend *be = NULL;
755 
756  be = g_new0 (QofBackend, 1);
757  g_assert (be);
758  be->load = mock_all_data_load;
759  fixture->session->backend = be;
760 
761  g_test_message ("Test load callback and artificial error");
762  data_load_struct.be = be;
763  data_load_struct.book = qof_session_get_book (fixture->session);
764  data_load_struct.called = FALSE;
765  qof_session_ensure_all_data_loaded (fixture->session);
766  g_assert (data_load_struct.called);
767  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_DATA_CORRUPT);
768  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "");
769 }
770 
771 static void
772 test_qof_backend_get_access_method_list (Fixture *fixture, gconstpointer pData)
773 {
774  GList *list = NULL;
775  const char *access_methods[4] = { "file", "http", "postgres", "sqlite" };
776  int i;
777 
778  for (i = 0; i < 4; i++)
779  {
780  QofBackendProvider *prov = g_new0 (QofBackendProvider, 1);
781  g_assert (prov);
782  prov->access_method = access_methods[ i ];
784  g_assert_cmpint (g_slist_length (get_provider_list ()), == , (i + 1));
785  }
786  g_assert_cmpint (g_slist_length (get_provider_list ()), == , 4);
787 
788  g_test_message ("Test list of access methods is returned");
790  g_assert (list);
791  g_assert_cmpint (g_list_length (list), == , 4);
792  g_assert_cmpstr (g_list_nth_data (list, 0), == , "file");
793  g_assert_cmpstr (g_list_nth_data (list, 1), == , "http");
794  g_assert_cmpstr (g_list_nth_data (list, 2), == , "postgres");
795  g_assert_cmpstr (g_list_nth_data (list, 3), == , "sqlite");
796 
797  g_list_free (list);
798  unregister_all_providers ();
799 }
800 
801 
802 static void
803 test_qof_session_get_book (Fixture *fixture, gconstpointer pData)
804 {
805  QofBook *book = NULL;
806 
807  g_test_message ("Test null check");
808  g_assert (!qof_session_get_book (NULL));
809 
810  g_test_message ("Test open book is returned");
811  g_assert (fixture->session->book);
812  book = qof_session_get_book (fixture->session);
813  g_assert (book);
814  g_assert_cmpuint (book->book_open, == , 'y');
815 
816  g_test_message ("Test when book is closed null returned");
817  qof_book_mark_closed (book);
818  g_assert (!qof_session_get_book (fixture->session));
819 
820 }
821 
822 static void
823 test_qof_session_get_error (Fixture *fixture, gconstpointer pData)
824 {
825  QofBackend *be = NULL;
826 
827  g_test_message ("Test if session is null");
828  g_assert_cmpint (qof_session_get_error (NULL), == , ERR_BACKEND_NO_BACKEND);
829 
830  g_test_message ("Test when there is a local error");
831  fixture->session->last_err = ERR_BACKEND_DATA_CORRUPT; /* just any error */
832  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_DATA_CORRUPT);
833 
834  g_test_message ("Test if session backend is null");
835  g_assert (!fixture->session->backend);
836  fixture->session->last_err = ERR_BACKEND_NO_ERR;
837  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
838 
839  g_test_message ("Test for backend error");
840  be = g_new0 (QofBackend, 1);
841  g_assert (be);
843  fixture->session->backend = be;
844  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_CANT_CONNECT);
845 }
846 
847 static void
848 test_qof_session_clear_error (Fixture *fixture, gconstpointer pData)
849 {
850  QofBackend *be = NULL;
851 
852  be = g_new0 (QofBackend, 1);
853  g_assert (be);
854 
855  g_test_message ("Test session and backend errors are cleared");
856  qof_session_push_error (fixture->session, ERR_BACKEND_NO_SUCH_DB, "push any error");
857  fixture->session->backend = be;
859  p_qof_session_clear_error (fixture->session);
860  g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
861  g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "");
862  g_assert (!fixture->session->error_message);
863  g_assert_cmpint (qof_backend_get_error (be), == , ERR_BACKEND_NO_ERR);
864 }
865 
866 static struct
867 {
868  QofSession *session;
869  gpointer data1;
870  gpointer data2;
871  gpointer data3;
872  guint call_count;
873 } hooks_struct;
874 
875 static void
876 mock_hook_fn (gpointer data, gpointer user_data)
877 {
878  QofSession *session;
879 
880  g_assert (data);
881  g_assert (user_data);
882  session = (QofSession*) data;
883  g_assert (session == hooks_struct.session);
884  if (hooks_struct.call_count == 0)
885  g_assert (hooks_struct.data1 == user_data);
886  if (hooks_struct.call_count == 1)
887  g_assert (hooks_struct.data2 == user_data);
888  if (hooks_struct.call_count == 2)
889  g_assert (hooks_struct.data3 == user_data);
890  hooks_struct.call_count++;
891 }
892 
893 static void
894 test_qof_session_close_hooks (Fixture *fixture, gconstpointer pData)
895 {
896  gint data1, data2, data3;
897 
898  g_test_message ("Test hooks list is initialized and hooks are added");
899  g_assert (!get_session_closed_hooks ());
900  qof_session_add_close_hook (mock_hook_fn, (gpointer) &data1);
901  g_assert (get_session_closed_hooks ());
902  g_assert (g_hook_find_func_data (get_session_closed_hooks (), FALSE, mock_hook_fn, (gpointer) &data1));
903  qof_session_add_close_hook (mock_hook_fn, (gpointer) &data2);
904  g_assert (g_hook_find_func_data (get_session_closed_hooks (), FALSE, mock_hook_fn, (gpointer) &data2));
905  qof_session_add_close_hook (mock_hook_fn, (gpointer) &data3);
906  g_assert (g_hook_find_func_data (get_session_closed_hooks (), FALSE, mock_hook_fn, (gpointer) &data3));
907 
908  g_test_message ("Test all close hooks are called");
909  hooks_struct.session = fixture->session;
910  hooks_struct.data1 = (gpointer) &data1;
911  hooks_struct.data2 = (gpointer) &data2;
912  hooks_struct.data3 = (gpointer) &data3;
913  hooks_struct.call_count = 0;
914  qof_session_call_close_hooks (fixture->session);
915  g_assert_cmpuint (hooks_struct.call_count, == , 3);
916 
917  /* currently qofsession does not provide a way to clear hooks list
918  * g_hook_list_clear is used to destroy list and all of it's elements
919  * though i' not sure if it frees all the memory allocated
920  */
921  g_hook_list_clear (get_session_closed_hooks ());
922 }
923 
924 void
925 test_suite_qofsession ( void )
926 {
927  GNC_TEST_ADD_FUNC (suitename, "qof session new and destroy", test_qof_session_new_destroy);
928  GNC_TEST_ADD (suitename, "qof session safe save", Fixture, NULL, setup, test_session_safe_save, teardown);
929  GNC_TEST_ADD (suitename, "qof session load backend", Fixture, NULL, setup, test_qof_session_load_backend, teardown);
930  GNC_TEST_ADD (suitename, "qof session load", Fixture, NULL, setup, test_qof_session_load, teardown);
931  GNC_TEST_ADD (suitename, "qof session begin", Fixture, NULL, setup, test_qof_session_begin, teardown);
932  GNC_TEST_ADD (suitename, "qof session save", Fixture, NULL, setup, test_qof_session_save, teardown);
933  GNC_TEST_ADD (suitename, "qof session destroy backend", Fixture, NULL, setup, test_qof_session_destroy_backend, teardown);
934  GNC_TEST_ADD (suitename, "qof session end", Fixture, NULL, setup, test_qof_session_end, teardown);
935  GNC_TEST_ADD (suitename, "qof session export", Fixture, NULL, setup, test_qof_session_export, teardown);
936  GNC_TEST_ADD (suitename, "qof session swap data", Fixture, NULL, setup, test_qof_session_swap_data, teardown);
937  GNC_TEST_ADD (suitename, "qof session events", Fixture, NULL, setup, test_qof_session_events, teardown);
938  GNC_TEST_ADD (suitename, "qof session data loaded", Fixture, NULL, setup, test_qof_session_data_loaded, teardown);
939  GNC_TEST_ADD (suitename, "qof backend access method list", Fixture, NULL, setup, test_qof_backend_get_access_method_list, teardown);
940  GNC_TEST_ADD (suitename, "qof session get book", Fixture, NULL, setup, test_qof_session_get_book, teardown);
941  GNC_TEST_ADD (suitename, "qof session get error", Fixture, NULL, setup, test_qof_session_get_error, teardown);
942  GNC_TEST_ADD (suitename, "qof session clear error", Fixture, NULL, setup, test_qof_session_clear_error, teardown);
943  GNC_TEST_ADD (suitename, "qof session close hooks", Fixture, NULL, setup, test_qof_session_close_hooks, teardown);
944 }
QofIdType e_type
Definition: qofinstance.h:69
void qof_session_save(QofSession *session, QofPercentageFunc percentage_func)
QofBackend *(* backend_new)(void)
Definition: qofbackend-p.h:255
void qof_backend_set_error(QofBackend *be, QofBackendError err)
void qof_backend_register_provider(QofBackendProvider *)
void qof_session_safe_save(QofSession *session, QofPercentageFunc percentage_func)
void qof_book_mark_closed(QofBook *book)
gboolean qof_session_events_pending(const QofSession *session)
void(* export_fn)(QofBackend *, QofBook *)
Definition: qofbackend-p.h:343
QofBook * qof_session_get_book(const QofSession *session)
void qof_backend_set_message(QofBackend *be, const char *format,...)
void qof_session_call_close_hooks(QofSession *session)
void qof_session_add_close_hook(GFunc fn, gpointer data)
QofBackendError qof_session_get_error(QofSession *session)
gboolean(* check_data_type)(const char *)
Distinguish two providers with same access method.
Definition: qofbackend-p.h:272
void qof_session_swap_data(QofSession *session_1, QofSession *session_2)
QofBackendError qof_backend_get_error(QofBackend *be)
void qof_session_begin(QofSession *session, const char *book_id, gboolean ignore_lock, gboolean create, gboolean force)
gboolean qof_session_process_events(QofSession *session)
const char * access_method
Definition: qofbackend-p.h:248
void qof_session_ensure_all_data_loaded(QofSession *session)
GList * qof_backend_get_registered_access_method_list(void)
void qof_session_end(QofSession *session)
QofBackend * qof_book_get_backend(const QofBook *book)
Retrieve the backend used by this book.