1 /*
2 * Copyright (C) 2009 - 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 <stdio.h>
20 #include <string.h>
21 #include <libgda/libgda.h>
22 #include <sql-parser/gda-sql-parser.h>
23 #include <thread-wrapper/gda-thread-recordset.h>
24 #include "common.h"
25
26 #define DBDIR "."
27
28 static void test_cnc_obj (GdaConnection *tcnc);
29 static void test_cnc_status (GdaConnection *tcnc, gboolean opened);
30
31 static gint test_select (GdaConnection *cnc, GdaConnection *tcnc);
32 static gint test_select_cursor (GdaConnection *cnc, GdaConnection *tcnc);
33 static gint test_insert (GdaConnection *tcnc);
34 static gint test_update (GdaConnection *tcnc);
35 static gint test_delete (GdaConnection *tcnc);
36 static gint test_meta_store (GdaConnection *cnc);
37 static gint test_meta_data (GdaConnection *cnc, GdaConnection *tcnc);
38 static gint test_signals (GdaConnection *cnc, GdaConnection *tcnc);
39
40 int
main(int argc,char ** argv)41 main (int argc, char** argv)
42 {
43 GdaConnection *cnc, *tcnc;
44 GError *error = NULL;
45 gint failures = 0;
46 gint ntests = 0;
47 gchar *fname;
48
49 gda_init ();
50
51 /* create test DB */
52 fname = g_build_filename (ROOT_DIR, "tests", "multi-threading", "testdb.sql", NULL);
53 if (!create_sqlite_db (DBDIR, "testdb", fname, &error)) {
54 g_print ("Cannot create test database: %s\n", error && error->message ?
55 error->message : "no detail");
56 return 1;
57 }
58 g_free (fname);
59
60
61 /* create a connection in threaded mode */
62 cnc = gda_connection_open_from_string ("SQlite", "DB_DIR=.;DB_NAME=testdb", NULL,
63 GDA_CONNECTION_OPTIONS_NONE, &error);
64 if (!cnc) {
65 g_print ("ERROR opening connection: %s\n",
66 error && error->message ? error->message : "No detail");
67 return 1;
68 }
69 tcnc = gda_connection_open_from_string ("SQlite", "DB_DIR=.;DB_NAME=testdb", NULL,
70 GDA_CONNECTION_OPTIONS_THREAD_ISOLATED, &error);
71 if (!tcnc) {
72 g_print ("ERROR opening connection in thread safe mode: %s\n",
73 error && error->message ? error->message : "No detail");
74 return 1;
75 }
76
77 test_cnc_obj (tcnc);
78 test_cnc_status (tcnc, TRUE);
79 gda_connection_close (tcnc);
80 test_cnc_status (tcnc, FALSE);
81 gda_connection_open (tcnc, NULL);
82 test_cnc_status (tcnc, TRUE);
83
84 ntests ++;
85 failures += test_select (cnc, tcnc);
86
87 ntests ++;
88 failures += test_select_cursor (cnc, tcnc);
89
90 ntests ++;
91 failures += test_insert (tcnc);
92 failures += test_select (cnc, tcnc);
93 failures += test_select_cursor (cnc, tcnc);
94
95 ntests ++;
96 failures += test_update (tcnc);
97 failures += test_select (cnc, tcnc);
98 failures += test_select_cursor (cnc, tcnc);
99
100 ntests ++;
101 failures += test_delete (tcnc);
102 failures += test_select (cnc, tcnc);
103 failures += test_select_cursor (cnc, tcnc);
104
105 ntests ++;
106 failures += test_meta_data (cnc, tcnc);
107
108 ntests ++;
109 failures += test_meta_store (cnc);
110
111 ntests ++;
112 failures += test_signals (cnc, tcnc);
113
114 /* get rid of connection */
115 g_object_unref (cnc);
116 g_object_unref (tcnc);
117 g_usleep (300000);
118
119 g_print ("TESTS COUNT: %d\n", ntests);
120 g_print ("FAILURES: %d\n", failures);
121
122 return failures != 0 ? 1 : 0;
123 }
124
125 static void
test_cnc_obj(GdaConnection * tcnc)126 test_cnc_obj (GdaConnection *tcnc)
127 {
128 gboolean is_wrapper;
129 g_object_get (G_OBJECT (tcnc), "is-wrapper", &is_wrapper, NULL);
130 if (!is_wrapper) {
131 g_print ("ERROR: connection is not a connection wrapper\n");
132 exit (1);
133 }
134 }
135
136 static void
test_cnc_status(GdaConnection * tcnc,gboolean opened)137 test_cnc_status (GdaConnection *tcnc, gboolean opened)
138 {
139 if (gda_connection_is_opened (tcnc) != opened) {
140 g_print ("ERROR: connection is %s, expecting it %s\n",
141 gda_connection_is_opened (tcnc) ? "Opened" : "Closed",
142 opened ? "Opened" : "Closed");
143 exit (1);
144 }
145 }
146
147 static gint
test_select(GdaConnection * cnc,GdaConnection * tcnc)148 test_select (GdaConnection *cnc, GdaConnection *tcnc)
149 {
150 /* execute statement */
151 gint failures = 0;
152 GdaDataModel *model, *tmodel;
153
154 model = run_sql_select (cnc, "SELECT * FROM person");
155 tmodel = run_sql_select (tcnc, "SELECT * FROM person");
156 if (! data_models_equal (model, tmodel))
157 failures ++;
158
159 if (strcmp (G_OBJECT_TYPE_NAME (tmodel), "GdaThreadRecordset")) {
160 g_print ("ERROR: data model from SELECT's type is '%s' and not 'GdaThreadRecordset'\n",
161 G_OBJECT_TYPE_NAME (tmodel));
162 exit (1);
163 }
164 if (gda_data_select_get_connection (GDA_DATA_SELECT (tmodel)) != tcnc) {
165 g_print ("ERROR: %s() returned wrong result\n", "gda_data_select_get_connection");
166 failures ++;
167 }
168
169 GdaDataModelIter *iter;
170 GdaDataModelIter *titer;
171 iter = gda_data_model_create_iter (model);
172 titer = gda_data_model_create_iter (tmodel);
173 if (!titer) {
174 g_print ("ERROR: %s() returned NULL\n", "gda_data_model_create_iter");
175 failures ++;
176 }
177 else {
178 GdaDataModel *m1;
179 g_object_get (G_OBJECT (titer), "data-model", &m1, NULL);
180 if (m1 != tmodel) {
181 g_print ("ERROR: \"data-model\" property of created iterator is wrong\n");
182 failures ++;
183 }
184 g_object_unref (m1);
185
186 /* check iter's contents */
187 guint ncols;
188 ncols = g_slist_length (GDA_SET (titer)->holders);
189 if (ncols != g_slist_length (GDA_SET (iter)->holders)) {
190 g_print ("ERROR: threaded iterator is at the wrong number of columns: "
191 "%d when it should be at %d\n",
192 ncols, g_slist_length (GDA_SET (iter)->holders));
193 failures ++;
194 ncols = -1;
195 }
196 else
197 g_assert (ncols > 0);
198
199 /* forward */
200 if (gda_data_model_iter_is_valid (titer)) {
201 g_print ("ERROR: threaded iterator is valid before any read\n");
202 failures ++;
203 }
204 if (gda_data_model_iter_is_valid (iter)) {
205 g_print ("ERROR: iterator is valid before any read\n");
206 failures ++;
207 }
208 gint row;
209 gboolean iterok;
210 iterok = gda_data_model_iter_move_next (iter);
211 iterok = gda_data_model_iter_move_next (titer) | iterok;
212 for (row = 0; iterok; row++) {
213 if (gda_data_model_iter_get_row (titer) != gda_data_model_iter_get_row (iter)) {
214 g_print ("ERROR: threaded iterator is at the wrong row: %d when it should be at %d\n",
215 gda_data_model_iter_get_row (titer), gda_data_model_iter_get_row (iter));
216 failures ++;
217 break;
218 }
219 if (ncols > 0) {
220 guint i;
221 for (i = 0; i < ncols; i++) {
222 const GValue *cv, *tcv;
223 cv = gda_data_model_iter_get_value_at (iter, i);
224 tcv = gda_data_model_iter_get_value_at (titer, i);
225 if (gda_value_differ (cv, tcv)) {
226 g_print ("ERROR: values in iterators differ at line %d, colunm %d\n",
227 row, i);
228 failures ++;
229 }
230 //g_print ("%d,%d: %s\n", row, i, gda_value_stringify (tcv));
231 }
232 }
233 gboolean v, tv;
234 v = gda_data_model_iter_move_next (iter);
235 tv = gda_data_model_iter_move_next (titer);
236 if (!v || !tv)
237 break;
238 }
239 if (gda_data_model_iter_is_valid (titer)) {
240 g_print ("ERROR: threaded iterator is still valid\n");
241 failures ++;
242 }
243 if (gda_data_model_iter_is_valid (iter)) {
244 g_print ("ERROR: iterator is still valid\n");
245 failures ++;
246 }
247
248 /* backward */
249 for (; row >= 0; row--) {
250 iterok = gda_data_model_iter_move_next (iter);
251 iterok = gda_data_model_iter_move_next (titer) | iterok;
252 if (!iterok)
253 break;
254 }
255 for (row = 0; iterok; row++) {
256 if (gda_data_model_iter_get_row (titer) != gda_data_model_iter_get_row (iter)) {
257 g_print ("ERROR: threaded iterator is at the wrong row: %d when it should be at %d\n",
258 gda_data_model_iter_get_row (titer), gda_data_model_iter_get_row (iter));
259 failures ++;
260 break;
261 }
262 if (ncols > 0) {
263 guint i;
264 for (i = 0; i < ncols; i++) {
265 const GValue *cv, *tcv;
266 cv = gda_data_model_iter_get_value_at (iter, i);
267 tcv = gda_data_model_iter_get_value_at (titer, i);
268 if (gda_value_differ (cv, tcv)) {
269 g_print ("ERROR: values in iterators differ at line %d, colunm %d\n",
270 row, i);
271 failures ++;
272 }
273 //g_print ("%d,%d: %s\n", row, i, gda_value_stringify (tcv));
274 }
275 }
276 gboolean v, tv;
277 v = gda_data_model_iter_move_prev (iter);
278 tv = gda_data_model_iter_move_prev (titer);
279 if (!v || !tv)
280 break;
281 }
282 if (gda_data_model_iter_is_valid (titer)) {
283 g_print ("ERROR: threaded iterator is still valid\n");
284 failures ++;
285 }
286 if (gda_data_model_iter_is_valid (iter)) {
287 g_print ("ERROR: iterator is still valid\n");
288 failures ++;
289 }
290
291 g_object_unref (iter);
292 g_object_unref (titer);
293 }
294
295 g_object_unref (model);
296 g_object_unref (tmodel);
297
298 return failures;
299 }
300
301 static gint
test_select_cursor(GdaConnection * cnc,GdaConnection * tcnc)302 test_select_cursor (GdaConnection *cnc, GdaConnection *tcnc)
303 {
304 /* execute statement */
305 gint failures = 0;
306 GdaDataModel *model, *tmodel;
307
308 model = run_sql_select_cursor (cnc, "SELECT * FROM person");
309 tmodel = run_sql_select_cursor (tcnc, "SELECT * FROM person");
310
311 if (gda_data_model_get_access_flags (model) !=
312 gda_data_model_get_access_flags (tmodel)) {
313 g_print ("ERROR: data models' access flags differ: %d and %d for threaded model\n",
314 gda_data_model_get_access_flags (model),
315 gda_data_model_get_access_flags (tmodel));
316 failures ++;
317 return failures;
318 }
319
320 if (strcmp (G_OBJECT_TYPE_NAME (tmodel), "GdaThreadRecordset")) {
321 g_print ("ERROR: data model from SELECT's type is '%s' and not 'GdaThreadRecordset'\n",
322 G_OBJECT_TYPE_NAME (tmodel));
323 exit (1);
324 }
325 if (gda_data_select_get_connection (GDA_DATA_SELECT (tmodel)) != tcnc) {
326 g_print ("ERROR: %s() returned wrong result\n", "gda_data_select_get_connection");
327 failures ++;
328 }
329
330 GdaDataModelIter *iter, *titer;
331 iter = gda_data_model_create_iter (model);
332 titer = gda_data_model_create_iter (tmodel);
333 if (!titer) {
334 g_print ("ERROR: %s() returned NULL\n", "gda_data_model_create_iter");
335 failures ++;
336 }
337 else {
338 /* iter's properties */
339 GdaDataModel *m1;
340 g_object_get (G_OBJECT (titer), "data-model", &m1, NULL);
341 if (m1 != tmodel) {
342 g_print ("ERROR: \"data-model\" property of created iterator is wrong\n");
343 failures ++;
344 }
345 g_object_unref (m1);
346
347 /* check iter's contents */
348 guint ncols;
349 ncols = g_slist_length (GDA_SET (titer)->holders);
350 if (ncols != g_slist_length (GDA_SET (iter)->holders)) {
351 g_print ("ERROR: threaded iterator is at the wrong number of columns: "
352 "%d when it should be at %d\n",
353 ncols, g_slist_length (GDA_SET (iter)->holders));
354 failures ++;
355 ncols = -1;
356 }
357 else
358 g_assert (ncols > 0);
359
360
361 if (gda_data_model_iter_is_valid (titer)) {
362 g_print ("ERROR: threaded iterator is valid before any read\n");
363 failures ++;
364 }
365 if (gda_data_model_iter_is_valid (iter)) {
366 g_print ("ERROR: iterator is valid before any read\n");
367 failures ++;
368 }
369 gint row;
370 gda_data_model_iter_move_next (iter);
371 gda_data_model_iter_move_next (titer);
372 for (row = 0; ; row++) {
373 if (gda_data_model_iter_get_row (titer) != gda_data_model_iter_get_row (iter)) {
374 g_print ("ERROR: threaded iterator is at the wrong row: %d when it should be at %d\n",
375 gda_data_model_iter_get_row (titer), gda_data_model_iter_get_row (iter));
376 failures ++;
377 break;
378 }
379 if (ncols > 0) {
380 guint i;
381 for (i = 0; i < ncols; i++) {
382 const GValue *cv, *tcv;
383 cv = gda_data_model_iter_get_value_at (iter, i);
384 tcv = gda_data_model_iter_get_value_at (titer, i);
385 if (gda_value_differ (cv, tcv)) {
386 g_print ("ERROR: values in iterators differ at line %d, colunm %d\n",
387 row, i);
388 failures ++;
389 }
390 //g_print ("%d,%d: %s\n", row, i, gda_value_stringify (tcv));
391 }
392 }
393 gboolean v, tv;
394 v = gda_data_model_iter_move_next (iter);
395 tv = gda_data_model_iter_move_next (titer);
396 if (!v || !tv)
397 break;
398 }
399 if (gda_data_model_iter_is_valid (titer)) {
400 g_print ("ERROR: threaded iterator is still valid\n");
401 failures ++;
402 }
403 if (gda_data_model_iter_is_valid (iter)) {
404 g_print ("ERROR: iterator is still valid\n");
405 failures ++;
406 }
407
408 g_object_unref (iter);
409 g_object_unref (titer);
410 }
411
412 g_object_unref (model);
413 g_object_unref (tmodel);
414
415 return failures;
416 }
417
418 static gint
test_insert(GdaConnection * tcnc)419 test_insert (GdaConnection *tcnc)
420 {
421 gint failures = 0;
422 if (!run_sql_non_select (tcnc, "INSERT INTO person (name, age) VALUES ('Alice', 12)")) {
423 g_print ("ERROR: can't INSERT into threaded connection\n");
424 failures ++;
425 }
426 return failures;
427 }
428
429 static gint
test_update(GdaConnection * tcnc)430 test_update (GdaConnection *tcnc)
431 {
432 gint failures = 0;
433 if (!run_sql_non_select (tcnc, "UPDATE person set name='Alf' where name='Grat'")) {
434 g_print ("ERROR: can't UPDATE threaded connection\n");
435 failures ++;
436 }
437 return failures;
438 }
439
440 static gint
test_delete(GdaConnection * tcnc)441 test_delete (GdaConnection *tcnc)
442 {
443 gint failures = 0;
444 if (!run_sql_non_select (tcnc, "DELETE FROM person WHERE name='Alf'")) {
445 g_print ("ERROR: can't DELETE from threaded connection\n");
446 failures ++;
447 }
448 return failures;
449 }
450
451 static gint
test_meta_store(GdaConnection * cnc)452 test_meta_store (GdaConnection *cnc)
453 {
454 GdaMetaStore *store;
455 GdaConnection *tcnc;
456 GError *error = NULL;
457
458 g_print ("=== Starting test where threaded connection is used internally by a meta store\n");
459 tcnc = gda_connection_open_from_string ("SQlite", "DB_DIR=.;DB_NAME=storedb", NULL,
460 GDA_CONNECTION_OPTIONS_THREAD_ISOLATED, &error);
461 if (!tcnc) {
462 g_print ("ERROR opening connection in thread safe mode: %s\n",
463 error && error->message ? error->message : "No detail");
464 return 1;
465 }
466
467 store = GDA_META_STORE (g_object_new (GDA_TYPE_META_STORE, "cnc", tcnc, NULL));
468 g_object_unref (tcnc);
469 g_object_set (G_OBJECT (cnc), "meta-store", store, NULL);
470 g_object_unref (store);
471
472 if (!gda_connection_update_meta_store (cnc, NULL, &error)) {
473 g_print ("ERROR in gda_connection_update_meta_store(): %s\n",
474 error && error->message ? error->message : "No detail");
475 return 1;
476 }
477
478 GdaDataModel *model;
479 model = gda_meta_store_extract (store, "SELECT * FROM _tables", NULL);
480 if (gda_data_model_get_n_rows (model) != 1) {
481 g_print ("ERROR in gda_connection_update_meta_store(): the _tables table "
482 "should have exactly 1 row\n");
483 g_object_unref (model);
484 return 1;
485 }
486 g_object_unref (model);
487
488 return 0;
489 }
490
491 static gint
compare_meta_data(GdaMetaStore * store1,GdaMetaStruct * mstruct1,GdaMetaStore * store2,GdaMetaStruct * mstruct2)492 compare_meta_data (GdaMetaStore *store1, GdaMetaStruct *mstruct1,
493 GdaMetaStore *store2, GdaMetaStruct *mstruct2)
494 {
495 GSList *all_dbo_list1, *all_dbo_list2, *list;
496
497 all_dbo_list1 = gda_meta_struct_get_all_db_objects (mstruct1);
498 all_dbo_list2 = gda_meta_struct_get_all_db_objects (mstruct2);
499
500 for (list = all_dbo_list1; list; list = list->next) {
501 GdaMetaDbObject *dbo1, *dbo2;
502 GValue *v1, *v2, *v3;
503 dbo1 = GDA_META_DB_OBJECT (list->data);
504
505 g_value_set_string ((v1 = gda_value_new (G_TYPE_STRING)), dbo1->obj_catalog);
506 g_value_set_string ((v2 = gda_value_new (G_TYPE_STRING)), dbo1->obj_schema);
507 g_value_set_string ((v3 = gda_value_new (G_TYPE_STRING)), dbo1->obj_name);
508 dbo2 = gda_meta_struct_get_db_object (mstruct2, v1, v2, v3);
509 gda_value_free (v1);
510 gda_value_free (v2);
511 gda_value_free (v3);
512 if (!dbo2) {
513 g_print ("Error: Could not find object %s.%s.%s\n",
514 dbo1->obj_catalog,
515 dbo1->obj_schema,
516 dbo1->obj_name);
517 return 1;
518 }
519
520 if (dbo1->obj_type != GDA_META_DB_TABLE)
521 continue;
522
523 g_print ("Checking meta store's table: %s\n", dbo1->obj_name);
524
525 GdaDataModel *m1, *m2;
526 gchar *str;
527 str = g_strdup_printf ("SELECT * FROM %s", dbo1->obj_name);
528 m1 = gda_meta_store_extract (store1, str, NULL);
529 m2 = gda_meta_store_extract (store2, str, NULL);
530 g_free (str);
531
532 GdaDataComparator *cmp;
533 GError *error = NULL;
534 cmp = (GdaDataComparator*) gda_data_comparator_new (m1, m2);
535 g_object_unref (m1);
536 g_object_unref (m2);
537 if (! gda_data_comparator_compute_diff (cmp, &error)) {
538 g_print ("Can't compute data model differences for %s.%s.%s: %s\n",
539 dbo1->obj_catalog,
540 dbo1->obj_schema,
541 dbo1->obj_name,
542 error && error->message ? error->message : "No detail");
543 g_object_unref (cmp);
544 return 1;
545 }
546 if (gda_data_comparator_get_n_diffs (cmp) != 0) {
547 g_print ("There are some data model differences!\n");
548 g_object_unref (cmp);
549 return 1;
550 }
551 g_object_unref (cmp);
552 }
553
554 g_slist_free (all_dbo_list1);
555 g_slist_free (all_dbo_list2);
556
557 return 0;
558 }
559
560 static gint
test_meta_data(GdaConnection * cnc,GdaConnection * tcnc)561 test_meta_data (GdaConnection *cnc, GdaConnection *tcnc)
562 {
563 GError *error = NULL;
564
565 g_print ("=== Starting test where updating the threaded connection's meta data\n");
566 if (!gda_connection_update_meta_store (tcnc, NULL, &error)) {
567 g_print ("ERROR in gda_connection_update_meta_store() applied to threaded connection: %s\n",
568 error && error->message ? error->message : "No detail");
569 return 1;
570 }
571 if (!gda_connection_update_meta_store (cnc, NULL, &error)) {
572 g_print ("ERROR in gda_connection_update_meta_store() applied to non threaded connection: %s\n",
573 error && error->message ? error->message : "No detail");
574 return 1;
575 }
576
577 GdaMetaStruct *mstruct, *tmstruct;
578 mstruct = gda_meta_store_schema_get_structure (gda_connection_get_meta_store (cnc), NULL);
579 tmstruct = gda_meta_store_schema_get_structure (gda_connection_get_meta_store (tcnc), NULL);
580 g_assert (mstruct);
581 g_assert (tmstruct);
582
583 return compare_meta_data (gda_connection_get_meta_store (cnc), mstruct,
584 gda_connection_get_meta_store (tcnc), tmstruct);
585 }
586
587
588 static void test_sig_error_cb (GdaConnection *cnc, GdaConnectionEvent *error, GdaConnectionEvent **ev);
589 static void test_sig_bool_cb (GdaConnection *cnc, gboolean *out_called);
590 static gint
test_signals(GdaConnection * cnc,GdaConnection * tcnc)591 test_signals (GdaConnection *cnc, GdaConnection *tcnc)
592 {
593 gint failures = 0;
594
595 /* test the "error" signal */
596 GdaConnectionEvent *ev = NULL, *tev = NULL;
597 g_signal_connect (G_OBJECT (cnc), "error",
598 G_CALLBACK (test_sig_error_cb), &ev);
599 g_signal_connect (G_OBJECT (tcnc), "error",
600 G_CALLBACK (test_sig_error_cb), &tev);
601 run_sql_non_select (cnc, "DELETE FROM person WHERE name = ##name::string");
602 run_sql_non_select (tcnc, "DELETE FROM person WHERE name = ##name::string");
603
604 g_assert (ev);
605 if (!tev) {
606 g_print ("ERROR: the threaded connection does not emit the \"error\" signal\n");
607 return 1;
608 }
609
610 /* test the "conn_to_close" and "conn-closed" signal */
611 gboolean called = FALSE, called2 = FALSE;
612 g_signal_connect (G_OBJECT (tcnc), "conn-to-close",
613 G_CALLBACK (test_sig_bool_cb), &called);
614 g_signal_connect (G_OBJECT (tcnc), "conn-closed",
615 G_CALLBACK (test_sig_bool_cb), &called2);
616 gda_connection_close (tcnc);
617 if (!called) {
618 g_print ("ERROR: the threaded connection does not emit the \"conn-to-close\" signal\n");
619 return 1;
620 }
621 if (!called2) {
622 g_print ("ERROR: the threaded connection does not emit the \"conn-closed\" signal\n");
623 return 1;
624 }
625 g_signal_handlers_disconnect_by_func (G_OBJECT (tcnc),
626 G_CALLBACK (test_sig_bool_cb), &called);
627 g_signal_handlers_disconnect_by_func (G_OBJECT (tcnc),
628 G_CALLBACK (test_sig_bool_cb), &called2);
629
630 /* test the "conn-opened" signal */
631 called = FALSE;
632 g_signal_connect (G_OBJECT (tcnc), "conn-opened",
633 G_CALLBACK (test_sig_bool_cb), &called);
634 gda_connection_open (tcnc, NULL);
635 g_assert (gda_connection_is_opened (tcnc));
636 if (!called) {
637 g_print ("ERROR: the threaded connection does not emit the \"conn-opened\" signal\n");
638 return 1;
639 }
640 g_signal_handlers_disconnect_by_func (G_OBJECT (tcnc),
641 G_CALLBACK (test_sig_bool_cb), &called);
642
643 /* test the "transaction-status-changed" signal */
644 called = FALSE;
645 g_signal_connect (G_OBJECT (tcnc), "transaction-status-changed",
646 G_CALLBACK (test_sig_bool_cb), &called);
647 g_assert (gda_connection_begin_transaction (tcnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL));
648 if (!called) {
649 g_print ("ERROR: the threaded connection does not emit the \"transaction-status-changed\" signal\n");
650 return 1;
651 }
652 g_signal_handlers_disconnect_by_func (G_OBJECT (tcnc),
653 G_CALLBACK (test_sig_bool_cb), &called);
654
655 /* test the "dsn_changed" signal */
656 called = FALSE;
657 gda_connection_close (tcnc);
658 if (gda_config_get_dsn_info ("SalesTest")) {
659 g_signal_connect (G_OBJECT (tcnc), "dsn-changed",
660 G_CALLBACK (test_sig_bool_cb), &called);
661 g_object_set (G_OBJECT (tcnc), "dsn", "SalesTest", NULL);
662 if (!called) {
663 g_print ("ERROR: the threaded connection does not emit the \"dsn-changed\" signal\n");
664 return 1;
665 }
666 g_signal_handlers_disconnect_by_func (G_OBJECT (tcnc),
667 G_CALLBACK (test_sig_bool_cb), &called);
668 }
669
670 return failures;
671 }
672
673 static void
test_sig_error_cb(GdaConnection * cnc,GdaConnectionEvent * error,GdaConnectionEvent ** ev)674 test_sig_error_cb (GdaConnection *cnc, GdaConnectionEvent *error, GdaConnectionEvent **ev)
675 {
676 *ev = error;
677 }
678
679 static void
test_sig_bool_cb(GdaConnection * cnc,gboolean * out_called)680 test_sig_bool_cb (GdaConnection *cnc, gboolean *out_called)
681 {
682 *out_called = TRUE;
683 }
684