test-event.c

00001 /***************************************************************************
00002  *            test-event.c
00003  *
00004  *  Sat Feb 11 11:00:02 2006
00005  *  Copyright  2006  Neil Williams
00006  *  linux@codehelp.co.uk
00007  ****************************************************************************/
00008 /*
00009  *  This program is free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  This program is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with this program; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin Street, Fifth Floor
00022  *  Boston, MA  02110-1301,  USA 
00023  */
00024 
00025 #include <glib.h>
00026 #include <glib/gprintf.h>
00027 #include "qof.h"
00028 #include "test-engine-stuff.h"
00029 #include "test-stuff.h"
00030 
00031 #define OBJ_NAME "somename"
00032 #define OBJ_AMOUNT "anamount"
00033 #define OBJ_DATE "nottoday"
00034 #define OBJ_GUID "unique"
00035 #define OBJ_DISCOUNT "hefty"
00036 #define OBJ_VERSION "early"
00037 #define OBJ_MINOR "tiny"
00038 #define OBJ_ACTIVE "ofcourse"
00039 #define OBJ_FLAG   "tiny_flag"
00040 #define OBJ_EVENT_NAME "test-event-object"
00041 #define OBJ_EVENT_DESC "test object for events"
00042 
00043 /* set to TRUE to get QSF XML output
00044  * requires QSF available (i.e. make install) */
00045 static gboolean debug = FALSE;
00046 
00047 /* deliberately make these global to the file to pick up
00048 errors where developers access handlers directly. This practice
00049 will be deprecated in qofevent. */
00050 static gint test, foo;
00051 
00052 /* simple object structure */
00053 typedef struct e_obj
00054 {
00055     QofInstance inst;
00056     gchar *Name;
00057     gchar flag;
00058     gnc_numeric Amount;
00059     QofTime *date;
00060     double discount;            /* cheap pun, I know. */
00061     gboolean active;
00062     gint32 version;
00063     gint64 minor;
00064 } event_obj;
00065 
00066 static event_obj *
00067 event_create (QofBook * book)
00068 {
00069     event_obj *e;
00070 
00071     g_return_val_if_fail (book, NULL);
00072     e = g_new0 (event_obj, 1);
00073     qof_instance_init (&e->inst, OBJ_EVENT_NAME, book);
00074     e->date = qof_time_get_current ();
00075     e->discount = get_random_double ();
00076     e->active = get_random_boolean ();
00077     e->version = get_random_int_in_range (1, 10000);
00078     e->minor = get_random_int_in_range (100000, 99999999);
00079     e->flag = get_random_character ();
00080     e->Name = get_random_string ();
00081     e->Amount = get_random_gnc_numeric ();
00082     qof_event_gen (&e->inst.entity, QOF_EVENT_CREATE, NULL);
00083     return e;
00084 }
00085 
00086 static void
00087 event_setFlag (event_obj * e, gchar f)
00088 {
00089     g_return_if_fail (e);
00090     e->flag = f;
00091 }
00092 
00093 static gchar
00094 event_getFlag (event_obj * e)
00095 {
00096     g_return_val_if_fail (e, 'n');
00097     return e->flag;
00098 }
00099 
00100 static void
00101 event_setMinor (event_obj * e, gint64 h)
00102 {
00103     g_return_if_fail (e != NULL);
00104     e->minor = h;
00105 }
00106 
00107 static gint64
00108 event_getMinor (event_obj * e)
00109 {
00110     g_return_val_if_fail (e, 0);
00111     return e->minor;
00112 }
00113 
00114 static void
00115 event_setVersion (event_obj * e, gint32 h)
00116 {
00117     g_return_if_fail (e);
00118     e->version = h;
00119 }
00120 
00121 static gint32
00122 event_getVersion (event_obj * e)
00123 {
00124     if (!e)
00125         return 0;
00126     return e->version;
00127 }
00128 
00129 static void
00130 event_setActive (event_obj * e, gboolean h)
00131 {
00132     if (!e)
00133         return;
00134     e->active = h;
00135 }
00136 
00137 static gboolean
00138 event_getActive (event_obj * e)
00139 {
00140     if (!e)
00141         return FALSE;
00142     return e->active;
00143 }
00144 
00145 static void
00146 event_setDiscount (event_obj * e, double h)
00147 {
00148     if (!e)
00149         return;
00150     e->discount = h;
00151 }
00152 
00153 static double
00154 event_getDiscount (event_obj * e)
00155 {
00156     if (!e)
00157         return 0;
00158     return e->discount;
00159 }
00160 
00161 static void
00162 event_setDate (event_obj * e, QofTime *h)
00163 {
00164     if (!e)
00165         return;
00166     e->date = h;
00167 }
00168 
00169 static QofTime*
00170 event_getDate (event_obj * e)
00171 {
00172     if (!e)
00173         return NULL;
00174     return e->date;
00175 }
00176 
00177 static void
00178 event_setName (event_obj * e, gchar * h)
00179 {
00180     if (!e || !h)
00181         return;
00182     e->Name = strdup (h);
00183 }
00184 
00185 static gchar *
00186 event_getName (event_obj * e)
00187 {
00188     if (!e)
00189         return NULL;
00190     return e->Name;
00191 }
00192 
00193 static void
00194 event_setAmount (event_obj * e, gnc_numeric h)
00195 {
00196     if (!e)
00197         return;
00198     e->Amount = h;
00199 }
00200 
00201 static gnc_numeric
00202 event_getAmount (event_obj * e)
00203 {
00204     if (!e)
00205         return gnc_numeric_zero ();
00206     return e->Amount;
00207 }
00208 
00209 static QofObject event_object_def = {
00210   interface_version:QOF_OBJECT_VERSION,
00211   e_type:OBJ_EVENT_NAME,
00212   type_label:OBJ_EVENT_DESC,
00213   create:(gpointer) event_create,
00214   book_begin:NULL,
00215   book_end:NULL,
00216   is_dirty:NULL,
00217   mark_clean:NULL,
00218   foreach:qof_collection_foreach,
00219   printable:NULL,
00220   version_cmp:(int (*)(gpointer, gpointer)) qof_instance_version_cmp,
00221 };
00222 
00223 static gboolean
00224 event_objRegister (void)
00225 {
00226     static QofParam params[] = {
00227         {OBJ_NAME, QOF_TYPE_STRING, (QofAccessFunc) event_getName,
00228          (QofSetterFunc) event_setName},
00229         {OBJ_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc) event_getAmount,
00230          (QofSetterFunc) event_setAmount},
00231         {OBJ_DATE, QOF_TYPE_TIME, (QofAccessFunc) event_getDate,
00232          (QofSetterFunc) event_setDate},
00233         {OBJ_DISCOUNT, QOF_TYPE_DOUBLE, (QofAccessFunc) event_getDiscount,
00234          (QofSetterFunc) event_setDiscount},
00235         {OBJ_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc) event_getActive,
00236          (QofSetterFunc) event_setActive},
00237         {OBJ_VERSION, QOF_TYPE_INT32, (QofAccessFunc) event_getVersion,
00238          (QofSetterFunc) event_setVersion},
00239         {OBJ_MINOR, QOF_TYPE_INT64, (QofAccessFunc) event_getMinor,
00240          (QofSetterFunc) event_setMinor},
00241         {OBJ_FLAG, QOF_TYPE_CHAR, (QofAccessFunc) event_getFlag,
00242          (QofSetterFunc) event_setFlag},
00243         {QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc) qof_instance_get_book,
00244          NULL},
00245         {QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc) qof_instance_get_guid,
00246          NULL},
00247         {NULL},
00248     };
00249 
00250     qof_class_register (OBJ_EVENT_NAME, NULL, params);
00251 
00252     return qof_object_register (&event_object_def);
00253 }
00254 
00255 typedef struct event_context_s
00256 {
00257     QofEventId event_type;
00258     QofEntity *entity_original;
00259     QofEntity *entity_modified;
00260     const QofParam *param;
00261     gboolean destroy_used;
00262     guint counter;
00263     guint old_test_id;
00264     guint old_foo_id;
00265 } event_context;
00266 
00267 static void
00268 test_event_handler (QofEntity *ent, QofEventId event_type, 
00269                     gpointer handler_data, gpointer user_data)
00270 {
00271     event_context *context;
00272 
00273     context = (event_context *) handler_data;
00274     do_test ((ent != NULL), "Null ent in test");
00275     do_test ((context != NULL), "Null context");
00276     switch (event_type)
00277     {
00278     case QOF_EVENT_NONE:
00279         {
00280             break;
00281         }
00282     case QOF_EVENT_CREATE:
00283         {
00284             break;
00285         }
00286     case QOF_EVENT_MODIFY:
00287         {
00288             do_test ((context->entity_original != NULL),
00289                      "No original entity");
00290             do_test ((context->event_type == QOF_EVENT_MODIFY),
00291                      "wrong event sent: test (GNC_EVENT_MODIFY)");
00292             break;
00293         }
00294     case QOF_EVENT_DESTROY:
00295         {
00296             do_test ((context->entity_original != NULL),
00297                      "No original entity");
00298             do_test ((context->event_type == QOF_EVENT_DESTROY),
00299                      "wrong event sent: test (GNC_EVENT_DESTROY)");
00300             do_test ((context->destroy_used),
00301                      "destroy sent without being called");
00302             /* make sure we can unregister an earlier handler */
00303             qof_event_unregister_handler (foo);
00304             break;
00305         }
00306     case QOF_EVENT_ADD:
00307         {
00308             do_test ((context->entity_original != NULL),
00309                      "No original entity: test");
00310             break;
00311         }
00312     case QOF_EVENT_REMOVE:
00313         {
00314             do_test ((context->entity_original != NULL),
00315                      "No original entity: test");
00316             break;
00317         }
00318     case QOF_EVENT_ALL:
00319         {
00320             do_test ((context->entity_original != NULL),
00321                      "No original entity: test");
00322             break;
00323         }
00324     }
00325 }
00326 
00327 static void
00328 foo_event_handler (QofEntity *ent, QofEventId event_type,
00329                    gpointer handler_data, gpointer user_data)
00330 {
00331     event_context *context;
00332 
00333     context = (event_context *) handler_data;
00334     do_test ((context != NULL), "Null context");
00335     do_test ((ent != NULL), "Null entity for foo");
00336     switch (event_type)
00337     {
00338     case QOF_EVENT_NONE:
00339         {
00340             break;
00341         }
00342     case QOF_EVENT_CREATE:
00343         {
00344             break;
00345         }
00346     case QOF_EVENT_MODIFY:
00347         {
00348             break;
00349         }
00350     case QOF_EVENT_DESTROY:
00351         {
00352             do_test ((context->entity_original != NULL),
00353                      "No original entity");
00354             do_test ((context->event_type == QOF_EVENT_DESTROY),
00355                      "wrong event sent: foo (GNC_EVENT_DESTROY)");
00356             do_test ((context->destroy_used),
00357                      "destroy sent without being called");
00358             /* make sure we can unregister a later handler */
00359             qof_event_unregister_handler (test);
00360             break;
00361         }
00362     case QOF_EVENT_ADD:
00363         {
00364             break;
00365         }
00366     case QOF_EVENT_REMOVE:
00367         {
00368             break;
00369         }
00370     case QOF_EVENT_ALL:
00371         {
00372             break;
00373         }
00374     }
00375 }
00376 
00377 static void
00378 create_data (QofSession * original, event_context * context)
00379 {
00380     QofBook *start;
00381     event_obj *e, *e2;
00382 
00383     start = qof_session_get_book (original);
00384     e = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME, start);
00385     do_test ((NULL != &e->inst), "instance init");
00386     e2 = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME, start);
00387     switch (context->counter)
00388     {
00389     case 0:
00390         {                       /* empty test */
00391             do_test ((e != NULL), "empty check");
00392             break;
00393         }
00394     case 1:
00395         {                       /* create a temporary entity, modify it and destroy it */
00396             event_obj *e1;
00397 
00398             do_test ((context->old_foo_id == foo), "forward foo");
00399             do_test ((context->old_test_id == test), "forward test");
00400             context->entity_original = (QofEntity *) e;
00401             e1 = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME,
00402                                                         start);
00403             do_test ((NULL != &e1->inst), "temporary instance init");
00404             context->entity_modified = (QofEntity *) e1;
00405             context->param =
00406                 qof_class_get_parameter (OBJ_EVENT_NAME, OBJ_NAME);
00407             context->event_type = QOF_EVENT_MODIFY;
00408             event_setName (e, event_getName (e1));
00409             qof_event_gen ((QofEntity *) e, QOF_EVENT_MODIFY, NULL);
00410             context->event_type = QOF_EVENT_DESTROY;
00411             context->destroy_used = TRUE;
00412             /* this block unregisters both handlers on DESTROY in turn.
00413                Here, foo is unregistered within test */
00414             qof_event_gen ((QofEntity *) e1, QOF_EVENT_DESTROY, NULL);
00415             qof_entity_release ((QofEntity *) e1);
00416             g_free (e1);
00417             e1 = NULL;
00418             context->destroy_used = FALSE;
00419             context->event_type = QOF_EVENT_NONE;
00420             context->entity_modified = NULL;
00421             context->param = NULL;
00422             /* repeat the test in reverse. */
00423             qof_event_unregister_handler (test);
00424             test =
00425                 qof_event_register_handler (test_event_handler,
00426                                                    context);
00427             foo =
00428                 qof_event_register_handler (foo_event_handler,
00429                                                    context);
00430             do_test ((context->old_foo_id < foo), "reverse foo");
00431             do_test ((context->old_test_id < test), "reverse test");
00432             /* test is unregistered within foo */
00433             e1 = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME,
00434                                                         start);
00435             context->entity_modified = (QofEntity *) e1;
00436             context->event_type = QOF_EVENT_DESTROY;
00437             context->destroy_used = TRUE;
00438             qof_event_gen ((QofEntity *) e1, QOF_EVENT_DESTROY, NULL);
00439             qof_entity_release ((QofEntity *) e1);
00440             g_free (e1);
00441             e1 = NULL;
00442             context->destroy_used = FALSE;
00443             context->event_type = QOF_EVENT_NONE;
00444             context->entity_original = NULL;
00445             context->entity_modified = NULL;
00446             test =
00447                 qof_event_register_handler (test_event_handler,
00448                                                    context);
00449             context->old_foo_id = foo;
00450             context->old_test_id = test;
00451             break;
00452         }
00453     case 2:
00454         {   /* create the second test entity */
00455             context->entity_original = (QofEntity *) e;
00456             do_test ((NULL != &e2->inst), "second instance init");
00457             context->entity_modified = (QofEntity *) e2;
00458             break;
00459         }
00460     case 3:
00461         {   /* destroy the entity e2 */
00462             context->event_type = QOF_EVENT_DESTROY;
00463             context->destroy_used = TRUE;
00464             qof_event_gen ((QofEntity *) e2, QOF_EVENT_DESTROY, NULL);
00465             qof_entity_release ((QofEntity *) e2);
00466             g_free (e2);
00467             e2 = NULL;
00468             context->destroy_used = FALSE;
00469             context->event_type = QOF_EVENT_NONE;
00470             context->entity_modified = NULL;
00471             break;
00472         }
00473     case 4:
00474         {   /* destroy the original entity e */
00475             context->event_type = QOF_EVENT_DESTROY;
00476             context->destroy_used = TRUE;
00477             qof_event_gen ((QofEntity *) e, QOF_EVENT_DESTROY, NULL);
00478             qof_entity_release ((QofEntity *) e);
00479             g_free (e);
00480             e = NULL;
00481             context->destroy_used = FALSE;
00482             context->event_type = QOF_EVENT_NONE;
00483             context->entity_original = NULL;
00484             break;
00485         }
00486     }
00487 }
00488 
00489 int
00490 main (int argc, const char *argv[])
00491 {
00492     QofSession *original;
00493     event_context context;
00494     guint count;
00495 
00496     qof_init ();
00497     event_objRegister ();
00498     original = qof_session_new ();
00499     if (debug)
00500     {
00501         qof_session_begin (original, QOF_STDOUT, TRUE, FALSE);
00502     }
00503     context.event_type = QOF_EVENT_NONE;
00504     context.entity_original = NULL;
00505     context.entity_modified = NULL;
00506     context.destroy_used = FALSE;
00507     context.param = NULL;
00508     /* events are unregistered in reverse order, so to test for
00509        a bug when unregistering a later module from an earlier one,
00510        register the foo module first and unregister it from within
00511        a later handler. */
00512     foo = qof_event_register_handler (foo_event_handler, &context);
00513     test = qof_event_register_handler (test_event_handler, &context);
00514     context.old_test_id = test;
00515     context.old_foo_id = foo;
00516     for (count = 0; count < 25; count++)
00517     {
00518         context.counter = (count % 5);
00519         create_data (original, &context);
00520     }
00521     print_test_results ();
00522     qof_close ();
00523     return get_rv();
00524 }

Generated on Fri Sep 1 15:33:50 2006 for QOF by  doxygen 1.4.6