00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <glib.h>
00026 #include "qof.h"
00027 #include "qofinstance-p.h"
00028 #include "qofevent-p.h"
00029 #include "test-stuff.h"
00030
00031 #define TEST_MODULE_NAME "book-merge-test"
00032 #define TEST_MODULE_DESC "Test Book Merge"
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
00043 static void test_rule_loop (QofBookMergeData *, QofBookMergeRule *,
00044 guint);
00045 static void test_merge (void);
00046 gboolean myobjRegister (void);
00047 #ifdef TEST_DEBUG
00048 static QofLogModule log_module = QOF_MOD_MERGE;
00049 #endif
00050
00051
00052 typedef struct obj_s
00053 {
00054 QofInstance inst;
00055 gchar *Name;
00056 gchar flag;
00057 QofNumeric Amount;
00058 const GUID *obj_guid;
00059 QofTime *date;
00060 gdouble discount;
00061 gboolean active;
00062 gint32 version;
00063 gint64 minor;
00064 } myobj;
00065
00066 static void
00067 obj_setGUID (myobj * g, const GUID * h)
00068 {
00069 if (!g)
00070 return;
00071 g->obj_guid = h;
00072 }
00073
00074 static myobj *
00075 obj_create (QofBook * book)
00076 {
00077 myobj *g;
00078 g_return_val_if_fail (book, NULL);
00079 g = g_new (myobj, 1);
00080 qof_instance_init (&g->inst, TEST_MODULE_NAME, book);
00081 obj_setGUID (g, qof_instance_get_guid (&g->inst));
00082 g->discount = 0;
00083 g->active = TRUE;
00084 g->version = 1;
00085 g->minor = 1;
00086 g->flag = 'n';
00087 qof_event_gen (&g->inst.entity, QOF_EVENT_CREATE, NULL);
00088 return g;
00089 }
00090
00091 static void
00092 obj_setFlag (myobj * g, char f)
00093 {
00094 g_return_if_fail (g);
00095 g->flag = f;
00096 }
00097
00098 static gchar
00099 obj_getFlag (myobj * g)
00100 {
00101 g_return_val_if_fail (g, 'n');
00102 return g->flag;
00103 }
00104
00105 static void
00106 obj_setMinor (myobj * g, gint64 h)
00107 {
00108 g_return_if_fail (g != NULL);
00109 g->minor = h;
00110 }
00111
00112 static gint64
00113 obj_getMinor (myobj * g)
00114 {
00115 g_return_val_if_fail ((g != NULL), 0);
00116 return g->minor;
00117 }
00118
00119 static void
00120 obj_setVersion (myobj * g, gint32 h)
00121 {
00122 g_return_if_fail (g != NULL);
00123 g->version = h;
00124 }
00125
00126 static gint32
00127 obj_getVersion (myobj * g)
00128 {
00129 if (!g)
00130 return 0;
00131 return g->version;
00132 }
00133
00134 static void
00135 obj_setActive (myobj * g, gboolean h)
00136 {
00137 if (!g)
00138 return;
00139 g->active = h;
00140 }
00141
00142 static gboolean
00143 obj_getActive (myobj * g)
00144 {
00145 if (!g)
00146 return FALSE;
00147 return g->active;
00148 }
00149
00150 static void
00151 obj_setDiscount (myobj * g, gdouble h)
00152 {
00153 if (!g)
00154 return;
00155 g->discount = h;
00156 }
00157
00158 static gdouble
00159 obj_getDiscount (myobj * g)
00160 {
00161 if (!g)
00162 return 0;
00163 return g->discount;
00164 }
00165
00166 static void
00167 obj_setDate (myobj * g, QofTime *h)
00168 {
00169 if (!g)
00170 return;
00171 do_test ((h != NULL), "passed a NULL time");
00172 do_test ((qof_time_is_valid (h) == TRUE),
00173 "passed an invalid time");
00174 g->date = h;
00175 }
00176
00177 static QofTime *
00178 obj_getDate (myobj * g)
00179 {
00180 if (!g)
00181 return NULL;
00182 do_test ((g->date != NULL), "stored time is NULL");
00183 do_test ((qof_time_is_valid (g->date) == TRUE),
00184 "stored time is invalid");
00185 return g->date;
00186 }
00187
00188 static const GUID *
00189 obj_getGUID (myobj * g)
00190 {
00191 if (!g)
00192 return NULL;
00193 return g->obj_guid;
00194 }
00195
00196 static void
00197 obj_setName (myobj * g, char *h)
00198 {
00199 if (!g || !h)
00200 return;
00201 g->Name = strdup (h);
00202 }
00203
00204 static gchar *
00205 obj_getName (myobj * g)
00206 {
00207 if (!g)
00208 return NULL;
00209 return g->Name;
00210 }
00211
00212 static void
00213 obj_setAmount (myobj * g, QofNumeric h)
00214 {
00215 if (!g)
00216 return;
00217 g->Amount = h;
00218 }
00219
00220 static QofNumeric
00221 obj_getAmount (myobj * g)
00222 {
00223 if (!g)
00224 return qof_numeric_zero ();
00225 return g->Amount;
00226 }
00227
00228 static QofObject obj_object_def = {
00229 .interface_version = QOF_OBJECT_VERSION,
00230 .e_type = TEST_MODULE_NAME,
00231 .type_label = TEST_MODULE_DESC,
00232 .create = (gpointer) obj_create,
00233 .book_begin = NULL,
00234 .book_end = NULL,
00235 .is_dirty = NULL,
00236 .mark_clean = NULL,
00237 .foreach = qof_collection_foreach,
00238 .printable = NULL,
00239 .version_cmp = (gint (*)(gpointer, gpointer))
00240 qof_instance_version_cmp,
00241 };
00242
00243 gboolean
00244 myobjRegister (void)
00245 {
00246 static QofParam params[] = {
00247 {OBJ_NAME, QOF_TYPE_STRING, (QofAccessFunc) obj_getName,
00248 (QofSetterFunc) obj_setName, NULL},
00249 {OBJ_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc) obj_getAmount,
00250 (QofSetterFunc) obj_setAmount, NULL},
00251 {OBJ_GUID, QOF_TYPE_GUID, (QofAccessFunc) obj_getGUID,
00252 (QofSetterFunc) obj_setGUID, NULL},
00253 {OBJ_DATE, QOF_TYPE_TIME, (QofAccessFunc) obj_getDate,
00254 (QofSetterFunc) obj_setDate, NULL},
00255 {OBJ_DISCOUNT, QOF_TYPE_DOUBLE, (QofAccessFunc) obj_getDiscount,
00256 (QofSetterFunc) obj_setDiscount, NULL},
00257 {OBJ_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc) obj_getActive,
00258 (QofSetterFunc) obj_setActive, NULL},
00259 {OBJ_VERSION, QOF_TYPE_INT32, (QofAccessFunc) obj_getVersion,
00260 (QofSetterFunc) obj_setVersion, NULL},
00261 {OBJ_MINOR, QOF_TYPE_INT64, (QofAccessFunc) obj_getMinor,
00262 (QofSetterFunc) obj_setMinor, NULL},
00263 {OBJ_FLAG, QOF_TYPE_CHAR, (QofAccessFunc) obj_getFlag,
00264 (QofSetterFunc) obj_setFlag, NULL},
00265 {QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc) qof_instance_get_book,
00266 NULL, NULL},
00267 {QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc) qof_instance_get_guid,
00268 NULL, NULL},
00269 {NULL, NULL, NULL, NULL, NULL},
00270 };
00271
00272 qof_class_register (TEST_MODULE_NAME, NULL, params);
00273
00274 return qof_object_register (&obj_object_def);
00275 }
00276
00277 static void
00278 test_merge (void)
00279 {
00280 QofBook *target, *import;
00281 gdouble init_value, discount;
00282 myobj *import_obj, *target_obj, *new_obj;
00283 gint result;
00284 QofTime *base_time, *temp_time;
00285 gboolean active;
00286 gint32 version;
00287 gint64 minor;
00288 gchar *import_init, *target_init;
00289 gchar flag, flag_check;
00290 QofNumeric obj_amount;
00291 QofBookMergeData *mergeData;
00292
00293 target = qof_book_new ();
00294 import = qof_book_new ();
00295 init_value = 1.00;
00296 result = 0;
00297 flag = get_random_character ();
00298 discount = 0.175;
00299 active = TRUE;
00300 version = get_random_int_in_range (0, 10000);
00301 minor = get_random_int_in_range (1000001, 2000000);
00302 import_init = "test";
00303 target_init = "testing";
00304 base_time = qof_time_set (1153309194, 568714241);
00305 do_test ((TRUE == qof_time_is_valid (base_time)),
00306 "invalid init time");
00307 {
00308 gchar *str;
00309 QofDate *qd;
00310
00311 qd = qof_date_from_qtime (base_time);
00312 str = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
00313 do_test ((0 == safe_strcmp (
00314 "2006-07-19 11:39:54.568714241 +0000", str)),
00315 "failed to compare base_time correctly.");
00316 g_free (str);
00317 qof_date_free (qd);
00318 }
00319
00320 do_test ((NULL != target), "#1 target book is NULL");
00321 do_test ((NULL != import), "#2 import book is NULL");
00322
00323
00324 import_obj = g_new (myobj, 1);
00325 do_test ((NULL != import_obj), "#3 new object create");
00326 qof_instance_init (&import_obj->inst, TEST_MODULE_NAME, import);
00327 do_test ((NULL != &import_obj->inst), "#4 instance init");
00328 obj_setGUID (import_obj, qof_instance_get_guid (&import_obj->inst));
00329 do_test ((NULL != &import_obj->obj_guid), "#5 guid set");
00330 qof_event_gen (&import_obj->inst.entity, QOF_EVENT_CREATE, NULL);
00331 do_test ((NULL != &import_obj->inst.entity), "#6 gnc event create");
00332 obj_setName (import_obj, import_init);
00333 do_test ((NULL != &import_obj->Name), "#7 string set");
00334 obj_amount = qof_numeric_from_double (init_value, 1, QOF_HOW_DENOM_EXACT);
00335 obj_setAmount (import_obj, obj_amount);
00336 do_test ((qof_numeric_check (obj_getAmount (import_obj)) == QOF_ERROR_OK),
00337 "#8 gnc_numeric set");
00338 obj_setActive (import_obj, active);
00339 do_test ((FALSE != &import_obj->active), "#9 gboolean set");
00340 obj_setDiscount (import_obj, discount);
00341 obj_setVersion (import_obj, version);
00342 do_test ((version == import_obj->version), "#11 gint32 set");
00343 obj_setMinor (import_obj, minor);
00344 do_test ((minor == import_obj->minor), "#12 gint64 set");
00345 do_test ((TRUE == qof_time_is_valid (base_time)),
00346 "invalid import time ts");
00347 {
00348 gchar *str;
00349 QofDate *qd;
00350
00351 qd = qof_date_from_qtime (base_time);
00352 str = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
00353 do_test ((0 == safe_strcmp (
00354 "2006-07-19 11:39:54.568714241 +0000", str)),
00355 "failed to compare base_time correctly.");
00356 g_free (str);
00357 qof_date_free (qd);
00358 }
00359 obj_setDate (import_obj, base_time);
00360 do_test ((TRUE == qof_time_is_valid (import_obj->date)),
00361 "invalid import time");
00362 do_test ((qof_time_cmp (base_time, import_obj->date) == 0),
00363 "test #13 date set");
00364 obj_setFlag (import_obj, flag);
00365 do_test ((flag == obj_getFlag (import_obj)), "#14 flag set");
00366
00367 obj_amount =
00368 qof_numeric_add (obj_amount, obj_amount, 1, QOF_HOW_DENOM_EXACT);
00369 discount = get_random_double ();
00370 version = 2;
00371 minor = 3;
00372
00373
00374 new_obj = g_new (myobj, 1);
00375 qof_instance_init (&new_obj->inst, TEST_MODULE_NAME, import);
00376 obj_setGUID (new_obj, qof_instance_get_guid (&new_obj->inst));
00377 qof_event_gen (&new_obj->inst.entity, QOF_EVENT_CREATE, NULL);
00378 obj_setName (new_obj, import_init);
00379 obj_setAmount (new_obj, obj_amount);
00380 obj_setActive (new_obj, active);
00381 obj_setDiscount (new_obj, discount);
00382 obj_setVersion (new_obj, version);
00383 obj_setMinor (new_obj, minor);
00384 do_test ((TRUE == qof_time_is_valid (base_time)),
00385 "second import time invalid");
00386 {
00387 gchar *str;
00388 QofDate *qd;
00389
00390 qd = qof_date_from_qtime (base_time);
00391 str = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
00392 do_test ((0 == safe_strcmp (
00393 "2006-07-19 11:39:54.568714241 +0000", str)),
00394 "failed to compare base_time correctly.");
00395 g_free (str);
00396 qof_date_free (qd);
00397 }
00398 obj_setDate (new_obj, base_time);
00399 obj_setFlag (new_obj, flag);
00400
00401 obj_amount =
00402 qof_numeric_add (obj_amount, obj_amount, 1, QOF_HOW_DENOM_EXACT);
00403 discount = get_random_double ();
00404 version = 2;
00405 minor = 3;
00406 flag = 'z';
00407
00408
00409 target_obj = g_new (myobj, 1);
00410 qof_instance_init (&target_obj->inst, TEST_MODULE_NAME, target);
00411 obj_setGUID (target_obj, qof_instance_get_guid (&target_obj->inst));
00412 qof_event_gen (&target_obj->inst.entity, QOF_EVENT_CREATE, NULL);
00413 obj_setName (target_obj, target_init);
00414 obj_setAmount (target_obj, obj_amount);
00415 obj_setActive (target_obj, active);
00416 obj_setDiscount (target_obj, discount);
00417 obj_setVersion (target_obj, version);
00418 obj_setMinor (target_obj, minor);
00419 {
00420 gchar *str;
00421 QofDate *qd;
00422
00423 qd = qof_date_from_qtime (base_time);
00424 str = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
00425 do_test ((0 == safe_strcmp (
00426 "2006-07-19 11:39:54.568714241 +0000", str)),
00427 "failed to compare base_time correctly.");
00428 g_free (str);
00429 qof_date_free (qd);
00430 }
00431 temp_time = qof_time_add_secs_copy (base_time, 65);
00432 do_test ((TRUE == qof_time_is_valid (temp_time)),
00433 "time add secs returned invalid");
00434 obj_setDate (target_obj, temp_time);
00435 obj_setFlag (target_obj, flag);
00436 do_test ((flag == obj_getFlag (target_obj)), "#15 flag set");
00437
00438 mergeData = qof_book_merge_init (import, target);
00439 do_test (mergeData != NULL,
00440 "FATAL: Merge could not be initialised!\t aborting . . ");
00441 g_return_if_fail (mergeData != NULL);
00442 qof_book_merge_rule_foreach (mergeData, test_rule_loop, MERGE_REPORT);
00443 qof_book_merge_rule_foreach (mergeData, test_rule_loop, MERGE_UPDATE);
00444 qof_book_merge_rule_foreach (mergeData, test_rule_loop, MERGE_NEW);
00445
00446 qof_book_merge_rule_foreach (mergeData, test_rule_loop, MERGE_ABSOLUTE);
00447 qof_book_merge_rule_foreach (mergeData, test_rule_loop, MERGE_DUPLICATE);
00448
00449
00450 do_test (((safe_strcmp (obj_getName (import_obj),
00451 obj_getName (target_obj))) != 0),
00452 "Init value test #1");
00453
00454
00455 do_test (qof_book_merge_commit (mergeData) == 0, "Commit failed");
00456
00457
00458 do_test (((safe_strcmp (import_init, obj_getName (target_obj))) == 0),
00459 "Merged value test #1");
00460
00461
00462 do_test (((safe_strcmp
00463 (obj_getName (target_obj), obj_getName (import_obj))) == 0),
00464 "Merged value test #2");
00465
00466
00467 do_test ((qof_numeric_check (obj_getAmount (import_obj)) == QOF_ERROR_OK),
00468 "import gnc_numeric check");
00469 do_test ((qof_numeric_check (obj_getAmount (target_obj)) == QOF_ERROR_OK),
00470 "target gnc_numeric check");
00471
00472
00473 do_test ((qof_numeric_compare (obj_getAmount (import_obj), obj_amount) !=
00474 QOF_ERROR_OK), "gnc_numeric value check #1");
00475
00476
00477 do_test ((qof_numeric_compare (obj_getAmount (target_obj), obj_amount) !=
00478 QOF_ERROR_OK), "gnc_numeric value check #2");
00479
00480
00481 qof_time_free (temp_time);
00482 temp_time = target_obj->date;
00483 {
00484 gchar *str;
00485 QofDate *qd;
00486
00487 qd = qof_date_from_qtime (base_time);
00488 str = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
00489 do_test ((0 == safe_strcmp (
00490 "2006-07-19 11:39:54.568714241 +0000", str)),
00491 "failed to compare base_time after merge.");
00492 g_free (str);
00493 qof_date_free (qd);
00494 }
00495 {
00496 gchar *str;
00497 QofDate *qd;
00498
00499 qd = qof_date_from_qtime (temp_time);
00500 str = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
00501 do_test ((0 == safe_strcmp (
00502 "2006-07-19 11:39:54.568714241 +0000", str)),
00503 "failed to compare target time after merge.");
00504 g_free (str);
00505 qof_date_free (qd);
00506 }
00507 do_test ((qof_time_cmp (base_time, temp_time) == 0),
00508 "date value check: 1");
00509 #ifdef TEST_DEBUG
00510 DEBUG (" import<->target=%d\n",
00511 (qof_time_cmp (base_time, target_obj->date)));
00512 {
00513 QofDate *qd;
00514 gchar *check;
00515
00516 qd = qof_date_from_qtime (base_time);
00517 DEBUG (" base_time=%" G_GINT64_FORMAT
00518 " nsecs=%ld", qof_time_get_secs (base_time),
00519 qof_time_get_nanosecs (base_time));
00520 DEBUG (" import:\nyear=%" G_GINT64_FORMAT
00521 " month=%ld day=%ld hour=%ld min=%ld sec=%"
00522 G_GINT64_FORMAT "nsecs=%ld\n",
00523 qd->qd_year, qd->qd_mon, qd->qd_mday, qd->qd_hour,
00524 qd->qd_min, qd->qd_sec, qd->qd_nanosecs);
00525 check = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
00526 DEBUG (" import=%s\n", check);
00527 qof_date_free (qd);
00528 qd = qof_date_from_qtime (target_obj->date);
00529 if (!qd)
00530 PERR ("qd failed");
00531 DEBUG (" target:\nyear=%" G_GINT64_FORMAT
00532 " month=%ld day=%ld hour=%ld min=%ld sec=%"
00533 G_GINT64_FORMAT "nsecs=%ld\n",
00534 qd->qd_year, qd->qd_mon, qd->qd_mday, qd->qd_hour,
00535 qd->qd_min, qd->qd_sec, qd->qd_nanosecs);
00536 check = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
00537 DEBUG (" target=%s\n", check);
00538 g_free (check);
00539 qof_date_free (qd);
00540 }
00541 #endif
00542 qof_time_free (base_time);
00543
00544 flag_check = obj_getFlag (target_obj);
00545 do_test ((flag_check == obj_getFlag (import_obj)), "flag value check: 1");
00546 do_test ((obj_getFlag (import_obj) == obj_getFlag (target_obj)),
00547 "flag value check: 2");
00548 }
00549
00550 static void
00551 test_rule_loop (QofBookMergeData * mergeData, QofBookMergeRule * rule,
00552 guint remainder)
00553 {
00554 GSList *testing;
00555 QofParam *eachParam;
00556 gchar *importstring;
00557 gchar *targetstring;
00558 gboolean skip_target;
00559
00560 importstring = NULL;
00561 targetstring = NULL;
00562 skip_target = FALSE;
00563 mergeData->currentRule = rule;
00564 do_test ((rule != NULL), "loop:#1 Rule is NULL");
00565 do_test (remainder > 0, "loop:#2 remainder error.");
00566 do_test ((safe_strcmp (NULL, rule->mergeLabel) != 0),
00567 "loop:#3 object label\n");
00568 do_test ((rule->importEnt != NULL),
00569 "loop:#4 empty import entity");
00570
00571 if (rule->targetEnt == NULL)
00572 {
00573 skip_target = TRUE;
00574 }
00575 if (!skip_target)
00576 {
00577 do_test ((safe_strcmp
00578 (rule->importEnt->e_type, rule->targetEnt->e_type) == 0),
00579 "loop: entity type mismatch");
00580 }
00581 do_test ((rule->mergeParam != NULL),
00582 "loop: empty parameter list");
00583 testing = rule->mergeParam;
00584
00585 while (testing != NULL)
00586 {
00587 eachParam = testing->data;
00588 do_test ((eachParam != NULL), "loop:#8 no QofParam data");
00589 do_test ((eachParam->param_name != NULL),
00590 "loop:#9 no parameter name");
00591 do_test ((eachParam->param_getfcn != NULL),
00592 "loop:#10 no get function");
00593 do_test ((eachParam->param_setfcn != NULL),
00594 "loop:#11 no set function");
00595
00596 if (safe_strcmp (eachParam->param_type, QOF_TYPE_STRING) == 0)
00597 {
00598 importstring =
00599 g_strdup (eachParam->
00600 param_getfcn (rule->importEnt, eachParam));
00601 do_test ((importstring != NULL),
00602 "loop:#12 direct get_fcn import");
00603 do_test ((safe_strcmp (importstring, "test") == 0),
00604 "loop:#13 direct import comparison");
00605 if (!skip_target)
00606 {
00607 targetstring =
00608 eachParam->param_getfcn (rule->targetEnt, eachParam);
00609 do_test ((targetstring != NULL),
00610 "loop:#14 direct get_fcn target");
00611 do_test ((safe_strcmp (targetstring, "testing") == 0),
00612 "loop:#15 direct target comparison");
00613 }
00614 }
00615
00616
00617 importstring =
00618 qof_book_merge_param_as_string (eachParam, rule->importEnt);
00619 do_test ((importstring != NULL),
00620 "loop:#16 import param_as_string is null");
00621 if (!skip_target)
00622 {
00623 targetstring =
00624 qof_book_merge_param_as_string (eachParam, rule->targetEnt);
00625 do_test ((targetstring != NULL),
00626 "loop:#17 target param_as_string is null");
00627 }
00628 testing = g_slist_next (testing);
00629 }
00630
00631
00632 mergeData = qof_book_merge_update_result (mergeData, MERGE_UPDATE);
00633 do_test ((rule->mergeResult != MERGE_REPORT),
00634 "update result fail");
00635 }
00636
00637 int
00638 main (void)
00639 {
00640 qof_init ();
00641 myobjRegister ();
00642 test_merge ();
00643 print_test_results ();
00644 qof_close ();
00645 return get_rv();
00646 }