g_thread_init should be called before any other glib function.
[platform/upstream/libsoup.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-logger.h"
7 #include "libsoup/soup-misc.h"
8 #include "libsoup/soup-server.h"
9
10 #include <signal.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 #ifdef HAVE_APACHE
17 static gboolean apache_running;
18 #endif
19 static SoupServer *test_server;
20 GThread *server_thread;
21 static void test_server_shutdown (void);
22
23 static SoupLogger *logger;
24
25 int debug_level, http_debug_level, errors;
26
27 static gboolean
28 increment_debug_level (const char *option_name, const char *value,
29                        gpointer data, GError **error)
30 {
31         debug_level++;
32         return TRUE;
33 }
34
35 static gboolean
36 increment_http_debug_level (const char *option_name, const char *value,
37                             gpointer data, GError **error)
38 {
39         http_debug_level++;
40         return TRUE;
41 }
42
43 static GOptionEntry debug_entry[] = {
44         { "debug", 'd', G_OPTION_FLAG_NO_ARG,
45           G_OPTION_ARG_CALLBACK, increment_debug_level,
46           "Enable (or increase) test-specific debugging", NULL },
47         { "http-debug", 'h', G_OPTION_FLAG_NO_ARG,
48           G_OPTION_ARG_CALLBACK, increment_http_debug_level,
49           "Enable (or increase) HTTP-level debugging", NULL },
50         { NULL }
51 };
52
53 static void
54 quit (int sig)
55 {
56 #ifdef HAVE_APACHE
57         if (apache_running)
58                 apache_cleanup ();
59 #endif
60         if (test_server)
61                 test_server_shutdown ();
62
63         exit (1);
64 }
65
66 void
67 test_init (int argc, char **argv, GOptionEntry *entries)
68 {
69         GOptionContext *opts;
70         char *name;
71         GError *error = NULL;
72
73         g_thread_init (NULL);
74         g_type_init ();
75
76         name = strrchr (argv[0], '/');
77         if (!name++)
78                 name = argv[0];
79         if (!strncmp (name, "lt-", 3))
80                 name += 3;
81         g_set_prgname (name);
82
83         opts = g_option_context_new (NULL);
84         g_option_context_add_main_entries (opts, debug_entry, NULL);
85         if (entries)
86                 g_option_context_add_main_entries (opts, entries, NULL);
87
88         if (!g_option_context_parse (opts, &argc, &argv, &error)) {
89                 fprintf (stderr, "Could not parse arguments: %s\n",
90                          error->message);
91                 fprintf (stderr, "%s",
92                          g_option_context_get_help (opts, TRUE, NULL));
93                 exit (1);
94         }
95         g_option_context_free (opts);
96
97         /* Exit cleanly on ^C in case we're valgrinding. */
98         signal (SIGINT, quit);
99 }
100
101 void
102 test_cleanup (void)
103 {
104         debug_printf (1, "\n");
105         if (errors) {
106                 printf ("%s: %d error(s).%s\n",
107                         g_get_prgname (), errors,
108                         debug_level == 0 ? " Run with '-d' for details" : "");
109         } else
110                 printf ("%s: OK\n", g_get_prgname ());
111
112 #ifdef HAVE_APACHE
113         if (apache_running)
114                 apache_cleanup ();
115 #endif
116         if (test_server)
117                 test_server_shutdown ();
118
119         if (logger)
120                 g_object_unref (logger);
121
122         g_main_context_unref (g_main_context_default ());
123 }
124
125 void
126 debug_printf (int level, const char *format, ...)
127 {
128         va_list args;
129
130         if (debug_level < level)
131                 return;
132
133         va_start (args, format);
134         vprintf (format, args);
135         va_end (args);
136 }
137
138 #ifdef HAVE_APACHE
139
140 static gboolean
141 apache_cmd (char *cmd)
142 {
143         char *argv[8];
144         char *cwd, *conf;
145         int status;
146         gboolean ok;
147
148         cwd = g_get_current_dir ();
149         conf = g_build_filename (cwd, "httpd.conf", NULL);
150
151         argv[0] = APACHE_HTTPD;
152         argv[1] = "-d";
153         argv[2] = cwd;
154         argv[3] = "-f";
155         argv[4] = conf;
156         argv[5] = "-k";
157         argv[6] = cmd;
158         argv[7] = NULL;
159
160         ok = g_spawn_sync (cwd, argv, NULL, 0, NULL, NULL,
161                            NULL, NULL, &status, NULL);
162         if (ok)
163                 ok = (status == 0);
164
165         g_free (cwd);
166         g_free (conf);
167
168         return ok;
169 }
170
171 void
172 apache_init (void)
173 {
174         if (!apache_cmd ("start")) {
175                 fprintf (stderr, "Could not start apache\n");
176                 exit (1);
177         }
178         apache_running = TRUE;
179 }
180
181 void
182 apache_cleanup (void)
183 {
184         pid_t pid;
185         char *contents;
186
187         if (g_file_get_contents ("httpd.pid", &contents, NULL, NULL)) {
188                 pid = strtoul (contents, NULL, 10);
189                 g_free (contents);
190         } else
191                 pid = 0;
192
193         if (!apache_cmd ("graceful-stop"))
194                 return;
195         apache_running = FALSE;
196
197         if (pid) {
198                 while (kill (pid, 0) == 0)
199                         g_usleep (100);
200         }
201 }
202
203 #endif /* HAVE_APACHE */
204
205 SoupSession *
206 soup_test_session_new (GType type, ...)
207 {
208         va_list args;
209         const char *propname;
210         SoupSession *session;
211
212         va_start (args, type);
213         propname = va_arg (args, const char *);
214         session = (SoupSession *)g_object_new_valist (type, propname, args);
215         va_end (args);
216
217         if (http_debug_level && !logger) {
218                 SoupLoggerLogLevel level = MIN ((SoupLoggerLogLevel)http_debug_level, SOUP_LOGGER_LOG_BODY);
219
220                 logger = soup_logger_new (level, -1);
221         }
222
223         if (logger)
224                 soup_logger_attach (logger, session);
225
226         return session;
227 }
228
229 static gpointer run_server_thread (gpointer user_data);
230
231 SoupServer *
232 soup_test_server_new (gboolean in_own_thread)
233 {
234         GMainContext *async_context;
235
236         async_context = in_own_thread ? g_main_context_new () : NULL;
237         test_server = soup_server_new (SOUP_SERVER_ASYNC_CONTEXT, async_context,
238                                        NULL);
239         if (async_context)
240                 g_main_context_unref (async_context);
241
242         if (!test_server) {
243                 fprintf (stderr, "Unable to create server\n");
244                 exit (1);
245         }
246
247         if (in_own_thread) {
248                 server_thread = g_thread_create (run_server_thread, test_server,
249                                                  TRUE, NULL);
250         } else
251                 soup_server_run_async (test_server);
252
253         return test_server;
254 }
255
256 static gpointer
257 run_server_thread (gpointer user_data)
258 {
259         SoupServer *server = user_data;
260
261         soup_server_run (server);
262         return NULL;
263 }
264
265 static gboolean
266 idle_quit_server (gpointer server)
267 {
268         soup_server_quit (server);
269         return FALSE;
270 }
271
272 static void
273 test_server_shutdown (void)
274 {
275         if (server_thread) {
276                 soup_add_idle (soup_server_get_async_context (test_server),
277                                idle_quit_server, test_server);
278                 g_thread_join (server_thread);
279         } else
280                 soup_server_quit (test_server);
281         g_object_unref (test_server);
282 }
283
284