• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007 Novell, Inc.
4  */
5 
6 #include "test-utils.h"
7 
8 #define SHORT_BODY "This is a test.\r\n"
9 #define LONG_BODY (SHORT_BODY SHORT_BODY)
10 
11 #define MAX_POST_LENGTH (sizeof (SHORT_BODY))
12 
13 static SoupURI *base_uri;
14 static GSList *events;
15 
16 static void
event(SoupMessage * msg,const char * side,const char * message)17 event (SoupMessage *msg, const char *side, const char *message)
18 {
19 	char *data = g_strdup_printf ("%s-%s", side, message);
20 	gboolean record_status =
21 		(!strcmp (data, "server-wrote_headers") ||
22 		 !strcmp (data, "server-wrote_informational"));
23 
24 	debug_printf (2, "  %s", data);
25 	if (record_status)
26 		debug_printf (2, " (%s)", msg->reason_phrase);
27 	debug_printf (2, "\n");
28 
29 	events = g_slist_append (events, data);
30 	if (record_status)
31 		events = g_slist_append (events, GUINT_TO_POINTER (msg->status_code));
32 }
33 
34 #define EVENT_HANDLER(name)			\
35 static void					\
36 name (SoupMessage *msg, gpointer side)		\
37 {						\
38 	event (msg, side, #name);		\
39 }
40 
41 EVENT_HANDLER (got_informational)
EVENT_HANDLER(got_headers)42 EVENT_HANDLER (got_headers)
43 EVENT_HANDLER (got_body)
44 EVENT_HANDLER (wrote_informational)
45 EVENT_HANDLER (wrote_headers)
46 EVENT_HANDLER (wrote_body)
47 EVENT_HANDLER (finished)
48 
49 static void
50 do_message (const char *path, gboolean long_body,
51 	    gboolean expect_continue, gboolean auth,
52 	    ...)
53 {
54 	SoupSession *session;
55 	SoupMessage *msg;
56 	const char *body;
57 	SoupURI *uri;
58 	va_list ap;
59 	const char *expected_event;
60 	char *actual_event;
61 	int expected_status, actual_status;
62 
63 	uri = soup_uri_copy (base_uri);
64 	if (auth) {
65 		soup_uri_set_user (uri, "user");
66 		soup_uri_set_password (uri, "pass");
67 	}
68 	soup_uri_set_path (uri, path);
69 	msg = soup_message_new_from_uri ("POST", uri);
70 	soup_uri_free (uri);
71 
72 	body = long_body ? LONG_BODY : SHORT_BODY;
73 	soup_message_set_request (msg, "text/plain", SOUP_MEMORY_STATIC,
74 				  body, strlen (body));
75 	soup_message_headers_append (msg->request_headers, "Connection", "close");
76 	if (expect_continue) {
77 		soup_message_headers_set_expectations (msg->request_headers,
78 						       SOUP_EXPECTATION_CONTINUE);
79 	}
80 
81 	g_signal_connect (msg, "got_informational",
82 			  G_CALLBACK (got_informational), "client");
83 	g_signal_connect (msg, "got_headers",
84 			  G_CALLBACK (got_headers), "client");
85 	g_signal_connect (msg, "got_body",
86 			  G_CALLBACK (got_body), "client");
87 	g_signal_connect (msg, "wrote_informational",
88 			  G_CALLBACK (wrote_informational), "client");
89 	g_signal_connect (msg, "wrote_headers",
90 			  G_CALLBACK (wrote_headers), "client");
91 	g_signal_connect (msg, "wrote_body",
92 			  G_CALLBACK (wrote_body), "client");
93 	g_signal_connect (msg, "finished",
94 			  G_CALLBACK (finished), "client");
95 
96 	events = NULL;
97 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
98 	soup_session_send_message (session, msg);
99 	soup_test_session_abort_unref (session);
100 
101 	va_start (ap, auth);
102 	while ((expected_event = va_arg (ap, const char *))) {
103 
104 		if (!events) {
105 			soup_test_assert (events != NULL,
106 					  "Expected '%s', got end of list",
107 					  expected_event);
108 			continue;
109 		} else {
110 			actual_event = events->data;
111 			g_assert_cmpstr (expected_event, ==, actual_event);
112 			events = g_slist_delete_link (events, events);
113 		}
114 
115 		if (!strcmp (expected_event, "server-wrote_headers") ||
116 		    !strcmp (expected_event, "server-wrote_informational"))
117 			expected_status = va_arg (ap, int);
118 		else
119 			expected_status = -1;
120 		if (!strcmp (actual_event, "server-wrote_headers") ||
121 		    !strcmp (actual_event, "server-wrote_informational")) {
122 			actual_status = GPOINTER_TO_INT (events->data);
123 			events = g_slist_delete_link (events, events);
124 		} else
125 			expected_status = -1;
126 
127 		if (expected_status != -1 && actual_status != -1 &&
128 		    expected_status != actual_status) {
129 			soup_test_assert (expected_status == actual_status,
130 					  "Expected status '%s', got '%s'",
131 					  soup_status_get_phrase (expected_status),
132 					  soup_status_get_phrase (actual_status));
133 		}
134 
135 		g_free (actual_event);
136 	}
137 	va_end (ap);
138 	while (events) {
139 		actual_event = events->data;
140 		soup_test_assert (events == NULL,
141 				  "Expected to be done, got '%s'", actual_event);
142 		events = g_slist_delete_link (events, events);
143 
144 		if (!strcmp (actual_event, "server-wrote_headers") ||
145 		    !strcmp (actual_event, "server-wrote_informational"))
146 			events = g_slist_delete_link (events, events);
147 	}
148 	g_object_unref (msg);
149 }
150 
151 static void
do_test_unauth_short_noexpect_nopass(void)152 do_test_unauth_short_noexpect_nopass (void)
153 {
154 	do_message ("/unauth", FALSE, FALSE, FALSE,
155 		    "client-wrote_headers",
156 		    "client-wrote_body",
157 		    "server-got_headers",
158 		    "server-got_body",
159 		    "server-wrote_headers", SOUP_STATUS_CREATED,
160 		    "server-wrote_body",
161 		    "server-finished",
162 		    "client-got_headers",
163 		    "client-got_body",
164 		    "client-finished",
165 		    NULL);
166 }
167 
168 static void
do_test_unauth_long_noexpect_nopass(void)169 do_test_unauth_long_noexpect_nopass (void)
170 {
171 	do_message ("/unauth", TRUE, FALSE, FALSE,
172 		    "client-wrote_headers",
173 		    "client-wrote_body",
174 		    "server-got_headers",
175 		    "server-got_body",
176 		    "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
177 		    "server-wrote_body",
178 		    "server-finished",
179 		    "client-got_headers",
180 		    "client-got_body",
181 		    "client-finished",
182 		    NULL);
183 }
184 
185 static void
do_test_unauth_short_expect_nopass(void)186 do_test_unauth_short_expect_nopass (void)
187 {
188 	do_message ("/unauth", FALSE, TRUE, FALSE,
189 		    "client-wrote_headers",
190 		    "server-got_headers",
191 		    "server-wrote_informational", SOUP_STATUS_CONTINUE,
192 		    "client-got_informational",
193 		    "client-wrote_body",
194 		    "server-got_body",
195 		    "server-wrote_headers", SOUP_STATUS_CREATED,
196 		    "server-wrote_body",
197 		    "server-finished",
198 		    "client-got_headers",
199 		    "client-got_body",
200 		    "client-finished",
201 		    NULL);
202 }
203 
204 static void
do_test_unauth_long_expect_nopass(void)205 do_test_unauth_long_expect_nopass (void)
206 {
207 	do_message ("/unauth", TRUE, TRUE, FALSE,
208 		    "client-wrote_headers",
209 		    "server-got_headers",
210 		    "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
211 		    "server-wrote_body",
212 		    "server-finished",
213 		    "client-got_headers",
214 		    "client-got_body",
215 		    "client-finished",
216 		    NULL);
217 }
218 
219 static void
do_test_auth_short_noexpect_nopass(void)220 do_test_auth_short_noexpect_nopass (void)
221 {
222 	do_message ("/auth", FALSE, FALSE, FALSE,
223 		    "client-wrote_headers",
224 		    "client-wrote_body",
225 		    "server-got_headers",
226 		    "server-got_body",
227 		    "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
228 		    "server-wrote_body",
229 		    "server-finished",
230 		    "client-got_headers",
231 		    "client-got_body",
232 		    "client-finished",
233 		    NULL);
234 }
235 
236 static void
do_test_auth_long_noexpect_nopass(void)237 do_test_auth_long_noexpect_nopass (void)
238 {
239 	do_message ("/auth", TRUE, FALSE, FALSE,
240 		    "client-wrote_headers",
241 		    "client-wrote_body",
242 		    "server-got_headers",
243 		    "server-got_body",
244 		    "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
245 		    "server-wrote_body",
246 		    "server-finished",
247 		    "client-got_headers",
248 		    "client-got_body",
249 		    "client-finished",
250 		    NULL);
251 }
252 
253 static void
do_test_auth_short_expect_nopass(void)254 do_test_auth_short_expect_nopass (void)
255 {
256 	do_message ("/auth", FALSE, TRUE, FALSE,
257 		    "client-wrote_headers",
258 		    "server-got_headers",
259 		    "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
260 		    "server-wrote_body",
261 		    "server-finished",
262 		    "client-got_headers",
263 		    "client-got_body",
264 		    "client-finished",
265 		    NULL);
266 }
267 
268 static void
do_test_auth_long_expect_nopass(void)269 do_test_auth_long_expect_nopass (void)
270 {
271 	do_message ("/auth", TRUE, TRUE, FALSE,
272 		    "client-wrote_headers",
273 		    "server-got_headers",
274 		    "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
275 		    "server-wrote_body",
276 		    "server-finished",
277 		    "client-got_headers",
278 		    "client-got_body",
279 		    "client-finished",
280 		    NULL);
281 }
282 
283 static void
do_test_auth_short_noexpect_pass(void)284 do_test_auth_short_noexpect_pass (void)
285 {
286 	do_message ("/auth", FALSE, FALSE, TRUE,
287 		    "client-wrote_headers",
288 		    "client-wrote_body",
289 		    "server-got_headers",
290 		    "server-got_body",
291 		    "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
292 		    "server-wrote_body",
293 		    "server-finished",
294 		    "client-got_headers",
295 		    "client-got_body",
296 		    "client-wrote_headers",
297 		    "client-wrote_body",
298 		    "server-got_headers",
299 		    "server-got_body",
300 		    "server-wrote_headers", SOUP_STATUS_CREATED,
301 		    "server-wrote_body",
302 		    "server-finished",
303 		    "client-got_headers",
304 		    "client-got_body",
305 		    "client-finished",
306 		    NULL);
307 }
308 
309 static void
do_test_auth_long_noexpect_pass(void)310 do_test_auth_long_noexpect_pass (void)
311 {
312 	do_message ("/auth", TRUE, FALSE, TRUE,
313 		    "client-wrote_headers",
314 		    "client-wrote_body",
315 		    "server-got_headers",
316 		    "server-got_body",
317 		    "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
318 		    "server-wrote_body",
319 		    "server-finished",
320 		    "client-got_headers",
321 		    "client-got_body",
322 		    "client-wrote_headers",
323 		    "client-wrote_body",
324 		    "server-got_headers",
325 		    "server-got_body",
326 		    "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
327 		    "server-wrote_body",
328 		    "server-finished",
329 		    "client-got_headers",
330 		    "client-got_body",
331 		    "client-finished",
332 		    NULL);
333 }
334 
335 static void
do_test_auth_short_expect_pass(void)336 do_test_auth_short_expect_pass (void)
337 {
338 	do_message ("/auth", FALSE, TRUE, TRUE,
339 		    "client-wrote_headers",
340 		    "server-got_headers",
341 		    "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
342 		    "server-wrote_body",
343 		    "server-finished",
344 		    "client-got_headers",
345 		    "client-got_body",
346 		    "client-wrote_headers",
347 		    "server-got_headers",
348 		    "server-wrote_informational", SOUP_STATUS_CONTINUE,
349 		    "client-got_informational",
350 		    "client-wrote_body",
351 		    "server-got_body",
352 		    "server-wrote_headers", SOUP_STATUS_CREATED,
353 		    "server-wrote_body",
354 		    "server-finished",
355 		    "client-got_headers",
356 		    "client-got_body",
357 		    "client-finished",
358 		    NULL);
359 }
360 
361 static void
do_test_auth_long_expect_pass(void)362 do_test_auth_long_expect_pass (void)
363 {
364 	do_message ("/auth", TRUE, TRUE, TRUE,
365 		    "client-wrote_headers",
366 		    "server-got_headers",
367 		    "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
368 		    "server-wrote_body",
369 		    "server-finished",
370 		    "client-got_headers",
371 		    "client-got_body",
372 		    "client-wrote_headers",
373 		    "server-got_headers",
374 		    "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
375 		    "server-wrote_body",
376 		    "server-finished",
377 		    "client-got_headers",
378 		    "client-got_body",
379 		    "client-finished",
380 		    NULL);
381 }
382 
383 
384 /* SERVER */
385 
386 static void
server_got_headers(SoupMessage * msg,gpointer server)387 server_got_headers (SoupMessage *msg, gpointer server)
388 {
389 	/* FIXME */
390 	if (msg->status_code != SOUP_STATUS_CONTINUE &&
391 	    msg->status_code != 0)
392 		return;
393 
394 	if (soup_message_headers_get_expectations (msg->request_headers) &
395 	    SOUP_EXPECTATION_CONTINUE) {
396 		const char *length;
397 
398 		length = soup_message_headers_get_one (msg->request_headers,
399 						       "Content-Length");
400 		if (length && atoi (length) > MAX_POST_LENGTH) {
401 			soup_message_set_status (msg, SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE);
402 			soup_message_headers_append (msg->response_headers, "Connection", "close");
403 		}
404 	}
405 }
406 
407 static void
request_started(SoupServer * server,SoupMessage * msg,SoupClientContext * client,gpointer user_data)408 request_started (SoupServer *server, SoupMessage *msg,
409 		 SoupClientContext *client, gpointer user_data)
410 {
411 	g_signal_connect (msg, "got_headers",
412 			  G_CALLBACK (server_got_headers), server);
413 
414 	g_signal_connect (msg, "got_informational",
415 			  G_CALLBACK (got_informational), "server");
416 	g_signal_connect (msg, "got_headers",
417 			  G_CALLBACK (got_headers), "server");
418 	g_signal_connect (msg, "got_body",
419 			  G_CALLBACK (got_body), "server");
420 	g_signal_connect (msg, "wrote_informational",
421 			  G_CALLBACK (wrote_informational), "server");
422 	g_signal_connect (msg, "wrote_headers",
423 			  G_CALLBACK (wrote_headers), "server");
424 	g_signal_connect (msg, "wrote_body",
425 			  G_CALLBACK (wrote_body), "server");
426 	g_signal_connect (msg, "finished",
427 			  G_CALLBACK (finished), "server");
428 }
429 
430 static gboolean
auth_callback(SoupAuthDomain * auth_domain,SoupMessage * msg,const char * username,const char * password,gpointer user_data)431 auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg,
432 	       const char *username, const char *password, gpointer user_data)
433 {
434 	return !strcmp (username, "user") && !strcmp (password, "pass");
435 }
436 
437 static void
server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * context,gpointer data)438 server_callback (SoupServer *server, SoupMessage *msg,
439 		 const char *path, GHashTable *query,
440 		 SoupClientContext *context, gpointer data)
441 {
442 	if (msg->method != SOUP_METHOD_POST) {
443 		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
444 		soup_message_headers_append (msg->response_headers, "Connection", "close");
445 	} else if (msg->request_body->length > MAX_POST_LENGTH) {
446 		soup_message_set_status (msg, SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE);
447 		soup_message_headers_append (msg->response_headers, "Connection", "close");
448 	} else
449 		soup_message_set_status (msg, SOUP_STATUS_CREATED);
450 }
451 
452 static SoupServer *
setup_server(void)453 setup_server (void)
454 {
455 	SoupServer *server;
456 	SoupAuthDomain *auth_domain;
457 
458 	server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
459 
460 	g_signal_connect (server, "request-started",
461 			  G_CALLBACK (request_started), NULL);
462 
463 	soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
464 
465 	auth_domain = soup_auth_domain_basic_new (
466 		SOUP_AUTH_DOMAIN_REALM, "continue-test",
467 		SOUP_AUTH_DOMAIN_ADD_PATH, "/auth",
468 		SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback,
469 		NULL);
470 	soup_server_add_auth_domain (server, auth_domain);
471 	g_object_unref (auth_domain);
472 
473 	return server;
474 }
475 
476 /* MAIN */
477 
478 int
main(int argc,char ** argv)479 main (int argc, char **argv)
480 {
481 	SoupServer *server;
482 	int ret;
483 
484 	test_init (argc, argv, NULL);
485 
486 	server = setup_server ();
487 	base_uri = soup_test_server_get_uri (server, "http", NULL);
488 
489 	g_test_add_func ("/continue/unauth_short_noexpect_nopass", do_test_unauth_short_noexpect_nopass);
490 	g_test_add_func ("/continue/unauth_long_noexpect_nopass", do_test_unauth_long_noexpect_nopass);
491 	g_test_add_func ("/continue/unauth_short_expect_nopass", do_test_unauth_short_expect_nopass);
492 	g_test_add_func ("/continue/unauth_long_expect_nopass", do_test_unauth_long_expect_nopass);
493 	g_test_add_func ("/continue/auth_short_noexpect_nopass", do_test_auth_short_noexpect_nopass);
494 	g_test_add_func ("/continue/auth_long_noexpect_nopass", do_test_auth_long_noexpect_nopass);
495 	g_test_add_func ("/continue/auth_short_expect_nopass", do_test_auth_short_expect_nopass);
496 	g_test_add_func ("/continue/auth_long_expect_nopass", do_test_auth_long_expect_nopass);
497 	g_test_add_func ("/continue/auth_short_noexpect_pass", do_test_auth_short_noexpect_pass);
498 	g_test_add_func ("/continue/auth_long_noexpect_pass", do_test_auth_long_noexpect_pass);
499 	g_test_add_func ("/continue/auth_short_expect_pass", do_test_auth_short_expect_pass);
500 	g_test_add_func ("/continue/auth_long_expect_pass", do_test_auth_long_expect_pass);
501 
502 	ret = g_test_run ();
503 
504 	soup_test_server_quit_unref (server);
505 	soup_uri_free (base_uri);
506 
507 	test_cleanup ();
508 
509 	return ret;
510 }
511