free proxy-related stuff
[platform/upstream/libsoup.git] / tests / xmlrpc-test.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2001-2003, Ximian, Inc.
4  */
5
6 #include <string.h>
7 #include <unistd.h>
8
9 #include <libsoup/soup.h>
10 #include <libsoup/soup-date.h>
11 #include <libsoup/soup-md5-utils.h>
12 #include <libsoup/soup-xmlrpc-message.h>
13 #include <libsoup/soup-xmlrpc-response.h>
14
15 #include "apache-wrapper.h"
16
17 SoupSession *session;
18 static const char *uri = "http://localhost:47524/xmlrpc-server.php";
19 int debug;
20
21 static void
22 dprintf (int level, const char *format, ...)
23 {
24         va_list args;
25
26         if (debug < level)
27                 return;
28
29         va_start (args, format);
30         vprintf (format, args);
31         va_end (args);
32 }
33
34 static const char *const value_type[] = {
35         "BAD",
36         "int",
37         "boolean",
38         "string",
39         "double",
40         "datetime",
41         "base64",
42         "struct",
43         "array"
44 };
45
46 static SoupXmlrpcResponse *
47 do_xmlrpc (SoupXmlrpcMessage *xmsg, SoupXmlrpcValueType type)
48 {
49         SoupMessage *msg = SOUP_MESSAGE (xmsg);
50         SoupXmlrpcResponse *response;
51         SoupXmlrpcValue *value;
52         int status;
53
54         soup_xmlrpc_message_persist (xmsg);
55         status = soup_session_send_message (session, msg);
56
57         dprintf (3, "\n%.*s\n%d %s\n%.*s\n",
58                  msg->request.length, msg->request.body,
59                  msg->status_code, msg->reason_phrase,
60                  msg->response.length, msg->response.body);
61
62         if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
63                 dprintf (1, "ERROR: %d %s\n", status, msg->reason_phrase);
64                 g_object_unref (msg);
65                 return FALSE;
66         }
67
68         response = soup_xmlrpc_message_parse_response (xmsg);
69         g_object_unref (msg);
70         if (!response || soup_xmlrpc_response_is_fault (response)) {
71                 if (!response)
72                         dprintf (1, "ERROR: no response\n");
73                 else {
74                         dprintf (1, "ERROR: fault\n");
75                         g_object_unref (response);
76                 }
77                 return FALSE;
78         }
79
80         value = soup_xmlrpc_response_get_value (response);
81         if (!value) {
82                 dprintf (1, "ERROR: no value?\n");
83                 g_object_unref (response);
84                 return NULL;
85         } else if (soup_xmlrpc_value_get_type (value) != type) {
86                 dprintf (1, "ERROR: wrong value type; expected %s, got %s\n",
87                          value_type[type], value_type[soup_xmlrpc_value_get_type (value)]);
88                 g_object_unref (response);
89                 return NULL;
90         }
91
92         return response;
93 }
94
95 static gboolean
96 test_sum (void)
97 {
98         SoupXmlrpcMessage *msg;
99         SoupXmlrpcResponse *response;
100         SoupXmlrpcValue *value;
101         int i, val, sum;
102         long result;
103
104         dprintf (1, "sum (array of int -> int): ");
105
106         msg = soup_xmlrpc_message_new (uri);
107         soup_xmlrpc_message_start_call (msg, "sum");
108         soup_xmlrpc_message_start_param (msg);
109         soup_xmlrpc_message_start_array (msg);
110         for (i = sum = 0; i < 10; i++) {
111                 val = rand () % 100;
112                 dprintf (2, "%s%d", i == 0 ? "[" : ", ", val);
113                 soup_xmlrpc_message_write_int (msg, val);
114                 sum += val;
115         }
116         dprintf (2, "] -> ");
117         soup_xmlrpc_message_end_array (msg);
118         soup_xmlrpc_message_end_param (msg);
119         soup_xmlrpc_message_end_call (msg);
120
121         response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_INT);
122         if (!response)
123                 return FALSE;
124         value = soup_xmlrpc_response_get_value (response);
125
126         if (!soup_xmlrpc_value_get_int (value, &result)) {
127                 dprintf (1, "wrong type?\n");
128                 g_object_unref (response);
129                 return FALSE;
130         }
131         g_object_unref (response);
132
133         dprintf (2, "%ld: ", result);
134         dprintf (1, "%s\n", result == sum ? "OK!" : "WRONG!");
135         return result == sum;
136 }
137
138 static gboolean
139 test_countBools (void)
140 {
141         SoupXmlrpcMessage *msg;
142         SoupXmlrpcResponse *response;
143         SoupXmlrpcValue *value;
144         int i, trues, falses;
145         long ret_trues, ret_falses;
146         gboolean val, ok;
147         GHashTable *result;
148
149         dprintf (1, "countBools (array of boolean -> struct of ints): ");
150
151         msg = soup_xmlrpc_message_new (uri);
152         soup_xmlrpc_message_start_call (msg, "countBools");
153         soup_xmlrpc_message_start_param (msg);
154         soup_xmlrpc_message_start_array (msg);
155         for (i = trues = falses = 0; i < 10; i++) {
156                 val = rand () > (RAND_MAX / 2);
157                 dprintf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
158                 soup_xmlrpc_message_write_boolean (msg, val);
159                 if (val)
160                         trues++;
161                 else
162                         falses++;
163         }
164         dprintf (2, "] -> ");
165         soup_xmlrpc_message_end_array (msg);
166         soup_xmlrpc_message_end_param (msg);
167         soup_xmlrpc_message_end_call (msg);
168
169         response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_STRUCT);
170         if (!response)
171                 return FALSE;
172         value = soup_xmlrpc_response_get_value (response);
173
174         if (!soup_xmlrpc_value_get_struct (value, &result)) {
175                 dprintf (1, "wrong type?\n");
176                 g_object_unref (response);
177                 return FALSE;
178         }
179
180         if (!soup_xmlrpc_value_get_int (g_hash_table_lookup (result, "true"), &ret_trues)) {
181                 dprintf (1, "NO 'true' value in response\n");
182                 g_hash_table_destroy (result);
183                 g_object_unref (response);
184                 return FALSE;
185         }
186         if (!soup_xmlrpc_value_get_int (g_hash_table_lookup (result, "false"), &ret_falses)) {
187                 dprintf (1, "NO 'false' value in response\n");
188                 g_hash_table_destroy (result);
189                 g_object_unref (response);
190                 return FALSE;
191         }
192         g_hash_table_destroy (result);
193         g_object_unref (response);
194
195         dprintf (2, "{ true: %ld, false: %ld } ", ret_trues, ret_falses);
196         ok = (trues == ret_trues) && (falses == ret_falses);
197         dprintf (1, "%s\n", ok ? "OK!" : "WRONG!");
198         return ok;
199 }
200
201 static gboolean
202 test_md5sum (void)
203 {
204         SoupXmlrpcMessage *msg;
205         SoupXmlrpcResponse *response;
206         SoupXmlrpcValue *value;
207         GByteArray *result;
208         char data[512];
209         int i;
210         SoupMD5Context md5;
211         guchar digest[16];
212         gboolean ok;
213
214         dprintf (1, "md5sum (base64 -> base64): ");
215
216         msg = soup_xmlrpc_message_new (uri);
217         soup_xmlrpc_message_start_call (msg, "md5sum");
218         soup_xmlrpc_message_start_param (msg);
219         for (i = 0; i < sizeof (data); i++)
220                 data[i] = (char)(rand () & 0xFF);
221         soup_xmlrpc_message_write_base64 (msg, data, sizeof (data));
222         soup_xmlrpc_message_end_param (msg);
223         soup_xmlrpc_message_end_call (msg);
224
225         response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_BASE64);
226         if (!response)
227                 return FALSE;
228         value = soup_xmlrpc_response_get_value (response);
229
230         if (!soup_xmlrpc_value_get_base64 (value, &result)) {
231                 dprintf (1, "wrong type?\n");
232                 g_object_unref (response);
233                 return FALSE;
234         }
235         g_object_unref (response);
236
237         if (result->len != 16) {
238                 dprintf (1, "result has WRONG length (%d)\n", result->len);
239                 g_byte_array_free (result, TRUE);
240                 return FALSE;
241         }
242
243         soup_md5_init (&md5);
244         soup_md5_update (&md5, data, sizeof (data));
245         soup_md5_final (&md5, digest);
246
247         ok = (memcmp (digest, result->data, 16) == 0);
248         dprintf (1, "%s\n", ok ? "OK!" : "WRONG!");
249         g_byte_array_free (result, TRUE);
250         return ok;
251 }
252
253 static gboolean
254 test_dateChange (void)
255 {
256         SoupXmlrpcMessage *msg;
257         SoupXmlrpcResponse *response;
258         SoupXmlrpcValue *value;
259         struct tm tm;
260         time_t when, result;
261         char timestamp[128];
262
263         dprintf (1, "dateChange (struct of time and ints -> time): ");
264
265         msg = soup_xmlrpc_message_new (uri);
266         soup_xmlrpc_message_start_call (msg, "dateChange");
267         soup_xmlrpc_message_start_param (msg);
268         soup_xmlrpc_message_start_struct (msg);
269
270         soup_xmlrpc_message_start_member (msg, "date");
271         memset (&tm, 0, sizeof (tm));
272         tm.tm_year = 70 + (rand () % 50);
273         tm.tm_mon = rand () % 12;
274         tm.tm_mday = 1 + (rand () % 28);
275         tm.tm_hour = rand () % 24;
276         tm.tm_min = rand () % 60;
277         tm.tm_sec = rand () % 60;
278         when = soup_mktime_utc (&tm);
279         soup_xmlrpc_message_write_datetime (msg, when);
280         soup_xmlrpc_message_end_member (msg);
281
282         strftime (timestamp, sizeof (timestamp),
283                   "%Y-%m-%dT%H:%M:%S", &tm);
284         dprintf (2, "{ date: %s", timestamp);
285
286         if (rand () % 3) {
287                 tm.tm_year = 70 + (rand () % 50);
288                 dprintf (2, ", tm_year: %d", tm.tm_year);
289                 soup_xmlrpc_message_start_member (msg, "tm_year");
290                 soup_xmlrpc_message_write_int (msg, tm.tm_year);
291                 soup_xmlrpc_message_end_member (msg);
292         }
293         if (rand () % 3) {
294                 tm.tm_mon = rand () % 12;
295                 dprintf (2, ", tm_mon: %d", tm.tm_mon);
296                 soup_xmlrpc_message_start_member (msg, "tm_mon");
297                 soup_xmlrpc_message_write_int (msg, tm.tm_mon);
298                 soup_xmlrpc_message_end_member (msg);
299         }
300         if (rand () % 3) {
301                 tm.tm_mday = 1 + (rand () % 28);
302                 dprintf (2, ", tm_mday: %d", tm.tm_mday);
303                 soup_xmlrpc_message_start_member (msg, "tm_mday");
304                 soup_xmlrpc_message_write_int (msg, tm.tm_mday);
305                 soup_xmlrpc_message_end_member (msg);
306         }
307         if (rand () % 3) {
308                 tm.tm_hour = rand () % 24;
309                 dprintf (2, ", tm_hour: %d", tm.tm_hour);
310                 soup_xmlrpc_message_start_member (msg, "tm_hour");
311                 soup_xmlrpc_message_write_int (msg, tm.tm_hour);
312                 soup_xmlrpc_message_end_member (msg);
313         }
314         if (rand () % 3) {
315                 tm.tm_min = rand () % 60;
316                 dprintf (2, ", tm_min: %d", tm.tm_min);
317                 soup_xmlrpc_message_start_member (msg, "tm_min");
318                 soup_xmlrpc_message_write_int (msg, tm.tm_min);
319                 soup_xmlrpc_message_end_member (msg);
320         }
321         if (rand () % 3) {
322                 tm.tm_sec = rand () % 60;
323                 dprintf (2, ", tm_sec: %d", tm.tm_sec);
324                 soup_xmlrpc_message_start_member (msg, "tm_sec");
325                 soup_xmlrpc_message_write_int (msg, tm.tm_sec);
326                 soup_xmlrpc_message_end_member (msg);
327         }
328         when = soup_mktime_utc (&tm);
329
330         dprintf (2, " } -> ");
331
332         soup_xmlrpc_message_end_struct (msg);
333         soup_xmlrpc_message_end_param (msg);
334         soup_xmlrpc_message_end_call (msg);
335
336         response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_DATETIME);
337         if (!response)
338                 return FALSE;
339         value = soup_xmlrpc_response_get_value (response);
340
341         if (!soup_xmlrpc_value_get_datetime (value, &result)) {
342                 dprintf (1, "wrong type?\n");
343                 g_object_unref (response);
344                 return FALSE;
345         }
346         g_object_unref (response);
347
348         memset (&tm, 0, sizeof (tm));
349         soup_gmtime (&result, &tm);
350         strftime (timestamp, sizeof (timestamp), "%Y-%m-%dT%H:%M:%S", &tm);
351         dprintf (2, "%s: ", timestamp);
352
353         dprintf (1, "%s\n", (when == result) ? "OK!" : "WRONG!");
354         return (when == result);
355 }
356
357 static const char *const echo_strings[] = {
358         "This is a test",
359         "& so is this",
360         "and so is <this>",
361         "&amp; so is &lt;this&gt;"
362 };
363 #define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings)
364
365 static gboolean
366 test_echo (void)
367 {
368         SoupXmlrpcMessage *msg;
369         SoupXmlrpcResponse *response;
370         SoupXmlrpcValue *value, *elt;
371         SoupXmlrpcValueArrayIterator *iter;
372         char *echo;
373         int i;
374
375         dprintf (1, "echo (array of string -> array of string): ");
376
377         msg = soup_xmlrpc_message_new (uri);
378         soup_xmlrpc_message_start_call (msg, "echo");
379         soup_xmlrpc_message_start_param (msg);
380         soup_xmlrpc_message_start_array (msg);
381         for (i = 0; i < N_ECHO_STRINGS; i++) {
382                 dprintf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo_strings[i]);
383                 soup_xmlrpc_message_write_string (msg, echo_strings[i]);
384         }
385         dprintf (2, "] -> ");
386         soup_xmlrpc_message_end_array (msg);
387         soup_xmlrpc_message_end_param (msg);
388         soup_xmlrpc_message_end_call (msg);
389
390         response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_ARRAY);
391         if (!response)
392                 return FALSE;
393         value = soup_xmlrpc_response_get_value (response);
394
395         if (!soup_xmlrpc_value_array_get_iterator (value, &iter)) {
396                 dprintf (1, "wrong type?\n");
397                 g_object_unref (response);
398                 return FALSE;
399         }
400         i = 0;
401         while (iter) {
402                 if (!soup_xmlrpc_value_array_iterator_get_value (iter, &elt)) {
403                         dprintf (1, " WRONG! Can't get result element %d\n", i + 1);
404                         g_object_unref (response);
405                         return FALSE;
406                 }
407                 if (!soup_xmlrpc_value_get_string (elt, &echo)) {
408                         dprintf (1, " WRONG! Result element %d is not a string", i + 1);
409                         g_object_unref (response);
410                         return FALSE;
411                 }
412                 dprintf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo);
413                 if (strcmp (echo_strings[i], echo) != 0) {
414                         dprintf (1, " WRONG! Mismatch at %d\n", i + 1);
415                         g_free (echo);
416                         g_object_unref (response);
417                         return FALSE;
418                 }
419                 g_free (echo);
420
421                 iter = soup_xmlrpc_value_array_iterator_next (iter);
422                 i++;
423         }
424         dprintf (2, "] ");
425         g_object_unref (response);
426
427         dprintf (1, "%s\n", i == N_ECHO_STRINGS ? "OK!" : "WRONG! Too few results");
428         return i == N_ECHO_STRINGS;
429 }
430
431 static void
432 usage (void)
433 {
434         fprintf (stderr, "Usage: xmlrpc-test [-d] [-d]\n");
435         exit (1);
436 }
437
438 int
439 main (int argc, char **argv)
440 {
441         int opt, errors = 0;
442
443         g_type_init ();
444         g_thread_init (NULL);
445
446         while ((opt = getopt (argc, argv, "d")) != -1) {
447                 switch (opt) {
448                 case 'd':
449                         debug++;
450                         break;
451
452                 case '?':
453                         usage ();
454                         break;
455                 }
456         }
457
458         srand (time (NULL));
459
460         if (!apache_init ()) {
461                 fprintf (stderr, "Could not start apache\n");
462                 return 1;
463         }
464
465         session = soup_session_sync_new ();
466
467         if (!test_sum ())
468                 errors++;
469         if (!test_countBools ())
470                 errors++;
471         if (!test_md5sum ())
472                 errors++;
473         if (!test_dateChange ())
474                 errors++;
475         if (!test_echo ())
476                 errors++;
477
478         apache_cleanup ();
479
480         dprintf (1, "\n");
481         if (errors) {
482                 printf ("xmlrpc-test: %d error(s). Run with '-d' for details\n",
483                         errors);
484         } else
485                 printf ("xmlrpc-test: OK\n");
486         return errors;
487 }