8686b71299f85463db88bf849095b327934d7dfd
[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 <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include <libsoup/soup.h>
12
13 #include "test-utils.h"
14
15 SoupSession *session;
16 static const char *uri = "http://localhost:47524/xmlrpc-server.php";
17
18 static const char *const value_type[] = {
19         "BAD",
20         "int",
21         "boolean",
22         "string",
23         "double",
24         "datetime",
25         "base64",
26         "struct",
27         "array"
28 };
29
30 static gboolean
31 do_xmlrpc (const char *method, GValue *retval, ...)
32 {
33         SoupMessage *msg;
34         va_list args;
35         GValueArray *params;
36         GError *err = NULL;
37         char *body;
38
39         va_start (args, retval);
40         params = soup_value_array_from_args (args);
41         va_end (args);
42
43         body = soup_xmlrpc_build_method_call (method, params->values,
44                                               params->n_values);
45         g_value_array_free (params);
46         if (!body)
47                 return FALSE;
48
49         msg = soup_message_new ("POST", uri);
50         soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE,
51                                   body, strlen (body));
52         soup_session_send_message (session, msg);
53
54         if (debug_level >= 3) {
55                 debug_printf (3, "\n%s\n%d %s\n%s\n",
56                               msg->request_body->data,
57                               msg->status_code, msg->reason_phrase,
58                               msg->response_body->data);
59         }
60
61         if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
62                 debug_printf (1, "ERROR: %d %s\n", msg->status_code,
63                               msg->reason_phrase);
64                 g_object_unref (msg);
65                 return FALSE;
66         }
67
68         if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
69                                                 msg->response_body->length,
70                                                 retval, &err)) {
71                 if (err) {
72                         debug_printf (1, "FAULT: %d %s\n", err->code, err->message);
73                         g_error_free (err);
74                 } else
75                         debug_printf (1, "ERROR: could not parse response\n");
76                 g_object_unref (msg);
77                 return FALSE;
78         }
79         g_object_unref (msg);
80
81         return TRUE;
82 }
83
84 static gboolean
85 check_xmlrpc (GValue *value, GType type, ...)
86 {
87         va_list args;
88
89         if (!G_VALUE_HOLDS (value, type)) {
90                 debug_printf (1, "ERROR: could not parse response\n");
91                 g_value_unset (value);
92                 return FALSE;
93         }
94
95         va_start (args, type);
96         SOUP_VALUE_GETV (value, type, args);
97         va_end (args);
98         return TRUE;
99 }
100
101 static gboolean
102 test_sum (void)
103 {
104         GValueArray *ints;
105         int i, val, sum, result;
106         GValue retval;
107         gboolean ok;
108
109         debug_printf (1, "sum (array of int -> int): ");
110
111         ints = g_value_array_new (10);
112         for (i = sum = 0; i < 10; i++) {
113                 val = rand () % 100;
114                 debug_printf (2, "%s%d", i == 0 ? "[" : ", ", val);
115                 soup_value_array_append (ints, G_TYPE_INT, val);
116                 sum += val;
117         }
118         debug_printf (2, "] -> ");
119
120         ok = (do_xmlrpc ("sum", &retval,
121                         G_TYPE_VALUE_ARRAY, ints,
122                         G_TYPE_INVALID) &&
123               check_xmlrpc (&retval, G_TYPE_INT, &result));
124         g_value_array_free (ints);
125
126         if (!ok)
127                 return FALSE;
128
129         debug_printf (2, "%d: ", result);
130         debug_printf (1, "%s\n", result == sum ? "OK!" : "WRONG!");
131         return result == sum;
132 }
133
134 static gboolean
135 test_countBools (void)
136 {
137         GValueArray *bools;
138         int i, trues, falses;
139         GValue retval;
140         int ret_trues, ret_falses;
141         gboolean val, ok;
142         GHashTable *result;
143
144         debug_printf (1, "countBools (array of boolean -> struct of ints): ");
145
146         bools = g_value_array_new (10);
147         for (i = trues = falses = 0; i < 10; i++) {
148                 val = rand () > (RAND_MAX / 2);
149                 debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
150                 soup_value_array_append (bools, G_TYPE_BOOLEAN, val);
151                 if (val)
152                         trues++;
153                 else
154                         falses++;
155         }
156         debug_printf (2, "] -> ");
157
158         ok = (do_xmlrpc ("countBools", &retval,
159                          G_TYPE_VALUE_ARRAY, bools,
160                          G_TYPE_INVALID) &&
161               check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result));
162         g_value_array_free (bools);
163         if (!ok)
164                 return FALSE;
165
166         if (!soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues)) {
167                 debug_printf (1, "NO 'true' value in response\n");
168                 return FALSE;
169         }
170         if (!soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses)) {
171                 debug_printf (1, "NO 'false' value in response\n");
172                 return FALSE;
173         }
174         g_hash_table_destroy (result);
175
176         debug_printf (2, "{ true: %d, false: %d } ", ret_trues, ret_falses);
177         ok = (trues == ret_trues) && (falses == ret_falses);
178         debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
179         return ok;
180 }
181
182 static gboolean
183 test_md5sum (void)
184 {
185         GByteArray *data, *result;
186         int i;
187         GChecksum *checksum;
188         guchar digest[16];
189         gsize digest_len = sizeof (digest);
190         GValue retval;
191         gboolean ok;
192
193         debug_printf (1, "md5sum (base64 -> base64): ");
194
195         data = g_byte_array_new ();
196         g_byte_array_set_size (data, 256);
197         for (i = 0; i < data->len; i++)
198                 data->data[i] = (char)(rand ());
199
200         checksum = g_checksum_new (G_CHECKSUM_MD5);
201         g_checksum_update (checksum, data->data, data->len);
202         g_checksum_get_digest (checksum, digest, &digest_len);
203         g_checksum_free (checksum);
204
205         ok = (do_xmlrpc ("md5sum", &retval,
206                          SOUP_TYPE_BYTE_ARRAY, data,
207                          G_TYPE_INVALID) &&
208               check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result));
209         g_byte_array_free (data, TRUE);
210         if (!ok)
211                 return FALSE;
212
213         if (result->len != digest_len) {
214                 debug_printf (1, "result has WRONG length (%d)\n", result->len);
215                 g_byte_array_free (result, TRUE);
216                 return FALSE;
217         }
218
219         ok = (memcmp (digest, result->data, digest_len) == 0);
220         debug_printf (1, "%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         GHashTable *structval;
229         SoupDate *date, *result;
230         char *timestamp;
231         GValue retval;
232         gboolean ok;
233
234         debug_printf (1, "dateChange (struct of time and ints -> time): ");
235
236         structval = soup_value_hash_new ();
237
238         date = soup_date_new (1970 + (rand () % 50),
239                               1 + rand () % 12,
240                               1 + rand () % 28,
241                               rand () % 24,
242                               rand () % 60,
243                               rand () % 60);
244         soup_value_hash_insert (structval, "date", SOUP_TYPE_DATE, date);
245
246         if (debug_level >= 2) {
247                 timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
248                 debug_printf (2, "{ date: %s", timestamp);
249                 g_free (timestamp);
250         }
251
252         if (rand () % 3) {
253                 date->year = 1970 + (rand () % 50);
254                 debug_printf (2, ", tm_year: %d", date->year - 1900);
255                 soup_value_hash_insert (structval, "tm_year",
256                                         G_TYPE_INT, date->year - 1900);
257         }
258         if (rand () % 3) {
259                 date->month = 1 + rand () % 12;
260                 debug_printf (2, ", tm_mon: %d", date->month - 1);
261                 soup_value_hash_insert (structval, "tm_mon",
262                                         G_TYPE_INT, date->month - 1);
263         }
264         if (rand () % 3) {
265                 date->day = 1 + rand () % 28;
266                 debug_printf (2, ", tm_mday: %d", date->day);
267                 soup_value_hash_insert (structval, "tm_mday",
268                                         G_TYPE_INT, date->day);
269         }
270         if (rand () % 3) {
271                 date->hour = rand () % 24;
272                 debug_printf (2, ", tm_hour: %d", date->hour);
273                 soup_value_hash_insert (structval, "tm_hour",
274                                         G_TYPE_INT, date->hour);
275         }
276         if (rand () % 3) {
277                 date->minute = rand () % 60;
278                 debug_printf (2, ", tm_min: %d", date->minute);
279                 soup_value_hash_insert (structval, "tm_min",
280                                         G_TYPE_INT, date->minute);
281         }
282         if (rand () % 3) {
283                 date->second = rand () % 60;
284                 debug_printf (2, ", tm_sec: %d", date->second);
285                 soup_value_hash_insert (structval, "tm_sec",
286                                         G_TYPE_INT, date->second);
287         }
288
289         debug_printf (2, " } -> ");
290
291         ok = (do_xmlrpc ("dateChange", &retval,
292                          G_TYPE_HASH_TABLE, structval,
293                          G_TYPE_INVALID) &&
294               check_xmlrpc (&retval, SOUP_TYPE_DATE, &result));
295         g_hash_table_destroy (structval);
296         if (!ok) {
297                 soup_date_free (date);
298                 return FALSE;
299         }
300
301         if (debug_level >= 2) {
302                 timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC);
303                 debug_printf (2, "%s: ", timestamp);
304                 g_free (timestamp);
305         }
306
307         ok = ((date->year   == result->year) &&
308               (date->month  == result->month) &&
309               (date->day    == result->day) &&
310               (date->hour   == result->hour) &&
311               (date->minute == result->minute) &&
312               (date->second == result->second));
313         soup_date_free (date);
314         soup_date_free (result);
315
316         debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
317         return ok;
318 }
319
320 static const char *const echo_strings[] = {
321         "This is a test",
322         "& so is this",
323         "and so is <this>",
324         "&amp; so is &lt;this&gt;"
325 };
326 #define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings)
327
328 static gboolean
329 test_echo (void)
330 {
331         GValueArray *originals, *echoes;
332         GValue retval;
333         int i;
334
335         debug_printf (1, "echo (array of string -> array of string): ");
336
337         originals = g_value_array_new (N_ECHO_STRINGS);
338         for (i = 0; i < N_ECHO_STRINGS; i++) {
339                 soup_value_array_append (originals, G_TYPE_STRING, echo_strings[i]);
340                 debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo_strings[i]);
341         }
342         debug_printf (2, "] -> ");
343
344         if (!(do_xmlrpc ("echo", &retval,
345                          G_TYPE_VALUE_ARRAY, originals,
346                          G_TYPE_INVALID) &&
347               check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) {
348                 g_value_array_free (originals);
349                 return FALSE;
350         }
351         g_value_array_free (originals);
352
353         if (debug_level >= 2) {
354                 for (i = 0; i < echoes->n_values; i++) {
355                         debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ",
356                                       g_value_get_string (&echoes->values[i]));
357                 }
358                 debug_printf (2, "] -> ");
359         }
360
361         if (echoes->n_values != N_ECHO_STRINGS) {
362                 debug_printf (1, " WRONG! Wrong number of return strings");
363                 g_value_array_free (echoes);
364                 return FALSE;
365         }
366
367         for (i = 0; i < echoes->n_values; i++) {
368                 if (strcmp (echo_strings[i], g_value_get_string (&echoes->values[i])) != 0) {
369                         debug_printf (1, " WRONG! Mismatch at %d\n", i + 1);
370                         g_value_array_free (echoes);
371                         return FALSE;
372                 }
373         }
374
375         debug_printf (1, "OK!\n");
376         g_value_array_free (echoes);
377         return TRUE;
378 }
379
380 int
381 main (int argc, char **argv)
382 {
383         test_init (argc, argv, NULL);
384         apache_init ();
385
386         srand (time (NULL));
387
388         session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
389
390         if (!test_sum ())
391                 errors++;
392         if (!test_countBools ())
393                 errors++;
394         if (!test_md5sum ())
395                 errors++;
396         if (!test_dateChange ())
397                 errors++;
398         if (!test_echo ())
399                 errors++;
400
401         soup_session_abort (session);
402         g_object_unref (session);
403
404         test_cleanup ();
405         return errors = 0;
406 }