Update to version 2.39.3
[profile/ivi/libsoup2.4.git] / tests / test-utils.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "test-utils.h"
6 #include "libsoup/soup.h"
7
8 #include <locale.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14
15 #ifdef HAVE_APACHE
16 static gboolean apache_running;
17 #endif
18
19 static SoupLogger *logger;
20
21 int debug_level, errors;
22 gboolean expect_warning, tls_available;
23 static int http_debug_level;
24
25 static gboolean
26 increment_debug_level (const char *option_name, const char *value,
27                        gpointer data, GError **error)
28 {
29         debug_level++;
30         return TRUE;
31 }
32
33 static gboolean
34 increment_http_debug_level (const char *option_name, const char *value,
35                             gpointer data, GError **error)
36 {
37         http_debug_level++;
38         return TRUE;
39 }
40
41 static GOptionEntry debug_entry[] = {
42         { "debug", 'd', G_OPTION_FLAG_NO_ARG,
43           G_OPTION_ARG_CALLBACK, increment_debug_level,
44           "Enable (or increase) test-specific debugging", NULL },
45         { "http-debug", 'h', G_OPTION_FLAG_NO_ARG,
46           G_OPTION_ARG_CALLBACK, increment_http_debug_level,
47           "Enable (or increase) HTTP-level debugging", NULL },
48         { NULL }
49 };
50
51 static void
52 quit (int sig)
53 {
54 #ifdef HAVE_APACHE
55         if (apache_running)
56                 apache_cleanup ();
57 #endif
58
59         exit (1);
60 }
61
62 static void
63 test_log_handler (const char *log_domain, GLogLevelFlags log_level,
64                   const char *message, gpointer user_data)
65 {
66         if (log_level & (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL)) {
67                 if (expect_warning) {
68                         expect_warning = FALSE;
69                         debug_printf (2, "Got expected warning: %s\n", message);
70                         return;
71                 } else
72                         errors++;
73         }
74         g_log_default_handler (log_domain, log_level, message, user_data);
75 }
76
77 void
78 test_init (int argc, char **argv, GOptionEntry *entries)
79 {
80         GOptionContext *opts;
81         char *name;
82         GError *error = NULL;
83         GTlsBackend *tls_backend;
84
85         setlocale (LC_ALL, "");
86         g_type_init ();
87
88         name = strrchr (argv[0], '/');
89         if (!name++)
90                 name = argv[0];
91         if (!strncmp (name, "lt-", 3))
92                 name += 3;
93         g_set_prgname (name);
94
95         opts = g_option_context_new (NULL);
96         g_option_context_add_main_entries (opts, debug_entry, NULL);
97         if (entries)
98                 g_option_context_add_main_entries (opts, entries, NULL);
99
100         if (!g_option_context_parse (opts, &argc, &argv, &error)) {
101                 fprintf (stderr, "Could not parse arguments: %s\n",
102                          error->message);
103                 fprintf (stderr, "%s",
104                          g_option_context_get_help (opts, TRUE, NULL));
105                 exit (1);
106         }
107         g_option_context_free (opts);
108
109         /* Exit cleanly on ^C in case we're valgrinding. */
110         signal (SIGINT, quit);
111
112         g_log_set_default_handler (test_log_handler, NULL);
113
114         tls_backend = g_tls_backend_get_default ();
115         tls_available = g_tls_backend_supports_tls (tls_backend);
116 }
117
118 void
119 test_cleanup (void)
120 {
121 #ifdef HAVE_APACHE
122         if (apache_running)
123                 apache_cleanup ();
124 #endif
125
126         if (logger)
127                 g_object_unref (logger);
128
129         g_main_context_unref (g_main_context_default ());
130
131         debug_printf (1, "\n");
132         if (errors) {
133                 printf ("%s: %d error(s).%s\n",
134                         g_get_prgname (), errors,
135                         debug_level == 0 ? " Run with '-d' for details" : "");
136         } else
137                 printf ("%s: OK\n", g_get_prgname ());
138 }
139
140 void
141 debug_printf (int level, const char *format, ...)
142 {
143         va_list args;
144
145         if (debug_level < level)
146                 return;
147
148         va_start (args, format);
149         vprintf (format, args);
150         va_end (args);
151 }
152
153 #ifdef HAVE_APACHE
154
155 static gboolean
156 apache_cmd (const char *cmd)
157 {
158         const char *argv[8];
159         char *cwd, *conf;
160         int status;
161         gboolean ok;
162
163         cwd = g_get_current_dir ();
164         conf = g_build_filename (cwd, "httpd.conf", NULL);
165
166         argv[0] = APACHE_HTTPD;
167         argv[1] = "-d";
168         argv[2] = cwd;
169         argv[3] = "-f";
170         argv[4] = conf;
171         argv[5] = "-k";
172         argv[6] = cmd;
173         argv[7] = NULL;
174
175         ok = g_spawn_sync (cwd, (char **)argv, NULL, 0, NULL, NULL,
176                            NULL, NULL, &status, NULL);
177         if (ok)
178                 ok = (status == 0);
179
180         g_free (cwd);
181         g_free (conf);
182
183         return ok;
184 }
185
186 void
187 apache_init (void)
188 {
189         if (!apache_cmd ("start")) {
190                 fprintf (stderr, "Could not start apache\n");
191                 exit (1);
192         }
193         apache_running = TRUE;
194 }
195
196 void
197 apache_cleanup (void)
198 {
199         pid_t pid;
200         char *contents;
201
202         if (g_file_get_contents ("httpd.pid", &contents, NULL, NULL)) {
203                 pid = strtoul (contents, NULL, 10);
204                 g_free (contents);
205         } else
206                 pid = 0;
207
208         if (!apache_cmd ("graceful-stop"))
209                 return;
210         apache_running = FALSE;
211
212         if (pid) {
213                 while (kill (pid, 0) == 0)
214                         g_usleep (100);
215         }
216 }
217
218 #endif /* HAVE_APACHE */
219
220 SoupSession *
221 soup_test_session_new (GType type, ...)
222 {
223         va_list args;
224         const char *propname;
225         SoupSession *session;
226
227         va_start (args, type);
228         propname = va_arg (args, const char *);
229         session = (SoupSession *)g_object_new_valist (type, propname, args);
230         va_end (args);
231
232         g_object_set (G_OBJECT (session),
233                       SOUP_SESSION_SSL_CA_FILE, SRCDIR "/test-cert.pem",
234                       NULL);
235
236         if (http_debug_level && !logger) {
237                 SoupLoggerLogLevel level = MIN ((SoupLoggerLogLevel)http_debug_level, SOUP_LOGGER_LOG_BODY);
238
239                 logger = soup_logger_new (level, -1);
240         }
241
242         if (logger)
243                 soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));
244
245         return session;
246 }
247
248 void
249 soup_test_session_abort_unref (SoupSession *session)
250 {
251         g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session);
252
253         soup_session_abort (session);
254         g_object_unref (session);
255
256         if (session) {
257                 errors++;
258                 debug_printf (1, "leaked SoupSession!\n");
259                 g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session);
260         }
261 }
262
263 static gpointer run_server_thread (gpointer user_data);
264
265 static SoupServer *
266 test_server_new (gboolean in_own_thread, gboolean ssl)
267 {
268         SoupServer *server;
269         GMainContext *async_context;
270         const char *ssl_cert_file, *ssl_key_file;
271         SoupAddress *addr;
272
273         async_context = in_own_thread ? g_main_context_new () : NULL;
274
275         if (ssl) {
276                 ssl_cert_file = SRCDIR "/test-cert.pem";
277                 ssl_key_file = SRCDIR "/test-key.pem";
278         } else
279                 ssl_cert_file = ssl_key_file = NULL;
280
281         addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT);
282         soup_address_resolve_sync (addr, NULL);
283
284         server = soup_server_new (SOUP_SERVER_INTERFACE, addr,
285                                   SOUP_SERVER_ASYNC_CONTEXT, async_context,
286                                   SOUP_SERVER_SSL_CERT_FILE, ssl_cert_file,
287                                   SOUP_SERVER_SSL_KEY_FILE, ssl_key_file,
288                                   NULL);
289         g_object_unref (addr);
290         if (async_context)
291                 g_main_context_unref (async_context);
292
293         if (!server) {
294                 fprintf (stderr, "Unable to create server\n");
295                 exit (1);
296         }
297
298         if (in_own_thread) {
299                 GThread *thread;
300
301                 thread = g_thread_new ("server_thread", run_server_thread, server);
302                 g_object_set_data (G_OBJECT (server), "thread", thread);
303         } else
304                 soup_server_run_async (server);
305
306         return server;
307 }
308
309 SoupServer *
310 soup_test_server_new (gboolean in_own_thread)
311 {
312         return test_server_new (in_own_thread, FALSE);
313 }
314
315 SoupServer *
316 soup_test_server_new_ssl (gboolean in_own_thread)
317 {
318         return test_server_new (in_own_thread, TRUE);
319 }
320
321 static gpointer
322 run_server_thread (gpointer user_data)
323 {
324         SoupServer *server = user_data;
325
326         soup_server_run (server);
327         return NULL;
328 }
329
330 static gboolean
331 idle_quit_server (gpointer server)
332 {
333         soup_server_quit (server);
334         return FALSE;
335 }
336
337 void
338 soup_test_server_quit_unref (SoupServer *server)
339 {
340         GThread *thread;
341
342         g_object_add_weak_pointer (G_OBJECT (server),
343                                    (gpointer *)&server);
344
345         thread = g_object_get_data (G_OBJECT (server), "thread");
346         if (thread) {
347                 soup_add_completion (soup_server_get_async_context (server),
348                                      idle_quit_server, server);
349                 g_thread_join (thread);
350         } else
351                 soup_server_quit (server);
352         g_object_unref (server);
353
354         if (server) {
355                 errors++;
356                 debug_printf (1, "leaked SoupServer!\n");
357                 g_object_remove_weak_pointer (G_OBJECT (server),
358                                               (gpointer *)&server);
359         }
360 }