• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2008 Red Hat, Inc.
4  */
5 
6 #include "test-utils.h"
7 
8 static char *uri;
9 
10 #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
11 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
12 #endif
13 
14 static void
type_error(SoupMessage * msg,GType expected,GValueArray * params,int bad_value)15 type_error (SoupMessage *msg, GType expected, GValueArray *params, int bad_value)
16 {
17 	soup_xmlrpc_set_fault (msg,
18 			       SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
19 			       "Bad parameter #%d: expected %s, got %s",
20 			       bad_value + 1, g_type_name (expected),
21 			       g_type_name (G_VALUE_TYPE (&params->values[bad_value])));
22 }
23 
24 static void
args_error(SoupMessage * msg,GValueArray * params,int expected)25 args_error (SoupMessage *msg, GValueArray *params, int expected)
26 {
27 	soup_xmlrpc_set_fault (msg,
28 			       SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
29 			       "Wrong number of parameters: expected %d, got %d",
30 			       expected, params->n_values);
31 }
32 
33 static void
do_sum(SoupMessage * msg,GValueArray * params)34 do_sum (SoupMessage *msg, GValueArray *params)
35 {
36 	int i;
37 	double sum = 0.0, val;
38 	GValueArray *nums;
39 
40 	if (params->n_values != 1) {
41 		args_error (msg, params, 1);
42 		return;
43 	}
44 	if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &nums)) {
45 		type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
46 		return;
47 	}
48 
49 	for (i = 0; i < nums->n_values; i++) {
50 		if (!soup_value_array_get_nth (nums, i, G_TYPE_DOUBLE, &val)) {
51 			type_error (msg, G_TYPE_DOUBLE, nums, i);
52 			return;
53 		}
54 		sum += val;
55 	}
56 
57 	soup_xmlrpc_set_response (msg, G_TYPE_DOUBLE, sum);
58 
59 }
60 
61 static void
do_countBools(SoupMessage * msg,GValueArray * params)62 do_countBools (SoupMessage *msg, GValueArray *params)
63 {
64 	int i, trues = 0, falses = 0;
65 	GValueArray *bools;
66 	GHashTable *ret = soup_value_hash_new ();
67 	gboolean val;
68 
69 	if (params->n_values != 1) {
70 		args_error (msg, params, 1);
71 		return;
72 	}
73 	if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &bools)) {
74 		type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
75 		return;
76 	}
77 
78 	for (i = 0; i < bools->n_values; i++) {
79 		if (!soup_value_array_get_nth (bools, i, G_TYPE_BOOLEAN, &val)) {
80 			type_error (msg, G_TYPE_BOOLEAN, params, i);
81 			return;
82 		}
83 		if (val)
84 			trues++;
85 		else
86 			falses++;
87 	}
88 
89 	soup_value_hash_insert (ret, "true", G_TYPE_INT, trues);
90 	soup_value_hash_insert (ret, "false", G_TYPE_INT, falses);
91 	soup_xmlrpc_set_response (msg, G_TYPE_HASH_TABLE, ret);
92 	g_hash_table_destroy (ret);
93 
94 }
95 
96 static void
do_md5sum(SoupMessage * msg,GValueArray * params)97 do_md5sum (SoupMessage *msg, GValueArray *params)
98 {
99 	GChecksum *checksum;
100 	GByteArray *data, *digest;
101 	gsize digest_len = 16;
102 
103 	if (params->n_values != 1) {
104 		args_error (msg, params, 1);
105 		return;
106 	}
107 
108 	if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_BYTE_ARRAY, &data)) {
109 		type_error (msg, SOUP_TYPE_BYTE_ARRAY, params, 0);
110 		return;
111 	}
112 	checksum = g_checksum_new (G_CHECKSUM_MD5);
113 	g_checksum_update (checksum, data->data, data->len);
114 	digest = g_byte_array_new ();
115 	g_byte_array_set_size (digest, digest_len);
116 	g_checksum_get_digest (checksum, digest->data, &digest_len);
117 	g_checksum_free (checksum);
118 
119 	soup_xmlrpc_set_response (msg, SOUP_TYPE_BYTE_ARRAY, digest);
120 	g_byte_array_free (digest, TRUE);
121 }
122 
123 
124 static void
do_dateChange(SoupMessage * msg,GValueArray * params)125 do_dateChange (SoupMessage *msg, GValueArray *params)
126 {
127 	GHashTable *arg;
128 	SoupDate *date;
129 	int val;
130 
131 	if (params->n_values != 2) {
132 		args_error (msg, params, 2);
133 		return;
134 	}
135 
136 	if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_DATE, &date)) {
137 		type_error (msg, SOUP_TYPE_DATE, params, 0);
138 		return;
139 	}
140 	if (!soup_value_array_get_nth (params, 1, G_TYPE_HASH_TABLE, &arg)) {
141 		type_error (msg, G_TYPE_HASH_TABLE, params, 1);
142 		return;
143 	}
144 
145 	if (soup_value_hash_lookup (arg, "tm_year", G_TYPE_INT, &val))
146 		date->year = val + 1900;
147 	if (soup_value_hash_lookup (arg, "tm_mon", G_TYPE_INT, &val))
148 		date->month = val + 1;
149 	if (soup_value_hash_lookup (arg, "tm_mday", G_TYPE_INT, &val))
150 		date->day = val;
151 	if (soup_value_hash_lookup (arg, "tm_hour", G_TYPE_INT, &val))
152 		date->hour = val;
153 	if (soup_value_hash_lookup (arg, "tm_min", G_TYPE_INT, &val))
154 		date->minute = val;
155 	if (soup_value_hash_lookup (arg, "tm_sec", G_TYPE_INT, &val))
156 		date->second = val;
157 
158 	soup_xmlrpc_set_response (msg, SOUP_TYPE_DATE, date);
159 }
160 
161 static void
do_echo(SoupMessage * msg,GValueArray * params)162 do_echo (SoupMessage *msg, GValueArray *params)
163 {
164 	int i;
165 	const char *val;
166 	GValueArray *in, *out;
167 
168 	if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &in)) {
169 		type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
170 		return;
171 	}
172 
173 	out = g_value_array_new (in->n_values);
174 	for (i = 0; i < in->n_values; i++) {
175 		if (!soup_value_array_get_nth (in, i, G_TYPE_STRING, &val)) {
176 			type_error (msg, G_TYPE_STRING, in, i);
177 			return;
178 		}
179 		soup_value_array_append (out, G_TYPE_STRING, val);
180 	}
181 
182 	soup_xmlrpc_set_response (msg, G_TYPE_VALUE_ARRAY, out);
183 	g_value_array_free (out);
184 }
185 
186 static void
do_ping(SoupMessage * msg,GValueArray * params)187 do_ping (SoupMessage *msg, GValueArray *params)
188 {
189 	if (params->n_values) {
190 		args_error (msg, params, 0);
191 		return;
192 	}
193 
194 	soup_xmlrpc_set_response (msg, G_TYPE_STRING, "pong");
195 }
196 
197 static void
server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * context,gpointer data)198 server_callback (SoupServer *server, SoupMessage *msg,
199 		 const char *path, GHashTable *query,
200 		 SoupClientContext *context, gpointer data)
201 {
202 	char *method_name;
203 	GValueArray *params;
204 
205 	if (msg->method != SOUP_METHOD_POST) {
206 		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
207 		return;
208 	}
209 
210 	soup_message_set_status (msg, SOUP_STATUS_OK);
211 
212 	if (!soup_xmlrpc_parse_method_call (msg->request_body->data,
213 					    msg->request_body->length,
214 					    &method_name, &params)) {
215 		soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED,
216 				       "Could not parse method call");
217 		return;
218 	}
219 
220 	if (!strcmp (method_name, "sum"))
221 		do_sum (msg, params);
222 	else if (!strcmp (method_name, "countBools"))
223 		do_countBools (msg, params);
224 	else if (!strcmp (method_name, "md5sum"))
225 		do_md5sum (msg, params);
226 	else if (!strcmp (method_name, "dateChange"))
227 		do_dateChange (msg, params);
228 	else if (!strcmp (method_name, "echo"))
229 		do_echo (msg, params);
230 	else if (!strcmp (method_name, "ping"))
231 		do_ping (msg, params);
232 	else {
233 		soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND,
234 				       "Unknown method %s", method_name);
235 	}
236 
237 	g_free (method_name);
238 	g_value_array_free (params);
239 }
240 
241 static gboolean
run_xmlrpc_test(char ** argv,char ** stdout_out,char ** stderr_out,GError ** error)242 run_xmlrpc_test (char **argv,
243 		 char **stdout_out,
244 		 char **stderr_out,
245 		 GError **error)
246 {
247 	gboolean ok;
248 	int status;
249 
250 	argv[0] = g_test_build_filename (G_TEST_BUILT, "xmlrpc-old-test", NULL);
251 	ok = g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL,
252 			   stdout_out, stderr_out, &status,
253 			   error);
254 	g_free (argv[0]);
255 
256 	if (!ok)
257 		return FALSE;
258 
259 	return g_spawn_check_exit_status (status, error);
260 }
261 
262 static void
do_one_xmlrpc_test(gconstpointer data)263 do_one_xmlrpc_test (gconstpointer data)
264 {
265 	const char *path = data;
266 	char *argv[12];
267 	char *stdout_out, *stderr_out;
268 	GError *error = NULL;
269 	int arg;
270 
271 	argv[0] = NULL;
272 	argv[1] = "-S";
273 	argv[2] = "-U";
274 	argv[3] = uri;
275 	argv[4] = "-q";
276 	argv[5] = "-p";
277 	argv[6] = (char *) path;
278 
279 	for (arg = 0; arg < debug_level && arg < 3; arg++)
280 		argv[arg + 7] = "-d";
281 	argv[arg + 7] = NULL;
282 
283 	run_xmlrpc_test (argv, &stdout_out, &stderr_out, &error);
284 	if (stdout_out) {
285 		g_print ("%s", stdout_out);
286 		g_free (stdout_out);
287 	}
288 	if (stderr_out) {
289 		g_printerr ("%s", stderr_out);
290 		g_free (stderr_out);
291 	}
292 
293 	if (   g_error_matches (error, G_SPAWN_EXIT_ERROR, 1)
294 	    || g_error_matches (error, G_SPAWN_EXIT_ERROR, 77))
295 		g_test_fail ();
296 	else
297 		g_assert_no_error (error);
298 	g_clear_error (&error);
299 }
300 
301 gboolean run_tests = TRUE;
302 
303 static GOptionEntry no_test_entry[] = {
304         { "no-tests", 'n', G_OPTION_FLAG_REVERSE,
305           G_OPTION_ARG_NONE, &run_tests,
306           "Don't run tests, just run the test server", NULL },
307         { NULL }
308 };
309 
310 int
main(int argc,char ** argv)311 main (int argc, char **argv)
312 {
313 	SoupServer *server;
314 	SoupURI *server_uri;
315 	int ret;
316 
317 	test_init (argc, argv, no_test_entry);
318 
319 	server = soup_test_server_new (run_tests ? SOUP_TEST_SERVER_IN_THREAD : SOUP_TEST_SERVER_DEFAULT);
320 	soup_server_add_handler (server, "/xmlrpc-server.php",
321 				 server_callback, NULL, NULL);
322 	server_uri = soup_test_server_get_uri (server, "http", NULL);
323 	soup_uri_set_path (server_uri, "/xmlrpc-server.php");
324 	uri = soup_uri_to_string (server_uri, FALSE);
325 
326 	if (run_tests) {
327 		char *out, **tests, *path;
328 		char *list_argv[4];
329 		GError *error = NULL;
330 		int i;
331 
332 		list_argv[0] = NULL;
333 		list_argv[1] = "-S";
334 		list_argv[2] = "-l";
335 		list_argv[3] = NULL;
336 
337 		if (!run_xmlrpc_test (list_argv, &out, NULL, &error)) {
338 			g_printerr ("'xmlrpc-old-test -l' failed: %s\n", error->message);
339 			g_error_free (error);
340 			return 1;
341 		}
342 
343 		tests = g_strsplit (out, "\n", -1);
344 		g_free (out);
345 
346 		for (i = 0; tests[i] && *tests[i]; i++) {
347 			/* GLib >= 2.62 defaults to TAP output for tests, and
348 			 * this adds TAP diagnostics "#..." and the test count
349 			 * "1..N", even in the output of "some-test -l".
350 			 * Ignore those. */
351 			if (tests[i][0] == '#' || g_str_has_prefix (tests[i], "1.."))
352 				continue;
353 
354 			g_assert_true (g_str_has_prefix (tests[i], "/xmlrpc-old/"));
355 			path = g_strdup_printf ("/xmlrpc-old-server/%s", tests[i] + strlen ("/xmlrpc-old/"));
356 			g_test_add_data_func (path, tests[i], do_one_xmlrpc_test);
357 			g_free (path);
358 		}
359 
360 		ret = g_test_run ();
361 
362 		g_strfreev (tests);
363 	} else {
364 		GMainLoop *loop;
365 
366 		g_print ("Listening on port %d\n", server_uri->port);
367 
368 		loop = g_main_loop_new (NULL, TRUE);
369 		g_main_loop_run (loop);
370 		g_main_loop_unref (loop);
371 
372 		ret = 0;
373 	}
374 
375 	soup_test_server_quit_unref (server);
376 	soup_uri_free (server_uri);
377 	g_free (uri);
378 	if (run_tests)
379 		test_cleanup ();
380 	return ret;
381 }
382