Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2011 Collabora Ltd.
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see
18 : * <http://www.gnu.org/licenses/>.
19 : *
20 : * Stef Walter <stefw@collabora.co.uk>
21 : */
22 :
23 : #include "config.h"
24 :
25 : #include "egg-testing.h"
26 :
27 : #include <glib/gstdio.h>
28 :
29 : #include <errno.h>
30 : #include <unistd.h>
31 :
32 : static const char HEXC[] = "0123456789ABCDEF";
33 :
34 : static gchar*
35 0 : hex_dump (const guchar *data, gsize n_data)
36 : {
37 : GString *result;
38 : gsize i;
39 : guchar j;
40 :
41 0 : g_assert (data);
42 :
43 0 : result = g_string_sized_new (n_data * 2 + 1);
44 0 : for (i = 0; i < n_data; ++i) {
45 0 : g_string_append (result, "\\x");
46 :
47 0 : j = data[i] >> 4 & 0xf;
48 0 : g_string_append_c (result, HEXC[j]);
49 0 : j = data[i] & 0xf;
50 0 : g_string_append_c (result, HEXC[j]);
51 : }
52 :
53 0 : return g_string_free (result, FALSE);
54 : }
55 :
56 : void
57 0 : egg_assertion_message_cmpmem (const char *domain,
58 : const char *file,
59 : int line,
60 : const char *func,
61 : const char *expr,
62 : gconstpointer arg1,
63 : gsize n_arg1,
64 : const char *cmp,
65 : gconstpointer arg2,
66 : gsize n_arg2)
67 : {
68 : char *a1, *a2, *s;
69 0 : a1 = arg1 ? hex_dump (arg1, n_arg1) : g_strdup ("NULL");
70 0 : a2 = arg2 ? hex_dump (arg2, n_arg2) : g_strdup ("NULL");
71 0 : s = g_strdup_printf ("assertion failed (%s): (%s %s %s)", expr, a1, cmp, a2);
72 0 : g_free (a1);
73 0 : g_free (a2);
74 0 : g_assertion_message (domain, file, line, func, s);
75 0 : g_free (s);
76 0 : }
77 :
78 : static void (*wait_stop_impl) (void);
79 : static gboolean (*wait_until_impl) (int timeout);
80 : static gboolean wait_waiting = FALSE;
81 :
82 : void
83 54 : egg_test_wait_stop (void)
84 : {
85 54 : g_assert (wait_stop_impl != NULL);
86 54 : (wait_stop_impl) ();
87 54 : }
88 :
89 : gboolean
90 60 : egg_test_wait_until (int timeout)
91 : {
92 60 : g_assert (wait_until_impl != NULL);
93 60 : return (wait_until_impl) (timeout);
94 : }
95 :
96 : static GCond wait_condition;
97 : static GCond wait_start;
98 : static GMutex wait_mutex;
99 :
100 : static void
101 0 : thread_wait_stop (void)
102 : {
103 0 : g_mutex_lock (&wait_mutex);
104 :
105 0 : if (!wait_waiting) {
106 0 : gint64 time = g_get_monotonic_time () + 1 * G_TIME_SPAN_SECOND;
107 0 : g_cond_wait_until (&wait_start, &wait_mutex, time);
108 : }
109 0 : g_assert (wait_waiting);
110 :
111 0 : g_cond_broadcast (&wait_condition);
112 0 : g_mutex_unlock (&wait_mutex);
113 0 : }
114 :
115 : static gboolean
116 6 : thread_wait_until (int timeout)
117 : {
118 : gboolean ret;
119 :
120 6 : g_mutex_lock (&wait_mutex);
121 :
122 6 : g_assert (!wait_waiting);
123 6 : wait_waiting = TRUE;
124 :
125 : {
126 6 : gint64 time = g_get_monotonic_time () + ((timeout + 1000) * G_TIME_SPAN_MILLISECOND);
127 6 : g_cond_broadcast (&wait_start);
128 6 : ret = g_cond_wait_until (&wait_start, &wait_mutex, time);
129 : }
130 :
131 6 : g_assert (wait_waiting);
132 6 : wait_waiting = FALSE;
133 6 : g_mutex_unlock (&wait_mutex);
134 :
135 6 : return ret;
136 : }
137 :
138 : static gpointer
139 14 : testing_thread (gpointer loop)
140 : {
141 : /* Must have been defined by the test including this file */
142 14 : gint ret = g_test_run ();
143 14 : g_main_loop_quit (loop);
144 14 : return GINT_TO_POINTER (ret);
145 : }
146 :
147 : gint
148 14 : egg_tests_run_in_thread_with_loop (void)
149 : {
150 : GThread *thread;
151 : GMainLoop *loop;
152 : gpointer ret;
153 :
154 14 : loop = g_main_loop_new (NULL, FALSE);
155 14 : g_cond_init (&wait_condition);
156 14 : g_cond_init (&wait_start);
157 14 : g_mutex_init (&wait_mutex);
158 :
159 14 : wait_stop_impl = thread_wait_stop;
160 14 : wait_until_impl = thread_wait_until;
161 :
162 14 : thread = g_thread_new ("testing", testing_thread, loop);
163 14 : g_assert (thread);
164 :
165 14 : g_main_loop_run (loop);
166 14 : ret = g_thread_join (thread);
167 14 : g_main_loop_unref (loop);
168 :
169 14 : g_cond_clear (&wait_condition);
170 14 : g_mutex_clear (&wait_mutex);
171 :
172 14 : return GPOINTER_TO_INT (ret);
173 : }
174 :
175 : static GMainLoop *wait_loop = NULL;
176 :
177 : static void
178 54 : loop_wait_stop (void)
179 : {
180 54 : g_assert (wait_loop != NULL);
181 54 : g_main_loop_quit (wait_loop);
182 54 : }
183 :
184 : static gboolean
185 0 : on_loop_wait_timeout (gpointer data)
186 : {
187 0 : gboolean *timed_out = data;
188 0 : *timed_out = TRUE;
189 :
190 0 : g_assert (wait_loop != NULL);
191 0 : g_main_loop_quit (wait_loop);
192 :
193 0 : return TRUE; /* we remove this source later */
194 : }
195 :
196 : static gboolean
197 54 : loop_wait_until (int timeout)
198 : {
199 54 : gboolean timed_out = FALSE;
200 : guint source;
201 :
202 54 : g_assert (wait_loop == NULL);
203 54 : wait_loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
204 :
205 54 : source = g_timeout_add (timeout, on_loop_wait_timeout, &timed_out);
206 :
207 54 : g_main_loop_run (wait_loop);
208 :
209 54 : g_source_remove (source);
210 54 : g_main_loop_unref (wait_loop);
211 54 : wait_loop = NULL;
212 54 : return !timed_out;
213 : }
214 :
215 : gint
216 5 : egg_tests_run_with_loop (void)
217 : {
218 : gint ret;
219 :
220 5 : wait_stop_impl = loop_wait_stop;
221 5 : wait_until_impl = loop_wait_until;
222 :
223 5 : ret = g_test_run ();
224 :
225 5 : wait_stop_impl = NULL;
226 5 : wait_until_impl = NULL;
227 :
228 5 : while (g_main_context_iteration (NULL, FALSE));
229 :
230 5 : return ret;
231 : }
232 :
233 : void
234 258 : egg_tests_copy_scratch_file (const gchar *directory,
235 : const gchar *filename)
236 : {
237 258 : GError *error = NULL;
238 : gchar *basename;
239 : gchar *contents;
240 : gchar *destination;
241 : gsize length;
242 :
243 258 : g_assert (directory);
244 :
245 258 : g_file_get_contents (filename, &contents, &length, &error);
246 258 : g_assert_no_error (error);
247 :
248 258 : basename = g_path_get_basename (filename);
249 258 : destination = g_build_filename (directory, basename, NULL);
250 258 : g_free (basename);
251 :
252 258 : g_file_set_contents (destination, contents, length, &error);
253 258 : g_assert_no_error (error);
254 258 : g_free (destination);
255 258 : g_free (contents);
256 258 : }
257 :
258 : gchar *
259 146 : egg_tests_create_scratch_directory (const gchar *file_to_copy,
260 : ...)
261 : {
262 : gchar *basename;
263 : gchar *directory;
264 : va_list va;
265 :
266 146 : basename = g_path_get_basename (g_get_prgname ());
267 146 : directory = g_strdup_printf ("/tmp/scratch-%s.XXXXXX", basename);
268 146 : g_free (basename);
269 :
270 146 : if (!g_mkdtemp (directory))
271 0 : g_assert_not_reached ();
272 :
273 146 : va_start (va, file_to_copy);
274 :
275 404 : while (file_to_copy != NULL) {
276 258 : egg_tests_copy_scratch_file (directory, file_to_copy);
277 258 : file_to_copy = va_arg (va, const gchar *);
278 : }
279 :
280 146 : va_end (va);
281 :
282 146 : return directory;
283 : }
284 :
285 : void
286 146 : egg_tests_remove_scratch_directory (const gchar *directory)
287 : {
288 146 : gchar *argv[] = { "rm", "-rf", (gchar *)directory, NULL };
289 146 : GError *error = NULL;
290 : gint rm_status;
291 :
292 146 : g_assert_cmpstr (directory, !=, "");
293 146 : g_assert_cmpstr (directory, !=, "/");
294 :
295 146 : g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
296 : NULL, NULL, NULL, &rm_status, &error);
297 146 : g_assert_no_error (error);
298 146 : g_assert_cmpint (rm_status, ==, 0);
299 146 : }
|