tests/get: use GProxyResolverDefault
[platform/upstream/libsoup.git] / tests / xmlrpc-server-test.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2008 Red Hat, Inc.
4  */
5
6 #include "config.h"
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/wait.h>
11
12 #include <libsoup/soup.h>
13
14 #include "test-utils.h"
15
16 #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
17 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
18 #endif
19
20 GMainLoop *loop;
21
22 static void
23 type_error (SoupMessage *msg, GType expected, GValueArray *params, int bad_value)
24 {
25         soup_xmlrpc_set_fault (msg,
26                                SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
27                                "Bad parameter #%d: expected %s, got %s",
28                                bad_value + 1, g_type_name (expected),
29                                g_type_name (G_VALUE_TYPE (&params->values[bad_value])));
30 }
31
32 static void
33 args_error (SoupMessage *msg, GValueArray *params, int expected)
34 {
35         soup_xmlrpc_set_fault (msg,
36                                SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
37                                "Wrong number of parameters: expected %d, got %d",
38                                expected, params->n_values);
39 }
40
41 static void
42 do_sum (SoupMessage *msg, GValueArray *params)
43 {
44         int sum = 0, i, val;
45         GValueArray *nums;
46
47         if (params->n_values != 1) {
48                 args_error (msg, params, 1);
49                 return;
50         }
51         if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &nums)) {
52                 type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
53                 return;
54         }
55
56         for (i = 0; i < nums->n_values; i++) {
57                 if (!soup_value_array_get_nth (nums, i, G_TYPE_INT, &val)) {
58                         type_error (msg, G_TYPE_INT, nums, i);
59                         return;
60                 }
61                 sum += val;
62         }
63
64         soup_xmlrpc_set_response (msg, G_TYPE_INT, sum);
65
66 }
67
68 static void
69 do_countBools (SoupMessage *msg, GValueArray *params)
70 {
71         int i, trues = 0, falses = 0;
72         GValueArray *bools;
73         GHashTable *ret = soup_value_hash_new ();
74         gboolean val;
75
76         if (params->n_values != 1) {
77                 args_error (msg, params, 1);
78                 return;
79         }
80         if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &bools)) {
81                 type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
82                 return;
83         }
84
85         for (i = 0; i < bools->n_values; i++) {
86                 if (!soup_value_array_get_nth (bools, i, G_TYPE_BOOLEAN, &val)) {
87                         type_error (msg, G_TYPE_BOOLEAN, params, i);
88                         return;
89                 }
90                 if (val)
91                         trues++;
92                 else
93                         falses++;
94         }
95
96         soup_value_hash_insert (ret, "true", G_TYPE_INT, trues);
97         soup_value_hash_insert (ret, "false", G_TYPE_INT, falses);
98         soup_xmlrpc_set_response (msg, G_TYPE_HASH_TABLE, ret);
99         g_hash_table_destroy (ret);
100
101 }
102
103 static void
104 do_md5sum (SoupMessage *msg, GValueArray *params)
105 {
106         GChecksum *checksum;
107         GByteArray *data, *digest;
108         gsize digest_len = 16;
109
110         if (params->n_values != 1) {
111                 args_error (msg, params, 1);
112                 return;
113         }
114
115         if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_BYTE_ARRAY, &data)) {
116                 type_error (msg, SOUP_TYPE_BYTE_ARRAY, params, 0);
117                 return;
118         }
119         checksum = g_checksum_new (G_CHECKSUM_MD5);
120         g_checksum_update (checksum, data->data, data->len);
121         digest = g_byte_array_new ();
122         g_byte_array_set_size (digest, digest_len);
123         g_checksum_get_digest (checksum, digest->data, &digest_len);
124         g_checksum_free (checksum);
125
126         soup_xmlrpc_set_response (msg, SOUP_TYPE_BYTE_ARRAY, digest);
127         g_byte_array_free (digest, TRUE);
128 }
129
130
131 static void
132 do_dateChange (SoupMessage *msg, GValueArray *params)
133 {
134         GHashTable *arg;
135         SoupDate *date;
136         int val;
137
138         if (params->n_values != 2) {
139                 args_error (msg, params, 2);
140                 return;
141         }
142
143         if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_DATE, &date)) {
144                 type_error (msg, SOUP_TYPE_DATE, params, 0);
145                 return;
146         }
147         if (!soup_value_array_get_nth (params, 1, G_TYPE_HASH_TABLE, &arg)) {
148                 type_error (msg, G_TYPE_HASH_TABLE, params, 1);
149                 return;
150         }
151
152         if (soup_value_hash_lookup (arg, "tm_year", G_TYPE_INT, &val))
153                 date->year = val + 1900;
154         if (soup_value_hash_lookup (arg, "tm_mon", G_TYPE_INT, &val))
155                 date->month = val + 1;
156         if (soup_value_hash_lookup (arg, "tm_mday", G_TYPE_INT, &val))
157                 date->day = val;
158         if (soup_value_hash_lookup (arg, "tm_hour", G_TYPE_INT, &val))
159                 date->hour = val;
160         if (soup_value_hash_lookup (arg, "tm_min", G_TYPE_INT, &val))
161                 date->minute = val;
162         if (soup_value_hash_lookup (arg, "tm_sec", G_TYPE_INT, &val))
163                 date->second = val;
164
165         soup_xmlrpc_set_response (msg, SOUP_TYPE_DATE, date);
166 }
167
168 static void
169 do_echo (SoupMessage *msg, GValueArray *params)
170 {
171         int i;
172         const char *val;
173         GValueArray *in, *out;
174
175         if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &in)) {
176                 type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
177                 return;
178         }
179
180         out = g_value_array_new (in->n_values);
181         for (i = 0; i < in->n_values; i++) {
182                 if (!soup_value_array_get_nth (in, i, G_TYPE_STRING, &val)) {
183                         type_error (msg, G_TYPE_STRING, in, i);
184                         return;
185                 }
186                 soup_value_array_append (out, G_TYPE_STRING, val);
187         }
188
189         soup_xmlrpc_set_response (msg, G_TYPE_VALUE_ARRAY, out);
190         g_value_array_free (out);
191
192 }
193
194 static void
195 server_callback (SoupServer *server, SoupMessage *msg,
196                  const char *path, GHashTable *query,
197                  SoupClientContext *context, gpointer data)
198 {
199         char *method_name;
200         GValueArray *params;
201
202         if (msg->method != SOUP_METHOD_POST) {
203                 soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
204                 return;
205         }
206
207         soup_message_set_status (msg, SOUP_STATUS_OK);
208
209         if (!soup_xmlrpc_parse_method_call (msg->request_body->data,
210                                             msg->request_body->length,
211                                             &method_name, &params)) {
212                 soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED,
213                                        "Could not parse method call");
214                 return;
215         }
216
217         if (!strcmp (method_name, "sum"))
218                 do_sum (msg, params);
219         else if (!strcmp (method_name, "countBools"))
220                 do_countBools (msg, params);
221         else if (!strcmp (method_name, "md5sum"))
222                 do_md5sum (msg, params);
223         else if (!strcmp (method_name, "dateChange"))
224                 do_dateChange (msg, params);
225         else if (!strcmp (method_name, "echo"))
226                 do_echo (msg, params);
227         else {
228                 soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND,
229                                        "Unknown method %s", method_name);
230         }
231
232         g_free (method_name);
233         g_value_array_free (params);
234 }
235
236 static void
237 xmlrpc_test_exited (GPid pid, int status, gpointer data)
238 {
239         errors = WIFEXITED (status) ? WEXITSTATUS (status) : 1;
240         g_main_loop_quit (loop);
241 }
242
243 static gboolean
244 xmlrpc_test_print (GIOChannel *io, GIOCondition cond, gpointer data)
245 {
246         char *line;
247         gsize len;
248         GIOStatus status;
249
250         if (!(cond & G_IO_IN))
251                 return FALSE;
252
253         status = g_io_channel_read_line (io, &line, &len, NULL, NULL);
254         if (status == G_IO_STATUS_NORMAL) {
255                 /* Don't print the exit status, just the debug stuff */
256                 if (strncmp (line, "xmlrpc-test:", strlen ("xmlrpc-test:")) != 0)
257                         printf ("%s", line);
258                 g_free (line);
259                 return TRUE;
260         } else if (status == G_IO_STATUS_AGAIN)
261                 return TRUE;
262         else
263                 return FALSE;
264 }
265
266 static void
267 do_xmlrpc_tests (SoupURI *uri)
268 {
269         char *argv[8];
270         int arg, out;
271         gboolean ok;
272         GPid pid;
273         GError *error = NULL;
274         GIOChannel *child_out;
275
276         argv[0] = "./xmlrpc-test";
277         argv[1] = "-s";
278         argv[2] = "-u";
279         argv[3] = soup_uri_to_string (uri, FALSE);
280
281         for (arg = 0; arg < debug_level && arg < 3; arg++)
282                 argv[arg + 4] = "-d";
283         argv[arg + 4] = NULL;
284
285         ok = g_spawn_async_with_pipes (NULL, argv, NULL,
286                                        G_SPAWN_DO_NOT_REAP_CHILD,
287                                        NULL, NULL, &pid,
288                                        NULL, &out, NULL,
289                                        &error);
290         g_free (argv[3]);
291
292         if (!ok) {
293                 printf ("Could not run xmlrpc-test: %s\n", error->message);
294                 errors++;
295                 return;
296         }
297
298         g_child_watch_add (pid, xmlrpc_test_exited, NULL);
299         child_out = g_io_channel_unix_new (out);
300         g_io_add_watch (child_out, G_IO_IN | G_IO_ERR | G_IO_HUP,
301                         xmlrpc_test_print, NULL);
302         g_io_channel_unref (child_out);
303 }
304
305 gboolean run_tests = TRUE;
306
307 static GOptionEntry no_test_entry[] = {
308         { "no-tests", 'n', G_OPTION_FLAG_REVERSE,
309           G_OPTION_ARG_NONE, &run_tests,
310           "Don't run tests, just run the test server", NULL },
311         { NULL }
312 };
313
314 int
315 main (int argc, char **argv)
316 {
317         SoupServer *server;
318         SoupURI *uri;
319
320         test_init (argc, argv, no_test_entry);
321
322         server = soup_test_server_new (FALSE);
323         soup_server_add_handler (server, "/xmlrpc-server.php",
324                                  server_callback, NULL, NULL);
325
326         loop = g_main_loop_new (NULL, TRUE);
327
328         if (run_tests) {
329                 uri = soup_uri_new ("http://127.0.0.1/xmlrpc-server.php");
330                 soup_uri_set_port (uri, soup_server_get_port (server));
331                 do_xmlrpc_tests (uri);
332                 soup_uri_free (uri);
333         } else
334                 printf ("Listening on port %d\n", soup_server_get_port (server));
335
336         g_main_loop_run (loop);
337         g_main_loop_unref (loop);
338
339         soup_test_server_quit_unref (server);
340         if (run_tests)
341                 test_cleanup ();
342         return errors != 0;
343 }