1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007 Red Hat, Inc.
4 * Copyright (C) 2011 Igalia, S.L.
7 #include "test-utils.h"
13 server_callback (SoupServer *server, SoupMessage *msg,
14 const char *path, GHashTable *query,
15 SoupClientContext *context, gpointer data)
17 const char *accept_encoding, *options;
19 char *file = NULL, *contents;
22 options = soup_message_headers_get_one (msg->request_headers,
27 accept_encoding = soup_message_headers_get_list (msg->request_headers,
29 if (accept_encoding && !soup_header_contains (options, "force-encode"))
30 codings = soup_header_parse_quality_list (accept_encoding, NULL);
35 gboolean claim_deflate, claim_gzip;
36 const char *file_path = NULL, *encoding = NULL;
38 claim_deflate = g_slist_find_custom (codings, "deflate", (GCompareFunc)g_ascii_strcasecmp) != NULL;
39 claim_gzip = g_slist_find_custom (codings, "gzip", (GCompareFunc)g_ascii_strcasecmp) != NULL;
41 if (claim_gzip && (!claim_deflate ||
42 (!soup_header_contains (options, "prefer-deflate-zlib") &&
43 !soup_header_contains (options, "prefer-deflate-raw")))) {
44 file_path = SRCDIR "/resources%s.gz";
46 } else if (claim_deflate) {
47 if (soup_header_contains (options, "prefer-deflate-raw")) {
48 file_path = SRCDIR "/resources%s.raw";
51 file_path = SRCDIR "/resources%s.zlib";
55 if (file_path && encoding) {
56 file = g_strdup_printf (file_path, path);
57 if (g_file_test (file, G_FILE_TEST_EXISTS)) {
58 soup_message_headers_append (msg->response_headers,
68 soup_header_free_list (codings);
71 file = g_strdup_printf (SRCDIR "/resources%s", path);
72 if (!g_file_get_contents (file, &contents, &length, NULL)) {
73 /* If path.gz exists but can't be read, we'll send back
74 * the error with "Content-Encoding: gzip" but there's
78 soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
83 if (soup_header_contains (options, "force-encode")) {
84 const gchar *encoding = "gzip";
86 if (soup_header_contains (options, "prefer-deflate-zlib") ||
87 soup_header_contains (options, "prefer-deflate-raw"))
90 soup_message_headers_replace (msg->response_headers,
95 /* Content-Type matches the "real" format, not the sent format */
96 if (g_str_has_suffix (path, ".gz")) {
97 soup_message_headers_append (msg->response_headers,
101 soup_message_headers_append (msg->response_headers,
106 soup_message_set_status (msg, SOUP_STATUS_OK);
107 soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CHUNKED);
109 soup_message_body_append (msg->response_body,
110 SOUP_MEMORY_TAKE, contents, length);
112 if (soup_header_contains (options, "trailing-junk")) {
113 soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY,
114 options, strlen (options));
116 soup_message_body_complete (msg->response_body);
123 } MessageContentStatus;
126 check_response (SoupMessage *msg,
127 const char *expected_encoding,
128 const char *expected_content_type,
129 MessageContentStatus status)
131 const char *coding, *type;
133 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
134 debug_printf (1, " Unexpected status %d %s\n",
135 msg->status_code, msg->reason_phrase);
139 coding = soup_message_headers_get_one (msg->response_headers, "Content-Encoding");
140 if (expected_encoding) {
141 if (!coding || g_ascii_strcasecmp (coding, expected_encoding) != 0) {
142 debug_printf (1, " Unexpected Content-Encoding: %s\n",
143 coding ? coding : "(none)");
148 debug_printf (1, " Unexpected Content-Encoding: %s\n",
154 if (status != NO_CHECK) {
155 if (status == EXPECT_DECODED) {
156 if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED)) {
157 debug_printf (1, " SOUP_MESSAGE_CONTENT_DECODED not set!\n");
161 if (soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED) {
162 debug_printf (1, " SOUP_MESSAGE_CONTENT_DECODED set!\n");
168 type = soup_message_headers_get_one (msg->response_headers, "Content-Type");
169 if (!type || g_ascii_strcasecmp (type, expected_content_type) != 0) {
170 debug_printf (1, " Unexpected Content-Type: %s\n",
171 type ? type : "(none)");
177 check_msg_bodies (SoupMessage *msg1,
179 const char *msg1_type,
180 const char *msg2_type)
182 if (msg1->response_body->length != msg2->response_body->length) {
183 debug_printf (1, " Message length mismatch: %lu (%s) vs %lu (%s)\n",
184 (gulong)msg1->response_body->length,
186 (gulong)msg2->response_body->length,
189 } else if (memcmp (msg1->response_body->data,
190 msg2->response_body->data,
191 msg1->response_body->length) != 0) {
192 debug_printf (1, " Message data mismatch (%s/%s)\n",
193 msg1_type, msg2_type);
199 do_coding_test (void)
201 SoupSession *session;
202 SoupMessage *msg, *msgz, *msgj, *msge, *msgzl, *msgzlj, *msgzle, *msgzlr, *msgzlre;
205 debug_printf (1, "SoupMessage tests\n");
207 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
208 uri = soup_uri_new_with_base (base_uri, "/mbox");
210 /* Plain text data, no claim */
211 debug_printf (1, " GET /mbox, plain\n");
212 msg = soup_message_new_from_uri ("GET", uri);
213 soup_session_send_message (session, msg);
214 check_response (msg, NULL, "text/plain", EXPECT_NOT_DECODED);
216 /* Plain text data, claim gzip */
217 debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n");
218 soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
219 msgz = soup_message_new_from_uri ("GET", uri);
220 soup_session_send_message (session, msgz);
221 check_response (msgz, "gzip", "text/plain", EXPECT_DECODED);
222 check_msg_bodies (msg, msgz, "plain", "compressed");
224 /* Plain text data, claim gzip w/ junk */
225 debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
226 msgj = soup_message_new_from_uri ("GET", uri);
227 soup_message_headers_append (msgj->request_headers,
228 "X-Test-Options", "trailing-junk");
229 soup_session_send_message (session, msgj);
230 check_response (msgj, "gzip", "text/plain", EXPECT_DECODED);
231 check_msg_bodies (msg, msgj, "plain", "compressed w/ junk");
233 /* Plain text data, claim gzip with server error */
234 debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n");
235 msge = soup_message_new_from_uri ("GET", uri);
236 soup_message_headers_append (msge->request_headers,
237 "X-Test-Options", "force-encode");
238 soup_session_send_message (session, msge);
239 check_response (msge, "gzip", "text/plain", EXPECT_NOT_DECODED);
241 /* Failed content-decoding should have left the body untouched
242 * from what the server sent... which happens to be the
245 check_msg_bodies (msg, msge, "plain", "mis-encoded");
247 /* Plain text data, claim deflate */
248 debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n");
249 msgzl = soup_message_new_from_uri ("GET", uri);
250 soup_message_headers_append (msgzl->request_headers,
251 "X-Test-Options", "prefer-deflate-zlib");
252 soup_session_send_message (session, msgzl);
253 check_response (msgzl, "deflate", "text/plain", EXPECT_DECODED);
254 check_msg_bodies (msg, msgzl, "plain", "compressed");
256 /* Plain text data, claim deflate w/ junk */
257 debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n");
258 msgzlj = soup_message_new_from_uri ("GET", uri);
259 soup_message_headers_append (msgzlj->request_headers,
260 "X-Test-Options", "prefer-deflate-zlib, trailing-junk");
261 soup_session_send_message (session, msgzlj);
262 check_response (msgzlj, "deflate", "text/plain", EXPECT_DECODED);
263 check_msg_bodies (msg, msgzlj, "plain", "compressed w/ junk");
265 /* Plain text data, claim deflate with server error */
266 debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n");
267 msgzle = soup_message_new_from_uri ("GET", uri);
268 soup_message_headers_append (msgzle->request_headers,
269 "X-Test-Options", "force-encode, prefer-deflate-zlib");
270 soup_session_send_message (session, msgzle);
271 check_response (msgzle, "deflate", "text/plain", EXPECT_NOT_DECODED);
272 check_msg_bodies (msg, msgzle, "plain", "mis-encoded");
274 /* Plain text data, claim deflate (no zlib headers)*/
275 debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n");
276 msgzlr = soup_message_new_from_uri ("GET", uri);
277 soup_message_headers_append (msgzlr->request_headers,
278 "X-Test-Options", "prefer-deflate-raw");
279 soup_session_send_message (session, msgzlr);
280 check_response (msgzlr, "deflate", "text/plain", EXPECT_DECODED);
281 check_msg_bodies (msg, msgzlr, "plain", "compressed");
283 /* Plain text data, claim deflate with server error */
284 debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n");
285 msgzlre = soup_message_new_from_uri ("GET", uri);
286 soup_message_headers_append (msgzlre->request_headers,
287 "X-Test-Options", "force-encode, prefer-deflate-raw");
288 soup_session_send_message (session, msgzlre);
289 check_response (msgzlre, "deflate", "text/plain", EXPECT_NOT_DECODED);
290 check_msg_bodies (msg, msgzlre, "plain", "mis-encoded");
292 g_object_unref (msg);
293 g_object_unref (msgzlre);
294 g_object_unref (msgzlr);
295 g_object_unref (msgzlj);
296 g_object_unref (msgzle);
297 g_object_unref (msgzl);
298 g_object_unref (msgz);
299 g_object_unref (msgj);
300 g_object_unref (msge);
303 soup_test_session_abort_unref (session);
307 read_finished (GObject *stream, GAsyncResult *result, gpointer user_data)
309 gssize *nread = user_data;
310 GError *error = NULL;
312 *nread = g_input_stream_read_finish (G_INPUT_STREAM (stream),
315 debug_printf (1, " Error reading: %s\n",
317 g_error_free (error);
323 do_single_coding_req_test (SoupRequest *req,
324 const char *expected_encoding,
325 const char *expected_content_type,
326 MessageContentStatus status)
328 GInputStream *stream;
333 GError *error = NULL;
335 data = g_byte_array_new ();
337 msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
339 stream = soup_test_request_send_async_as_sync (req, NULL, &error);
341 debug_printf (1, " Error sending request: %s\n",
343 g_error_free (error);
350 g_input_stream_read_async (stream, buf, sizeof (buf),
352 NULL, read_finished, &nread);
354 g_main_context_iteration (NULL, TRUE);
357 g_byte_array_append (data, buf, nread);
360 soup_test_stream_close_async_as_sync (stream, NULL, &error);
362 debug_printf (1, " error closing stream: %s\n",
364 g_error_free (error);
368 check_response (msg, expected_encoding, expected_content_type, status);
369 g_object_unref (msg);
375 check_req_bodies (GByteArray *body1,
377 const char *msg1_type,
378 const char *msg2_type)
380 if (body1->len != body2->len) {
381 debug_printf (1, " Message length mismatch: %lu (%s) vs %lu (%s)\n",
382 (gulong)body1->len, msg1_type,
383 (gulong)body2->len, msg2_type);
385 } else if (memcmp (body1->data, body2->data, body1->len) != 0) {
386 debug_printf (1, " Message data mismatch (%s/%s)\n",
387 msg1_type, msg2_type);
393 do_coding_req_test (void)
395 SoupSession *session;
396 SoupRequester *requester;
400 GByteArray *plain, *cmp;
402 debug_printf (1, "\nSoupRequest tests\n");
404 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
405 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
406 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
408 requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
409 uri = soup_uri_new_with_base (base_uri, "/mbox");
411 /* Plain text data, no claim */
412 debug_printf (1, " GET /mbox, plain\n");
413 req = soup_requester_request_uri (requester, uri, NULL);
414 plain = do_single_coding_req_test (req, NULL, "text/plain", EXPECT_NOT_DECODED);
415 g_object_unref (req);
417 /* Plain text data, claim gzip */
418 debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n");
419 soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
420 req = soup_requester_request_uri (requester, uri, NULL);
421 cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED);
422 check_req_bodies (plain, cmp, "plain", "compressed");
423 g_byte_array_free (cmp, TRUE);
424 g_object_unref (req);
426 /* Plain text data, claim gzip w/ junk */
427 debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
428 req = soup_requester_request_uri (requester, uri, NULL);
429 msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
430 soup_message_headers_append (msg->request_headers,
431 "X-Test-Options", "trailing-junk");
432 cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED);
433 check_req_bodies (plain, cmp, "plain", "compressed w/ junk");
434 g_byte_array_free (cmp, TRUE);
435 g_object_unref (req);
437 /* Plain text data, claim gzip with server error */
438 debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n");
439 req = soup_requester_request_uri (requester, uri, NULL);
440 msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
441 soup_message_headers_append (msg->request_headers,
442 "X-Test-Options", "force-encode");
443 cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_NOT_DECODED);
445 /* Failed content-decoding should have left the body untouched
446 * from what the server sent... which happens to be the
449 check_req_bodies (plain, cmp, "plain", "mis-encoded");
450 g_byte_array_free (cmp, TRUE);
451 g_object_unref (req);
453 /* Plain text data, claim deflate */
454 debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n");
455 req = soup_requester_request_uri (requester, uri, NULL);
456 msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
457 soup_message_headers_append (msg->request_headers,
458 "X-Test-Options", "prefer-deflate-zlib");
459 cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED);
460 check_req_bodies (plain, cmp, "plain", "compressed");
461 g_byte_array_free (cmp, TRUE);
462 g_object_unref (req);
464 /* Plain text data, claim deflate w/ junk */
465 debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n");
466 req = soup_requester_request_uri (requester, uri, NULL);
467 msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
468 soup_message_headers_append (msg->request_headers,
469 "X-Test-Options", "prefer-deflate-zlib, trailing-junk");
470 cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED);
471 check_req_bodies (plain, cmp, "plain", "compressed w/ junk");
472 g_byte_array_free (cmp, TRUE);
473 g_object_unref (req);
475 /* Plain text data, claim deflate with server error */
476 debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n");
477 req = soup_requester_request_uri (requester, uri, NULL);
478 msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
479 soup_message_headers_append (msg->request_headers,
480 "X-Test-Options", "force-encode, prefer-deflate-zlib");
481 cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED);
482 check_req_bodies (plain, cmp, "plain", "mis-encoded");
483 g_byte_array_free (cmp, TRUE);
484 g_object_unref (req);
486 /* Plain text data, claim deflate (no zlib headers)*/
487 debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n");
488 req = soup_requester_request_uri (requester, uri, NULL);
489 msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
490 soup_message_headers_append (msg->request_headers,
491 "X-Test-Options", "prefer-deflate-raw");
492 cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED);
493 check_req_bodies (plain, cmp, "plain", "compressed");
494 g_byte_array_free (cmp, TRUE);
495 g_object_unref (req);
497 /* Plain text data, claim deflate with server error */
498 debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n");
499 req = soup_requester_request_uri (requester, uri, NULL);
500 msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
501 soup_message_headers_append (msg->request_headers,
502 "X-Test-Options", "force-encode, prefer-deflate-raw");
503 cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED);
504 check_req_bodies (plain, cmp, "plain", "mis-encoded");
505 g_byte_array_free (cmp, TRUE);
506 g_object_unref (req);
508 g_byte_array_free (plain, TRUE);
511 soup_test_session_abort_unref (session);
515 main (int argc, char **argv)
517 test_init (argc, argv, NULL);
519 server = soup_test_server_new (TRUE);
520 soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
521 base_uri = soup_uri_new ("http://127.0.0.1/");
522 soup_uri_set_port (base_uri, soup_server_get_port (server));
525 do_coding_req_test ();
527 soup_uri_free (base_uri);
528 soup_test_server_quit_unref (server);