Remove extern "C" wrapping other includes
[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 SoupURI *base_uri;
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         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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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 }