1 /*
2 * Copyright (C) 2008 - 2011 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 <libgda/libgda.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #define NTHREADS 3
24 #define DEBUG_PRINT
25 #undef DEBUG_PRINT
26
27
28 /*
29 * tests
30 */
31 typedef gboolean (*TestFunc) (GError **);
32 static gboolean test1 (GError **error);
33 static gboolean test2 (GError **error);
34 static gboolean test3 (GError **error);
35
36 TestFunc tests[] = {
37 test1,
38 test2,
39 test3
40 };
41
42 int
main(int argc,char ** argv)43 main (int argc, char** argv)
44 {
45 #if GLIB_CHECK_VERSION(2,36,0)
46 #else
47 g_type_init ();
48 #endif
49 gda_init ();
50
51 gint failures = 0;
52 gint j, ntests = 0;;
53 for (j = 0; j < 10; j++) {
54 guint i;
55
56 for (i = 0; i < sizeof (tests) / sizeof (TestFunc); i++) {
57 GError *error = NULL;
58 if (! tests[i] (&error)) {
59 g_print ("Test %d failed: %s\n", i+1,
60 error && error->message ? error->message : "No detail");
61 if (error)
62 g_error_free (error);
63 failures ++;
64 }
65 ntests ++;
66 }
67 }
68
69 g_print ("TESTS COUNT: %d\n", ntests);
70 g_print ("FAILURES: %d\n", failures);
71
72 return failures != 0 ? 1 : 0;
73 }
74
75 typedef struct {
76 GThread *thread;
77 gint th_id;
78 gboolean finished;
79 GdaMutex *mutex;
80 } ThData;
81
82 static gboolean
test_multiple_threads(GThreadFunc func,GError ** error)83 test_multiple_threads (GThreadFunc func, GError **error)
84 {
85 GdaMutex *mutex;
86 ThData data[NTHREADS];
87 gint i;
88
89 mutex = gda_mutex_new ();
90
91 for (i = 0; i < NTHREADS; i++) {
92 ThData *d = &(data[i]);
93 d->th_id = i;
94 d->mutex = mutex;
95 d->finished = FALSE;
96 }
97
98 for (i = 0; i < NTHREADS; i++) {
99 ThData *d = &(data[i]);
100 #ifdef DEBUG_PRINT
101 g_print ("Running thread %d\n", d->th_id);
102 #endif
103 d->thread = g_thread_create (func, d, TRUE, NULL);
104 }
105
106 /* wait a bit */
107 usleep (100000);
108
109 for (i = 0; i < NTHREADS; i++) {
110 ThData *d = &(data[i]);
111 if (!d->finished) {
112 /* there are some threads locked somethere */
113 exit (EXIT_FAILURE);
114 }
115 else
116 g_thread_join (d->thread);
117 }
118
119 gda_mutex_free (mutex);
120
121 return TRUE;
122 }
123
124 /*
125 * Creation and destruction test
126 */
127 static gboolean
test1(GError ** error)128 test1 (GError **error)
129 {
130 GdaMutex *mutex;
131
132 mutex = gda_mutex_new ();
133 gda_mutex_free (mutex);
134
135 return TRUE;
136 }
137
138 /*
139 * Twice locking
140 */
141 gpointer
test2_start_thread(ThData * data)142 test2_start_thread (ThData *data)
143 {
144 gda_mutex_lock (data->mutex);
145 #ifdef DEBUG_PRINT
146 g_print ("Mutex locked for %d\n", data->th_id);
147 #endif
148 g_thread_yield ();
149 gda_mutex_lock (data->mutex);
150 #ifdef DEBUG_PRINT
151 g_print ("Mutex re-locked for %d\n", data->th_id);
152 #endif
153 gda_mutex_unlock (data->mutex);
154 #ifdef DEBUG_PRINT
155 g_print ("Mutex unlocked for %d\n", data->th_id);
156 g_print ("Mutex unlocked for %d\n", data->th_id);
157 #endif
158 gda_mutex_unlock (data->mutex);
159 data->finished = TRUE;
160 return NULL;
161 }
162
163 static gboolean
test2(GError ** error)164 test2 (GError **error)
165 {
166 return test_multiple_threads ((GThreadFunc) test2_start_thread, error);
167 }
168
169 /*
170 * Try lock
171 */
172 gpointer
test3_start_thread(ThData * data)173 test3_start_thread (ThData *data)
174 {
175 gboolean tried = FALSE;
176 while (!tried) {
177 tried = gda_mutex_trylock (data->mutex);
178 #ifdef DEBUG_PRINT
179 g_print ("TRY for %d: %s\n", data->th_id, tried ? "got it" : "no luck");
180 #endif
181 g_thread_yield ();
182 }
183 #ifdef DEBUG_PRINT
184 g_print ("Mutex locked for %d\n", data->th_id);
185 #endif
186 g_thread_yield ();
187 gda_mutex_lock (data->mutex);
188 #ifdef DEBUG_PRINT
189 g_print ("Mutex re-locked for %d\n", data->th_id);
190 #endif
191 gda_mutex_unlock (data->mutex);
192 #ifdef DEBUG_PRINT
193 g_print ("Mutex unlocked for %d\n", data->th_id);
194 g_print ("Mutex unlocked for %d\n", data->th_id);
195 #endif
196 gda_mutex_unlock (data->mutex);
197 data->finished = TRUE;
198 return NULL;
199 }
200
201 static gboolean
test3(GError ** error)202 test3 (GError **error)
203 {
204 return test_multiple_threads ((GThreadFunc) test3_start_thread, error);
205 }
206