Git init
[profile/ivi/libsoup2.4.git] / tests / streaming-test.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2008 Red Hat, Inc.
4  */
5
6 #include "config.h"
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include <glib.h>
13 #include <libsoup/soup.h>
14
15 #include "test-utils.h"
16
17 #define RESPONSE_CHUNK_SIZE 1024
18
19 char *full_response, *full_response_md5;
20 gsize full_response_length;
21
22 static void
23 get_full_response (void)
24 {
25         GError *error = NULL;
26
27         if (!g_file_get_contents (SRCDIR "/index.txt",
28                                   &full_response,
29                                   &full_response_length,
30                                   &error)) {
31                 fprintf (stderr, "Could not read index file %s: %s\n",
32                          SRCDIR "/index.txt", error->message);
33                 g_error_free (error);
34                 exit (1);
35         }
36
37         full_response_md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
38                                                          (guchar *)full_response,
39                                                          full_response_length);
40 }
41
42 static void
43 write_next_chunk (SoupMessage *msg, gpointer user_data)
44 {
45         gsize *offset = user_data;
46         gsize chunk_length;
47
48         chunk_length = MIN (RESPONSE_CHUNK_SIZE, full_response_length - *offset);
49         if (chunk_length > 0) {
50                 debug_printf (2, "  writing chunk\n");
51                 soup_message_body_append (msg->response_body,
52                                           SOUP_MEMORY_STATIC,
53                                           full_response + *offset,
54                                           chunk_length);
55                 *offset += chunk_length;
56         } else {
57                 debug_printf (2, "  done\n");
58                 /* This is only actually needed in the chunked and eof
59                  * cases, but it's harmless in the content-length
60                  * case.
61                  */
62                 soup_message_body_complete (msg->response_body);
63         }
64 }
65
66 static void
67 free_offset (SoupMessage *msg, gpointer offset)
68 {
69         g_free (offset);
70 }
71
72 static void
73 server_callback (SoupServer *server, SoupMessage *msg,
74                  const char *path, GHashTable *query,
75                  SoupClientContext *context, gpointer data)
76 {
77         gsize *offset;
78
79         if (!strcmp (path, "/chunked")) {
80                 soup_message_headers_set_encoding (msg->response_headers,
81                                                    SOUP_ENCODING_CHUNKED);
82         } else if (!strcmp (path, "/content-length")) {
83                 soup_message_headers_set_encoding (msg->response_headers,
84                                                    SOUP_ENCODING_CONTENT_LENGTH);
85                 soup_message_headers_set_content_length (msg->response_headers,
86                                                          full_response_length);
87         } else if (!strcmp (path, "/eof")) {
88                 soup_message_headers_set_encoding (msg->response_headers,
89                                                    SOUP_ENCODING_EOF);
90         } else {
91                 soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
92                 return;
93         }
94         soup_message_set_status (msg, SOUP_STATUS_OK);
95
96         offset = g_new0 (gsize, 1);
97         g_signal_connect (msg, "wrote_headers",
98                           G_CALLBACK (write_next_chunk), offset);
99         g_signal_connect (msg, "wrote_chunk",
100                           G_CALLBACK (write_next_chunk), offset);
101         g_signal_connect (msg, "finished",
102                           G_CALLBACK (free_offset), offset);
103 }
104
105 static void
106 do_request (SoupSession *session, SoupURI *base_uri, char *path)
107 {
108         SoupURI *uri;
109         SoupMessage *msg;
110         char *md5;
111
112         uri = soup_uri_new_with_base (base_uri, path);
113         msg = soup_message_new_from_uri ("GET", uri);
114         soup_uri_free (uri);
115
116         soup_session_send_message (session, msg);
117
118         if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
119                 debug_printf (1, "  message failed: %d %s\n",
120                               msg->status_code, msg->reason_phrase);
121                 errors++;
122         }
123
124         if (msg->response_body->length != full_response_length) {
125                 debug_printf (1, "  received length mismatch: expected %d, got %d\n",
126                               (int)full_response_length, (int)msg->request_body->length);
127                 errors++;
128         }
129
130         md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
131                                            (guchar *)msg->response_body->data,
132                                            msg->response_body->length);
133         if (strcmp (md5, full_response_md5) != 0) {
134                 debug_printf (1, "  data mismatch: expected %s, got %s\n",
135                               full_response_md5, md5);
136                 errors++;
137         }
138         g_free (md5);
139
140         g_object_unref (msg);
141 }
142
143 static void
144 do_tests (SoupURI *base_uri)
145 {
146         SoupSession *session;
147
148         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
149         debug_printf (1, "Chunked encoding\n");
150         do_request (session, base_uri, "chunked");
151         debug_printf (1, "\n");
152         debug_printf (1, "Content-Length encoding\n");
153         do_request (session, base_uri, "content-length");
154         debug_printf (1, "\n");
155         debug_printf (1, "EOF encoding\n");
156         do_request (session, base_uri, "eof");
157         soup_test_session_abort_unref (session);
158 }
159
160 int
161 main (int argc, char **argv)
162 {
163         GMainLoop *loop;
164         SoupServer *server;
165         guint port;
166         SoupURI *base_uri;
167
168         test_init (argc, argv, NULL);
169         get_full_response ();
170
171         server = soup_test_server_new (FALSE);
172         soup_server_add_handler (server, NULL,
173                                  server_callback, NULL, NULL);
174         port =  soup_server_get_port (server);
175
176         loop = g_main_loop_new (NULL, TRUE);
177
178         base_uri = soup_uri_new ("http://127.0.0.1");
179         soup_uri_set_port (base_uri, port);
180         do_tests (base_uri);
181         soup_uri_free (base_uri);
182
183         g_main_loop_unref (loop);
184
185         g_free (full_response);
186         g_free (full_response_md5);
187         soup_test_server_quit_unref (server);
188         test_cleanup ();
189         return errors != 0;
190 }