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 static SoupSession *session;
16 static const char *default_uri = "http://localhost:47524/xmlrpc-server.php";
17 static const char *uri = NULL;
19 static const char *const value_type[] = {
32 do_xmlrpc (const char *method, GValue *retval, ...)
40 va_start (args, retval);
41 params = soup_value_array_from_args (args);
44 body = soup_xmlrpc_build_method_call (method, params->values,
46 g_value_array_free (params);
50 msg = soup_message_new ("POST", uri);
51 soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE,
53 soup_session_send_message (session, msg);
55 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
56 debug_printf (1, "ERROR: %d %s\n", msg->status_code,
62 if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
63 msg->response_body->length,
66 debug_printf (1, "FAULT: %d %s\n", err->code, err->message);
69 debug_printf (1, "ERROR: could not parse response\n");
79 check_xmlrpc (GValue *value, GType type, ...)
83 if (!G_VALUE_HOLDS (value, type)) {
84 debug_printf (1, "ERROR: could not parse response\n");
85 g_value_unset (value);
89 va_start (args, type);
90 SOUP_VALUE_GETV (value, type, args);
99 int i, val, sum, result;
103 debug_printf (1, "sum (array of int -> int): ");
105 ints = g_value_array_new (10);
106 for (i = sum = 0; i < 10; i++) {
108 debug_printf (2, "%s%d", i == 0 ? "[" : ", ", val);
109 soup_value_array_append (ints, G_TYPE_INT, val);
112 debug_printf (2, "] -> ");
114 ok = (do_xmlrpc ("sum", &retval,
115 G_TYPE_VALUE_ARRAY, ints,
117 check_xmlrpc (&retval, G_TYPE_INT, &result));
118 g_value_array_free (ints);
123 debug_printf (2, "%d: ", result);
124 debug_printf (1, "%s\n", result == sum ? "OK!" : "WRONG!");
125 return result == sum;
129 test_countBools (void)
132 int i, trues, falses;
134 int ret_trues, ret_falses;
138 debug_printf (1, "countBools (array of boolean -> struct of ints): ");
140 bools = g_value_array_new (10);
141 for (i = trues = falses = 0; i < 10; i++) {
142 val = rand () > (RAND_MAX / 2);
143 debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
144 soup_value_array_append (bools, G_TYPE_BOOLEAN, val);
150 debug_printf (2, "] -> ");
152 ok = (do_xmlrpc ("countBools", &retval,
153 G_TYPE_VALUE_ARRAY, bools,
155 check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result));
156 g_value_array_free (bools);
160 if (!soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues)) {
161 debug_printf (1, "NO 'true' value in response\n");
164 if (!soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses)) {
165 debug_printf (1, "NO 'false' value in response\n");
168 g_hash_table_destroy (result);
170 debug_printf (2, "{ true: %d, false: %d } ", ret_trues, ret_falses);
171 ok = (trues == ret_trues) && (falses == ret_falses);
172 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
179 GByteArray *data, *result;
183 gsize digest_len = sizeof (digest);
187 debug_printf (1, "md5sum (base64 -> base64): ");
189 data = g_byte_array_new ();
190 g_byte_array_set_size (data, 256);
191 for (i = 0; i < data->len; i++)
192 data->data[i] = (char)(rand ());
194 checksum = g_checksum_new (G_CHECKSUM_MD5);
195 g_checksum_update (checksum, data->data, data->len);
196 g_checksum_get_digest (checksum, digest, &digest_len);
197 g_checksum_free (checksum);
199 ok = (do_xmlrpc ("md5sum", &retval,
200 SOUP_TYPE_BYTE_ARRAY, data,
202 check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result));
203 g_byte_array_free (data, TRUE);
207 if (result->len != digest_len) {
208 debug_printf (1, "result has WRONG length (%d)\n", result->len);
209 g_byte_array_free (result, TRUE);
213 ok = (memcmp (digest, result->data, digest_len) == 0);
214 debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
215 g_byte_array_free (result, TRUE);
220 test_dateChange (void)
222 GHashTable *structval;
223 SoupDate *date, *result;
228 debug_printf (1, "dateChange (date, struct of ints -> time): ");
230 date = soup_date_new (1970 + (rand () % 50),
236 if (debug_level >= 2) {
237 timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
238 debug_printf (2, "date: %s, {", timestamp);
242 structval = soup_value_hash_new ();
245 date->year = 1970 + (rand () % 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 + rand () % 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 + rand () % 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 = rand () % 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 = rand () % 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 = rand () % 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)
324 GValueArray *originals, *echoes;
328 debug_printf (1, "echo (array of string -> array of string): ");
330 originals = g_value_array_new (N_ECHO_STRINGS);
331 for (i = 0; i < N_ECHO_STRINGS; i++) {
332 soup_value_array_append (originals, G_TYPE_STRING, echo_strings[i]);
333 debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo_strings[i]);
335 debug_printf (2, "] -> ");
337 if (!(do_xmlrpc ("echo", &retval,
338 G_TYPE_VALUE_ARRAY, originals,
340 check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) {
341 g_value_array_free (originals);
344 g_value_array_free (originals);
346 if (debug_level >= 2) {
347 for (i = 0; i < echoes->n_values; i++) {
348 debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ",
349 g_value_get_string (&echoes->values[i]));
351 debug_printf (2, "] -> ");
354 if (echoes->n_values != N_ECHO_STRINGS) {
355 debug_printf (1, " WRONG! Wrong number of return strings");
356 g_value_array_free (echoes);
360 for (i = 0; i < echoes->n_values; i++) {
361 if (strcmp (echo_strings[i], g_value_get_string (&echoes->values[i])) != 0) {
362 debug_printf (1, " WRONG! Mismatch at %d\n", i + 1);
363 g_value_array_free (echoes);
368 debug_printf (1, "OK!\n");
369 g_value_array_free (echoes);
374 do_bad_xmlrpc (const char *body)
380 msg = soup_message_new ("POST", uri);
381 soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
382 body, strlen (body));
383 soup_session_send_message (session, msg);
385 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
386 debug_printf (1, "ERROR: %d %s\n", msg->status_code,
388 g_object_unref (msg);
392 if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
393 msg->response_body->length,
396 debug_printf (1, "FAULT: %d %s (OK!)\n",
397 err->code, err->message);
399 g_object_unref (msg);
402 debug_printf (1, "ERROR: could not parse response\n");
404 debug_printf (1, "Unexpectedly got successful response!\n");
406 g_object_unref (msg);
411 test_fault_malformed (void)
413 debug_printf (1, "malformed request: ");
415 return do_bad_xmlrpc ("<methodCall/>");
419 test_fault_method (void)
421 debug_printf (1, "request to non-existent method: ");
423 return do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
427 test_fault_args (void)
429 debug_printf (1, "request with invalid args: ");
431 return do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
434 static GOptionEntry uri_entry[] = {
435 { "uri", 'u', 0, G_OPTION_ARG_STRING, &uri,
436 "Alternate URI for server", NULL },
441 main (int argc, char **argv)
443 test_init (argc, argv, uri_entry);
452 session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
456 if (!test_countBools ())
460 if (!test_dateChange ())
464 if (!test_fault_malformed ())
466 if (!test_fault_method ())
468 if (!test_fault_args ())
471 soup_test_session_abort_unref (session);