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

Generated on Fri May 12 17:57:21 2006 for QOF by  doxygen 1.4.4