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