2 * Copyright (C) 2012 Nokia.
4 * Author: Jens Georg <jensg@openismus.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include <libsoup/soup.h>
27 #include "libgupnp/gupnp.h"
30 on_message_finished (SoupSession *session,
33 GMainLoop *loop = (GMainLoop*) user_data;
35 g_main_loop_quit (loop);
39 request_range_and_compare (GMappedFile *file,
46 SoupMessage *message = NULL;
47 goffset want_length = 0, full_length = 0;
48 goffset got_start = 0, got_end = 0, got_length = 0;
51 full_length = g_mapped_file_get_length (file);
53 /* interpretation according to SoupRange documentation */
56 want_length = -want_start;
58 want_length = full_length - want_start;
60 want_length = want_end - want_start + 1;
62 message = soup_message_new ("GET", uri);
63 g_object_ref (message);
65 soup_message_headers_set_range (message->request_headers,
69 /* interpretation according to SoupRange documentation */
72 want_length = -want_start;
73 want_start = full_length + want_start;
74 want_end = want_start + want_length - 1;
77 want_length = full_length - want_start;
78 want_end = full_length - 1;
81 want_length = want_end - want_start + 1;
84 soup_session_queue_message (session,
89 g_main_loop_run (loop);
90 g_assert_cmpint (message->status_code, ==, SOUP_STATUS_PARTIAL_CONTENT);
91 g_assert_cmpint (message->response_body->length, ==, want_length);
92 got_length = soup_message_headers_get_content_length
93 (message->response_headers);
94 g_assert_cmpint (got_length, ==, want_length);
95 soup_message_headers_get_content_range (message->response_headers,
99 g_assert_cmpint (got_start, ==, want_start);
100 g_assert_cmpint (got_end, ==, want_end);
101 result = memcmp (g_mapped_file_get_contents (file) + want_start,
102 message->response_body->data,
104 g_assert_cmpint (result, ==, 0);
106 g_object_unref (message);
108 message = soup_message_new ("GET", uri);
109 g_object_ref (message);
113 test_gupnp_context_http_ranged_requests (void)
115 GUPnPContext *context = NULL;
116 GError *error = NULL;
117 SoupSession *session = NULL;
118 SoupMessage *message = NULL;
122 goffset start, end, length;
125 goffset file_length = 0;
127 loop = g_main_loop_new (NULL, FALSE);
128 g_assert (loop != NULL);
130 file = g_mapped_file_new (DATA_PATH "/random4k.bin",
133 g_assert (file != NULL);
134 g_assert (error == NULL);
135 file_length = g_mapped_file_get_length (file);
137 context = gupnp_context_new (NULL,
141 g_assert (context != NULL);
142 g_assert (error == NULL);
143 port = gupnp_context_get_port (context);
145 gupnp_context_host_path (context,
146 DATA_PATH "/random4k.bin",
149 uri = g_strdup_printf ("http://localhost:%u/random4k.bin", port);
150 g_assert (uri != NULL);
152 session = soup_session_async_new ();
154 /* Corner cases: First byte */
155 request_range_and_compare (file, session, loop, uri, 0, 0);
157 /* Corner cases: Last byte */
158 request_range_and_compare (file,
165 /* Examples from http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html */
166 /* Request first 500 bytes */
167 request_range_and_compare (file, session, loop, uri, 0, 499);
169 /* Request second 500 bytes */
170 request_range_and_compare (file, session, loop, uri, 500, 999);
172 /* Request everything but the first 500 bytes */
173 request_range_and_compare (file, session, loop, uri, 500, file_length - 1);
175 /* Request the last 500 bytes */
176 request_range_and_compare (file, session, loop, uri, file_length - 500, file_length - 1);
178 /* Request the last 500 bytes by using negative requests: Range:
180 request_range_and_compare (file, session, loop, uri, -500, -1);
182 /* Request the last 1k bytes by using negative requests: Range:
184 request_range_and_compare (file, session, loop, uri, 3072, -1);
186 /* Try to get 1 byte after the end of the file */
187 message = soup_message_new ("GET", uri);
188 g_object_ref (message);
190 soup_message_headers_set_range (message->request_headers,
193 soup_session_queue_message (session,
198 g_main_loop_run (loop);
199 g_assert_cmpint (message->status_code, ==, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
201 g_object_unref (message);
203 /* Try with inverted arguments */
204 message = soup_message_new ("GET", uri);
205 g_object_ref (message);
207 soup_message_headers_set_range (message->request_headers, 499, 0);
208 soup_session_queue_message (session,
213 g_main_loop_run (loop);
214 g_assert_cmpint (message->status_code, ==, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
216 g_object_unref (message);
219 g_object_unref (context);
220 g_main_loop_unref (loop);
221 g_mapped_file_unref (file);
224 int main (int argc, char *argv[]) {
226 g_test_init (&argc, &argv, NULL);
227 g_test_add_func ("/context/http/ranged-requests",
228 test_gupnp_context_http_ranged_requests);