1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2001-2003, Ximian, Inc.
11 #include <libsoup/soup.h>
13 #include "test-utils.h"
15 #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
16 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
19 static SoupSession *session;
20 static const char *default_uri = "http://127.0.0.1:47524/xmlrpc-server.php";
21 static const char *uri = NULL;
22 static gboolean server_test = FALSE;
24 static const char *const value_type[] = {
37 do_xmlrpc (const char *method, GValue *retval, ...)
45 va_start (args, retval);
46 params = soup_value_array_from_args (args);
49 body = soup_xmlrpc_build_method_call (method, params->values,
51 g_value_array_free (params);
55 msg = soup_message_new ("POST", uri);
56 soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE,
58 soup_session_send_message (session, msg);
60 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
61 debug_printf (1, "ERROR: %d %s\n", msg->status_code,
67 if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
68 msg->response_body->length,
71 debug_printf (1, "FAULT: %d %s\n", err->code, err->message);
74 debug_printf (1, "ERROR: could not parse response\n");
84 check_xmlrpc (GValue *value, GType type, ...)
88 if (!G_VALUE_HOLDS (value, type)) {
89 debug_printf (1, "ERROR: could not parse response\n");
90 g_value_unset (value);
94 va_start (args, type);
95 SOUP_VALUE_GETV (value, type, args);
104 int i, val, sum, result;
108 debug_printf (1, "sum (array of int -> int): ");
110 ints = g_value_array_new (10);
111 for (i = sum = 0; i < 10; i++) {
113 debug_printf (2, "%s%d", i == 0 ? "[" : ", ", val);
114 soup_value_array_append (ints, G_TYPE_INT, val);
117 debug_printf (2, "] -> ");
119 ok = (do_xmlrpc ("sum", &retval,
120 G_TYPE_VALUE_ARRAY, ints,
122 check_xmlrpc (&retval, G_TYPE_INT, &result));
123 g_value_array_free (ints);
128 debug_printf (2, "%d: ", result);
129 debug_printf (1, "%s\n", result == sum ? "OK!" : "WRONG!");
130 return result == sum;
134 test_countBools (void)
137 int i, trues, falses;
139 int ret_trues, ret_falses;
143 debug_printf (1, "countBools (array of boolean -> struct of ints): ");
145 bools = g_value_array_new (10);
146 for (i = trues = falses = 0; i < 10; i++) {
147 val = rand () > (RAND_MAX / 2);
148 debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
149 soup_value_array_append (bools, G_TYPE_BOOLEAN, val);
155 debug_printf (2, "] -> ");
157 ok = (do_xmlrpc ("countBools", &retval,
158 G_TYPE_VALUE_ARRAY, bools,
160 check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result));
161 g_value_array_free (bools);
165 if (!soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues)) {
166 debug_printf (1, "NO 'true' value in response\n");
169 if (!soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses)) {
170 debug_printf (1, "NO 'false' value in response\n");
173 g_hash_table_destroy (result);
175 debug_printf (2, "{ true: %d, false: %d } ", ret_trues, ret_falses);
176 ok = (trues == ret_trues) && (falses == ret_falses);
177 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
184 GByteArray *data, *result;
188 gsize digest_len = sizeof (digest);
192 debug_printf (1, "md5sum (base64 -> base64): ");
194 data = g_byte_array_new ();
195 g_byte_array_set_size (data, 256);
196 for (i = 0; i < data->len; i++)
197 data->data[i] = (char)(rand ());
199 checksum = g_checksum_new (G_CHECKSUM_MD5);
200 g_checksum_update (checksum, data->data, data->len);
201 g_checksum_get_digest (checksum, digest, &digest_len);
202 g_checksum_free (checksum);
204 ok = (do_xmlrpc ("md5sum", &retval,
205 SOUP_TYPE_BYTE_ARRAY, data,
207 check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result));
208 g_byte_array_free (data, TRUE);
212 if (result->len != digest_len) {
213 debug_printf (1, "result has WRONG length (%d)\n", result->len);
214 g_byte_array_free (result, TRUE);
218 ok = (memcmp (digest, result->data, digest_len) == 0);
219 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
220 g_byte_array_free (result, TRUE);
225 test_dateChange (void)
227 GHashTable *structval;
228 SoupDate *date, *result;
233 debug_printf (1, "dateChange (date, struct of ints -> time): ");
235 date = soup_date_new (1970 + (rand () % 50),
241 if (debug_level >= 2) {
242 timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
243 debug_printf (2, "date: %s, {", timestamp);
247 structval = soup_value_hash_new ();
250 date->year = 1970 + (rand () % 50);
251 debug_printf (2, "tm_year: %d, ", date->year - 1900);
252 soup_value_hash_insert (structval, "tm_year",
253 G_TYPE_INT, date->year - 1900);
256 date->month = 1 + rand () % 12;
257 debug_printf (2, "tm_mon: %d, ", date->month - 1);
258 soup_value_hash_insert (structval, "tm_mon",
259 G_TYPE_INT, date->month - 1);
262 date->day = 1 + rand () % 28;
263 debug_printf (2, "tm_mday: %d, ", date->day);
264 soup_value_hash_insert (structval, "tm_mday",
265 G_TYPE_INT, date->day);
268 date->hour = rand () % 24;
269 debug_printf (2, "tm_hour: %d, ", date->hour);
270 soup_value_hash_insert (structval, "tm_hour",
271 G_TYPE_INT, date->hour);
274 date->minute = rand () % 60;
275 debug_printf (2, "tm_min: %d, ", date->minute);
276 soup_value_hash_insert (structval, "tm_min",
277 G_TYPE_INT, date->minute);
280 date->second = rand () % 60;
281 debug_printf (2, "tm_sec: %d, ", date->second);
282 soup_value_hash_insert (structval, "tm_sec",
283 G_TYPE_INT, date->second);
286 debug_printf (2, "} -> ");
288 ok = (do_xmlrpc ("dateChange", &retval,
289 SOUP_TYPE_DATE, date,
290 G_TYPE_HASH_TABLE, structval,
292 check_xmlrpc (&retval, SOUP_TYPE_DATE, &result));
293 g_hash_table_destroy (structval);
295 soup_date_free (date);
299 if (debug_level >= 2) {
300 timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC);
301 debug_printf (2, "%s: ", timestamp);
305 ok = ((date->year == result->year) &&
306 (date->month == result->month) &&
307 (date->day == result->day) &&
308 (date->hour == result->hour) &&
309 (date->minute == result->minute) &&
310 (date->second == result->second));
311 soup_date_free (date);
312 soup_date_free (result);
314 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
318 static const char *const echo_strings[] = {
322 "& so is <this>"
324 #define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings)
326 static const char *const echo_strings_broken[] = {
330 "amp; so is lt;thisgt;"
336 GValueArray *originals, *echoes;
339 gboolean php_bug = FALSE;
341 debug_printf (1, "echo (array of string -> array of string): ");
343 originals = g_value_array_new (N_ECHO_STRINGS);
344 for (i = 0; i < N_ECHO_STRINGS; i++) {
345 soup_value_array_append (originals, G_TYPE_STRING, echo_strings[i]);
346 debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo_strings[i]);
348 debug_printf (2, "] -> ");
350 if (!(do_xmlrpc ("echo", &retval,
351 G_TYPE_VALUE_ARRAY, originals,
353 check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) {
354 g_value_array_free (originals);
357 g_value_array_free (originals);
359 if (debug_level >= 2) {
360 for (i = 0; i < echoes->n_values; i++) {
361 debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ",
362 g_value_get_string (&echoes->values[i]));
364 debug_printf (2, "] -> ");
367 if (echoes->n_values != N_ECHO_STRINGS) {
368 debug_printf (1, " WRONG! Wrong number of return strings");
369 g_value_array_free (echoes);
373 for (i = 0; i < echoes->n_values; i++) {
374 if (strcmp (echo_strings[i], g_value_get_string (&echoes->values[i])) != 0) {
375 if (!server_test && strcmp (echo_strings_broken[i], g_value_get_string (&echoes->values[i])) == 0)
378 debug_printf (1, " WRONG! Mismatch at %d\n", i + 1);
379 g_value_array_free (echoes);
386 debug_printf (1, "WRONG, but it's php's fault\n");
388 debug_printf (1, "OK!\n");
389 g_value_array_free (echoes);
394 do_bad_xmlrpc (const char *body)
400 msg = soup_message_new ("POST", uri);
401 soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
402 body, strlen (body));
403 soup_session_send_message (session, msg);
405 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
406 debug_printf (1, "ERROR: %d %s\n", msg->status_code,
408 g_object_unref (msg);
412 if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
413 msg->response_body->length,
416 debug_printf (1, "FAULT: %d %s (OK!)\n",
417 err->code, err->message);
419 g_object_unref (msg);
422 debug_printf (1, "ERROR: could not parse response\n");
424 debug_printf (1, "Unexpectedly got successful response!\n");
426 g_object_unref (msg);
431 test_fault_malformed (void)
433 debug_printf (1, "malformed request: ");
435 return do_bad_xmlrpc ("<methodCall/>");
439 test_fault_method (void)
441 debug_printf (1, "request to non-existent method: ");
443 return do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
447 test_fault_args (void)
449 debug_printf (1, "request with invalid args: ");
451 return do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
454 static GOptionEntry xmlrpc_entries[] = {
455 { "uri", 'u', 0, G_OPTION_ARG_STRING, &uri,
456 "Alternate URI for server", NULL },
457 { "server-test", 's', 0, G_OPTION_ARG_NONE, &server_test,
458 "If this is being run from xmlrpc-server-test", NULL },
463 main (int argc, char **argv)
465 test_init (argc, argv, xmlrpc_entries);
474 session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
478 if (!test_countBools ())
482 if (!test_dateChange ())
486 if (!test_fault_malformed ())
488 if (!test_fault_method ())
490 if (!test_fault_args ())
493 soup_test_session_abort_unref (session);