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 guint test, foo;
00051 
00052 /* simple object structure */
00053 typedef struct e_obj
00054 {
00055     QofInstance inst;
00056     gchar *Name;
00057     gchar flag;
00058     QofNumeric Amount;
00059     QofTime *date;
00060     gdouble 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_qof_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, QofNumeric h)
00195 {
00196     if (!e)
00197         return;
00198     e->Amount = h;
00199 }
00200 
00201 static QofNumeric
00202 event_getAmount (event_obj * e)
00203 {
00204     if (!e)
00205         return qof_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 = (gint (*)(gpointer, gpointer)) 
00221                 qof_instance_version_cmp,
00222 };
00223 
00224 static gboolean
00225 event_objRegister (void)
00226 {
00227     static QofParam params[] = {
00228         {OBJ_NAME, QOF_TYPE_STRING, (QofAccessFunc) event_getName,
00229          (QofSetterFunc) event_setName, NULL},
00230         {OBJ_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc) event_getAmount,
00231          (QofSetterFunc) event_setAmount, NULL},
00232         {OBJ_DATE, QOF_TYPE_TIME, (QofAccessFunc) event_getDate,
00233          (QofSetterFunc) event_setDate, NULL},
00234         {OBJ_DISCOUNT, QOF_TYPE_DOUBLE, (QofAccessFunc) event_getDiscount,
00235          (QofSetterFunc) event_setDiscount, NULL},
00236         {OBJ_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc) event_getActive,
00237          (QofSetterFunc) event_setActive, NULL},
00238         {OBJ_VERSION, QOF_TYPE_INT32, (QofAccessFunc) event_getVersion,
00239          (QofSetterFunc) event_setVersion, NULL},
00240         {OBJ_MINOR, QOF_TYPE_INT64, (QofAccessFunc) event_getMinor,
00241          (QofSetterFunc) event_setMinor, NULL},
00242         {OBJ_FLAG, QOF_TYPE_CHAR, (QofAccessFunc) event_getFlag,
00243          (QofSetterFunc) event_setFlag, NULL},
00244         {QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc) qof_instance_get_book,
00245          NULL, NULL},
00246         {QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc) qof_instance_get_guid,
00247          NULL, NULL},
00248         {NULL, NULL, NULL, NULL, NULL},
00249     };
00250 
00251     qof_class_register (OBJ_EVENT_NAME, NULL, params);
00252 
00253     return qof_object_register (&event_object_def);
00254 }
00255 
00256 typedef struct event_context_s
00257 {
00258     QofEventId event_type;
00259     QofEntity *entity_original;
00260     QofEntity *entity_modified;
00261     const QofParam *param;
00262     gboolean destroy_used;
00263     guint counter;
00264     guint old_test_id;
00265     guint old_foo_id;
00266 } event_context;
00267 
00268 static void
00269 test_event_handler (QofEntity *ent, QofEventId event_type, 
00270                     gpointer handler_data, 
00271                     gpointer user_data __attribute__ ((unused)))
00272 {
00273     event_context *context;
00274 
00275     context = (event_context *) handler_data;
00276     do_test ((ent != NULL), "Null ent in test");
00277     do_test ((context != NULL), "Null context");
00278     switch (event_type)
00279     {
00280     case QOF_EVENT_NONE:
00281         {
00282             break;
00283         }
00284     case QOF_EVENT_CREATE:
00285         {
00286             break;
00287         }
00288     case QOF_EVENT_MODIFY:
00289         {
00290             do_test ((context->entity_original != NULL),
00291                      "No original entity");
00292             do_test ((context->event_type == QOF_EVENT_MODIFY),
00293                      "wrong event sent: test (QOF_EVENT_MODIFY)");
00294             break;
00295         }
00296     case QOF_EVENT_DESTROY:
00297         {
00298             do_test ((context->entity_original != NULL),
00299                      "No original entity");
00300             do_test ((context->event_type == QOF_EVENT_DESTROY),
00301                      "wrong event sent: test (QOF_EVENT_DESTROY)");
00302             do_test ((context->destroy_used),
00303                      "destroy sent without being called");
00304             /* make sure we can unregister an earlier handler */
00305             qof_event_unregister_handler (foo);
00306             break;
00307         }
00308     case QOF_EVENT_ADD:
00309         {
00310             do_test ((context->entity_original != NULL),
00311                      "No original entity: test");
00312             break;
00313         }
00314     case QOF_EVENT_REMOVE:
00315         {
00316             do_test ((context->entity_original != NULL),
00317                      "No original entity: test");
00318             break;
00319         }
00320     case QOF_EVENT_ALL:
00321         {
00322             do_test ((context->entity_original != NULL),
00323                      "No original entity: test");
00324             break;
00325         }
00326     }
00327 }
00328 
00329 static void
00330 foo_event_handler (QofEntity *ent, QofEventId event_type,
00331                    gpointer handler_data, 
00332                    gpointer user_data __attribute__ ((unused)))
00333 {
00334     event_context *context;
00335 
00336     context = (event_context *) handler_data;
00337     do_test ((context != NULL), "Null context");
00338     do_test ((ent != NULL), "Null entity for foo");
00339     switch (event_type)
00340     {
00341     case QOF_EVENT_NONE:
00342         {
00343             break;
00344         }
00345     case QOF_EVENT_CREATE:
00346         {
00347             break;
00348         }
00349     case QOF_EVENT_MODIFY:
00350         {
00351             break;
00352         }
00353     case QOF_EVENT_DESTROY:
00354         {
00355             do_test ((context->entity_original != NULL),
00356                      "No original entity");
00357             do_test ((context->event_type == QOF_EVENT_DESTROY),
00358                      "wrong event sent: foo (QOF_EVENT_DESTROY)");
00359             do_test ((context->destroy_used),
00360                      "destroy sent without being called");
00361             /* make sure we can unregister a later handler */
00362             qof_event_unregister_handler (test);
00363             break;
00364         }
00365     case QOF_EVENT_ADD:
00366         {
00367             break;
00368         }
00369     case QOF_EVENT_REMOVE:
00370         {
00371             break;
00372         }
00373     case QOF_EVENT_ALL:
00374         {
00375             break;
00376         }
00377     }
00378 }
00379 
00380 static void
00381 create_data (QofSession * original, event_context * context)
00382 {
00383     QofBook *start;
00384     event_obj *e, *e2;
00385 
00386     start = qof_session_get_book (original);
00387     e = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME, start);
00388     do_test ((NULL != &e->inst), "instance init");
00389     e2 = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME, start);
00390     switch (context->counter)
00391     {
00392     case 0:
00393         {                       /* empty test */
00394             do_test ((e != NULL), "empty check");
00395             break;
00396         }
00397     case 1:
00398         {                       /* create a temporary entity, modify it and destroy it */
00399             event_obj *e1;
00400 
00401             do_test ((context->old_foo_id == foo), "forward foo");
00402             do_test ((context->old_test_id == test), "forward test");
00403             context->entity_original = (QofEntity *) e;
00404             e1 = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME,
00405                                                         start);
00406             do_test ((NULL != &e1->inst), "temporary instance init");
00407             context->entity_modified = (QofEntity *) e1;
00408             context->param =
00409                 qof_class_get_parameter (OBJ_EVENT_NAME, OBJ_NAME);
00410             context->event_type = QOF_EVENT_MODIFY;
00411             event_setName (e, event_getName (e1));
00412             qof_event_gen ((QofEntity *) e, QOF_EVENT_MODIFY, NULL);
00413             context->event_type = QOF_EVENT_DESTROY;
00414             context->destroy_used = TRUE;
00415             /* this block unregisters both handlers on DESTROY in turn.
00416                Here, foo is unregistered within test */
00417             qof_event_gen ((QofEntity *) e1, QOF_EVENT_DESTROY, NULL);
00418             qof_entity_release ((QofEntity *) e1);
00419             g_free (e1);
00420             e1 = NULL;
00421             context->destroy_used = FALSE;
00422             context->event_type = QOF_EVENT_NONE;
00423             context->entity_modified = NULL;
00424             context->param = NULL;
00425             /* repeat the test in reverse. */
00426             qof_event_unregister_handler (test);
00427             test =
00428                 qof_event_register_handler (test_event_handler,
00429                                                    context);
00430             foo =
00431                 qof_event_register_handler (foo_event_handler,
00432                                                    context);
00433             do_test ((context->old_foo_id < foo), "reverse foo");
00434             do_test ((context->old_test_id < test), "reverse test");
00435             /* test is unregistered within foo */
00436             e1 = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME,
00437                                                         start);
00438             context->entity_modified = (QofEntity *) e1;
00439             context->event_type = QOF_EVENT_DESTROY;
00440             context->destroy_used = TRUE;
00441             qof_event_gen ((QofEntity *) e1, QOF_EVENT_DESTROY, NULL);
00442             qof_entity_release ((QofEntity *) e1);
00443             g_free (e1);
00444             e1 = NULL;
00445             context->destroy_used = FALSE;
00446             context->event_type = QOF_EVENT_NONE;
00447             context->entity_original = NULL;
00448             context->entity_modified = NULL;
00449             test =
00450                 qof_event_register_handler (test_event_handler,
00451                                                    context);
00452             context->old_foo_id = foo;
00453             context->old_test_id = test;
00454             break;
00455         }
00456     case 2:
00457         {   /* create the second test entity */
00458             context->entity_original = (QofEntity *) e;
00459             do_test ((NULL != &e2->inst), "second instance init");
00460             context->entity_modified = (QofEntity *) e2;
00461             break;
00462         }
00463     case 3:
00464         {   /* destroy the entity e2 */
00465             context->event_type = QOF_EVENT_DESTROY;
00466             context->destroy_used = TRUE;
00467             qof_event_gen ((QofEntity *) e2, QOF_EVENT_DESTROY, NULL);
00468             qof_entity_release ((QofEntity *) e2);
00469             g_free (e2);
00470             e2 = NULL;
00471             context->destroy_used = FALSE;
00472             context->event_type = QOF_EVENT_NONE;
00473             context->entity_modified = NULL;
00474             break;
00475         }
00476     case 4:
00477         {   /* destroy the original entity e */
00478             context->event_type = QOF_EVENT_DESTROY;
00479             context->destroy_used = TRUE;
00480             qof_event_gen ((QofEntity *) e, QOF_EVENT_DESTROY, NULL);
00481             qof_entity_release ((QofEntity *) e);
00482             g_free (e);
00483             e = NULL;
00484             context->destroy_used = FALSE;
00485             context->event_type = QOF_EVENT_NONE;
00486             context->entity_original = NULL;
00487             break;
00488         }
00489     }
00490 }
00491 
00492 int
00493 main (void)
00494 {
00495     QofSession *original;
00496     event_context context;
00497     guint count;
00498 
00499     qof_init ();
00500     event_objRegister ();
00501     original = qof_session_new ();
00502     if (debug)
00503     {
00504         qof_session_begin (original, QOF_STDOUT, TRUE, FALSE);
00505     }
00506     context.event_type = QOF_EVENT_NONE;
00507     context.entity_original = NULL;
00508     context.entity_modified = NULL;
00509     context.destroy_used = FALSE;
00510     context.param = NULL;
00511     /* events are unregistered in reverse order, so to test for
00512        a bug when unregistering a later module from an earlier one,
00513        register the foo module first and unregister it from within
00514        a later handler. */
00515     foo = qof_event_register_handler (foo_event_handler, &context);
00516     test = qof_event_register_handler (test_event_handler, &context);
00517     context.old_test_id = test;
00518     context.old_foo_id = foo;
00519     for (count = 0; count < 25; count++)
00520     {
00521         context.counter = (count % 5);
00522         create_data (original, &context);
00523     }
00524     print_test_results ();
00525     qof_close ();
00526     return get_rv();
00527 }

Generated on Thu Jan 31 22:50:26 2008 for QOF by  doxygen 1.5.4