requester-test: add some more tests
[platform/upstream/libsoup.git] / tests / requester-test.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2011 Red Hat, Inc.
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #define LIBSOUP_USE_UNSTABLE_REQUEST_API
11 #include <libsoup/soup.h>
12 #include <libsoup/soup-requester.h>
13 #include <libsoup/soup-request-http.h>
14
15 #include "test-utils.h"
16
17 SoupServer *server;
18 GMainLoop *loop;
19 char buf[1024];
20
21 SoupBuffer *response;
22
23 static void
24 get_index (void)
25 {
26         char *contents;
27         gsize length;
28         GError *error = NULL;
29
30         if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) {
31                 fprintf (stderr, "Could not read index.txt: %s\n",
32                          error->message);
33                 exit (1);
34         }
35
36         response = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length);
37 }
38
39 #define REDIRECT_HTML_BODY "<html><body>Try again</body></html>\r\n"
40
41 static void
42 server_callback (SoupServer *server, SoupMessage *msg,
43                  const char *path, GHashTable *query,
44                  SoupClientContext *context, gpointer data)
45 {
46         if (strcmp (path, "/") != 0) {
47                 soup_message_set_redirect (msg, SOUP_STATUS_FOUND, "/");
48                 /* Make the response HTML so if we sniff that instead of the
49                  * real body, we'll notice.
50                  */
51                 soup_message_set_response (msg, "text/html",
52                                            SOUP_MEMORY_STATIC,
53                                            REDIRECT_HTML_BODY,
54                                            strlen (REDIRECT_HTML_BODY));
55                 return;
56         }
57
58         soup_message_set_status (msg, SOUP_STATUS_OK);
59         soup_message_body_append_buffer (msg->response_body, response);
60 }
61
62 static void
63 test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data)
64 {
65         GInputStream *stream = G_INPUT_STREAM (source);
66         GString *body = user_data;
67         GError *error = NULL;
68         gsize nread;
69
70         nread = g_input_stream_read_finish (stream, res, &error);
71         if (nread == -1) {
72                 debug_printf (1, "  read_async failed: %s", error->message);
73                 errors++;
74                 g_object_unref (stream);
75                 g_main_loop_quit (loop);
76                 return;
77         } else if (nread == 0) {
78                 g_object_unref (stream);
79                 g_main_loop_quit (loop);
80                 return;
81         }
82
83         g_string_append_len (body, buf, nread);
84         g_input_stream_read_async (stream, buf, sizeof (buf),
85                                    G_PRIORITY_DEFAULT, NULL,
86                                    test_read_ready, body);
87 }
88
89 static void
90 test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
91 {
92         GString *body = user_data;
93         GInputStream *stream;
94         GError *error = NULL;
95         SoupMessage *msg;
96         const char *content_type;
97
98         stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error);
99         if (!stream) {
100                 debug_printf (1, "  send_async failed: %s\n", error->message);
101                 errors++;
102                 g_main_loop_quit (loop);
103                 return;
104         }
105
106         msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (source));
107         if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
108                 debug_printf (1, "  GET failed: %d %s\n", msg->status_code,
109                               msg->reason_phrase);
110                 errors++;
111                 g_main_loop_quit (loop);
112                 return;
113         }
114         g_object_unref (msg);
115
116         content_type = soup_request_get_content_type (SOUP_REQUEST (source));
117         if (g_strcmp0 (content_type, "text/plain") != 0) {
118                 debug_printf (1, "  failed to sniff Content-Type: got %s\n",
119                               content_type ? content_type : "(NULL)");
120                 errors++;
121         }
122
123         g_input_stream_read_async (stream, buf, sizeof (buf),
124                                    G_PRIORITY_DEFAULT, NULL,
125                                    test_read_ready, body);
126 }
127
128 static void
129 do_test_for_thread_and_context (SoupSession *session, const char *uri)
130 {
131         SoupRequester *requester;
132         SoupRequest *request;
133         GString *body;
134
135         requester = soup_requester_new ();
136         soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
137         g_object_unref (requester);
138         soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
139
140         body = g_string_new (NULL);
141
142         request = soup_requester_request (requester, uri, NULL);
143         soup_request_send_async (request, NULL, test_sent, body);
144         g_object_unref (request);
145
146         loop = g_main_loop_new (soup_session_get_async_context (session), TRUE);
147         g_main_loop_run (loop);
148         g_main_loop_unref (loop);
149
150         if (body->len != response->length) {
151                 debug_printf (1, "  body length mismatch: expected %d, got %d\n",
152                               (int)response->length, (int)body->len);
153                 errors++;
154         } else if (memcmp (body->str, response->data, response->length) != 0) {
155                 debug_printf (1, "  body data mismatch\n");
156                 errors++;
157         }
158
159         g_string_free (body, TRUE);
160 }
161
162 static void
163 do_simple_test (const char *uri)
164 {
165         SoupSession *session;
166
167         debug_printf (1, "Simple streaming test\n");
168
169         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
170         do_test_for_thread_and_context (session, uri);
171         soup_test_session_abort_unref (session);
172 }
173
174 static gpointer
175 do_test_with_context (const char *uri)
176 {
177         GMainContext *async_context;
178         SoupSession *session;
179
180         async_context = g_main_context_new ();
181         g_main_context_push_thread_default (async_context);
182
183         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
184                                          SOUP_SESSION_ASYNC_CONTEXT, async_context,
185                                          NULL);
186
187         do_test_for_thread_and_context (session, uri);
188         soup_test_session_abort_unref (session);
189
190         g_main_context_pop_thread_default (async_context);
191         g_main_context_unref (async_context);
192         return NULL;
193 }
194
195 static void
196 do_context_test (const char *uri)
197 {
198         debug_printf (1, "Streaming with a non-default-context\n");
199         do_test_with_context (uri);
200 }
201
202 static void
203 do_thread_test (const char *uri)
204 {
205         GThread *thread;
206
207         debug_printf (1, "Streaming in another thread\n");
208
209         thread = g_thread_new ("do_test_with_context",
210                                (GThreadFunc)do_test_with_context,
211                                (gpointer)uri);
212         g_thread_join (thread);
213 }
214
215 int
216 main (int argc, char **argv)
217 {
218         char *uri;
219
220         test_init (argc, argv, NULL);
221         get_index ();
222
223         server = soup_test_server_new (TRUE);
224         soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
225         uri = g_strdup_printf ("http://127.0.0.1:%u/foo", soup_server_get_port (server));
226
227         do_simple_test (uri);
228         do_thread_test (uri);
229         do_context_test (uri);
230
231         g_free (uri);
232         soup_buffer_free (response);
233         soup_test_server_quit_unref (server);
234
235         test_cleanup ();
236         return errors != 0;
237 }