1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007 Novell, Inc.
11 #include <libsoup/soup.h>
12 #include <libsoup/soup-auth-domain-basic.h>
13 #include <libsoup/soup-server.h>
15 #include "test-utils.h"
17 #define SHORT_BODY "This is a test.\r\n"
18 #define LONG_BODY (SHORT_BODY SHORT_BODY)
20 #define MAX_POST_LENGTH (sizeof (SHORT_BODY))
23 static GSList *events;
26 event (SoupMessage *msg, const char *side, const char *message)
28 char *data = g_strdup_printf ("%s-%s", side, message);
29 gboolean record_status =
30 (!strcmp (data, "server-wrote_headers") ||
31 !strcmp (data, "server-wrote_informational"));
33 debug_printf (2, " %s", data);
35 debug_printf (2, " (%s)", msg->reason_phrase);
36 debug_printf (2, "\n");
38 events = g_slist_append (events, data);
40 events = g_slist_append (events, GUINT_TO_POINTER (msg->status_code));
43 #define EVENT_HANDLER(name) \
45 name (SoupMessage *msg, gpointer side) \
47 event (msg, side, #name); \
50 EVENT_HANDLER (got_informational)
51 EVENT_HANDLER (got_headers)
52 EVENT_HANDLER (got_body)
53 EVENT_HANDLER (wrote_informational)
54 EVENT_HANDLER (wrote_headers)
55 EVENT_HANDLER (wrote_body)
56 EVENT_HANDLER (finished)
59 do_message (const char *path, gboolean long_body,
60 gboolean expect_continue, gboolean auth,
68 const char *expected_event;
70 int expected_status, actual_status;
73 debug_printf (1, "%d. /%s, %s body, %sExpect, %s password\n",
75 long_body ? "long" : "short",
76 expect_continue ? "" : "no ",
77 auth ? "with" : "without");
79 uri = g_strdup_printf ("http://%s127.0.0.1:%d/%s",
80 auth ? "user:pass@" : "",
82 msg = soup_message_new ("POST", uri);
85 body = long_body ? LONG_BODY : SHORT_BODY;
86 soup_message_set_request (msg, "text/plain", SOUP_MEMORY_STATIC,
88 soup_message_headers_append (msg->request_headers, "Connection", "close");
89 if (expect_continue) {
90 soup_message_headers_set_expectations (msg->request_headers,
91 SOUP_EXPECTATION_CONTINUE);
94 g_signal_connect (msg, "got_informational",
95 G_CALLBACK (got_informational), "client");
96 g_signal_connect (msg, "got_headers",
97 G_CALLBACK (got_headers), "client");
98 g_signal_connect (msg, "got_body",
99 G_CALLBACK (got_body), "client");
100 g_signal_connect (msg, "wrote_informational",
101 G_CALLBACK (wrote_informational), "client");
102 g_signal_connect (msg, "wrote_headers",
103 G_CALLBACK (wrote_headers), "client");
104 g_signal_connect (msg, "wrote_body",
105 G_CALLBACK (wrote_body), "client");
106 g_signal_connect (msg, "finished",
107 G_CALLBACK (finished), "client");
110 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
111 soup_session_send_message (session, msg);
112 soup_test_session_abort_unref (session);
115 while ((expected_event = va_arg (ap, const char *))) {
118 actual_event = g_strdup ("");
119 debug_printf (1, " Expected '%s', got end of list\n",
123 actual_event = events->data;
124 if (strcmp (expected_event, actual_event) != 0) {
125 debug_printf (1, " Expected '%s', got '%s'\n",
126 expected_event, actual_event);
129 events = g_slist_delete_link (events, events);
132 if (!strcmp (expected_event, "server-wrote_headers") ||
133 !strcmp (expected_event, "server-wrote_informational"))
134 expected_status = va_arg (ap, int);
136 expected_status = -1;
137 if (!strcmp (actual_event, "server-wrote_headers") ||
138 !strcmp (actual_event, "server-wrote_informational")) {
139 actual_status = GPOINTER_TO_INT (events->data);
140 events = g_slist_delete_link (events, events);
142 expected_status = -1;
144 if (expected_status != -1 && actual_status != -1 &&
145 expected_status != actual_status) {
146 debug_printf (1, " Expected status '%s', got '%s'\n",
147 soup_status_get_phrase (expected_status),
148 soup_status_get_phrase (actual_status));
152 g_free (actual_event);
156 actual_event = events->data;
157 debug_printf (1, " Expected to be done, got '%s'\n", actual_event);
159 events = g_slist_delete_link (events, events);
161 if (!strcmp (actual_event, "server-wrote_headers") ||
162 !strcmp (actual_event, "server-wrote_informational"))
163 events = g_slist_delete_link (events, events);
165 g_object_unref (msg);
171 do_message ("unauth", FALSE, FALSE, FALSE,
172 "client-wrote_headers",
174 "server-got_headers",
176 "server-wrote_headers", SOUP_STATUS_CREATED,
179 "client-got_headers",
183 do_message ("unauth", TRUE, FALSE, FALSE,
184 "client-wrote_headers",
186 "server-got_headers",
188 "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
191 "client-got_headers",
195 do_message ("unauth", FALSE, TRUE, FALSE,
196 "client-wrote_headers",
197 "server-got_headers",
198 "server-wrote_informational", SOUP_STATUS_CONTINUE,
199 "client-got_informational",
202 "server-wrote_headers", SOUP_STATUS_CREATED,
205 "client-got_headers",
209 do_message ("unauth", TRUE, TRUE, FALSE,
210 "client-wrote_headers",
211 "server-got_headers",
212 "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
215 "client-got_headers",
220 do_message ("auth", FALSE, FALSE, FALSE,
221 "client-wrote_headers",
223 "server-got_headers",
225 "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
228 "client-got_headers",
232 do_message ("auth", TRUE, FALSE, FALSE,
233 "client-wrote_headers",
235 "server-got_headers",
237 "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
240 "client-got_headers",
244 do_message ("auth", FALSE, TRUE, FALSE,
245 "client-wrote_headers",
246 "server-got_headers",
247 "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
250 "client-got_headers",
254 do_message ("auth", TRUE, TRUE, FALSE,
255 "client-wrote_headers",
256 "server-got_headers",
257 "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
260 "client-got_headers",
265 do_message ("auth", FALSE, FALSE, TRUE,
266 "client-wrote_headers",
268 "server-got_headers",
270 "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
273 "client-got_headers",
275 "client-wrote_headers",
277 "server-got_headers",
279 "server-wrote_headers", SOUP_STATUS_CREATED,
282 "client-got_headers",
286 do_message ("auth", TRUE, FALSE, TRUE,
287 "client-wrote_headers",
289 "server-got_headers",
291 "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
294 "client-got_headers",
296 "client-wrote_headers",
298 "server-got_headers",
300 "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
303 "client-got_headers",
307 do_message ("auth", FALSE, TRUE, TRUE,
308 "client-wrote_headers",
309 "server-got_headers",
310 "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
313 "client-got_headers",
315 "client-wrote_headers",
316 "server-got_headers",
317 "server-wrote_informational", SOUP_STATUS_CONTINUE,
318 "client-got_informational",
321 "server-wrote_headers", SOUP_STATUS_CREATED,
324 "client-got_headers",
328 do_message ("auth", TRUE, TRUE, TRUE,
329 "client-wrote_headers",
330 "server-got_headers",
331 "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
334 "client-got_headers",
336 "client-wrote_headers",
337 "server-got_headers",
338 "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
341 "client-got_headers",
351 server_got_headers (SoupMessage *msg, gpointer server)
354 if (msg->status_code != SOUP_STATUS_CONTINUE &&
355 msg->status_code != 0)
358 if (soup_message_headers_get_expectations (msg->request_headers) &
359 SOUP_EXPECTATION_CONTINUE) {
362 length = soup_message_headers_get_one (msg->request_headers,
364 if (length && atoi (length) > MAX_POST_LENGTH) {
365 soup_message_set_status (msg, SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE);
366 soup_message_headers_append (msg->response_headers, "Connection", "close");
372 request_started (SoupServer *server, SoupMessage *msg,
373 SoupClientContext *client, gpointer user_data)
375 g_signal_connect (msg, "got_headers",
376 G_CALLBACK (server_got_headers), server);
378 g_signal_connect (msg, "got_informational",
379 G_CALLBACK (got_informational), "server");
380 g_signal_connect (msg, "got_headers",
381 G_CALLBACK (got_headers), "server");
382 g_signal_connect (msg, "got_body",
383 G_CALLBACK (got_body), "server");
384 g_signal_connect (msg, "wrote_informational",
385 G_CALLBACK (wrote_informational), "server");
386 g_signal_connect (msg, "wrote_headers",
387 G_CALLBACK (wrote_headers), "server");
388 g_signal_connect (msg, "wrote_body",
389 G_CALLBACK (wrote_body), "server");
390 g_signal_connect (msg, "finished",
391 G_CALLBACK (finished), "server");
395 auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg,
396 const char *username, const char *password, gpointer user_data)
398 return !strcmp (username, "user") && !strcmp (password, "pass");
402 server_callback (SoupServer *server, SoupMessage *msg,
403 const char *path, GHashTable *query,
404 SoupClientContext *context, gpointer data)
406 if (msg->method != SOUP_METHOD_POST) {
407 soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
408 soup_message_headers_append (msg->response_headers, "Connection", "close");
409 } else if (msg->request_body->length > MAX_POST_LENGTH) {
410 soup_message_set_status (msg, SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE);
411 soup_message_headers_append (msg->response_headers, "Connection", "close");
413 soup_message_set_status (msg, SOUP_STATUS_CREATED);
420 SoupAuthDomain *auth_domain;
422 server = soup_test_server_new (FALSE);
424 g_signal_connect (server, "request-started",
425 G_CALLBACK (request_started), NULL);
427 soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
429 auth_domain = soup_auth_domain_basic_new (
430 SOUP_AUTH_DOMAIN_REALM, "continue-test",
431 SOUP_AUTH_DOMAIN_ADD_PATH, "/auth",
432 SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback,
434 soup_server_add_auth_domain (server, auth_domain);
435 g_object_unref (auth_domain);
443 main (int argc, char **argv)
447 test_init (argc, argv, NULL);
449 server = setup_server ();
450 port = soup_server_get_port (server);
454 soup_test_server_quit_unref (server);