1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2001-2003, Ximian, Inc.
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>
15 #include "apache-wrapper.h"
18 static const char *uri = "http://localhost:47524/xmlrpc-server.php";
22 dprintf (int level, const char *format, ...)
29 va_start (args, format);
30 vprintf (format, args);
34 static const char *const value_type[] = {
46 static SoupXmlrpcResponse *
47 do_xmlrpc (SoupXmlrpcMessage *xmsg, SoupXmlrpcValueType type)
49 SoupMessage *msg = SOUP_MESSAGE (xmsg);
50 SoupXmlrpcResponse *response;
51 SoupXmlrpcValue *value;
54 soup_xmlrpc_message_persist (xmsg);
55 status = soup_session_send_message (session, msg);
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);
62 if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
63 dprintf (1, "ERROR: %d %s\n", status, msg->reason_phrase);
68 response = soup_xmlrpc_message_parse_response (xmsg);
70 if (!response || soup_xmlrpc_response_is_fault (response)) {
72 dprintf (1, "ERROR: no response\n");
74 dprintf (1, "ERROR: fault\n");
75 g_object_unref (response);
80 value = soup_xmlrpc_response_get_value (response);
82 dprintf (1, "ERROR: no value?\n");
83 g_object_unref (response);
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);
98 SoupXmlrpcMessage *msg;
99 SoupXmlrpcResponse *response;
100 SoupXmlrpcValue *value;
104 dprintf (1, "sum (array of int -> int): ");
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++) {
112 dprintf (2, "%s%d", i == 0 ? "[" : ", ", val);
113 soup_xmlrpc_message_write_int (msg, val);
116 dprintf (2, "] -> ");
117 soup_xmlrpc_message_end_array (msg);
118 soup_xmlrpc_message_end_param (msg);
119 soup_xmlrpc_message_end_call (msg);
121 response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_INT);
124 value = soup_xmlrpc_response_get_value (response);
126 if (!soup_xmlrpc_value_get_int (value, &result)) {
127 dprintf (1, "wrong type?\n");
128 g_object_unref (response);
131 g_object_unref (response);
133 dprintf (2, "%ld: ", result);
134 dprintf (1, "%s\n", result == sum ? "OK!" : "WRONG!");
135 return result == sum;
139 test_countBools (void)
141 SoupXmlrpcMessage *msg;
142 SoupXmlrpcResponse *response;
143 SoupXmlrpcValue *value;
144 int i, trues, falses;
145 long ret_trues, ret_falses;
149 dprintf (1, "countBools (array of boolean -> struct of ints): ");
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);
164 dprintf (2, "] -> ");
165 soup_xmlrpc_message_end_array (msg);
166 soup_xmlrpc_message_end_param (msg);
167 soup_xmlrpc_message_end_call (msg);
169 response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_STRUCT);
172 value = soup_xmlrpc_response_get_value (response);
174 if (!soup_xmlrpc_value_get_struct (value, &result)) {
175 dprintf (1, "wrong type?\n");
176 g_object_unref (response);
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);
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);
192 g_hash_table_destroy (result);
193 g_object_unref (response);
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!");
204 SoupXmlrpcMessage *msg;
205 SoupXmlrpcResponse *response;
206 SoupXmlrpcValue *value;
214 dprintf (1, "md5sum (base64 -> base64): ");
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);
225 response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_BASE64);
228 value = soup_xmlrpc_response_get_value (response);
230 if (!soup_xmlrpc_value_get_base64 (value, &result)) {
231 dprintf (1, "wrong type?\n");
232 g_object_unref (response);
235 g_object_unref (response);
237 if (result->len != 16) {
238 dprintf (1, "result has WRONG length (%d)\n", result->len);
239 g_byte_array_free (result, TRUE);
243 soup_md5_init (&md5);
244 soup_md5_update (&md5, data, sizeof (data));
245 soup_md5_final (&md5, digest);
247 ok = (memcmp (digest, result->data, 16) == 0);
248 dprintf (1, "%s\n", ok ? "OK!" : "WRONG!");
249 g_byte_array_free (result, TRUE);
254 test_dateChange (void)
256 SoupXmlrpcMessage *msg;
257 SoupXmlrpcResponse *response;
258 SoupXmlrpcValue *value;
263 dprintf (1, "dateChange (struct of time and ints -> time): ");
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);
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);
282 strftime (timestamp, sizeof (timestamp),
283 "%Y-%m-%dT%H:%M:%S", &tm);
284 dprintf (2, "{ date: %s", timestamp);
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);
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);
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);
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);
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);
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);
328 when = soup_mktime_utc (&tm);
330 dprintf (2, " } -> ");
332 soup_xmlrpc_message_end_struct (msg);
333 soup_xmlrpc_message_end_param (msg);
334 soup_xmlrpc_message_end_call (msg);
336 response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_DATETIME);
339 value = soup_xmlrpc_response_get_value (response);
341 if (!soup_xmlrpc_value_get_datetime (value, &result)) {
342 dprintf (1, "wrong type?\n");
343 g_object_unref (response);
346 g_object_unref (response);
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);
353 dprintf (1, "%s\n", (when == result) ? "OK!" : "WRONG!");
354 return (when == result);
357 static const char *const echo_strings[] = {
361 "& so is <this>"
363 #define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings)
368 SoupXmlrpcMessage *msg;
369 SoupXmlrpcResponse *response;
370 SoupXmlrpcValue *value, *elt;
371 SoupXmlrpcValueArrayIterator *iter;
375 dprintf (1, "echo (array of string -> array of string): ");
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]);
385 dprintf (2, "] -> ");
386 soup_xmlrpc_message_end_array (msg);
387 soup_xmlrpc_message_end_param (msg);
388 soup_xmlrpc_message_end_call (msg);
390 response = do_xmlrpc (msg, SOUP_XMLRPC_VALUE_TYPE_ARRAY);
393 value = soup_xmlrpc_response_get_value (response);
395 if (!soup_xmlrpc_value_array_get_iterator (value, &iter)) {
396 dprintf (1, "wrong type?\n");
397 g_object_unref (response);
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);
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);
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);
416 g_object_unref (response);
421 iter = soup_xmlrpc_value_array_iterator_next (iter);
425 g_object_unref (response);
427 dprintf (1, "%s\n", i == N_ECHO_STRINGS ? "OK!" : "WRONG! Too few results");
428 return i == N_ECHO_STRINGS;
434 fprintf (stderr, "Usage: xmlrpc-test [-d] [-d]\n");
439 main (int argc, char **argv)
444 g_thread_init (NULL);
446 while ((opt = getopt (argc, argv, "d")) != -1) {
460 if (!apache_init ()) {
461 fprintf (stderr, "Could not start apache\n");
465 session = soup_session_sync_new ();
469 if (!test_countBools ())
473 if (!test_dateChange ())
482 printf ("xmlrpc-test: %d error(s). Run with '-d' for details\n",
485 printf ("xmlrpc-test: OK\n");