1 /*
2 * Copyright (C) 2010 - 2012 Vivien Malerba <malerba@gnome-db.org>
3 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 #include <stdlib.h>
20 #include <string.h>
21 #include <glib.h>
22 #include <libgda/libgda.h>
23 #include <sql-parser/gda-sql-parser.h>
24 #include <sql-parser/gda-sql-statement.h>
25 #include <tests/gda-ddl-creator.h>
26 #include <glib/gstdio.h>
27 #include "../test-cnc-utils.h"
28 #include "../data-model-errors.h"
29 #include <virtual/libgda-virtual.h>
30
31 #define fail(x) g_warning (x)
32 #define fail_if(x,y) if (x) g_warning (y)
33 #define fail_unless(x,y) if (!(x)) g_warning (y)
34
35 #define CHECK_EXTRA_INFO
36
37 static void dump_data_model (GdaDataModel *model);
38
39 typedef gboolean (*TestFunc) (GdaConnection *);
40 static gint test1 (GdaConnection *cnc);
41 static gint test2 (GdaConnection *cnc);
42
43 TestFunc tests[] = {
44 test1,
45 test2
46 };
47
48 int
main(int argc,char ** argv)49 main (int argc, char **argv)
50 {
51 guint i, ntests = 0, number_failed = 0;
52
53 gda_init ();
54
55 for (i = 0; i < sizeof (tests) / sizeof (TestFunc); i++) {
56 g_print ("---------- test %d ----------\n", i+1);
57 gint n = tests[i] (NULL);
58 number_failed += n;
59 if (n > 0)
60 g_print ("Test %d failed\n", i+1);
61 ntests ++;
62 }
63
64 g_print ("TESTS COUNT: %d\n", i);
65 g_print ("FAILURES: %d\n", number_failed);
66
67 return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
68 }
69
70 /* Commented out because it is not used:
71 static GdaStatement *
72 stmt_from_string (const gchar *sql)
73 {
74 GdaStatement *stmt;
75 GError *error = NULL;
76
77 static GdaSqlParser *parser = NULL;
78 if (!parser)
79 parser = gda_sql_parser_new ();
80
81 stmt = gda_sql_parser_parse_string (parser, sql, NULL, &error);
82 if (!stmt) {
83 g_print ("Cound not parse SQL: %s\nSQL was: %s\n",
84 error && error->message ? error->message : "No detail",
85 sql);
86 exit (EXIT_FAILURE);
87 }
88 return stmt;
89 }
90 */
91
92 static gboolean
check_iter_contents(GdaDataModel * model,GdaDataModelIter * iter)93 check_iter_contents (GdaDataModel *model, GdaDataModelIter *iter)
94 {
95 gint i, row;
96 row = gda_data_model_iter_get_row (iter);
97 for (i = 0; i < gda_data_model_get_n_columns (model); i++) {
98 GdaHolder *holder;
99 const GValue *vi, *vm;
100 GError *lerror1 = NULL, *lerror2 = NULL;
101
102 holder = gda_set_get_nth_holder (GDA_SET (iter), i);
103 if (gda_holder_is_valid_e (holder, &lerror1))
104 vi = gda_holder_get_value (holder);
105 else
106 vi = NULL;
107 vm = gda_data_model_get_value_at (model, i, row, &lerror2);
108 if (vi == vm) {
109 if (!vi) {
110 if (! lerror1 || !lerror1->message) {
111 #ifdef CHECK_EXTRA_INFO
112 g_print ("Iterator reported invalid value without any error set\n");
113 #endif
114 return FALSE;
115 }
116 else if (! lerror2 || !lerror2->message) {
117 #ifdef CHECK_EXTRA_INFO
118 g_print ("Data model reported invalid value without any error set\n");
119 #endif
120 return FALSE;
121 }
122 else if (lerror1->code != lerror2->code) {
123 #ifdef CHECK_EXTRA_INFO
124 g_print ("Error codes differ!\n");
125 #endif
126 return FALSE;
127 }
128 else if (lerror1->domain != lerror2->domain) {
129 #ifdef CHECK_EXTRA_INFO
130 g_print ("Error domains differ!\n");
131 #endif
132 return FALSE;
133 }
134 else if (strcmp (lerror1->message, lerror2->message)) {
135 #ifdef CHECK_EXTRA_INFO
136 g_print ("Error messages differ:\n\t%s\t%s",
137 lerror1->message, lerror2->message);
138 #endif
139 return FALSE;
140 }
141 }
142 else if (gda_value_differ (vi, vm)) {
143 #ifdef CHECK_EXTRA_INFO
144 g_print ("Iter's contents at (%d,%d) is wrong: expected [%s], got [%s]\n",
145 i, row,
146 vm ? gda_value_stringify (vm) : "ERROR",
147 vi ? gda_value_stringify (vi) : "ERROR");
148 #endif
149 return FALSE;
150 }
151 }
152 else if (gda_value_differ (vi, vm)) {
153 #ifdef CHECK_EXTRA_INFO
154 g_print ("Iter's contents at (%d,%d) is wrong: expected [%s], got [%s]\n",
155 i, row,
156 vm ? gda_value_stringify (vm) : "ERROR",
157 vi ? gda_value_stringify (vi) : "ERROR");
158 #endif
159 return FALSE;
160 }
161 }
162 return TRUE;
163 }
164
165 /*
166 * check modifications statements' setting
167 *
168 * Returns the number of failures
169 */
170 static gint
test1(GdaConnection * cnc)171 test1 (GdaConnection *cnc)
172 {
173 GdaDataModel *model;
174 gint nfailed = 0;
175
176 model = data_model_errors_new ();
177 if (!model) {
178 nfailed++;
179 #ifdef CHECK_EXTRA_INFO
180 g_print ("Could not create DataModelErrors!\n");
181 #endif
182 goto out;
183 }
184 dump_data_model (model);
185
186 /* iterate forward */
187 GdaDataModelIter *iter;
188 gint i, row;
189 iter = gda_data_model_create_iter (model);
190 for (i = 0, gda_data_model_iter_move_next (iter);
191 gda_data_model_iter_is_valid (iter);
192 i++, gda_data_model_iter_move_next (iter)) {
193 row = gda_data_model_iter_get_row (iter);
194 if (i != row) {
195 nfailed++;
196 #ifdef CHECK_EXTRA_INFO
197 g_print ("Error iterating: expected to be at row %d and reported row is %d!\n",
198 i, row);
199 #endif
200 goto out;
201 }
202 g_print ("Now at row %d\n", i);
203
204 if (! check_iter_contents (model, iter)) {
205 nfailed++;
206 goto out;
207 }
208 }
209 g_print ("Now at row %d\n", gda_data_model_iter_get_row (iter));
210
211 /* iterate backward */
212 i--;
213 if (!gda_data_model_iter_move_to_row (iter, i)) {
214 nfailed++;
215 #ifdef CHECK_EXTRA_INFO
216 g_print ("Error iterating: move to last row (%d) failed\n", i);
217 #endif
218 goto out;
219 }
220 row = gda_data_model_iter_get_row (iter);
221 if (row != i) {
222 nfailed++;
223 #ifdef CHECK_EXTRA_INFO
224 g_print ("Error iterating: move to last row (%d) should have set row to %d and is set to %d\n",
225 i, i, row);
226 #endif
227 goto out;
228 }
229 for (;
230 gda_data_model_iter_is_valid (iter);
231 i--, gda_data_model_iter_move_prev (iter)) {
232 row = gda_data_model_iter_get_row (iter);
233 if (i != row) {
234 nfailed++;
235 #ifdef CHECK_EXTRA_INFO
236 g_print ("Error iterating: expected to be at row %d and reported row is %d!\n",
237 i, row);
238 #endif
239 goto out;
240 }
241 g_print ("Now at row %d\n", i);
242
243 if (! check_iter_contents (model, iter)) {
244 nfailed++;
245 goto out;
246 }
247 }
248 g_print ("Now at row %d\n", gda_data_model_iter_get_row (iter));
249
250 out:
251 g_object_unref (model);
252
253 return nfailed;
254 }
255
256 static void
dump_data_model(GdaDataModel * model)257 dump_data_model (GdaDataModel *model)
258 {
259 gint i, ncols;
260 g_print ("=== Data Model Dump ===\n");
261 ncols = gda_data_model_get_n_columns (model);
262 for (i = 0; i < ncols; i++) {
263 GdaColumn *col;
264 col = gda_data_model_describe_column (model, i);
265 if (!col)
266 g_print ("Missing column %d\n", i);
267 g_print ("Column %d: ptr=>%p type=>%s\n", i, col, g_type_name (gda_column_get_g_type (col)));
268 }
269 gda_data_model_dump (model, stdout);
270 }
271
272 /* Commented out because it is not used.
273 static gboolean
274 compare_data_models (GdaDataModel *model1, GdaDataModel *model2, GError **error)
275 {
276 GdaDataComparator *cmp;
277 GError *lerror = NULL;
278 cmp = (GdaDataComparator*) gda_data_comparator_new (model1, model2);
279 if (! gda_data_comparator_compute_diff (cmp, &lerror)) {
280 #ifdef CHECK_EXTRA_INFO
281 g_print ("Could not compute the data model differences: %s\n",
282 lerror && lerror->message ? lerror->message : "No detail");
283 g_print ("Model1 is:\n");
284 gda_data_model_dump (model1, stdout);
285 g_print ("Model2 is:\n");
286 gda_data_model_dump (model2, stdout);
287 #endif
288 goto onerror;
289 }
290 if (gda_data_comparator_get_n_diffs (cmp) != 0) {
291 #ifdef CHECK_EXTRA_INFO
292 g_print ("There are some differences when comparing data models...\n");
293 g_print ("Model1 is:\n");
294 gda_data_model_dump (model1, stdout);
295 g_print ("Model2 is:\n");
296 gda_data_model_dump (model2, stdout);
297 #endif
298 g_set_error (&lerror, TEST_ERROR, TEST_ERROR_GENERIC,
299 "%s", "There are some differences when comparing data models...");
300 goto onerror;
301 }
302 g_object_unref (cmp);
303
304 return TRUE;
305
306 onerror:
307 g_propagate_error (error, lerror);
308 return FALSE;
309 }
310 */
311
312 /*
313 * check modifications statements' setting
314 *
315 * Returns the number of failures
316 */
317 static gint
test2(GdaConnection * cnc)318 test2 (GdaConnection *cnc)
319 {
320 #define TABLE_NAME "data"
321 GdaDataModel *model;
322 gint nfailed = 0;
323
324 model = data_model_errors_new ();
325 if (!model) {
326 nfailed++;
327 #ifdef CHECK_EXTRA_INFO
328 g_print ("Could not create DataModelErrors!\n");
329 #endif
330 goto out;
331 }
332
333 GdaVirtualProvider *virtual_provider;
334 GError *lerror = NULL;
335 GdaConnection *vcnc;
336 GdaDataModelIter *iter = NULL;
337 GdaStatement *stmt;
338 virtual_provider = gda_vprovider_data_model_new ();
339 vcnc = gda_virtual_connection_open (virtual_provider, &lerror);
340 if (!vcnc) {
341 #ifdef CHECK_EXTRA_INFO
342 g_print ("Virtual ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
343 #endif
344 nfailed++;
345 g_clear_error (&lerror);
346 goto out;
347 }
348
349 if (!gda_vconnection_data_model_add_model (GDA_VCONNECTION_DATA_MODEL (vcnc), model,
350 TABLE_NAME, &lerror)) {
351 #ifdef CHECK_EXTRA_INFO
352 g_print ("Add model as table ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
353 #endif
354 nfailed++;
355 g_clear_error (&lerror);
356 goto out;
357 }
358 g_object_unref (model);
359
360 /* Execute SELECT */
361 stmt = gda_connection_parse_sql_string (vcnc, "SELECT * FROM " TABLE_NAME, NULL, NULL);
362 g_assert (stmt);
363 model = gda_connection_statement_execute_select (vcnc, stmt, NULL, &lerror);
364 g_object_unref (stmt);
365 if (!model) {
366 #ifdef CHECK_EXTRA_INFO
367 g_print ("SELECT ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
368 #endif
369 nfailed++;
370 g_clear_error (&lerror);
371 goto out;
372 }
373
374 dump_data_model (model);
375
376 /* iterate forward */
377 gint i, row;
378 iter = gda_data_model_create_iter (model);
379 for (i = 0, gda_data_model_iter_move_next (iter);
380 gda_data_model_iter_is_valid (iter);
381 i++, gda_data_model_iter_move_next (iter)) {
382 row = gda_data_model_iter_get_row (iter);
383 if (i != row) {
384 nfailed++;
385 #ifdef CHECK_EXTRA_INFO
386 g_print ("Error iterating: expected to be at row %d and reported row is %d!\n",
387 i, row);
388 #endif
389 goto out;
390 }
391 g_print ("Now at row %d\n", i);
392
393 if (! check_iter_contents (model, iter)) {
394 nfailed++;
395 goto out;
396 }
397 }
398 if (i != 4) {
399 #ifdef CHECK_EXTRA_INFO
400 g_print ("Error iterating: expected to have read %d rows, and read %d\n", 3,
401 i - 1);
402 nfailed++;
403 goto out;
404 #endif
405 }
406 if (gda_data_model_iter_get_row (iter) != -1) {
407 #ifdef CHECK_EXTRA_INFO
408 g_print ("Error iterating: expected to be at row -1 and reported row is %d!\n",
409 gda_data_model_iter_get_row (iter));
410 #endif
411 nfailed++;
412 goto out;
413 }
414
415 /* bind as another table */
416 if (!gda_vconnection_data_model_add_model (GDA_VCONNECTION_DATA_MODEL (vcnc), model,
417 TABLE_NAME "2", &lerror)) {
418 #ifdef CHECK_EXTRA_INFO
419 g_print ("Add model as table2 ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
420 #endif
421 nfailed++;
422 g_clear_error (&lerror);
423 goto out;
424 }
425 g_object_unref (model);
426
427 stmt = gda_connection_parse_sql_string (vcnc, "SELECT * FROM " TABLE_NAME "2", NULL, NULL);
428 g_assert (stmt);
429 model = gda_connection_statement_execute_select (vcnc, stmt, NULL, &lerror);
430 g_object_unref (stmt);
431 if (!model) {
432 #ifdef CHECK_EXTRA_INFO
433 g_print ("SELECT ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
434 #endif
435 nfailed++;
436 g_clear_error (&lerror);
437 goto out;
438 }
439
440 /* iterate forward */
441 iter = gda_data_model_create_iter (model);
442 for (i = 0, gda_data_model_iter_move_next (iter);
443 gda_data_model_iter_is_valid (iter);
444 i++, gda_data_model_iter_move_next (iter)) {
445 row = gda_data_model_iter_get_row (iter);
446 if (i != row) {
447 nfailed++;
448 #ifdef CHECK_EXTRA_INFO
449 g_print ("Error iterating: expected to be at row %d and reported row is %d!\n",
450 i, row);
451 #endif
452 goto out;
453 }
454 g_print ("Now at row %d\n", i);
455
456 if (! check_iter_contents (model, iter)) {
457 nfailed++;
458 goto out;
459 }
460 }
461 if (i != 4) {
462 #ifdef CHECK_EXTRA_INFO
463 g_print ("Error iterating: expected to have read %d rows, and read %d\n", 3,
464 i - 1);
465 nfailed++;
466 goto out;
467 #endif
468 }
469 if (gda_data_model_iter_get_row (iter) != -1) {
470 #ifdef CHECK_EXTRA_INFO
471 g_print ("Error iterating: expected to be at row -1 and reported row is %d!\n",
472 gda_data_model_iter_get_row (iter));
473 #endif
474 nfailed++;
475 goto out;
476 }
477
478 out:
479 if (iter)
480 g_object_unref (iter);
481 if (model)
482 g_object_unref (model);
483 g_object_unref (vcnc);
484 g_object_unref (virtual_provider);
485
486 return nfailed;
487 }
488