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