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