QOF: test-event.c Source File

QOF 0.7.5

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

test-event.c
1 /***************************************************************************
2 * test-event.c
3 *
4 * Sat Feb 11 11:00:02 2006
5 * Copyright 2006 Neil Williams
6 * linux@codehelp.co.uk
7 ****************************************************************************/
8 /*
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA
23 */
24
25 #include <glib.h>
26 #include <glib/gprintf.h>
27 #include "qof.h"
28 #include "test-engine-stuff.h"
29 #include "test-stuff.h"
30
31 #define OBJ_NAME "somename"
32 #define OBJ_AMOUNT "anamount"
33 #define OBJ_DATE "nottoday"
34 #define OBJ_GUID "unique"
35 #define OBJ_DISCOUNT "hefty"
36 #define OBJ_VERSION "early"
37 #define OBJ_MINOR "tiny"
38 #define OBJ_ACTIVE "ofcourse"
39 #define OBJ_FLAG "tiny_flag"
40 #define OBJ_EVENT_NAME "test-event-object"
41 #define OBJ_EVENT_DESC "test object for events"
42
43 /* set to TRUE to get QSF XML output
44 * requires QSF available (i.e. make install) */
45 static gboolean debug = FALSE;
46
47 /* deliberately make these global to the file to pick up
48 errors where developers access handlers directly. This practice
49 will be deprecated in qofevent. */
50 static guint test, foo;
51
52 /* simple object structure */
53 typedef struct e_obj
54 {
55 QofInstance inst;
56 gchar *Name;
57 gchar flag;
58 QofNumeric Amount;
59 QofTime *date;
60 gdouble discount; /* cheap pun, I know. */
61 gboolean active;
62 gint32 version;
63 gint64 minor;
64 } event_obj;
65
66 static event_obj *
67 event_create (QofBook * book)
68 {
69 event_obj *e;
70
71 g_return_val_if_fail (book, NULL);
72 e = g_new0 (event_obj, 1);
73 qof_instance_init (&e->inst, OBJ_EVENT_NAME, book);
74 e->date = qof_time_get_current ();
75 e->discount = get_random_double ();
76 e->active = get_random_boolean ();
77 e->version = get_random_int_in_range (1, 10000);
78 e->minor = get_random_int_in_range (100000, 99999999);
79 e->flag = get_random_character ();
80 e->Name = get_random_string ();
81 e->Amount = get_random_qof_numeric ();
82 qof_event_gen (&e->inst.entity, QOF_EVENT_CREATE, NULL);
83 return e;
84 }
85
86 static void
87 event_setFlag (event_obj * e, gchar f)
88 {
89 g_return_if_fail (e);
90 e->flag = f;
91 }
92
93 static gchar
94 event_getFlag (event_obj * e)
95 {
96 g_return_val_if_fail (e, 'n');
97 return e->flag;
98 }
99
100 static void
101 event_setMinor (event_obj * e, gint64 h)
102 {
103 g_return_if_fail (e != NULL);
104 e->minor = h;
105 }
106
107 static gint64
108 event_getMinor (event_obj * e)
109 {
110 g_return_val_if_fail (e, 0);
111 return e->minor;
112 }
113
114 static void
115 event_setVersion (event_obj * e, gint32 h)
116 {
117 g_return_if_fail (e);
118 e->version = h;
119 }
120
121 static gint32
122 event_getVersion (event_obj * e)
123 {
124 if (!e)
125 return 0;
126 return e->version;
127 }
128
129 static void
130 event_setActive (event_obj * e, gboolean h)
131 {
132 if (!e)
133 return;
134 e->active = h;
135 }
136
137 static gboolean
138 event_getActive (event_obj * e)
139 {
140 if (!e)
141 return FALSE;
142 return e->active;
143 }
144
145 static void
146 event_setDiscount (event_obj * e, double h)
147 {
148 if (!e)
149 return;
150 e->discount = h;
151 }
152
153 static double
154 event_getDiscount (event_obj * e)
155 {
156 if (!e)
157 return 0;
158 return e->discount;
159 }
160
161 static void
162 event_setDate (event_obj * e, QofTime *h)
163 {
164 if (!e)
165 return;
166 e->date = h;
167 }
168
169 static QofTime*
170 event_getDate (event_obj * e)
171 {
172 if (!e)
173 return NULL;
174 return e->date;
175 }
176
177 static void
178 event_setName (event_obj * e, gchar * h)
179 {
180 if (!e || !h)
181 return;
182 e->Name = strdup (h);
183 }
184
185 static gchar *
186 event_getName (event_obj * e)
187 {
188 if (!e)
189 return NULL;
190 return e->Name;
191 }
192
193 static void
194 event_setAmount (event_obj * e, QofNumeric h)
195 {
196 if (!e)
197 return;
198 e->Amount = h;
199 }
200
201 static QofNumeric
202 event_getAmount (event_obj * e)
203 {
204 if (!e)
205 return qof_numeric_zero ();
206 return e->Amount;
207 }
208
209 static QofObject event_object_def = {
210 .interface_version = QOF_OBJECT_VERSION,
211 .e_type = OBJ_EVENT_NAME,
212 .type_label = OBJ_EVENT_DESC,
213 .create = (gpointer) event_create,
214 .book_begin = NULL,
215 .book_end = NULL,
216 .is_dirty = NULL,
217 .mark_clean = NULL,
218 .foreach = qof_collection_foreach,
219 .printable = NULL,
220 .version_cmp = (gint (*)(gpointer, gpointer))
221 qof_instance_version_cmp,
222 };
223
224 static gboolean
225 event_objRegister (void)
226 {
227 static QofParam params[] = {
228 {OBJ_NAME, QOF_TYPE_STRING, (QofAccessFunc) event_getName,
229 (QofSetterFunc) event_setName, NULL},
230 {OBJ_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc) event_getAmount,
231 (QofSetterFunc) event_setAmount, NULL},
232 {OBJ_DATE, QOF_TYPE_TIME, (QofAccessFunc) event_getDate,
233 (QofSetterFunc) event_setDate, NULL},
234 {OBJ_DISCOUNT, QOF_TYPE_DOUBLE, (QofAccessFunc) event_getDiscount,
235 (QofSetterFunc) event_setDiscount, NULL},
236 {OBJ_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc) event_getActive,
237 (QofSetterFunc) event_setActive, NULL},
238 {OBJ_VERSION, QOF_TYPE_INT32, (QofAccessFunc) event_getVersion,
239 (QofSetterFunc) event_setVersion, NULL},
240 {OBJ_MINOR, QOF_TYPE_INT64, (QofAccessFunc) event_getMinor,
241 (QofSetterFunc) event_setMinor, NULL},
242 {OBJ_FLAG, QOF_TYPE_CHAR, (QofAccessFunc) event_getFlag,
243 (QofSetterFunc) event_setFlag, NULL},
244 {QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc) qof_instance_get_book,
245 NULL, NULL},
246 {QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc) qof_instance_get_guid,
247 NULL, NULL},
248 {NULL, NULL, NULL, NULL, NULL},
249 };
250
251 qof_class_register (OBJ_EVENT_NAME, NULL, params);
252
253 return qof_object_register (&event_object_def);
254 }
255
256 typedef struct event_context_s
257 {
258 QofEventId event_type;
259 QofEntity *entity_original;
260 QofEntity *entity_modified;
261 const QofParam *param;
262 gboolean destroy_used;
263 guint counter;
264 guint old_test_id;
265 guint old_foo_id;
266 } event_context;
267
268 static void
269 test_event_handler (QofEntity *ent, QofEventId event_type,
270 gpointer handler_data,
271 gpointer user_data __attribute__ ((unused)))
272 {
273 event_context *context;
274
275 context = (event_context *) handler_data;
276 do_test ((ent != NULL), "Null ent in test");
277 do_test ((context != NULL), "Null context");
278 switch (event_type)
279 {
280 case QOF_EVENT_NONE:
281 {
282 break;
283 }
284 case QOF_EVENT_CREATE:
285 {
286 break;
287 }
288 case QOF_EVENT_MODIFY:
289 {
290 do_test ((context->entity_original != NULL),
291 "No original entity");
292 do_test ((context->event_type == QOF_EVENT_MODIFY),
293 "wrong event sent: test (QOF_EVENT_MODIFY)");
294 break;
295 }
296 case QOF_EVENT_DESTROY:
297 {
298 do_test ((context->entity_original != NULL),
299 "No original entity");
300 do_test ((context->event_type == QOF_EVENT_DESTROY),
301 "wrong event sent: test (QOF_EVENT_DESTROY)");
302 do_test ((context->destroy_used),
303 "destroy sent without being called");
304 /* make sure we can unregister an earlier handler */
305 qof_event_unregister_handler (foo);
306 break;
307 }
308 case QOF_EVENT_ADD:
309 {
310 do_test ((context->entity_original != NULL),
311 "No original entity: test");
312 break;
313 }
314 case QOF_EVENT_REMOVE:
315 {
316 do_test ((context->entity_original != NULL),
317 "No original entity: test");
318 break;
319 }
320 case QOF_EVENT_ALL:
321 {
322 do_test ((context->entity_original != NULL),
323 "No original entity: test");
324 break;
325 }
326 }
327 }
328
329 static void
330 foo_event_handler (QofEntity *ent, QofEventId event_type,
331 gpointer handler_data,
332 gpointer user_data __attribute__ ((unused)))
333 {
334 event_context *context;
335
336 context = (event_context *) handler_data;
337 do_test ((context != NULL), "Null context");
338 do_test ((ent != NULL), "Null entity for foo");
339 switch (event_type)
340 {
341 case QOF_EVENT_NONE:
342 {
343 break;
344 }
345 case QOF_EVENT_CREATE:
346 {
347 break;
348 }
349 case QOF_EVENT_MODIFY:
350 {
351 break;
352 }
353 case QOF_EVENT_DESTROY:
354 {
355 do_test ((context->entity_original != NULL),
356 "No original entity");
357 do_test ((context->event_type == QOF_EVENT_DESTROY),
358 "wrong event sent: foo (QOF_EVENT_DESTROY)");
359 do_test ((context->destroy_used),
360 "destroy sent without being called");
361 /* make sure we can unregister a later handler */
362 qof_event_unregister_handler (test);
363 break;
364 }
365 case QOF_EVENT_ADD:
366 {
367 break;
368 }
369 case QOF_EVENT_REMOVE:
370 {
371 break;
372 }
373 case QOF_EVENT_ALL:
374 {
375 break;
376 }
377 }
378 }
379
380 static void
381 create_data (QofSession * original, event_context * context)
382 {
383 QofBook *start;
384 event_obj *e, *e2;
385
386 start = qof_session_get_book (original);
387 e = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME, start);
388 do_test ((NULL != &e->inst), "instance init");
389 e2 = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME, start);
390 switch (context->counter)
391 {
392 case 0:
393 { /* empty test */
394 do_test ((e != NULL), "empty check");
395 break;
396 }
397 case 1:
398 { /* create a temporary entity, modify it and destroy it */
399 event_obj *e1;
400
401 do_test ((context->old_foo_id == foo), "forward foo");
402 do_test ((context->old_test_id == test), "forward test");
403 context->entity_original = (QofEntity *) e;
404 e1 = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME,
405 start);
406 do_test ((NULL != &e1->inst), "temporary instance init");
407 context->entity_modified = (QofEntity *) e1;
408 context->param =
409 qof_class_get_parameter (OBJ_EVENT_NAME, OBJ_NAME);
410 context->event_type = QOF_EVENT_MODIFY;
411 event_setName (e, event_getName (e1));
412 qof_event_gen ((QofEntity *) e, QOF_EVENT_MODIFY, NULL);
413 context->event_type = QOF_EVENT_DESTROY;
414 context->destroy_used = TRUE;
415 /* this block unregisters both handlers on DESTROY in turn.
416 Here, foo is unregistered within test */
417 qof_event_gen ((QofEntity *) e1, QOF_EVENT_DESTROY, NULL);
418 qof_entity_release ((QofEntity *) e1);
419 g_free (e1);
420 e1 = NULL;
421 context->destroy_used = FALSE;
422 context->event_type = QOF_EVENT_NONE;
423 context->entity_modified = NULL;
424 context->param = NULL;
425 /* repeat the test in reverse. */
426 qof_event_unregister_handler (test);
427 test =
428 qof_event_register_handler (test_event_handler,
429 context);
430 foo =
431 qof_event_register_handler (foo_event_handler,
432 context);
433 do_test ((context->old_foo_id < foo), "reverse foo");
434 do_test ((context->old_test_id < test), "reverse test");
435 /* test is unregistered within foo */
436 e1 = (event_obj *) qof_object_new_instance (OBJ_EVENT_NAME,
437 start);
438 context->entity_modified = (QofEntity *) e1;
439 context->event_type = QOF_EVENT_DESTROY;
440 context->destroy_used = TRUE;
441 qof_event_gen ((QofEntity *) e1, QOF_EVENT_DESTROY, NULL);
442 qof_entity_release ((QofEntity *) e1);
443 g_free (e1);
444 e1 = NULL;
445 context->destroy_used = FALSE;
446 context->event_type = QOF_EVENT_NONE;
447 context->entity_original = NULL;
448 context->entity_modified = NULL;
449 test =
450 qof_event_register_handler (test_event_handler,
451 context);
452 context->old_foo_id = foo;
453 context->old_test_id = test;
454 break;
455 }
456 case 2:
457 { /* create the second test entity */
458 context->entity_original = (QofEntity *) e;
459 do_test ((NULL != &e2->inst), "second instance init");
460 context->entity_modified = (QofEntity *) e2;
461 break;
462 }
463 case 3:
464 { /* destroy the entity e2 */
465 context->event_type = QOF_EVENT_DESTROY;
466 context->destroy_used = TRUE;
467 qof_event_gen ((QofEntity *) e2, QOF_EVENT_DESTROY, NULL);
468 qof_entity_release ((QofEntity *) e2);
469 g_free (e2);
470 e2 = NULL;
471 context->destroy_used = FALSE;
472 context->event_type = QOF_EVENT_NONE;
473 context->entity_modified = NULL;
474 break;
475 }
476 case 4:
477 { /* destroy the original entity e */
478 context->event_type = QOF_EVENT_DESTROY;
479 context->destroy_used = TRUE;
480 qof_event_gen ((QofEntity *) e, QOF_EVENT_DESTROY, NULL);
481 qof_entity_release ((QofEntity *) e);
482 g_free (e);
483 e = NULL;
484 context->destroy_used = FALSE;
485 context->event_type = QOF_EVENT_NONE;
486 context->entity_original = NULL;
487 break;
488 }
489 }
490 }
491
492 int
493 main (void)
494 {
495 QofSession *original;
496 event_context context;
497 guint count;
498
499 qof_init ();
500 event_objRegister ();
501 original = qof_session_new ();
502 if (debug)
503 {
504 qof_session_begin (original, QOF_STDOUT, TRUE, FALSE);
505 }
506 context.event_type = QOF_EVENT_NONE;
507 context.entity_original = NULL;
508 context.entity_modified = NULL;
509 context.destroy_used = FALSE;
510 context.param = NULL;
511 /* events are unregistered in reverse order, so to test for
512 a bug when unregistering a later module from an earlier one,
513 register the foo module first and unregister it from within
514 a later handler. */
515 foo = qof_event_register_handler (foo_event_handler, &context);
516 test = qof_event_register_handler (test_event_handler, &context);
517 context.old_test_id = test;
518 context.old_foo_id = foo;
519 for (count = 0; count < 25; count++)
520 {
521 context.counter = (count % 5);
522 create_data (original, &context);
523 }
524 print_test_results ();
525 qof_close ();
526 return get_rv();
527 }
qof_object_new_instance
gpointer qof_object_new_instance(QofIdTypeConst type_name, QofBook *book)
Definition: qofobject.c:42
QofInstance_s
Definition: qofinstance-p.h:35
_QofParam
Definition: qofclass.h:195
QOF_OBJECT_VERSION
#define QOF_OBJECT_VERSION
Definition: qofobject.h:57
_QofSession
Definition: qofsession-p.h:35
QofEntity_s
Definition: qofid.h:147
QOF_EVENT_DESTROY
#define QOF_EVENT_DESTROY
Definition: qofevent.h:81
qof_class_register
void qof_class_register(QofIdTypeConst obj_name, QofSortFunc default_sort_function, const QofParam *params)
registers a new object class with the Qof subsystem.
Definition: qofclass.c:93
test-engine-stuff.h
This file declares testing functions for the engine.
qof_instance_get_book
QofBook * qof_instance_get_book(QofInstance *inst)
Definition: qofinstance.c:87
QOF_PARAM_BOOK
#define QOF_PARAM_BOOK
Definition: qofquery.h:104
qof_event_gen
void qof_event_gen(QofEntity *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition: qofevent.c:292
QofSetterFunc
void(* QofSetterFunc)(gpointer, gpointer)
Definition: qofclass.h:176
qof_time_get_current
QofTime * qof_time_get_current(void)
Get the current QofTime.
Definition: qoftime.c:362
qof_class_get_parameter
const QofParam * qof_class_get_parameter(QofIdTypeConst obj_name, const gchar *parameter)
Definition: qofclass.c:146
QOF_EVENT_CREATE
#define QOF_EVENT_CREATE
Definition: qofevent.h:71
qof_event_register_handler
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
Definition: qofevent.c:108
qof_instance_get_guid
const GUID * qof_instance_get_guid(QofInstance *inst)
Definition: qofinstance.c:79
qof_session_begin
void qof_session_begin(QofSession *session, const gchar *book_id, gboolean ignore_lock, gboolean create_if_nonexistent)
Definition: qofsession.c:1057
QofEventId
gint QofEventId
Definition: qofevent.h:40
qof_collection_foreach
void qof_collection_foreach(QofCollection *col, QofEntityForeachCB cb_func, gpointer user_data)
Definition: qofid.c:421
_QofObject
Definition: qofobject.h:70
_QofNumeric
Definition: qofnumeric.h:52
qof_event_unregister_handler
void qof_event_unregister_handler(gint handler_id)
Unregister an event handler.
Definition: qofevent.c:139
qof_entity_release
void qof_entity_release(QofEntity *ent)
Definition: qofid.c:79
QofAccessFunc
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
Definition: qofclass.h:169
QOF_EVENT_MODIFY
#define QOF_EVENT_MODIFY
an entity is about to be modified.
Definition: qofevent.h:79
QOF_EVENT_NONE
#define QOF_EVENT_NONE
Definition: qofevent.h:69
qof_object_register
gboolean qof_object_register(const QofObject *object)
Definition: qofobject.c:278
qof_close
void qof_close(void)
Safely close down the Query Object Framework.
Definition: qofutil.c:844
QOF_STDOUT
#define QOF_STDOUT
Allow session data to be printed to stdout.
Definition: qofsession.h:385
QofTime
struct QofTime64 QofTime
Use a 64-bit signed int QofTime.
Definition: qoftime.h:120
qof_numeric_zero
static QofNumeric qof_numeric_zero(void)
Definition: qofnumeric.h:253
_QofBook
Definition: qofbook-p.h:48
qof_instance_version_cmp
int qof_instance_version_cmp(QofInstance *left, QofInstance *right)
Definition: qofinstance.c:116
qof_instance_init
void qof_instance_init(QofInstance *inst, QofIdType type, QofBook *book)
Definition: qofinstance.c:53
qof_init
void qof_init(void)
Initialise the Query Object Framework.
Definition: qofutil.c:833