QOF  0.8.0
test-sql.c
00001 /***************************************************************************
00002  *            test-sql.c
00003  *
00004  *  Copyright  2008  Neil Williams <linux@codehelp.co.uk>
00005  ****************************************************************************/
00006 /*
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Library General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
00020  */
00021  
00022 /*
00023  * lightly test the QofSql conversions.
00024  *
00025  * The problem with more intensive testing is that checking the syntax
00026  * of the returned strings requires complex SQL parsing and not all
00027  * checks are currently implemented in QOF.
00028  */
00029 #include <glib.h>
00030 #include "qof.h"
00031 #include "qofsql-p.h"
00032 #include "test-stuff.h"
00033 
00035 #define TEST_MODULE_NAME "object_test"
00036 #define TEST_MODULE_DESC "Test Object"
00037 #define OBJ_AMOUNT "anamount"
00038 #define OBJ_KVP "kvp"
00039 
00040 /* simple object structure */
00041 typedef struct d_obj
00042 {
00043     QofInstance inst;
00044     gchar *Name;
00045     gchar flag;
00046     QofNumeric Amount;
00047     QofTime *date;
00048     gdouble discount;           /* cheap pun, I know. */
00049     gboolean active;
00050     gint32 version;
00051     gint64 minor;
00052 } dyn_obj;
00053 
00054 static dyn_obj *
00055 dyn_create (QofBook * book)
00056 {
00057     dyn_obj * d;
00058 
00059     g_return_val_if_fail (book, NULL);
00060     d = g_new0 (dyn_obj, 1);
00061     qof_instance_init (&d->inst, TEST_MODULE_NAME, book);
00062     return d;
00063 }
00064 
00065 static void
00066 dyn_setAmount (dyn_obj * e, QofNumeric h)
00067 {
00068     if (!e)
00069         return;
00070     e->Amount = h;
00071 }
00072 
00073 static QofNumeric
00074 dyn_getAmount (dyn_obj * e)
00075 {
00076     if (!e)
00077         return qof_numeric_zero ();
00078     return e->Amount;
00079 }
00080 
00081 static G_GNUC_UNUSED const gchar *
00082 test_dyn_printable (gpointer obj)
00083 {
00084     return "test";
00085 }
00086 
00087 static QofObject bus_obj = {
00088     .interface_version = QOF_OBJECT_VERSION,
00089     .e_type = TEST_MODULE_NAME,
00090     .type_label = TEST_MODULE_DESC,
00091     .create = (gpointer)dyn_create,
00092     .book_begin = NULL,
00093     .book_end = NULL,
00094     .is_dirty = qof_collection_is_dirty,
00095     .mark_clean = qof_collection_mark_clean,
00096     .foreach = qof_collection_foreach,
00097     .printable = test_dyn_printable,
00098     .version_cmp = (gint (*)(gpointer, gpointer)) qof_instance_version_cmp,
00099 };
00100 
00101 static gboolean
00102 dyn_objRegister (void)
00103 {
00104     static QofParam params[] = {
00105         {OBJ_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc) dyn_getAmount,
00106          (QofSetterFunc) dyn_setAmount, NULL},
00107         {OBJ_KVP, QOF_TYPE_KVP, (QofAccessFunc) qof_instance_get_slots,
00108             NULL, NULL},
00109         {QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc) qof_instance_get_book,
00110          NULL, NULL},
00111         {QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc) qof_instance_get_guid,
00112          NULL, NULL},
00113         {NULL, NULL, NULL, NULL, NULL},
00114     };
00115 
00116     qof_class_register (TEST_MODULE_NAME, NULL, params);
00117 
00118     return qof_object_register (&bus_obj);
00119 }
00120 
00121 static void
00122 dyn_foreach (QofParam * param, gpointer user_data)
00123 {
00124     do_test (param != NULL, "Fail");
00125 }
00126 
00127 static void
00128 dyn_foreach2 (QofEntity * ent, gpointer user_data)
00129 {
00130     do_test (ent != NULL, "Fail");
00131 }
00132 
00133 static void
00134 test_sql (QofBook * book)
00135 {
00136     KvpFrame * slots;
00137     const QofParam * param;
00138     QofEntity * ent;
00139     QofInstance * inst;
00140     gdouble rand_dbl;
00141     QofNumeric rand_num;
00142     QofCollection * col;
00143     gchar * sql_str, * gstr, * test, * err, *rand_str;
00144     gchar * num_str;
00145     gulong kvp_id;
00146 
00147     sql_str = NULL;
00148     inst = qof_object_new_instance (TEST_MODULE_NAME, book);
00149     do_test (inst != NULL, "object new instance");
00150     g_return_if_fail (inst);
00151     /* create some slots */
00152     rand_str = g_strescape (get_random_string (), NULL);
00153     slots = qof_instance_get_slots (inst);
00154     do_test (slots != NULL, "creating some slots");
00155     kvp_frame_set_string (qof_instance_get_slots (inst), "debug/test/string", rand_str);
00156     test = g_strdup(kvp_frame_get_string (qof_instance_get_slots (inst), "debug/test/string"));
00157     err = g_strdup_printf ("compare slots: %s", test);
00158     do_test (0 == safe_strcasecmp (test, rand_str), err);
00159     g_free (test);
00160     g_free (err);
00161     ent = (QofEntity*)inst;
00162     do_test (ent != NULL, "convert to entity");
00163     qof_class_param_foreach (ent->e_type, dyn_foreach, NULL);
00164     col = qof_book_get_collection (book, ent->e_type);
00165     qof_collection_foreach (col, dyn_foreach2, NULL);
00166     /* test CREATE TABLE */
00167     rand_dbl = get_random_double ();
00168     rand_num = qof_numeric_from_double (rand_dbl, QOF_DENOM_AUTO, QOF_HOW_RND_ROUND);
00169     num_str = qof_numeric_to_string (rand_num);
00170     sql_str = qof_sql_entity_create_table (ent);
00171     test = g_strdup ("CREATE TABLE object_test ( guid char(32) primary key not null, "
00172         "anamount text, dbversion int ); CREATE TABLE sql_kvp (kvp_id int "
00173         "primary key not null, guid char(32), path mediumtext, type mediumtext, "
00174         "value text,  dbversion int );");
00175     do_test (0 == safe_strcasecmp (sql_str, test), 
00176         g_strdup_printf ("Create table SQL statement:%s:%s", sql_str, test));
00177     g_free (test);
00178     g_free (sql_str);
00179     qof_sql_entity_set_kvp_exists (TRUE);
00180     /* test INSERT */
00181     kvp_id = qof_sql_entity_get_kvp_id ();
00182     sql_str = qof_sql_entity_insert (ent);
00183     gstr = g_strnfill (GUID_ENCODING_LENGTH + 1, ' ');
00184     guid_to_string_buff (qof_instance_get_guid (inst), gstr);
00185     test = g_strdup_printf ("INSERT into object_test (guid , anamount) VALUES "
00186         "('%s' , '%s'); INSERT into sql_kvp  (kvp_id, guid, type, path, value) "
00187         "VALUES ('%ld', '%s', 'string', '/debug/test/string', '%s');", 
00188         gstr, num_str, kvp_id, gstr, rand_str);
00189     err = g_strdup_printf ("Insert entity SQL statement:%s:%s", sql_str, test);
00190     do_test (0 == safe_strcasecmp (sql_str, test),err);
00191     g_free (test);
00192     g_free (err);
00193     g_free (sql_str);
00194     /* test UPDATE */
00195     param = qof_class_get_parameter (TEST_MODULE_NAME, OBJ_AMOUNT);
00196     /* pretend we are using qof_util_param_edit so that we don't need a backend */
00197     inst->param = param;
00198     do_test (param != NULL, "no OBJ_AMOUNT parameter");
00199     sql_str = qof_sql_entity_update (ent);
00200     do_test (sql_str != NULL, "failed to mark instance as dirty");
00201     test = g_strdup_printf ("UPDATE object_test SET anamount = '%s' WHERE "
00202         "guid='%s';", num_str, gstr);
00203     err = g_strdup_printf ("Update entity SQL statement: %s", sql_str);
00204     do_test (0 == safe_strcasecmp (sql_str, test), err);
00205     g_free (test);
00206     g_free (err);
00207     g_free (sql_str);
00208     /* test update KVP */
00209     sql_str = qof_sql_entity_update_kvp (ent);
00210     test = g_strdup_printf ("UPDATE sql_kvp SET type='string', value='%s' "
00211         "WHERE path='/debug/test/string' and  guid='%s';", rand_str, gstr);
00212     err = g_strdup_printf ("Update entity SQL statement: %s", sql_str);
00213     do_test (0 == safe_strcasecmp (sql_str, test), err);
00214     g_free (test);
00215     g_free (err);
00216     g_free (sql_str);
00217     /* test update list */
00219     /* test DELETE */
00220     sql_str = qof_sql_entity_delete (ent);
00221     test = g_strconcat ("DELETE from object_test WHERE guid='", gstr, "';", 
00222         "DELETE from sql_kvp WHERE kvp_id ='", gstr, "';", NULL);
00223     err = g_strdup_printf ("DELETE entity SQL statement: %s", sql_str);
00224     do_test (0 == safe_strcasecmp (sql_str, test), err);
00225     g_free (test);
00226     g_free (err);
00227     g_free (sql_str);
00228     sql_str = qof_sql_entity_drop_table (ent);
00229     /* test DROP TABLE */
00230     err = g_strdup_printf ("DROP TABLE SQL statement: %s", sql_str);
00231     do_test (0 == safe_strcasecmp (sql_str, "DROP TABLE object_test;"), err);
00232     g_free (err);
00233     g_free (sql_str);
00234     qof_sql_entity_set_kvp_exists (FALSE);
00235 }
00236 
00237 int
00238 main (void)
00239 {
00240     QofBook *book;
00241     gint c;
00242     qof_init ();
00243     book = qof_book_new ();
00244     do_test ((NULL != book), "book null");
00245     do_test (dyn_objRegister() == TRUE, "register test object");
00246     do_test (qof_object_lookup (TEST_MODULE_NAME) == &bus_obj,
00247                 "lookup our installed object");
00248     do_test (qof_class_is_registered(TEST_MODULE_NAME) == TRUE, "class registration");
00249     for (c=0;c<10;c++)
00250     {
00251         test_sql (book);
00252     }
00253     print_test_results ();
00254     qof_close ();
00255     return get_rv ();
00256 }