GnuCash 2.4.99
test-qofsession.c
00001 /********************************************************************
00002  * test_qofsession.c: GLib g_test test suite for qofsession.        *
00003  * Copyright 2011 John Ralls <jralls@ceridwen.us>                   *
00004  *                                                                  *
00005  * This program is free software; you can redistribute it and/or    *
00006  * modify it under the terms of the GNU General Public License as   *
00007  * published by the Free Software Foundation; either version 2 of   *
00008  * the License, or (at your option) any later version.              *
00009  *                                                                  *
00010  * This program is distributed in the hope that it will be useful,  *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00013  * GNU General Public License for more details.                     *
00014  *                                                                  *
00015  * You should have received a copy of the GNU General Public License*
00016  * along with this program; if not, contact:                        *
00017  *                                                                  *
00018  * Free Software Foundation           Voice:  +1-617-542-5942       *
00019  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00020  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00021 \********************************************************************/
00022 
00023 #include "config.h"
00024 #include <glib.h>
00025 #include <unittest-support.h>
00026 #include "../qof.h"
00027 #include "../qofbackend-p.h"
00028 #include "../qofsession-p.h"
00029 #include "../qofclass-p.h"
00030 
00031 static const gchar *suitename = "/qof/qofsession";
00032 void test_suite_qofsession ( void );
00033 
00034 extern GHookList* get_session_closed_hooks (void);
00035 extern GSList* get_provider_list (void);
00036 extern gboolean get_qof_providers_initialized (void);
00037 extern void unregister_all_providers (void);
00038 
00039 extern void (*p_qof_session_load_backend) (QofSession * session, const char * access_method);
00040 extern void (*p_qof_session_clear_error) (QofSession * session);
00041 extern void (*p_qof_session_destroy_backend) (QofSession * session);
00042 
00043 extern void init_static_qofsession_pointers (void);
00044 
00045 typedef struct
00046 {
00047     QofSession *session;
00048 } Fixture;
00049 
00050 static void
00051 safe_sync( QofBackend *be, QofBook *book )
00052 {
00053     qof_backend_set_error( be, ERR_BACKEND_DATA_CORRUPT );
00054     qof_backend_set_message( be, "Just Kidding!" );
00055 }
00056 
00057 static void
00058 percentage_fn ( const char* message, double percent )
00059 {
00060     g_print( "%s %f complete", message, percent );
00061 }
00062 
00063 static void
00064 setup( Fixture *fixture, gconstpointer pData )
00065 {
00066     fixture->session = qof_session_new();
00067     init_static_qofsession_pointers ();
00068     g_assert (p_qof_session_clear_error && p_qof_session_destroy_backend && p_qof_session_load_backend);
00069 }
00070 
00071 static void
00072 teardown( Fixture *fixture, gconstpointer pData )
00073 {
00074     qof_session_destroy( fixture->session );
00075     p_qof_session_clear_error = NULL;
00076     p_qof_session_destroy_backend = NULL;
00077     p_qof_session_load_backend = NULL;
00078 }
00079 
00080 static void
00081 test_qof_session_new_destroy (void)
00082 {
00083     QofSession *session = NULL;
00084     QofBook *book = NULL;
00085 
00086     g_test_message ("Test session initialization");
00087     session = qof_session_new ();
00088     g_assert (session);
00089     g_assert_cmpstr (session->entity.e_type, == , QOF_ID_SESSION);
00090     g_assert (session->book);
00091     book = (QofBook*) session->book;
00092     g_assert (book);
00093     g_assert (QOF_IS_BOOK (book));
00094     g_assert (!session->book_id);
00095     g_assert (!session->backend);
00096     g_assert_cmpint (session->lock, == , 1);
00097     g_assert_cmpint (qof_session_get_error (session), == , ERR_BACKEND_NO_ERR);
00098 
00099     g_test_message ("Test session destroy");
00100     qof_session_destroy (session);
00101     /* all data structures of session get deallocated so we can't really test this place
00102      * instead qof_session_destroy_backend and qof_session_end are tested
00103      */
00104 }
00105 
00106 static void
00107 test_session_safe_save( Fixture *fixture, gconstpointer pData )
00108 {
00109     fixture->session->backend = g_new0 (QofBackend, 1);
00110     fixture->session->backend->safe_sync = safe_sync;
00111     qof_session_safe_save( fixture->session, percentage_fn );
00112     g_assert_cmpint( ERR_BACKEND_DATA_CORRUPT, == ,
00113                      qof_session_get_error( fixture->session ));
00114     g_assert( NULL == qof_session_get_url( fixture->session ));
00115 }
00116 
00117 static struct
00118 {
00119     QofBackend *be;
00120     gboolean data_compatible;
00121     gboolean check_data_type_called;
00122     gboolean backend_new_called;
00123 } load_backend_struct;
00124 
00125 static gboolean
00126 mock_check_data_type (const char* book_id)
00127 {
00128     g_assert (book_id);
00129     g_assert_cmpstr (book_id, == , "my book");
00130     load_backend_struct.check_data_type_called = TRUE;
00131     return load_backend_struct.data_compatible;
00132 }
00133 
00134 static QofBackend*
00135 mock_backend_new (void)
00136 {
00137     QofBackend *be = NULL;
00138 
00139     be = g_new0 (QofBackend, 1);
00140     g_assert (be);
00141     load_backend_struct.be = be;
00142     load_backend_struct.backend_new_called = TRUE;
00143     return be;
00144 }
00145 
00146 static void
00147 test_qof_session_load_backend (Fixture *fixture, gconstpointer pData)
00148 {
00149     QofBackendProvider *prov = NULL;
00150     QofBook *book = NULL;
00151 
00152     /* init */
00153     prov = g_new0 (QofBackendProvider, 1);
00154 
00155     g_test_message ("Test when no provider is registered");
00156     g_assert (!get_qof_providers_initialized ());
00157     g_assert (get_provider_list () == NULL);
00158     p_qof_session_load_backend (fixture->session, "file");
00159     g_assert (get_qof_providers_initialized ());
00160     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
00161     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
00162     p_qof_session_clear_error (fixture->session);
00163 
00164     g_test_message ("Test with provider registered but access method not supported");
00165     prov->access_method = "unsupported";
00166     qof_backend_register_provider (prov);
00167     g_assert (get_provider_list ());
00168     g_assert_cmpint (g_slist_length (get_provider_list ()), == , 1);
00169     p_qof_session_load_backend (fixture->session, "file");
00170     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
00171     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
00172     p_qof_session_clear_error (fixture->session);
00173 
00174     g_test_message ("Test with access method supported but type incompatible");
00175     prov->access_method = "file";
00176     prov->check_data_type = mock_check_data_type;
00177     load_backend_struct.data_compatible = FALSE;
00178     load_backend_struct.check_data_type_called = FALSE;
00179     fixture->session->book_id = g_strdup ("my book");
00180     p_qof_session_load_backend (fixture->session, "file");
00181     g_assert (load_backend_struct.check_data_type_called);
00182     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
00183     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
00184     p_qof_session_clear_error (fixture->session);
00185 
00186     g_test_message ("Test with type compatible but backend_new not set");
00187     prov->backend_new = NULL;
00188     load_backend_struct.data_compatible = TRUE;
00189     load_backend_struct.check_data_type_called = FALSE;
00190     p_qof_session_load_backend (fixture->session, "file");
00191     g_assert (load_backend_struct.check_data_type_called);
00192     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
00193     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
00194     p_qof_session_clear_error (fixture->session);
00195 
00196     g_test_message ("Test with type compatible backend_new set");
00197     prov->backend_new = mock_backend_new;
00198     load_backend_struct.be = NULL;
00199     load_backend_struct.data_compatible = TRUE;
00200     load_backend_struct.check_data_type_called = FALSE;
00201     load_backend_struct.backend_new_called = FALSE;
00202     g_assert (fixture->session->backend == NULL);
00203     book = qof_session_get_book (fixture->session);
00204     g_assert (book);
00205     g_assert (qof_book_get_backend (book) == NULL);
00206     p_qof_session_load_backend (fixture->session, "file");
00207     g_assert (load_backend_struct.check_data_type_called);
00208     g_assert (load_backend_struct.backend_new_called);
00209     g_assert (load_backend_struct.be);
00210     g_assert (load_backend_struct.be == fixture->session->backend);
00211     g_assert (prov == fixture->session->backend->provider);
00212     g_assert (qof_book_get_backend (book) == load_backend_struct.be);
00213     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
00214 
00215     unregister_all_providers ();
00216     g_assert_cmpint (g_slist_length (get_provider_list ()), == , 0);
00217 }
00218 
00219 static struct
00220 {
00221     QofBackend *be;
00222     QofBook *oldbook;
00223     gboolean error;
00224     gboolean load_called;
00225 } load_session_struct;
00226 
00227 static void
00228 mock_load (QofBackend *be, QofBook *book, QofBackendLoadType type)
00229 {
00230     g_assert (be);
00231     g_assert (book);
00232     g_assert (be == load_session_struct.be);
00233     g_assert (book != load_session_struct.oldbook);
00234     g_assert (qof_book_get_backend (book) == be);
00235     if (load_session_struct.error)
00236         qof_backend_set_error (be, ERR_BACKEND_DATA_CORRUPT); /* just any valid error */
00237     load_session_struct.load_called = TRUE;
00238 }
00239 
00240 static void
00241 test_qof_session_load (Fixture *fixture, gconstpointer pData)
00242 {
00243     /* Method initializes a new book and loads data into it
00244      * if load fails old books are restored
00245      */
00246     QofBackend *be = NULL;
00247     QofBook *newbook = NULL;
00248 
00249     /* init */
00250     fixture->session->book_id = g_strdup ("my book");
00251     be = g_new0 (QofBackend, 1);
00252     g_assert (be);
00253     fixture->session->backend = be;
00254     be->load = mock_load;
00255 
00256     g_test_message ("Test when no error is produced");
00257     g_assert (be->percentage == NULL);
00258     load_session_struct.be = be;
00259     load_session_struct.oldbook = qof_session_get_book (fixture->session);
00260     g_assert (fixture->session->book);
00261     load_session_struct.error = FALSE;
00262     load_session_struct.load_called = FALSE;
00263     qof_session_load (fixture->session, percentage_fn);
00264     newbook = qof_session_get_book (fixture->session);
00265     g_assert (newbook);
00266     g_assert (load_session_struct.oldbook != newbook);
00267     g_assert (fixture->session->book);
00268     g_assert (load_session_struct.load_called);
00269 
00270     g_test_message ("Test when no is produced");
00271     load_session_struct.oldbook = qof_session_get_book (fixture->session);
00272     g_assert (fixture->session->book);
00273     load_session_struct.error = TRUE;
00274     load_session_struct.load_called = FALSE;
00275     qof_session_load (fixture->session, percentage_fn);
00276     newbook = qof_session_get_book (fixture->session);
00277     g_assert (newbook);
00278     g_assert (load_session_struct.oldbook == newbook);
00279     g_assert (fixture->session->book);
00280     g_assert (load_session_struct.load_called);
00281 }
00282 
00283 static struct
00284 {
00285     QofBackend *be;
00286     QofSession *session;
00287     const char *book_id;
00288     gboolean backend_new_called;
00289     gboolean session_begin_called;
00290     gboolean produce_error;
00291 } session_begin_struct;
00292 
00293 static void
00294 mock_session_begin (QofBackend *be, QofSession *session, const char *book_id,
00295                     gboolean ignore_lock, gboolean create, gboolean force)
00296 {
00297     g_assert (be);
00298     g_assert (be == session_begin_struct.be);
00299     g_assert (session);
00300     g_assert (session == session_begin_struct.session);
00301     g_assert (book_id);
00302     g_assert_cmpstr (book_id, == , session_begin_struct.book_id);
00303     g_assert (ignore_lock);
00304     g_assert (!create);
00305     g_assert (force);
00306     if (session_begin_struct.produce_error)
00307     {
00308         qof_backend_set_error (be, ERR_BACKEND_DATA_CORRUPT);
00309         qof_backend_set_message (be, "push any error");
00310     }
00311     session_begin_struct.session_begin_called = TRUE;
00312 }
00313 
00314 static QofBackend*
00315 mock_backend_new_for_begin (void)
00316 {
00317     QofBackend *be = NULL;
00318 
00319     be = g_new0 (QofBackend, 1);
00320     g_assert (be);
00321     be->session_begin = mock_session_begin;
00322     session_begin_struct.be = be;
00323     session_begin_struct.backend_new_called = TRUE;
00324     return be;
00325 }
00326 
00327 static void
00328 test_qof_session_begin (Fixture *fixture, gconstpointer pData)
00329 {
00330     gboolean ignore_lock, create, force;
00331     QofBackend *be = NULL;
00332     QofBackendProvider *prov = NULL;
00333 
00334     /* setup */
00335     ignore_lock = TRUE;
00336     create = FALSE;
00337     force = TRUE;
00338 
00339     be = g_new0 (QofBackend, 1);
00340     g_assert (be);
00341     g_assert_cmpint (g_slist_length (get_provider_list ()), == , 0);
00342     prov = g_new0 (QofBackendProvider, 1);
00343     prov->backend_new = mock_backend_new_for_begin;
00344 
00345     /* run tests */
00346     g_test_message ("Test when book_id is set backend is not changed");
00347     fixture->session->backend = be;
00348     fixture->session->book_id = g_strdup ("my book");
00349     qof_session_begin (fixture->session, "my book", ignore_lock, create, force);
00350     g_assert (fixture->session->backend == be);
00351 
00352     g_test_message ("Test when session book_id is not set and book_id passed is null backend is not changed");
00353     g_free (fixture->session->book_id);
00354     fixture->session->book_id = NULL;
00355     qof_session_begin (fixture->session, NULL, ignore_lock, create, force);
00356     g_assert (fixture->session->backend == be);
00357 
00358     g_test_message ("Test default access_method parsing");
00359     /* routine will destroy old backend
00360      * parse access_method as 'file' and try to find backend
00361      * as there is no backend registered error will be raised
00362      */
00363     qof_session_begin (fixture->session, "default_should_be_file", ignore_lock, create, force);
00364     g_assert (fixture->session->backend == NULL);
00365     g_assert (fixture->session->book_id == NULL);
00366     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
00367     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'file' using access_method");
00368 
00369     g_test_message ("Test access_method parsing");
00370     qof_session_begin (fixture->session, "postgres://localhost:8080", ignore_lock, create, force);
00371     g_assert (fixture->session->backend == NULL);
00372     g_assert (fixture->session->book_id == NULL);
00373     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
00374     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load 'postgres' using access_method");
00375 
00376     g_test_message ("Test with valid backend returned and session begin set; error is produced");
00377     session_begin_struct.session = fixture->session;
00378     session_begin_struct.book_id = "postgres://localhost:8080";
00379     session_begin_struct.backend_new_called = FALSE;
00380     session_begin_struct.session_begin_called = FALSE;
00381     session_begin_struct.produce_error = TRUE;
00382     prov->access_method = "postgres";
00383     qof_backend_register_provider (prov);
00384     qof_session_begin (fixture->session, "postgres://localhost:8080", ignore_lock, create, force);
00385     g_assert (fixture->session->backend);
00386     g_assert (session_begin_struct.be == fixture->session->backend);
00387     g_assert (session_begin_struct.backend_new_called == TRUE);
00388     g_assert (session_begin_struct.session_begin_called == TRUE);
00389     g_assert (fixture->session->book_id == NULL);
00390     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_DATA_CORRUPT);
00391     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "push any error");
00392 
00393     g_test_message ("Test normal session_begin execution");
00394     session_begin_struct.backend_new_called = FALSE;
00395     session_begin_struct.session_begin_called = FALSE;
00396     session_begin_struct.produce_error = FALSE;
00397     qof_session_begin (fixture->session, "postgres://localhost:8080", ignore_lock, create, force);
00398     g_assert (fixture->session->backend);
00399     g_assert (session_begin_struct.be == fixture->session->backend);
00400     g_assert (session_begin_struct.backend_new_called == TRUE);
00401     g_assert (session_begin_struct.session_begin_called == TRUE);
00402     g_assert (fixture->session->book_id);
00403     g_assert_cmpstr (fixture->session->book_id, == , "postgres://localhost:8080");
00404     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
00405 
00406     unregister_all_providers ();
00407 }
00408 
00409 static struct
00410 {
00411     QofBackend *be;
00412     QofBook *book;
00413     QofSession *session;
00414     const char *book_id;
00415     gboolean sync_called;
00416     gboolean backend_new_called;
00417     gboolean session_begin_called;
00418 } session_save_struct;
00419 
00420 static void
00421 mock_sync (QofBackend *be, QofBook *book)
00422 {
00423     g_assert (be);
00424     g_assert (book);
00425     g_assert (be == session_save_struct.be);
00426     g_assert (book == session_save_struct.book);
00427     session_save_struct.sync_called = TRUE;
00428 }
00429 
00430 static void
00431 mock_session_begin_for_save (QofBackend *be, QofSession *session, const char *book_id,
00432                              gboolean ignore_lock, gboolean create, gboolean force)
00433 {
00434     g_assert (be);
00435     g_assert (be == session_save_struct.be);
00436     g_assert (session);
00437     g_assert (session == session_save_struct.session);
00438     g_assert (book_id);
00439     g_assert_cmpstr (book_id, == , session_save_struct.book_id);
00440     g_assert (ignore_lock);
00441     g_assert (create);
00442     g_assert (force);
00443     session_save_struct.session_begin_called = TRUE;
00444 }
00445 
00446 static QofBackend*
00447 mock_backend_new_for_save (void)
00448 {
00449     QofBackend *be = NULL;
00450 
00451     be = g_new0 (QofBackend, 1);
00452     g_assert (be);
00453     be->session_begin = mock_session_begin_for_save;
00454     be->sync = mock_sync;
00455     session_save_struct.be = be;
00456     session_save_struct.backend_new_called = TRUE;
00457     return be;
00458 }
00459 
00460 static void
00461 test_qof_session_save (Fixture *fixture, gconstpointer pData)
00462 {
00463     QofBook *book = NULL;
00464     QofBackend *be = NULL;
00465     QofBackendProvider *prov = NULL, *reg_prov = NULL;
00466 
00467     g_test_message ("Test when book not partial and backend not set");
00468     g_assert (fixture->session->backend == NULL);
00469     book = qof_session_get_book (fixture->session);
00470     g_assert (book);
00471     qof_book_set_data (book, PARTIAL_QOFBOOK, GINT_TO_POINTER (FALSE));
00472     qof_session_push_error (fixture->session, ERR_BACKEND_DATA_CORRUPT, "push any error");
00473     g_assert_cmpint (fixture->session->lock, == , 1);
00474     qof_session_save (fixture->session, NULL);
00475     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_HANDLER);
00476     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "failed to load backend");
00477     g_assert_cmpint (fixture->session->lock, == , 1);
00478 
00479     g_test_message ("Test when book not partial and backend set; imitate error");
00480     be = g_new0 (QofBackend, 1);
00481     g_assert (be);
00482     be->sync = mock_sync;
00483     fixture->session->backend = be;
00484     g_assert_cmpint (fixture->session->lock, == , 1);
00485     session_save_struct.sync_called = FALSE;
00486     session_save_struct.be = be;
00487     session_save_struct.book = book;
00488     qof_backend_set_error (be, ERR_BACKEND_DATA_CORRUPT);
00489     qof_backend_set_message (be, "push any error");
00490     qof_session_save (fixture->session, percentage_fn);
00491     g_assert (qof_book_get_backend (book) == be);
00492     g_assert (be->percentage == percentage_fn);
00493     g_assert (session_save_struct.sync_called);
00494     g_assert_cmpint (fixture->session->lock, == , 1);
00495     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_DATA_CORRUPT);
00496     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "");
00497 
00498     g_test_message ("Test when book not partial and backend set; successful save");
00499     g_assert_cmpint (fixture->session->lock, == , 1);
00500     session_save_struct.sync_called = FALSE;
00501     qof_session_save (fixture->session, percentage_fn);
00502     g_assert (qof_book_get_backend (book) == be);
00503     g_assert (be->percentage == percentage_fn);
00504     g_assert (session_save_struct.sync_called);
00505     g_assert_cmpint (fixture->session->lock, == , 1);
00506     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
00507 
00508     /* change backend testing
00509      * code probably should be moved to separate routine or some existing code can be reused
00510      * for example: qof_session_load_backend
00511      */
00512     g_test_message ("Test when book is partial and current backend supports it; successful save backend not changed");
00513     prov = g_new0 (QofBackendProvider, 1);
00514     prov->partial_book_supported = TRUE;
00515     fixture->session->backend->provider = prov;
00516     g_assert_cmpint (fixture->session->lock, == , 1);
00517     qof_book_set_data (book, PARTIAL_QOFBOOK, GINT_TO_POINTER (TRUE));
00518     session_save_struct.sync_called = FALSE;
00519     qof_session_save (fixture->session, percentage_fn);
00520     g_assert (fixture->session->backend == be);
00521     g_assert (fixture->session->backend->provider == prov);
00522     g_assert (qof_book_get_backend (book) == be);
00523     g_assert (be->percentage == percentage_fn);
00524     g_assert (session_save_struct.sync_called);
00525     g_assert_cmpint (fixture->session->lock, == , 1);
00526     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
00527 
00528     g_test_message ("Test when book is partial and current backend does not support it; backend should be changed");
00529     prov->partial_book_supported = FALSE;
00530     g_assert_cmpint (fixture->session->lock, == , 1);
00531     reg_prov = g_new0 (QofBackendProvider, 1);
00532     reg_prov->partial_book_supported = TRUE;
00533     reg_prov->backend_new = mock_backend_new_for_save;
00534     qof_backend_register_provider (reg_prov);
00535     g_assert_cmpint (g_slist_length (get_provider_list ()), == , 1);
00536     session_save_struct.book = book;
00537     session_save_struct.session = fixture->session;
00538     fixture->session->book_id = g_strdup ("my book");
00539     session_save_struct.book_id = "my book";
00540     session_save_struct.sync_called = FALSE;
00541     session_save_struct.backend_new_called = FALSE;
00542     session_save_struct.session_begin_called = FALSE;
00543 
00544     qof_session_save (fixture->session, percentage_fn);
00545 
00546     g_assert (session_save_struct.backend_new_called);
00547     g_assert (fixture->session->backend == session_save_struct.be);
00548     g_assert (fixture->session->backend->provider == reg_prov);
00549     g_assert (fixture->session->book_id == NULL);
00550     g_assert (session_save_struct.session_begin_called);
00551     g_assert (qof_book_get_backend (book) == session_save_struct.be);
00552     g_assert (session_save_struct.sync_called);
00553     g_assert_cmpint (fixture->session->lock, == , 1);
00554     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
00555 
00556     unregister_all_providers ();
00557     g_free (prov);
00558 }
00559 
00560 static struct
00561 {
00562     QofBackend *be;
00563     gboolean called;
00564 } destroy_backend_struct;
00565 
00566 static void
00567 mock_destroy_backend (QofBackend *be)
00568 {
00569     g_assert (be);
00570     g_assert (destroy_backend_struct.be == be);
00571     destroy_backend_struct.called = TRUE;
00572 }
00573 
00574 static void
00575 test_qof_session_destroy_backend (Fixture *fixture, gconstpointer pData)
00576 {
00577     QofBackend *be = NULL;
00578 
00579     g_test_message ("Test with destroy backend callback not set");
00580     be = g_new0 (QofBackend, 1);
00581     g_assert (be);
00582     fixture->session->backend = be;
00583     p_qof_session_destroy_backend (fixture->session);
00584     g_assert (!fixture->session->backend);
00585 
00586     g_test_message ("Test with destroy backend callback set");
00587     be = g_new0 (QofBackend, 1);
00588     g_assert (be);
00589     be->destroy_backend = mock_destroy_backend;
00590     fixture->session->backend = be;
00591     destroy_backend_struct.called = FALSE;
00592     destroy_backend_struct.be = be;
00593     p_qof_session_destroy_backend (fixture->session);
00594     g_assert (!fixture->session->backend);
00595     g_assert (destroy_backend_struct.called);
00596 }
00597 
00598 static struct
00599 {
00600     QofBackend *be;
00601     gboolean called;
00602 } session_end_struct;
00603 
00604 static void
00605 mock_session_end (QofBackend *be)
00606 {
00607     g_assert (be);
00608     g_assert (session_end_struct.be == be);
00609     session_end_struct.called = TRUE;
00610 }
00611 
00612 static void
00613 test_qof_session_end (Fixture *fixture, gconstpointer pData)
00614 {
00615     QofBackend *be = NULL;
00616 
00617     g_test_message ("Test backend is closed, errors cleared and book_id removed");
00618     be = g_new0 (QofBackend, 1);
00619     g_assert (be);
00620     be->session_end = mock_session_end;
00621     fixture->session->backend = be;
00622     qof_session_push_error (fixture->session, ERR_BACKEND_DATA_CORRUPT, "push any error");
00623     fixture->session->book_id = g_strdup ("my book");
00624     session_end_struct.called = FALSE;
00625     session_end_struct.be = be;
00626     qof_session_end (fixture->session);
00627     g_assert (session_end_struct.called);
00628     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
00629     g_assert (!fixture->session->book_id);
00630 }
00631 
00632 static struct
00633 {
00634     QofBackend *be;
00635     QofBook *book;
00636     gboolean called;
00637 } session_export_struct;
00638 
00639 static void
00640 mock_export (QofBackend *be, QofBook *book)
00641 {
00642     g_assert (be);
00643     g_assert (session_export_struct.be == be);
00644     g_assert (book);
00645     g_assert (session_export_struct.book == book);
00646     session_export_struct.called = TRUE;
00647 }
00648 
00649 static void
00650 test_qof_session_export (Fixture *fixture, gconstpointer pData)
00651 {
00652     QofSession *real_session = NULL;
00653     QofBook *tmp_book = NULL, *real_book = NULL;
00654     QofBackend *be = NULL;
00655 
00656     real_session = qof_session_new ();
00657     g_assert (real_session);
00658 
00659     g_test_message ("Test null checks");
00660     g_assert (!qof_session_export (NULL, real_session, percentage_fn));
00661     g_assert (!qof_session_export (fixture->session, NULL, percentage_fn));
00662 
00663     g_test_message ("Test with backend not set");
00664     tmp_book = qof_session_get_book (fixture->session);
00665     g_assert (tmp_book);
00666     be = qof_book_get_backend (tmp_book);
00667     g_assert (!be);
00668     g_assert (!qof_session_export (fixture->session, real_session, percentage_fn));
00669 
00670     g_test_message ("Test with backend set");
00671     be = g_new0 (QofBackend, 1);
00672     g_assert (be);
00673     fixture->session->backend = be;
00674     qof_book_set_backend (tmp_book, be);
00675     g_assert (!be->percentage);
00676     g_assert (qof_session_export (fixture->session, real_session, percentage_fn));
00677     g_assert (be->percentage == percentage_fn);
00678 
00679     g_test_message ("Test with backend export function set and error is produced");
00680     be->export_fn = mock_export;
00681     qof_backend_set_error (be, ERR_BACKEND_DATA_CORRUPT);
00682     qof_backend_set_message (be, "push any error");
00683     session_export_struct.called = FALSE;
00684     real_book = qof_session_get_book (real_session);
00685     g_assert (real_book);
00686     session_export_struct.be = be;
00687     session_export_struct.book = real_book;
00688     g_assert (!qof_session_export (fixture->session, real_session, percentage_fn));
00689     g_assert (session_export_struct.called);
00690 
00691     g_test_message ("Test with backend export function set and no error produced");
00692     p_qof_session_clear_error (fixture->session);
00693     session_export_struct.called = FALSE;
00694     g_assert (qof_session_export (fixture->session, real_session, percentage_fn));
00695     g_assert (session_export_struct.called);
00696 
00697     qof_session_destroy (real_session);
00698 }
00699 
00700 static void
00701 test_qof_session_swap_data (Fixture *fixture, gconstpointer pData)
00702 {
00703     QofSession *session2 = NULL;
00704     QofBackend *be1 = NULL, *be2 = NULL;
00705     QofBook *book1 = NULL, *book2 = NULL;
00706     GList *node;
00707 
00708     /* init */
00709     g_assert (fixture->session);
00710     session2 = qof_session_new ();
00711     g_assert (session2);
00712     g_assert (fixture->session != session2);
00713     be1 = g_new0 (QofBackend, 1);
00714     g_assert (be1);
00715     be2 = g_new0 (QofBackend, 1);
00716     g_assert (be2);
00717     fixture->session->backend = be1;
00718     session2->backend = be2;
00719     book1 = fixture->session->book;
00720     book2 = session2->book;
00721     g_assert (book1);
00722     g_assert (book2);
00723     qof_book_set_backend (book1, fixture->session->backend);
00724     qof_book_set_backend (book2, session2->backend);
00725 
00726 
00727     g_test_message ("Test book lists are swapped and backend for each book is swapped");
00728     qof_session_swap_data (fixture->session, session2);
00729     g_assert (fixture->session->book == book2);
00730     g_assert (session2->book == book1);
00731 
00732     qof_session_destroy (session2);
00733 }
00734 
00735 static struct
00736 {
00737     QofBackend *be;
00738     gboolean called;
00739 } events_struct;
00740 
00741 static gboolean
00742 mock_events_fn (QofBackend *be)
00743 {
00744     g_assert (be);
00745     g_assert (be == events_struct.be);
00746     events_struct.called = TRUE;
00747     return TRUE;
00748 }
00749 
00750 static void
00751 test_qof_session_events (Fixture *fixture, gconstpointer pData)
00752 {
00753     QofBackend *be = NULL;
00754 
00755     g_test_message ("Test pending events null checks");
00756     g_assert (!qof_session_events_pending (NULL));
00757     g_assert (!fixture->session->backend);
00758     g_assert (!qof_session_events_pending (fixture->session));
00759     be = g_new0 (QofBackend, 1);
00760     g_assert (be);
00761     be->events_pending = NULL;
00762     fixture->session->backend = be;
00763     g_assert (!qof_session_events_pending (fixture->session));
00764 
00765     g_test_message ("Test pending events callback");
00766     be->events_pending = mock_events_fn;
00767     events_struct.called = FALSE;
00768     events_struct.be = be;
00769     g_assert (qof_session_events_pending (fixture->session));
00770     g_assert (events_struct.called);
00771 
00772     g_test_message ("Test process events null checks");
00773     g_assert (!qof_session_process_events (NULL));
00774     fixture->session->backend = NULL;
00775     g_assert (!qof_session_process_events (fixture->session));
00776     be->process_events = NULL;
00777     fixture->session->backend = be;
00778     g_assert (!qof_session_process_events (fixture->session));
00779 
00780     g_test_message ("Test process events callback");
00781     be->process_events = mock_events_fn;
00782     events_struct.called = FALSE;
00783     events_struct.be = be;
00784     g_assert (qof_session_process_events (fixture->session));
00785     g_assert (events_struct.called);
00786 }
00787 
00788 static struct
00789 {
00790     QofBackend *be;
00791     QofBook *book;
00792     gboolean called;
00793 } data_load_struct;
00794 
00795 static void
00796 mock_all_data_load (QofBackend *be, QofBook *book, QofBackendLoadType type)
00797 {
00798     g_assert (be);
00799     g_assert (book);
00800     g_assert (be == data_load_struct.be);
00801     g_assert (book == data_load_struct.book);
00802     g_assert_cmpint (type, == , LOAD_TYPE_LOAD_ALL);
00803     qof_backend_set_error (be, ERR_BACKEND_DATA_CORRUPT);
00804     data_load_struct.called = TRUE;
00805 }
00806 
00807 static void
00808 test_qof_session_data_loaded (Fixture *fixture, gconstpointer pData)
00809 {
00810     QofBackend *be = NULL;
00811 
00812     be = g_new0 (QofBackend, 1);
00813     g_assert (be);
00814     be->load = mock_all_data_load;
00815     fixture->session->backend = be;
00816 
00817     g_test_message ("Test load callback and artificial error");
00818     data_load_struct.be = be;
00819     data_load_struct.book = qof_session_get_book (fixture->session);
00820     data_load_struct.called = FALSE;
00821     qof_session_ensure_all_data_loaded (fixture->session);
00822     g_assert (data_load_struct.called);
00823     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_DATA_CORRUPT);
00824     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "");
00825 }
00826 
00827 static void
00828 test_qof_backend_get_access_method_list (Fixture *fixture, gconstpointer pData)
00829 {
00830     GList *list = NULL;
00831     const char *access_methods[4] = { "file", "http", "postgres", "sqlite" };
00832     int i;
00833 
00834     for (i = 0; i < 4; i++)
00835     {
00836         QofBackendProvider *prov = g_new0 (QofBackendProvider, 1);
00837         g_assert (prov);
00838         prov->access_method = access_methods[ i ];
00839         qof_backend_register_provider (prov);
00840         g_assert_cmpint (g_slist_length (get_provider_list ()), == , (i + 1));
00841     }
00842     g_assert_cmpint (g_slist_length (get_provider_list ()), == , 4);
00843 
00844     g_test_message ("Test list of access methods is returned");
00845     list = qof_backend_get_registered_access_method_list ();
00846     g_assert (list);
00847     g_assert_cmpint (g_list_length (list), == , 4);
00848     g_assert_cmpstr (g_list_nth_data (list, 0), == , "file");
00849     g_assert_cmpstr (g_list_nth_data (list, 1), == , "http");
00850     g_assert_cmpstr (g_list_nth_data (list, 2), == , "postgres");
00851     g_assert_cmpstr (g_list_nth_data (list, 3), == , "sqlite");
00852 
00853     g_list_free (list);
00854     unregister_all_providers ();
00855 }
00856 
00857 
00858 static void
00859 test_qof_session_get_book (Fixture *fixture, gconstpointer pData)
00860 {
00861     QofBook *book = NULL;
00862 
00863     g_test_message ("Test null check");
00864     g_assert (!qof_session_get_book (NULL));
00865 
00866     g_test_message ("Test open book is returned");
00867     g_assert (fixture->session->book);
00868     book = qof_session_get_book (fixture->session);
00869     g_assert (book);
00870     g_assert_cmpuint (book->book_open, == , 'y');
00871 
00872     g_test_message ("Test when book is closed null returned");
00873     qof_book_mark_closed (book);
00874     g_assert (!qof_session_get_book (fixture->session));
00875 
00876 }
00877 
00878 static void
00879 test_qof_session_get_error (Fixture *fixture, gconstpointer pData)
00880 {
00881     QofBackend *be = NULL;
00882 
00883     g_test_message ("Test if session is null");
00884     g_assert_cmpint (qof_session_get_error (NULL), == , ERR_BACKEND_NO_BACKEND);
00885 
00886     g_test_message ("Test when there is a local error");
00887     fixture->session->last_err = ERR_BACKEND_DATA_CORRUPT; /* just any error */
00888     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_DATA_CORRUPT);
00889 
00890     g_test_message ("Test if session backend is null");
00891     g_assert (!fixture->session->backend);
00892     fixture->session->last_err = ERR_BACKEND_NO_ERR;
00893     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
00894 
00895     g_test_message ("Test for backend error");
00896     be = g_new0 (QofBackend, 1);
00897     g_assert (be);
00898     qof_backend_set_error (be, ERR_BACKEND_CANT_CONNECT);
00899     fixture->session->backend = be;
00900     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_CANT_CONNECT);
00901 }
00902 
00903 static void
00904 test_qof_session_clear_error (Fixture *fixture, gconstpointer pData)
00905 {
00906     QofBackend *be = NULL;
00907 
00908     be = g_new0 (QofBackend, 1);
00909     g_assert (be);
00910 
00911     g_test_message ("Test session and backend errors are cleared");
00912     qof_session_push_error (fixture->session, ERR_BACKEND_NO_SUCH_DB, "push any error");
00913     fixture->session->backend = be;
00914     qof_backend_set_error (be, ERR_BACKEND_CANT_CONNECT);
00915     p_qof_session_clear_error (fixture->session);
00916     g_assert_cmpint (qof_session_get_error (fixture->session), == , ERR_BACKEND_NO_ERR);
00917     g_assert_cmpstr (qof_session_get_error_message (fixture->session), == , "");
00918     g_assert (!fixture->session->error_message);
00919     g_assert_cmpint (qof_backend_get_error (be), == , ERR_BACKEND_NO_ERR);
00920 }
00921 
00922 static struct
00923 {
00924     QofSession *session;
00925     gpointer data1;
00926     gpointer data2;
00927     gpointer data3;
00928     guint call_count;
00929 } hooks_struct;
00930 
00931 static void
00932 mock_hook_fn (gpointer data, gpointer user_data)
00933 {
00934     QofSession *session;
00935 
00936     g_assert (data);
00937     g_assert (user_data);
00938     session = (QofSession*) data;
00939     g_assert (session == hooks_struct.session);
00940     if (hooks_struct.call_count == 0)
00941         g_assert (hooks_struct.data1 == user_data);
00942     if (hooks_struct.call_count == 1)
00943         g_assert (hooks_struct.data2 == user_data);
00944     if (hooks_struct.call_count == 2)
00945         g_assert (hooks_struct.data3 == user_data);
00946     hooks_struct.call_count++;
00947 }
00948 
00949 static void
00950 test_qof_session_close_hooks (Fixture *fixture, gconstpointer pData)
00951 {
00952     gint data1, data2, data3;
00953 
00954     g_test_message ("Test hooks list is initialized and hooks are added");
00955     g_assert (!get_session_closed_hooks ());
00956     qof_session_add_close_hook (mock_hook_fn, (gpointer) &data1);
00957     g_assert (get_session_closed_hooks ());
00958     g_assert (g_hook_find_func_data (get_session_closed_hooks (), FALSE, mock_hook_fn, (gpointer) &data1));
00959     qof_session_add_close_hook (mock_hook_fn, (gpointer) &data2);
00960     g_assert (g_hook_find_func_data (get_session_closed_hooks (), FALSE, mock_hook_fn, (gpointer) &data2));
00961     qof_session_add_close_hook (mock_hook_fn, (gpointer) &data3);
00962     g_assert (g_hook_find_func_data (get_session_closed_hooks (), FALSE, mock_hook_fn, (gpointer) &data3));
00963 
00964     g_test_message ("Test all close hooks are called");
00965     hooks_struct.session = fixture->session;
00966     hooks_struct.data1 = (gpointer) &data1;
00967     hooks_struct.data2 = (gpointer) &data2;
00968     hooks_struct.data3 = (gpointer) &data3;
00969     hooks_struct.call_count = 0;
00970     qof_session_call_close_hooks (fixture->session);
00971     g_assert_cmpuint (hooks_struct.call_count, == , 3);
00972 
00973     /* currently qofsession does not provide a way to clear hooks list
00974      * g_hook_list_clear is used to destroy list and all of it's elements
00975      * though i' not sure if it frees all the memory allocated
00976      */
00977     g_hook_list_clear (get_session_closed_hooks ());
00978 }
00979 
00980 void
00981 test_suite_qofsession ( void )
00982 {
00983     GNC_TEST_ADD_FUNC (suitename, "qof session new and destroy", test_qof_session_new_destroy);
00984     GNC_TEST_ADD (suitename, "qof session safe save", Fixture, NULL, setup, test_session_safe_save, teardown);
00985     GNC_TEST_ADD (suitename, "qof session load backend", Fixture, NULL, setup, test_qof_session_load_backend, teardown);
00986     GNC_TEST_ADD (suitename, "qof session load", Fixture, NULL, setup, test_qof_session_load, teardown);
00987     GNC_TEST_ADD (suitename, "qof session begin", Fixture, NULL, setup, test_qof_session_begin, teardown);
00988     GNC_TEST_ADD (suitename, "qof session save", Fixture, NULL, setup, test_qof_session_save, teardown);
00989     GNC_TEST_ADD (suitename, "qof session destroy backend", Fixture, NULL, setup, test_qof_session_destroy_backend, teardown);
00990     GNC_TEST_ADD (suitename, "qof session end", Fixture, NULL, setup, test_qof_session_end, teardown);
00991     GNC_TEST_ADD (suitename, "qof session export", Fixture, NULL, setup, test_qof_session_export, teardown);
00992     GNC_TEST_ADD (suitename, "qof session swap data", Fixture, NULL, setup, test_qof_session_swap_data, teardown);
00993     GNC_TEST_ADD (suitename, "qof session events", Fixture, NULL, setup, test_qof_session_events, teardown);
00994     GNC_TEST_ADD (suitename, "qof session data loaded", Fixture, NULL, setup, test_qof_session_data_loaded, teardown);
00995     GNC_TEST_ADD (suitename, "qof backend access method list", Fixture, NULL, setup, test_qof_backend_get_access_method_list, teardown);
00996     GNC_TEST_ADD (suitename, "qof session get book", Fixture, NULL, setup, test_qof_session_get_book, teardown);
00997     GNC_TEST_ADD (suitename, "qof session get error", Fixture, NULL, setup, test_qof_session_get_error, teardown);
00998     GNC_TEST_ADD (suitename, "qof session clear error", Fixture, NULL, setup, test_qof_session_clear_error, teardown);
00999     GNC_TEST_ADD (suitename, "qof session close hooks", Fixture, NULL, setup, test_qof_session_close_hooks, teardown);
01000 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines