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"
8 #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
9 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
12 static SoupSession *session;
13 static const char *default_uri = "http://127.0.0.1:47524/xmlrpc-server.php";
14 static const char *uri = NULL;
15 static gboolean server_test = FALSE;
17 static const char *const value_type[] = {
30 do_xmlrpc (const char *method, GValue *retval, ...)
38 va_start (args, retval);
39 params = soup_value_array_from_args (args);
42 body = soup_xmlrpc_build_method_call (method, params->values,
44 g_value_array_free (params);
48 msg = soup_message_new ("POST", uri);
49 soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE,
51 soup_session_send_message (session, msg);
53 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
54 debug_printf (1, "ERROR: %d %s\n", msg->status_code,
60 if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
61 msg->response_body->length,
64 debug_printf (1, "FAULT: %d %s\n", err->code, err->message);
67 debug_printf (1, "ERROR: could not parse response\n");
77 check_xmlrpc (GValue *value, GType type, ...)
81 if (!G_VALUE_HOLDS (value, type)) {
82 debug_printf (1, "ERROR: could not parse response\n");
83 g_value_unset (value);
87 va_start (args, type);
88 SOUP_VALUE_GETV (value, type, args);
97 int i, val, sum, result;
101 debug_printf (1, "sum (array of int -> int): ");
103 ints = g_value_array_new (10);
104 for (i = sum = 0; i < 10; i++) {
105 val = g_random_int_range (0, 100);
106 debug_printf (2, "%s%d", i == 0 ? "[" : ", ", val);
107 soup_value_array_append (ints, G_TYPE_INT, val);
110 debug_printf (2, "] -> ");
112 ok = (do_xmlrpc ("sum", &retval,
113 G_TYPE_VALUE_ARRAY, ints,
115 check_xmlrpc (&retval, G_TYPE_INT, &result));
116 g_value_array_free (ints);
121 debug_printf (2, "%d: ", result);
122 debug_printf (1, "%s\n", result == sum ? "OK!" : "WRONG!");
123 return result == sum;
127 test_countBools (void)
130 int i, trues, falses;
132 int ret_trues, ret_falses;
136 debug_printf (1, "countBools (array of boolean -> struct of ints): ");
138 bools = g_value_array_new (10);
139 for (i = trues = falses = 0; i < 10; i++) {
140 val = g_random_boolean ();
141 debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
142 soup_value_array_append (bools, G_TYPE_BOOLEAN, val);
148 debug_printf (2, "] -> ");
150 ok = (do_xmlrpc ("countBools", &retval,
151 G_TYPE_VALUE_ARRAY, bools,
153 check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result));
154 g_value_array_free (bools);
158 if (!soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues)) {
159 debug_printf (1, "NO 'true' value in response\n");
162 if (!soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses)) {
163 debug_printf (1, "NO 'false' value in response\n");
166 g_hash_table_destroy (result);
168 debug_printf (2, "{ true: %d, false: %d } ", ret_trues, ret_falses);
169 ok = (trues == ret_trues) && (falses == ret_falses);
170 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
177 GByteArray *data, *result;
181 gsize digest_len = sizeof (digest);
185 debug_printf (1, "md5sum (base64 -> base64): ");
187 data = g_byte_array_new ();
188 g_byte_array_set_size (data, 256);
189 for (i = 0; i < data->len; i++)
190 data->data[i] = (char)(g_random_int_range (0, 256));
192 checksum = g_checksum_new (G_CHECKSUM_MD5);
193 g_checksum_update (checksum, data->data, data->len);
194 g_checksum_get_digest (checksum, digest, &digest_len);
195 g_checksum_free (checksum);
197 ok = (do_xmlrpc ("md5sum", &retval,
198 SOUP_TYPE_BYTE_ARRAY, data,
200 check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result));
201 g_byte_array_free (data, TRUE);
205 if (result->len != digest_len) {
206 debug_printf (1, "result has WRONG length (%d)\n", result->len);
207 g_byte_array_free (result, TRUE);
211 ok = (memcmp (digest, result->data, digest_len) == 0);
212 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
213 g_byte_array_free (result, TRUE);
218 test_dateChange (void)
220 GHashTable *structval;
221 SoupDate *date, *result;
226 debug_printf (1, "dateChange (date, struct of ints -> time): ");
228 date = soup_date_new (1970 + (g_random_int_range (0, 50)),
229 1 + g_random_int_range (0, 12),
230 1 + g_random_int_range (0, 28),
231 g_random_int_range (0, 24),
232 g_random_int_range (0, 60),
233 g_random_int_range (0, 60));
234 if (debug_level >= 2) {
235 timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
236 debug_printf (2, "date: %s, {", timestamp);
240 structval = soup_value_hash_new ();
242 #define MAYBE (g_random_int_range (0, 3) != 0)
245 date->year = 1970 + (g_random_int_range (0, 50));
246 debug_printf (2, "tm_year: %d, ", date->year - 1900);
247 soup_value_hash_insert (structval, "tm_year",
248 G_TYPE_INT, date->year - 1900);
251 date->month = 1 + g_random_int_range (0, 12);
252 debug_printf (2, "tm_mon: %d, ", date->month - 1);
253 soup_value_hash_insert (structval, "tm_mon",
254 G_TYPE_INT, date->month - 1);
257 date->day = 1 + g_random_int_range (0, 28);
258 debug_printf (2, "tm_mday: %d, ", date->day);
259 soup_value_hash_insert (structval, "tm_mday",
260 G_TYPE_INT, date->day);
263 date->hour = g_random_int_range (0, 24);
264 debug_printf (2, "tm_hour: %d, ", date->hour);
265 soup_value_hash_insert (structval, "tm_hour",
266 G_TYPE_INT, date->hour);
269 date->minute = g_random_int_range (0, 60);
270 debug_printf (2, "tm_min: %d, ", date->minute);
271 soup_value_hash_insert (structval, "tm_min",
272 G_TYPE_INT, date->minute);
275 date->second = g_random_int_range (0, 60);
276 debug_printf (2, "tm_sec: %d, ", date->second);
277 soup_value_hash_insert (structval, "tm_sec",
278 G_TYPE_INT, date->second);
281 debug_printf (2, "} -> ");
283 ok = (do_xmlrpc ("dateChange", &retval,
284 SOUP_TYPE_DATE, date,
285 G_TYPE_HASH_TABLE, structval,
287 check_xmlrpc (&retval, SOUP_TYPE_DATE, &result));
288 g_hash_table_destroy (structval);
290 soup_date_free (date);
294 if (debug_level >= 2) {
295 timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC);
296 debug_printf (2, "%s: ", timestamp);
300 ok = ((date->year == result->year) &&
301 (date->month == result->month) &&
302 (date->day == result->day) &&
303 (date->hour == result->hour) &&
304 (date->minute == result->minute) &&
305 (date->second == result->second));
306 soup_date_free (date);
307 soup_date_free (result);
309 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
313 static const char *const echo_strings[] = {
317 "& so is <this>"
319 #define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings)
321 static const char *const echo_strings_broken[] = {
325 "amp; so is lt;thisgt;"
331 GValueArray *originals, *echoes;
334 gboolean php_bug = FALSE;
336 debug_printf (1, "echo (array of string -> array of string): ");
338 originals = g_value_array_new (N_ECHO_STRINGS);
339 for (i = 0; i < N_ECHO_STRINGS; i++) {
340 soup_value_array_append (originals, G_TYPE_STRING, echo_strings[i]);
341 debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo_strings[i]);
343 debug_printf (2, "] -> ");
345 if (!(do_xmlrpc ("echo", &retval,
346 G_TYPE_VALUE_ARRAY, originals,
348 check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) {
349 g_value_array_free (originals);
352 g_value_array_free (originals);
354 if (debug_level >= 2) {
355 for (i = 0; i < echoes->n_values; i++) {
356 debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ",
357 g_value_get_string (&echoes->values[i]));
359 debug_printf (2, "] -> ");
362 if (echoes->n_values != N_ECHO_STRINGS) {
363 debug_printf (1, " WRONG! Wrong number of return strings");
364 g_value_array_free (echoes);
368 for (i = 0; i < echoes->n_values; i++) {
369 if (strcmp (echo_strings[i], g_value_get_string (&echoes->values[i])) != 0) {
370 if (!server_test && strcmp (echo_strings_broken[i], g_value_get_string (&echoes->values[i])) == 0)
373 debug_printf (1, " WRONG! Mismatch at %d\n", i + 1);
374 g_value_array_free (echoes);
381 debug_printf (1, "WRONG, but it's php's fault\n");
383 debug_printf (1, "OK!\n");
384 g_value_array_free (echoes);
389 do_bad_xmlrpc (const char *body)
395 msg = soup_message_new ("POST", uri);
396 soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
397 body, strlen (body));
398 soup_session_send_message (session, msg);
400 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
401 debug_printf (1, "ERROR: %d %s\n", msg->status_code,
403 g_object_unref (msg);
407 if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
408 msg->response_body->length,
411 debug_printf (1, "FAULT: %d %s (OK!)\n",
412 err->code, err->message);
414 g_object_unref (msg);
417 debug_printf (1, "ERROR: could not parse response\n");
419 debug_printf (1, "Unexpectedly got successful response!\n");
421 g_object_unref (msg);
426 test_fault_malformed (void)
428 debug_printf (1, "malformed request: ");
430 return do_bad_xmlrpc ("<methodCall/>");
434 test_fault_method (void)
436 debug_printf (1, "request to non-existent method: ");
438 return do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
442 test_fault_args (void)
444 debug_printf (1, "request with invalid args: ");
446 return do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
449 static GOptionEntry xmlrpc_entries[] = {
450 { "uri", 'u', 0, G_OPTION_ARG_STRING, &uri,
451 "Alternate URI for server", NULL },
452 { "server-test", 's', 0, G_OPTION_ARG_NONE, &server_test,
453 "If this is being run from xmlrpc-server-test", NULL },
458 main (int argc, char **argv)
460 test_init (argc, argv, xmlrpc_entries);
467 session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
471 if (!test_countBools ())
475 if (!test_dateChange ())
479 if (!test_fault_malformed ())
481 if (!test_fault_method ())
483 if (!test_fault_args ())
486 soup_test_session_abort_unref (session);