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 "test-utils.h"
7
8 #define RESPONSE_CHUNK_SIZE 1024
9
10 SoupBuffer *full_response;
11 char *full_response_md5;
12
13 static void
write_next_chunk(SoupMessage * msg,gpointer user_data)14 write_next_chunk (SoupMessage *msg, gpointer user_data)
15 {
16 gsize *offset = user_data;
17 gsize chunk_length;
18
19 chunk_length = MIN (RESPONSE_CHUNK_SIZE, full_response->length - *offset);
20 if (chunk_length > 0) {
21 debug_printf (2, " writing chunk\n");
22 soup_message_body_append (msg->response_body,
23 SOUP_MEMORY_STATIC,
24 full_response->data + *offset,
25 chunk_length);
26 *offset += chunk_length;
27 } else {
28 debug_printf (2, " done\n");
29 /* This is only actually needed in the chunked and eof
30 * cases, but it's harmless in the content-length
31 * case.
32 */
33 soup_message_body_complete (msg->response_body);
34 }
35 }
36
37 static void
free_offset(SoupMessage * msg,gpointer offset)38 free_offset (SoupMessage *msg, gpointer offset)
39 {
40 g_free (offset);
41 }
42
43 static void
server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * context,gpointer data)44 server_callback (SoupServer *server, SoupMessage *msg,
45 const char *path, GHashTable *query,
46 SoupClientContext *context, gpointer data)
47 {
48 gsize *offset;
49
50 if (!strcmp (path, "/chunked")) {
51 soup_message_headers_set_encoding (msg->response_headers,
52 SOUP_ENCODING_CHUNKED);
53 } else if (!strcmp (path, "/content-length")) {
54 soup_message_headers_set_encoding (msg->response_headers,
55 SOUP_ENCODING_CONTENT_LENGTH);
56 soup_message_headers_set_content_length (msg->response_headers,
57 full_response->length);
58 } else if (!strcmp (path, "/eof")) {
59 soup_message_headers_set_encoding (msg->response_headers,
60 SOUP_ENCODING_EOF);
61 } else {
62 soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
63 return;
64 }
65 soup_message_set_status (msg, SOUP_STATUS_OK);
66
67 offset = g_new0 (gsize, 1);
68 g_signal_connect (msg, "wrote_headers",
69 G_CALLBACK (write_next_chunk), offset);
70 g_signal_connect (msg, "wrote_chunk",
71 G_CALLBACK (write_next_chunk), offset);
72 g_signal_connect (msg, "finished",
73 G_CALLBACK (free_offset), offset);
74 }
75
76 static void
do_request(SoupSession * session,SoupURI * base_uri,char * path)77 do_request (SoupSession *session, SoupURI *base_uri, char *path)
78 {
79 SoupURI *uri;
80 SoupMessage *msg;
81 char *md5;
82
83 uri = soup_uri_new_with_base (base_uri, path);
84 msg = soup_message_new_from_uri ("GET", uri);
85 soup_uri_free (uri);
86
87 soup_session_send_message (session, msg);
88
89 soup_test_assert_message_status (msg, SOUP_STATUS_OK);
90 g_assert_cmpint (msg->response_body->length, ==, full_response->length);
91
92 md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
93 (guchar *)msg->response_body->data,
94 msg->response_body->length);
95 g_assert_cmpstr (md5, ==, full_response_md5);
96 g_free (md5);
97
98 g_object_unref (msg);
99 }
100
101 static void
do_chunked_test(gconstpointer data)102 do_chunked_test (gconstpointer data)
103 {
104 SoupURI *base_uri = (SoupURI *)data;
105 SoupSession *session;
106
107 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
108 do_request (session, base_uri, "chunked");
109 soup_test_session_abort_unref (session);
110 }
111
112 static void
do_content_length_test(gconstpointer data)113 do_content_length_test (gconstpointer data)
114 {
115 SoupURI *base_uri = (SoupURI *)data;
116 SoupSession *session;
117
118 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
119 do_request (session, base_uri, "content-length");
120 soup_test_session_abort_unref (session);
121 }
122
123 static void
do_eof_test(gconstpointer data)124 do_eof_test (gconstpointer data)
125 {
126 SoupURI *base_uri = (SoupURI *)data;
127 SoupSession *session;
128
129 g_test_bug ("572153");
130
131 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
132 do_request (session, base_uri, "eof");
133 soup_test_session_abort_unref (session);
134 }
135
136 int
main(int argc,char ** argv)137 main (int argc, char **argv)
138 {
139 GMainLoop *loop;
140 SoupServer *server;
141 SoupURI *base_uri;
142 int ret;
143
144 test_init (argc, argv, NULL);
145
146 full_response = soup_test_get_index ();
147 full_response_md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
148 (guchar *)full_response->data,
149 full_response->length);
150
151 server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
152 soup_server_add_handler (server, NULL,
153 server_callback, NULL, NULL);
154
155 loop = g_main_loop_new (NULL, TRUE);
156
157 base_uri = soup_test_server_get_uri (server, "http", NULL);
158
159 g_test_add_data_func ("/streaming/chunked", base_uri, do_chunked_test);
160 g_test_add_data_func ("/streaming/content-length", base_uri, do_content_length_test);
161 g_test_add_data_func ("/streaming/eof", base_uri, do_eof_test);
162
163 ret = g_test_run ();
164
165 soup_uri_free (base_uri);
166 g_main_loop_unref (loop);
167
168 g_free (full_response_md5);
169 soup_test_server_quit_unref (server);
170 test_cleanup ();
171
172 return ret;
173 }
174