QOF  0.8.7
test-sql.c
1 /***************************************************************************
2  * test-sql.c
3  *
4  * Copyright 2008 Neil Williams <linux@codehelp.co.uk>
5  ****************************************************************************/
6 /*
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA
20  */
21 
22 /*
23  * lightly test the QofSql conversions.
24  *
25  * The problem with more intensive testing is that checking the syntax
26  * of the returned strings requires complex SQL parsing and not all
27  * checks are currently implemented in QOF.
28  */
29 #include <glib.h>
30 #include "qof.h"
31 #include "qofsql-p.h"
32 #include "test-stuff.h"
33 
35 #define TEST_MODULE_NAME "object_test"
36 #define TEST_MODULE_DESC "Test Object"
37 #define OBJ_AMOUNT "anamount"
38 #define OBJ_KVP "kvp"
39 
40 /* simple object structure */
41 typedef struct d_obj
42 {
43  QofInstance inst;
44  gchar *Name;
45  gchar flag;
46  QofNumeric Amount;
47  QofTime *date;
48  gdouble discount; /* cheap pun, I know. */
49  gboolean active;
50  gint32 version;
51  gint64 minor;
52 } dyn_obj;
53 
54 static dyn_obj *
55 dyn_create (QofBook * book)
56 {
57  dyn_obj * d;
58 
59  g_return_val_if_fail (book, NULL);
60  d = g_new0 (dyn_obj, 1);
61  qof_instance_init (&d->inst, TEST_MODULE_NAME, book);
62  return d;
63 }
64 
65 static void
66 dyn_setAmount (dyn_obj * e, QofNumeric h)
67 {
68  if (!e)
69  return;
70  e->Amount = h;
71 }
72 
73 static QofNumeric
74 dyn_getAmount (dyn_obj * e)
75 {
76  if (!e)
77  return qof_numeric_zero ();
78  return e->Amount;
79 }
80 
81 static G_GNUC_UNUSED const gchar *
82 test_dyn_printable (gpointer obj)
83 {
84  return "test";
85 }
86 
87 static QofObject bus_obj = {
88  .interface_version = QOF_OBJECT_VERSION,
89  .e_type = TEST_MODULE_NAME,
90  .type_label = TEST_MODULE_DESC,
91  .create = (gpointer)dyn_create,
92  .book_begin = NULL,
93  .book_end = NULL,
94  .is_dirty = qof_collection_is_dirty,
95  .mark_clean = qof_collection_mark_clean,
96  .foreach = qof_collection_foreach,
97  .printable = test_dyn_printable,
98  .version_cmp = (gint (*)(gpointer, gpointer)) qof_instance_version_cmp,
99 };
100 
101 static gboolean
102 dyn_objRegister (void)
103 {
104  static QofParam params[] = {
105  {OBJ_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc) dyn_getAmount,
106  (QofSetterFunc) dyn_setAmount, NULL},
107  {OBJ_KVP, QOF_TYPE_KVP, (QofAccessFunc) qof_instance_get_slots,
108  NULL, NULL},
110  NULL, NULL},
111  {QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc) qof_instance_get_guid,
112  NULL, NULL},
113  {NULL, NULL, NULL, NULL, NULL},
114  };
115 
116  qof_class_register (TEST_MODULE_NAME, NULL, params);
117 
118  return qof_object_register (&bus_obj);
119 }
120 
121 static void
122 dyn_foreach (QofParam * param, gpointer user_data)
123 {
124  do_test (param != NULL, "Fail");
125 }
126 
127 static void
128 dyn_foreach2 (QofEntity * ent, gpointer user_data)
129 {
130  do_test (ent != NULL, "Fail");
131 }
132 
133 static void
134 test_sql (QofBook * book)
135 {
136  KvpFrame * slots;
137  const QofParam * param;
138  QofEntity * ent;
139  QofInstance * inst;
140  gdouble rand_dbl;
141  QofNumeric rand_num;
142  QofCollection * col;
143  gchar * sql_str, * gstr, * test, * err, *rand_str;
144  gchar * num_str;
145  gulong kvp_id;
146 
147  sql_str = NULL;
148  inst = qof_object_new_instance (TEST_MODULE_NAME, book);
149  do_test (inst != NULL, "object new instance");
150  g_return_if_fail (inst);
151  /* create some slots */
152  rand_str = g_strescape (get_random_string (), NULL);
153  slots = qof_instance_get_slots (inst);
154  do_test (slots != NULL, "creating some slots");
155  kvp_frame_set_string (qof_instance_get_slots (inst), "debug/test/string", rand_str);
156  test = g_strdup(kvp_frame_get_string (qof_instance_get_slots (inst), "debug/test/string"));
157  err = g_strdup_printf ("compare slots: %s", test);
158  do_test (0 == safe_strcasecmp (test, rand_str), err);
159  g_free (test);
160  g_free (err);
161  ent = (QofEntity*)inst;
162  do_test (ent != NULL, "convert to entity");
163  qof_class_param_foreach (ent->e_type, dyn_foreach, NULL);
164  col = qof_book_get_collection (book, ent->e_type);
165  qof_collection_foreach (col, dyn_foreach2, NULL);
166  /* test CREATE TABLE */
167  rand_dbl = get_random_double ();
169  num_str = qof_numeric_to_string (rand_num);
170  sql_str = qof_sql_entity_create_table (ent);
171  test = g_strdup ("CREATE TABLE object_test ( guid char(32) primary key not null, "
172  "anamount text, dbversion int ); CREATE TABLE sql_kvp (kvp_id int "
173  "primary key not null, guid char(32), path mediumtext, type mediumtext, "
174  "value text, dbversion int );");
175  do_test (0 == safe_strcasecmp (sql_str, test),
176  g_strdup_printf ("Create table SQL statement:%s:%s", sql_str, test));
177  g_free (test);
178  g_free (sql_str);
180  /* test INSERT */
181  kvp_id = qof_sql_entity_get_kvp_id ();
182  sql_str = qof_sql_entity_insert (ent);
183  gstr = g_strnfill (GUID_ENCODING_LENGTH + 1, ' ');
185  test = g_strdup_printf ("INSERT into object_test (guid , anamount) VALUES "
186  "('%s' , '%s'); INSERT into sql_kvp (kvp_id, guid, type, path, value) "
187  "VALUES ('%ld', '%s', 'string', '/debug/test/string', '%s');",
188  gstr, num_str, kvp_id, gstr, rand_str);
189  err = g_strdup_printf ("Insert entity SQL statement:%s:%s", sql_str, test);
190  do_test (0 == safe_strcasecmp (sql_str, test),err);
191  g_free (test);
192  g_free (err);
193  g_free (sql_str);
194  /* test UPDATE */
195  param = qof_class_get_parameter (TEST_MODULE_NAME, OBJ_AMOUNT);
196  /* pretend we are using qof_util_param_edit so that we don't need a backend */
197  inst->param = param;
198  do_test (param != NULL, "no OBJ_AMOUNT parameter");
199  sql_str = qof_sql_entity_update (ent);
200  do_test (sql_str != NULL, "failed to mark instance as dirty");
201  test = g_strdup_printf ("UPDATE object_test SET anamount = '%s' WHERE "
202  "guid='%s';", num_str, gstr);
203  err = g_strdup_printf ("Update entity SQL statement: %s", sql_str);
204  do_test (0 == safe_strcasecmp (sql_str, test), err);
205  g_free (test);
206  g_free (err);
207  g_free (sql_str);
208  /* test update KVP */
209  sql_str = qof_sql_entity_update_kvp (ent);
210  test = g_strdup_printf ("UPDATE sql_kvp SET type='string', value='%s' "
211  "WHERE path='/debug/test/string' and guid='%s';", rand_str, gstr);
212  err = g_strdup_printf ("Update entity SQL statement: %s", sql_str);
213  do_test (0 == safe_strcasecmp (sql_str, test), err);
214  g_free (test);
215  g_free (err);
216  g_free (sql_str);
217  /* test update list */
219  /* test DELETE */
220  sql_str = qof_sql_entity_delete (ent);
221  test = g_strconcat ("DELETE from object_test WHERE guid='", gstr, "';",
222  "DELETE from sql_kvp WHERE kvp_id ='", gstr, "';", NULL);
223  err = g_strdup_printf ("DELETE entity SQL statement: %s", sql_str);
224  do_test (0 == safe_strcasecmp (sql_str, test), err);
225  g_free (test);
226  g_free (err);
227  g_free (sql_str);
228  sql_str = qof_sql_entity_drop_table (ent);
229  /* test DROP TABLE */
230  err = g_strdup_printf ("DROP TABLE SQL statement: %s", sql_str);
231  do_test (0 == safe_strcasecmp (sql_str, "DROP TABLE object_test;"), err);
232  g_free (err);
233  g_free (sql_str);
235 }
236 
237 int
238 main (void)
239 {
240  QofBook *book;
241  gint c;
242  qof_init ();
243  book = qof_book_new ();
244  do_test ((NULL != book), "book null");
245  do_test (dyn_objRegister() == TRUE, "register test object");
246  do_test (qof_object_lookup (TEST_MODULE_NAME) == &bus_obj,
247  "lookup our installed object");
248  do_test (qof_class_is_registered(TEST_MODULE_NAME) == TRUE, "class registration");
249  for (c=0;c<10;c++)
250  {
251  test_sql (book);
252  }
253  print_test_results ();
254  qof_close ();
255  return get_rv ();
256 }
gpointer qof_object_new_instance(QofIdTypeConst type_name, QofBook *book)
Definition: qofobject.c:42
QofCollection * qof_book_get_collection(QofBook *book, QofIdType entity_type)
Definition: qofbook.c:220
gboolean qof_class_is_registered(QofIdTypeConst obj_name)
Definition: qofclass.c:133
gboolean qof_collection_is_dirty(QofCollection *col)
Definition: qofid.c:333
void qof_class_param_foreach(QofIdTypeConst obj_name, QofParamForeachCB cb, gpointer user_data)
Definition: qofclass.c:268
#define QOF_OBJECT_VERSION
Definition: qofobject.h:57
gchar * qof_sql_entity_insert(QofEntity *ent)
Build a SQL &#39;INSERT&#39; statement for this entity.
Definition: qofsql.c:1389
const QofObject * qof_object_lookup(QofIdTypeConst name)
Definition: qofobject.c:305
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:94
struct _KvpFrame KvpFrame
Definition: kvpframe.h:74
QofBook * qof_book_new(void)
Definition: qofbook.c:75
gint safe_strcasecmp(const gchar *da, const gchar *db)
Definition: qofutil.c:95
gulong qof_sql_entity_get_kvp_id(void)
Get the index value of the KVP table after the operation(s).
Definition: qofsql.c:1569
QofBook * qof_instance_get_book(QofInstance *inst)
Definition: qofinstance.c:87
#define GUID_ENCODING_LENGTH
Definition: guid.h:64
#define QOF_PARAM_BOOK
Definition: qofquery.h:104
void(* QofSetterFunc)(gpointer, gpointer)
Definition: qofclass.h:151
gchar * qof_sql_entity_update(QofEntity *ent)
Build a SQL &#39;UPDATE&#39; statement for the current entity parameter.
Definition: qofsql.c:1460
gchar * qof_sql_entity_create_table(QofEntity *ent)
Build a SQL &#39;CREATE&#39; statement for this entity.
Definition: qofsql.c:1368
struct QofCollection_s QofCollection
Definition: qofid.h:138
const QofParam * qof_class_get_parameter(QofIdTypeConst obj_name, const gchar *parameter)
Definition: qofclass.c:147
const GUID * qof_instance_get_guid(QofInstance *inst)
Definition: qofinstance.c:79
KvpFrame * qof_instance_get_slots(QofInstance *inst)
Definition: qofinstance.c:95
void qof_collection_foreach(QofCollection *col, QofEntityForeachCB cb_func, gpointer user_data)
Definition: qofid.c:392
gchar * guid_to_string_buff(const GUID *guid, gchar *buff)
void qof_sql_entity_set_kvp_exists(gboolean exist)
Set or clear a flag that the KVP table exists or not.
Definition: qofsql.c:1574
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
Definition: qofclass.h:144
Private QOF SQL generation routines.
void qof_collection_mark_clean(QofCollection *)
Definition: qofid.c:339
gchar * qof_sql_entity_update_kvp(QofEntity *ent)
Build a SQL &#39;UPDATE&#39; statement for the KVP data in this entity.
Definition: qofsql.c:1495
gchar * qof_sql_entity_drop_table(QofEntity *ent)
Build a SQL &#39;DROP&#39; statement for this entity type.
Definition: qofsql.c:1549
gchar * qof_numeric_to_string(QofNumeric n)
Definition: qofnumeric.c:1084
gboolean qof_object_register(const QofObject *object)
Definition: qofobject.c:278
void qof_close(void)
Safely close down the Query Object Framework.
Definition: qofutil.c:840
struct QofTime64 QofTime
Use a 64-bit signed int QofTime.
Definition: qoftime.h:112
QofNumeric qof_numeric_from_double(gdouble in, gint64 denom, gint how)
Definition: qofnumeric.c:914
static QofNumeric qof_numeric_zero(void)
Definition: qofnumeric.h:253
const QofParam * param
Definition: qofinstance-p.h:53
int qof_instance_version_cmp(QofInstance *left, QofInstance *right)
Definition: qofinstance.c:116
void qof_instance_init(QofInstance *inst, QofIdType type, QofBook *book)
Definition: qofinstance.c:53
void qof_init(void)
Initialise the Query Object Framework.
Definition: qofutil.c:829
gchar * qof_sql_entity_delete(QofEntity *ent)
Build a SQL &#39;DELETE&#39; statement for this entity.
Definition: qofsql.c:1535
void kvp_frame_set_string(KvpFrame *frame, const gchar *path, const gchar *str)
Store a copy of the string at the indicated path.
Definition: kvpframe.c:439
#define QOF_DENOM_AUTO
Definition: qofnumeric.h:231