• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2001-2003, Ximian, Inc.
4  */
5 
6 #include "test-utils.h"
7 
8 #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
9 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
10 #endif
11 
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;
16 
17 #ifdef HAVE_PHP_XMLRPC
18 #define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER
19 #else
20 #define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER				\
21 	G_STMT_START {							\
22 		if (!server_test) {					\
23 			g_test_skip ("php-xmlrpc is not available");	\
24 			return;						\
25 		}							\
26 	} G_STMT_END
27 #endif
28 
29 static gboolean
send_xmlrpc(const char * body,GValue * retval)30 send_xmlrpc (const char *body, GValue *retval)
31 {
32 	SoupMessage *msg;
33 	GError *err = NULL;
34 
35 	msg = soup_message_new ("POST", uri);
36 	soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
37 				  body, strlen (body));
38 	soup_session_send_message (session, msg);
39 
40 	soup_test_assert_message_status (msg, SOUP_STATUS_OK);
41 
42 	if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
43 						msg->response_body->length,
44 						retval, &err)) {
45 		if (err) {
46 			soup_test_assert (FALSE, "FAULT: %d %s\n", err->code, err->message);
47 			g_error_free (err);
48 		} else
49 			soup_test_assert (FALSE, "ERROR: could not parse response\n");
50 		g_object_unref (msg);
51 		return FALSE;
52 	}
53 	g_object_unref (msg);
54 
55 	return TRUE;
56 }
57 
58 static gboolean
do_xmlrpc(const char * method,GValue * retval,...)59 do_xmlrpc (const char *method, GValue *retval, ...)
60 {
61 	va_list args;
62 	GValueArray *params;
63 	char *body;
64 	gboolean ret;
65 
66 	va_start (args, retval);
67 	params = soup_value_array_from_args (args);
68 	va_end (args);
69 
70 	body = soup_xmlrpc_build_method_call (method, params->values,
71 					      params->n_values);
72 	g_value_array_free (params);
73 	if (!body)
74 		return FALSE;
75 
76 	ret = send_xmlrpc (body, retval);
77 	g_free (body);
78 
79 	return ret;
80 }
81 
82 static gboolean
check_xmlrpc(GValue * value,GType type,...)83 check_xmlrpc (GValue *value, GType type, ...)
84 {
85 	va_list args;
86 
87 	if (!G_VALUE_HOLDS (value, type)) {
88 		g_assert_true (G_VALUE_HOLDS (value, type));
89 		return FALSE;
90 	}
91 
92 	va_start (args, type);
93 	SOUP_VALUE_GETV (value, type, args);
94 	va_end (args);
95 	return TRUE;
96 }
97 
98 static void
test_sum(void)99 test_sum (void)
100 {
101 	GValueArray *dbls;
102 	int i;
103 	double val, sum, result;
104 	GValue retval;
105 	gboolean ok;
106 
107 	SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
108 
109 	debug_printf (2, "sum (array of double -> double): ");
110 
111 	dbls = g_value_array_new (10);
112 	for (i = sum = 0; i < 10; i++) {
113 		val = g_random_int_range (0, 400) / 4.0;
114 		debug_printf (2, "%s%.2f", i == 0 ? "[" : ", ", val);
115 		soup_value_array_append (dbls, G_TYPE_DOUBLE, val);
116 		sum += val;
117 	}
118 	debug_printf (2, "] -> ");
119 
120 	ok = (do_xmlrpc ("sum", &retval,
121 			G_TYPE_VALUE_ARRAY, dbls,
122 			G_TYPE_INVALID) &&
123 	      check_xmlrpc (&retval, G_TYPE_DOUBLE, &result));
124 	g_value_array_free (dbls);
125 
126 	if (!ok)
127 		return;
128 
129 	debug_printf (2, "%.2f\n", result);
130 	g_assert_cmpfloat (result, ==, sum);
131 }
132 
133 static void
test_countBools(void)134 test_countBools (void)
135 {
136 	GValueArray *bools;
137 	int i, trues, falses;
138 	GValue retval;
139 	int ret_trues, ret_falses;
140 	gboolean val, ok;
141 	GHashTable *result;
142 
143 	SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
144 
145 	debug_printf (2, "countBools (array of boolean -> struct of ints): ");
146 
147 	bools = g_value_array_new (10);
148 	for (i = trues = falses = 0; i < 10; i++) {
149 		val = g_random_boolean ();
150 		debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
151 		soup_value_array_append (bools, G_TYPE_BOOLEAN, val);
152 		if (val)
153 			trues++;
154 		else
155 			falses++;
156 	}
157 	debug_printf (2, "] -> ");
158 
159 	ok = (do_xmlrpc ("countBools", &retval,
160 			 G_TYPE_VALUE_ARRAY, bools,
161 			 G_TYPE_INVALID) &&
162 	      check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result));
163 	g_value_array_free (bools);
164 	if (!ok)
165 		return;
166 
167 	g_assert_true (soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues));
168 	g_assert_true (soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses));
169 
170 	g_hash_table_destroy (result);
171 
172 	debug_printf (2, "{ true: %d, false: %d }\n", ret_trues, ret_falses);
173 	g_assert_cmpint (trues, ==, ret_trues);
174 	g_assert_cmpint (falses, ==, ret_falses);
175 }
176 
177 static void
test_md5sum(void)178 test_md5sum (void)
179 {
180 	GByteArray *data, *result;
181 	int i;
182 	GChecksum *checksum;
183 	guchar digest[16];
184 	gsize digest_len = sizeof (digest);
185 	GValue retval;
186 	gboolean ok;
187 
188 	SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
189 
190 	debug_printf (2, "md5sum (base64 -> base64)\n");
191 
192 	data = g_byte_array_new ();
193 	g_byte_array_set_size (data, 256);
194 	for (i = 0; i < data->len; i++)
195 		data->data[i] = (char)(g_random_int_range (0, 256));
196 
197 	checksum = g_checksum_new (G_CHECKSUM_MD5);
198 	g_checksum_update (checksum, data->data, data->len);
199 	g_checksum_get_digest (checksum, digest, &digest_len);
200 	g_checksum_free (checksum);
201 
202 	ok = (do_xmlrpc ("md5sum", &retval,
203 			 SOUP_TYPE_BYTE_ARRAY, data,
204 			 G_TYPE_INVALID) &&
205 	      check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result));
206 	g_byte_array_free (data, TRUE);
207 	if (!ok)
208 		return;
209 
210 	soup_assert_cmpmem (result->data, result->len,
211 			    digest, digest_len);
212 	g_byte_array_free (result, TRUE);
213 }
214 
215 static void
test_dateChange(void)216 test_dateChange (void)
217 {
218 	GHashTable *structval;
219 	SoupDate *date, *result;
220 	char *timestamp;
221 	GValue retval;
222 	gboolean ok;
223 
224 	SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
225 
226 	debug_printf (2, "dateChange (date, struct of ints -> time)\n");
227 
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);
237 		g_free (timestamp);
238 	}
239 
240 	structval = soup_value_hash_new ();
241 
242 #define MAYBE (g_random_int_range (0, 3) != 0)
243 
244 	if (MAYBE) {
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);
249 	}
250 	if (MAYBE) {
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);
255 	}
256 	if (MAYBE) {
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);
261 	}
262 	if (MAYBE) {
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);
267 	}
268 	if (MAYBE) {
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);
273 	}
274 	if (MAYBE) {
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);
279 	}
280 
281 	debug_printf (2, "} -> ");
282 
283 	ok = (do_xmlrpc ("dateChange", &retval,
284 			 SOUP_TYPE_DATE, date,
285 			 G_TYPE_HASH_TABLE, structval,
286 			 G_TYPE_INVALID) &&
287 	      check_xmlrpc (&retval, SOUP_TYPE_DATE, &result));
288 	g_hash_table_destroy (structval);
289 	if (!ok) {
290 		soup_date_free (date);
291 		return;
292 	}
293 
294 	if (debug_level >= 2) {
295 		timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC);
296 		debug_printf (2, "%s\n", timestamp);
297 		g_free (timestamp);
298 	}
299 
300 	g_assert_cmpint (date->year,   ==, result->year);
301 	g_assert_cmpint (date->month,  ==, result->month);
302 	g_assert_cmpint (date->day,    ==, result->day);
303 	g_assert_cmpint (date->hour,   ==, result->hour);
304 	g_assert_cmpint (date->minute, ==, result->minute);
305 	g_assert_cmpint (date->second, ==, result->second);
306 
307 	soup_date_free (date);
308 	soup_date_free (result);
309 }
310 
311 static const char *const echo_strings[] = {
312 	"This is a test",
313 	"& so is this",
314 	"and so is <this>",
315 	"&amp; so is &lt;this&gt;"
316 };
317 #define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings)
318 
319 static void
test_echo(void)320 test_echo (void)
321 {
322 	GValueArray *originals, *echoes;
323 	GValue retval;
324 	int i;
325 
326 	SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
327 
328 	debug_printf (2, "echo (array of string -> array of string):\n");
329 
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]);
334 	}
335 	debug_printf (2, "] -> ");
336 
337 	if (!(do_xmlrpc ("echo", &retval,
338 			 G_TYPE_VALUE_ARRAY, originals,
339 			 G_TYPE_INVALID) &&
340 	      check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) {
341 		g_value_array_free (originals);
342 		return;
343 	}
344 	g_value_array_free (originals);
345 
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]));
350 		}
351 		debug_printf (2, "]\n");
352 	}
353 
354 	g_assert_cmpint (echoes->n_values, ==, N_ECHO_STRINGS);
355 
356 	for (i = 0; i < echoes->n_values; i++)
357 		g_assert_cmpstr (echo_strings[i], ==, g_value_get_string (&echoes->values[i]));
358 
359 	g_value_array_free (echoes);
360 }
361 
362 static void
test_ping(gconstpointer include_params)363 test_ping (gconstpointer include_params)
364 {
365 	GValueArray *params;
366 	GValue retval;
367 	char *request;
368 	char *out;
369 	gboolean ret;
370 
371 	g_test_bug ("671661");
372 
373 	SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
374 
375 	debug_printf (2, "ping (void (%s) -> string)\n",
376 		      include_params ? "empty <params>" : "no <params>");
377 
378 	params = soup_value_array_new ();
379 	request = soup_xmlrpc_build_method_call ("ping", params->values,
380 						 params->n_values);
381 	g_value_array_free (params);
382 	if (!request)
383 		return;
384 
385 	if (!include_params) {
386 		char *params, *end;
387 
388 		params = strstr (request, "<params/>");
389 		if (!params) {
390 			soup_test_assert (FALSE, "ERROR: XML did not contain <params/>!");
391 			return;
392 		}
393 		end = params + strlen ("<params/>");
394 		memmove (params, end, strlen (end) + 1);
395 	}
396 
397 	ret = send_xmlrpc (request, &retval);
398 	g_free (request);
399 
400 	if (!ret || !check_xmlrpc (&retval, G_TYPE_STRING, &out))
401 		return;
402 
403 	g_assert_cmpstr (out, ==, "pong");
404 
405 	g_free (out);
406 }
407 
408 static void
do_bad_xmlrpc(const char * body)409 do_bad_xmlrpc (const char *body)
410 {
411 	SoupMessage *msg;
412 	GError *err = NULL;
413 	GValue retval;
414 
415 	msg = soup_message_new ("POST", uri);
416 	soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
417 				  body, strlen (body));
418 	soup_session_send_message (session, msg);
419 
420 	soup_test_assert_message_status (msg, SOUP_STATUS_OK);
421 
422 	if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
423 						msg->response_body->length,
424 						&retval, &err)) {
425 		if (err) {
426 			debug_printf (1, "FAULT: %d %s (OK!)\n",
427 				      err->code, err->message);
428 			g_error_free (err);
429 			g_object_unref (msg);
430 			return;
431 		} else
432 			soup_test_assert (FALSE, "ERROR: could not parse response\n");
433 	} else
434 		soup_test_assert (FALSE, "Unexpectedly got successful response!\n");
435 
436 	g_object_unref (msg);
437 }
438 
439 static void
test_fault_malformed(void)440 test_fault_malformed (void)
441 {
442 	SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
443 
444 	do_bad_xmlrpc ("<methodCall/>");
445 }
446 
447 static void
test_fault_method(void)448 test_fault_method (void)
449 {
450 	SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
451 
452 	do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
453 }
454 
455 static void
test_fault_args(void)456 test_fault_args (void)
457 {
458 	SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
459 
460 	do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
461 }
462 
463 static GOptionEntry xmlrpc_entries[] = {
464         { "uri", 'U', 0, G_OPTION_ARG_STRING, &uri,
465           "Alternate URI for server", NULL },
466         { "server-test", 'S', 0, G_OPTION_ARG_NONE, &server_test,
467           "If this is being run from xmlrpc-old-server-test", NULL },
468         { NULL }
469 };
470 
471 int
main(int argc,char ** argv)472 main (int argc, char **argv)
473 {
474 	int ret;
475 
476 	test_init (argc, argv, xmlrpc_entries);
477 
478 	if (!uri && !server_test) {
479 		apache_init ();
480 		uri = default_uri;
481 	}
482 
483 	session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
484 
485 	g_test_add_func ("/xmlrpc-old/sum", test_sum);
486 	g_test_add_func ("/xmlrpc-old/countBools", test_countBools);
487 	g_test_add_func ("/xmlrpc-old/md5sum", test_md5sum);
488 	g_test_add_func ("/xmlrpc-old/dateChange", test_dateChange);
489 	g_test_add_func ("/xmlrpc-old/echo", test_echo);
490 	g_test_add_data_func ("/xmlrpc-old/ping/empty-params", GINT_TO_POINTER (TRUE), test_ping);
491 	g_test_add_data_func ("/xmlrpc-old/ping/no-params", GINT_TO_POINTER (FALSE), test_ping);
492 	g_test_add_func ("/xmlrpc-old/fault/malformed", test_fault_malformed);
493 	g_test_add_func ("/xmlrpc-old/fault/method", test_fault_method);
494 	g_test_add_func ("/xmlrpc-old/fault/args", test_fault_args);
495 
496 	ret = g_test_run ();
497 
498 	soup_test_session_abort_unref (session);
499 
500 	test_cleanup ();
501 	return ret;
502 }
503