1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2001-2003, Ximian, Inc.
6 #include "test-utils.h"
10 #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
11 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
14 static SoupSession *session;
15 static const char *default_uri = "http://127.0.0.1:47524/xmlrpc-server.php";
16 static const char *uri = NULL;
17 static gboolean server_test = FALSE;
19 static const char *const value_type[] = {
32 send_xmlrpc (const char *body, GValue *retval)
37 msg = soup_message_new ("POST", uri);
38 soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
40 soup_session_send_message (session, msg);
42 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
43 debug_printf (1, "ERROR: %d %s\n", msg->status_code,
49 if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
50 msg->response_body->length,
53 debug_printf (1, "FAULT: %d %s\n", err->code, err->message);
56 debug_printf (1, "ERROR: could not parse response\n");
66 do_xmlrpc (const char *method, GValue *retval, ...)
73 va_start (args, retval);
74 params = soup_value_array_from_args (args);
77 body = soup_xmlrpc_build_method_call (method, params->values,
79 g_value_array_free (params);
83 ret = send_xmlrpc (body, retval);
90 check_xmlrpc (GValue *value, GType type, ...)
94 if (!G_VALUE_HOLDS (value, type)) {
95 debug_printf (1, "ERROR: could not parse response\n");
96 g_value_unset (value);
100 va_start (args, type);
101 SOUP_VALUE_GETV (value, type, args);
110 int i, val, sum, result;
114 debug_printf (1, "sum (array of int -> int): ");
116 ints = g_value_array_new (10);
117 for (i = sum = 0; i < 10; i++) {
118 val = g_random_int_range (0, 100);
119 debug_printf (2, "%s%d", i == 0 ? "[" : ", ", val);
120 soup_value_array_append (ints, G_TYPE_INT, val);
123 debug_printf (2, "] -> ");
125 ok = (do_xmlrpc ("sum", &retval,
126 G_TYPE_VALUE_ARRAY, ints,
128 check_xmlrpc (&retval, G_TYPE_INT, &result));
129 g_value_array_free (ints);
134 debug_printf (2, "%d: ", result);
135 debug_printf (1, "%s\n", result == sum ? "OK!" : "WRONG!");
136 return result == sum;
140 test_countBools (void)
143 int i, trues, falses;
145 int ret_trues, ret_falses;
149 debug_printf (1, "countBools (array of boolean -> struct of ints): ");
151 bools = g_value_array_new (10);
152 for (i = trues = falses = 0; i < 10; i++) {
153 val = g_random_boolean ();
154 debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
155 soup_value_array_append (bools, G_TYPE_BOOLEAN, val);
161 debug_printf (2, "] -> ");
163 ok = (do_xmlrpc ("countBools", &retval,
164 G_TYPE_VALUE_ARRAY, bools,
166 check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result));
167 g_value_array_free (bools);
171 if (!soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues)) {
172 debug_printf (1, "NO 'true' value in response\n");
175 if (!soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses)) {
176 debug_printf (1, "NO 'false' value in response\n");
179 g_hash_table_destroy (result);
181 debug_printf (2, "{ true: %d, false: %d } ", ret_trues, ret_falses);
182 ok = (trues == ret_trues) && (falses == ret_falses);
183 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
190 GByteArray *data, *result;
194 gsize digest_len = sizeof (digest);
198 debug_printf (1, "md5sum (base64 -> base64): ");
200 data = g_byte_array_new ();
201 g_byte_array_set_size (data, 256);
202 for (i = 0; i < data->len; i++)
203 data->data[i] = (char)(g_random_int_range (0, 256));
205 checksum = g_checksum_new (G_CHECKSUM_MD5);
206 g_checksum_update (checksum, data->data, data->len);
207 g_checksum_get_digest (checksum, digest, &digest_len);
208 g_checksum_free (checksum);
210 ok = (do_xmlrpc ("md5sum", &retval,
211 SOUP_TYPE_BYTE_ARRAY, data,
213 check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result));
214 g_byte_array_free (data, TRUE);
218 if (result->len != digest_len) {
219 debug_printf (1, "result has WRONG length (%d)\n", result->len);
220 g_byte_array_free (result, TRUE);
224 ok = (memcmp (digest, result->data, digest_len) == 0);
225 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
226 g_byte_array_free (result, TRUE);
231 test_dateChange (void)
233 GHashTable *structval;
234 SoupDate *date, *result;
239 debug_printf (1, "dateChange (date, struct of ints -> time): ");
241 date = soup_date_new (1970 + (g_random_int_range (0, 50)),
242 1 + g_random_int_range (0, 12),
243 1 + g_random_int_range (0, 28),
244 g_random_int_range (0, 24),
245 g_random_int_range (0, 60),
246 g_random_int_range (0, 60));
247 if (debug_level >= 2) {
248 timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
249 debug_printf (2, "date: %s, {", timestamp);
253 structval = soup_value_hash_new ();
255 #define MAYBE (g_random_int_range (0, 3) != 0)
258 date->year = 1970 + (g_random_int_range (0, 50));
259 debug_printf (2, "tm_year: %d, ", date->year - 1900);
260 soup_value_hash_insert (structval, "tm_year",
261 G_TYPE_INT, date->year - 1900);
264 date->month = 1 + g_random_int_range (0, 12);
265 debug_printf (2, "tm_mon: %d, ", date->month - 1);
266 soup_value_hash_insert (structval, "tm_mon",
267 G_TYPE_INT, date->month - 1);
270 date->day = 1 + g_random_int_range (0, 28);
271 debug_printf (2, "tm_mday: %d, ", date->day);
272 soup_value_hash_insert (structval, "tm_mday",
273 G_TYPE_INT, date->day);
276 date->hour = g_random_int_range (0, 24);
277 debug_printf (2, "tm_hour: %d, ", date->hour);
278 soup_value_hash_insert (structval, "tm_hour",
279 G_TYPE_INT, date->hour);
282 date->minute = g_random_int_range (0, 60);
283 debug_printf (2, "tm_min: %d, ", date->minute);
284 soup_value_hash_insert (structval, "tm_min",
285 G_TYPE_INT, date->minute);
288 date->second = g_random_int_range (0, 60);
289 debug_printf (2, "tm_sec: %d, ", date->second);
290 soup_value_hash_insert (structval, "tm_sec",
291 G_TYPE_INT, date->second);
294 debug_printf (2, "} -> ");
296 ok = (do_xmlrpc ("dateChange", &retval,
297 SOUP_TYPE_DATE, date,
298 G_TYPE_HASH_TABLE, structval,
300 check_xmlrpc (&retval, SOUP_TYPE_DATE, &result));
301 g_hash_table_destroy (structval);
303 soup_date_free (date);
307 if (debug_level >= 2) {
308 timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC);
309 debug_printf (2, "%s: ", timestamp);
313 ok = ((date->year == result->year) &&
314 (date->month == result->month) &&
315 (date->day == result->day) &&
316 (date->hour == result->hour) &&
317 (date->minute == result->minute) &&
318 (date->second == result->second));
319 soup_date_free (date);
320 soup_date_free (result);
322 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
326 static const char *const echo_strings[] = {
330 "& so is <this>"
332 #define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings)
334 static const char *const echo_strings_broken[] = {
338 "amp; so is lt;thisgt;"
344 GValueArray *originals, *echoes;
347 gboolean php_bug = FALSE;
349 debug_printf (1, "echo (array of string -> array of string): ");
351 originals = g_value_array_new (N_ECHO_STRINGS);
352 for (i = 0; i < N_ECHO_STRINGS; i++) {
353 soup_value_array_append (originals, G_TYPE_STRING, echo_strings[i]);
354 debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo_strings[i]);
356 debug_printf (2, "] -> ");
358 if (!(do_xmlrpc ("echo", &retval,
359 G_TYPE_VALUE_ARRAY, originals,
361 check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) {
362 g_value_array_free (originals);
365 g_value_array_free (originals);
367 if (debug_level >= 2) {
368 for (i = 0; i < echoes->n_values; i++) {
369 debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ",
370 g_value_get_string (&echoes->values[i]));
372 debug_printf (2, "] -> ");
375 if (echoes->n_values != N_ECHO_STRINGS) {
376 debug_printf (1, " WRONG! Wrong number of return strings");
377 g_value_array_free (echoes);
381 for (i = 0; i < echoes->n_values; i++) {
382 if (strcmp (echo_strings[i], g_value_get_string (&echoes->values[i])) != 0) {
383 if (!server_test && strcmp (echo_strings_broken[i], g_value_get_string (&echoes->values[i])) == 0)
386 debug_printf (1, " WRONG! Mismatch at %d\n", i + 1);
387 g_value_array_free (echoes);
394 debug_printf (1, "WRONG, but it's php's fault\n");
396 debug_printf (1, "OK!\n");
397 g_value_array_free (echoes);
402 test_ping (gboolean include_params)
410 debug_printf (1, "ping (void (%s) -> string): ",
411 include_params ? "empty <params>" : "no <params>");
413 params = soup_value_array_new ();
414 request = soup_xmlrpc_build_method_call ("ping", params->values,
416 g_value_array_free (params);
420 if (!include_params) {
423 params = strstr (request, "<params/>");
425 debug_printf (1, "ERROR: XML did not contain <params/>!");
428 end = params + strlen ("<params/>");
429 memmove (params, end, strlen (end) + 1);
432 ret = send_xmlrpc (request, &retval);
435 if (!ret || !check_xmlrpc (&retval, G_TYPE_STRING, &out))
438 if (!strcmp (out, "pong")) {
439 debug_printf (1, "OK!\n");
442 debug_printf (1, "WRONG! Bad response '%s'", out);
451 do_bad_xmlrpc (const char *body)
457 msg = soup_message_new ("POST", uri);
458 soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
459 body, strlen (body));
460 soup_session_send_message (session, msg);
462 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
463 debug_printf (1, "ERROR: %d %s\n", msg->status_code,
465 g_object_unref (msg);
469 if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
470 msg->response_body->length,
473 debug_printf (1, "FAULT: %d %s (OK!)\n",
474 err->code, err->message);
476 g_object_unref (msg);
479 debug_printf (1, "ERROR: could not parse response\n");
481 debug_printf (1, "Unexpectedly got successful response!\n");
483 g_object_unref (msg);
488 test_fault_malformed (void)
490 debug_printf (1, "malformed request: ");
492 return do_bad_xmlrpc ("<methodCall/>");
496 test_fault_method (void)
498 debug_printf (1, "request to non-existent method: ");
500 return do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
504 test_fault_args (void)
506 debug_printf (1, "request with invalid args: ");
508 return do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
511 static GOptionEntry xmlrpc_entries[] = {
512 { "uri", 'u', 0, G_OPTION_ARG_STRING, &uri,
513 "Alternate URI for server", NULL },
514 { "server-test", 's', 0, G_OPTION_ARG_NONE, &server_test,
515 "If this is being run from xmlrpc-server-test", NULL },
520 main (int argc, char **argv)
522 test_init (argc, argv, xmlrpc_entries);
529 session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
533 if (!test_countBools ())
537 if (!test_dateChange ())
541 if (!test_ping (TRUE))
543 if (!test_ping (FALSE))
545 if (!test_fault_malformed ())
547 if (!test_fault_method ())
549 if (!test_fault_args ())
552 soup_test_session_abort_unref (session);
558 #else /* HAVE_PHP_XMLRPC */
561 main (int argc, char **argv)
563 return 77; /* SKIP */