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