Git init
[profile/ivi/libsoup2.4.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 <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include <libsoup/soup.h>
12 #include <libsoup/soup-auth-domain-basic.h>
13 #include <libsoup/soup-server.h>
14
15 #include "test-utils.h"
16
17 #define SHORT_BODY "This is a test.\r\n"
18 #define LONG_BODY (SHORT_BODY SHORT_BODY)
19
20 #define MAX_POST_LENGTH (sizeof (SHORT_BODY))
21
22 static int port;
23 static GSList *events;
24
25 static void
26 event (SoupMessage *msg, const char *side, const char *message)
27 {
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"));
32
33         debug_printf (2, "  %s", data);
34         if (record_status)
35                 debug_printf (2, " (%s)", msg->reason_phrase);
36         debug_printf (2, "\n");
37
38         events = g_slist_append (events, data);
39         if (record_status)
40                 events = g_slist_append (events, GUINT_TO_POINTER (msg->status_code));
41 }
42
43 #define EVENT_HANDLER(name)                     \
44 static void                                     \
45 name (SoupMessage *msg, gpointer side)          \
46 {                                               \
47         event (msg, side, #name);               \
48 }
49
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)
57
58 static void
59 do_message (const char *path, gboolean long_body,
60             gboolean expect_continue, gboolean auth,
61             ...)
62 {
63         SoupSession *session;
64         SoupMessage *msg;
65         const char *body;
66         char *uri;
67         va_list ap;
68         const char *expected_event;
69         char *actual_event;
70         int expected_status, actual_status;
71         static int count = 1;
72
73         debug_printf (1, "%d. /%s, %s body, %sExpect, %s password\n",
74                       count++, path,
75                       long_body ? "long" : "short",
76                       expect_continue ? "" : "no ",
77                       auth ? "with" : "without");
78
79         uri = g_strdup_printf ("http://%s127.0.0.1:%d/%s",
80                                auth ? "user:pass@" : "",
81                                port, path);
82         msg = soup_message_new ("POST", uri);
83         g_free (uri);
84
85         body = long_body ? LONG_BODY : SHORT_BODY;
86         soup_message_set_request (msg, "text/plain", SOUP_MEMORY_STATIC,
87                                   body, strlen (body));
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);
92         }
93
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");
108
109         events = NULL;
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);
113
114         va_start (ap, auth);
115         while ((expected_event = va_arg (ap, const char *))) {
116
117                 if (!events) {
118                         actual_event = g_strdup ("");
119                         debug_printf (1, "  Expected '%s', got end of list\n",
120                                       expected_event);
121                         errors++;
122                 } else {
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);
127                                 errors++;
128                         }
129                         events = g_slist_delete_link (events, events);
130                 }
131
132                 if (!strcmp (expected_event, "server-wrote_headers") ||
133                     !strcmp (expected_event, "server-wrote_informational"))
134                         expected_status = va_arg (ap, int);
135                 else
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);
141                 } else
142                         expected_status = -1;
143
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));
149                         errors++;
150                 }
151
152                 g_free (actual_event);
153         }
154         va_end (ap);
155         while (events) {
156                 actual_event = events->data;
157                 debug_printf (1, "  Expected to be done, got '%s'\n", actual_event);
158                 errors++;
159                 events = g_slist_delete_link (events, events);
160
161                 if (!strcmp (actual_event, "server-wrote_headers") ||
162                     !strcmp (actual_event, "server-wrote_informational"))
163                         events = g_slist_delete_link (events, events);
164         }
165         g_object_unref (msg);
166 }
167
168 static void
169 run_tests (void)
170 {
171         do_message ("unauth", FALSE, FALSE, FALSE,
172                     "client-wrote_headers",
173                     "client-wrote_body",
174                     "server-got_headers",
175                     "server-got_body",
176                     "server-wrote_headers", SOUP_STATUS_CREATED,
177                     "server-wrote_body",
178                     "server-finished",
179                     "client-got_headers",
180                     "client-got_body",
181                     "client-finished",
182                     NULL);
183         do_message ("unauth", TRUE, FALSE, FALSE,
184                     "client-wrote_headers",
185                     "client-wrote_body",
186                     "server-got_headers",
187                     "server-got_body",
188                     "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
189                     "server-wrote_body",
190                     "server-finished",
191                     "client-got_headers",
192                     "client-got_body",
193                     "client-finished",
194                     NULL);
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",
200                     "client-wrote_body",
201                     "server-got_body",
202                     "server-wrote_headers", SOUP_STATUS_CREATED,
203                     "server-wrote_body",
204                     "server-finished",
205                     "client-got_headers",
206                     "client-got_body",
207                     "client-finished",
208                     NULL);
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,
213                     "server-wrote_body",
214                     "server-finished",
215                     "client-got_headers",
216                     "client-got_body",
217                     "client-finished",
218                     NULL);
219
220         do_message ("auth", FALSE, FALSE, FALSE,
221                     "client-wrote_headers",
222                     "client-wrote_body",
223                     "server-got_headers",
224                     "server-got_body",
225                     "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
226                     "server-wrote_body",
227                     "server-finished",
228                     "client-got_headers",
229                     "client-got_body",
230                     "client-finished",
231                     NULL);
232         do_message ("auth", TRUE, FALSE, FALSE,
233                     "client-wrote_headers",
234                     "client-wrote_body",
235                     "server-got_headers",
236                     "server-got_body",
237                     "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
238                     "server-wrote_body",
239                     "server-finished",
240                     "client-got_headers",
241                     "client-got_body",
242                     "client-finished",
243                     NULL);
244         do_message ("auth", FALSE, TRUE, FALSE,
245                     "client-wrote_headers",
246                     "server-got_headers",
247                     "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
248                     "server-wrote_body",
249                     "server-finished",
250                     "client-got_headers",
251                     "client-got_body",
252                     "client-finished",
253                     NULL);
254         do_message ("auth", TRUE, TRUE, FALSE,
255                     "client-wrote_headers",
256                     "server-got_headers",
257                     "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
258                     "server-wrote_body",
259                     "server-finished",
260                     "client-got_headers",
261                     "client-got_body",
262                     "client-finished",
263                     NULL);
264
265         do_message ("auth", FALSE, FALSE, TRUE,
266                     "client-wrote_headers",
267                     "client-wrote_body",
268                     "server-got_headers",
269                     "server-got_body",
270                     "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
271                     "server-wrote_body",
272                     "server-finished",
273                     "client-got_headers",
274                     "client-got_body",
275                     "client-wrote_headers",
276                     "client-wrote_body",
277                     "server-got_headers",
278                     "server-got_body",
279                     "server-wrote_headers", SOUP_STATUS_CREATED,
280                     "server-wrote_body",
281                     "server-finished",
282                     "client-got_headers",
283                     "client-got_body",
284                     "client-finished",
285                     NULL);
286         do_message ("auth", TRUE, 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_REQUEST_ENTITY_TOO_LARGE,
301                     "server-wrote_body",
302                     "server-finished",
303                     "client-got_headers",
304                     "client-got_body",
305                     "client-finished",
306                     NULL);
307         do_message ("auth", FALSE, TRUE, TRUE,
308                     "client-wrote_headers",
309                     "server-got_headers",
310                     "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
311                     "server-wrote_body",
312                     "server-finished",
313                     "client-got_headers",
314                     "client-got_body",
315                     "client-wrote_headers",
316                     "server-got_headers",
317                     "server-wrote_informational", SOUP_STATUS_CONTINUE,
318                     "client-got_informational",
319                     "client-wrote_body",
320                     "server-got_body",
321                     "server-wrote_headers", SOUP_STATUS_CREATED,
322                     "server-wrote_body",
323                     "server-finished",
324                     "client-got_headers",
325                     "client-got_body",
326                     "client-finished",
327                     NULL);
328         do_message ("auth", TRUE, TRUE, TRUE,
329                     "client-wrote_headers",
330                     "server-got_headers",
331                     "server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
332                     "server-wrote_body",
333                     "server-finished",
334                     "client-got_headers",
335                     "client-got_body",
336                     "client-wrote_headers",
337                     "server-got_headers",
338                     "server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
339                     "server-wrote_body",
340                     "server-finished",
341                     "client-got_headers",
342                     "client-got_body",
343                     "client-finished",
344                     NULL);
345 }
346
347
348 /* SERVER */
349
350 static void
351 server_got_headers (SoupMessage *msg, gpointer server)
352 {
353         /* FIXME */
354         if (msg->status_code != SOUP_STATUS_CONTINUE &&
355             msg->status_code != 0)
356                 return;
357
358         if (soup_message_headers_get_expectations (msg->request_headers) &
359             SOUP_EXPECTATION_CONTINUE) {
360                 const char *length;
361
362                 length = soup_message_headers_get_one (msg->request_headers,
363                                                        "Content-Length");
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");
367                 }
368         }
369 }       
370
371 static void
372 request_started (SoupServer *server, SoupMessage *msg,
373                  SoupClientContext *client, gpointer user_data)
374 {
375         g_signal_connect (msg, "got_headers",
376                           G_CALLBACK (server_got_headers), server);
377
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");
392 }
393
394 static gboolean
395 auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg,
396                const char *username, const char *password, gpointer user_data)
397 {
398         return !strcmp (username, "user") && !strcmp (password, "pass");
399 }
400
401 static void
402 server_callback (SoupServer *server, SoupMessage *msg,
403                  const char *path, GHashTable *query,
404                  SoupClientContext *context, gpointer data)
405 {
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");
412         } else
413                 soup_message_set_status (msg, SOUP_STATUS_CREATED);
414 }
415
416 static SoupServer *
417 setup_server (void)
418 {
419         SoupServer *server;
420         SoupAuthDomain *auth_domain;
421
422         server = soup_test_server_new (FALSE);
423
424         g_signal_connect (server, "request-started",
425                           G_CALLBACK (request_started), NULL);
426
427         soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
428
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,
433                 NULL);
434         soup_server_add_auth_domain (server, auth_domain);
435         g_object_unref (auth_domain);
436
437         return server;
438 }
439
440 /* MAIN */
441
442 int
443 main (int argc, char **argv)
444 {
445         SoupServer *server;
446
447         test_init (argc, argv, NULL);
448
449         server = setup_server ();
450         port = soup_server_get_port (server);
451
452         run_tests ();
453
454         soup_test_server_quit_unref (server);
455         test_cleanup ();
456         return errors != 0;
457 }