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 if (!soup_header_contains (options, "empty")) {
110 soup_message_body_append (msg->response_body,
111 SOUP_MEMORY_TAKE, contents, length);
115 if (soup_header_contains (options, "trailing-junk")) {
116 soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY,
117 options, strlen (options));
119 soup_message_body_complete (msg->response_body);
126 } MessageContentStatus;
129 check_response (SoupMessage *msg,
130 const char *expected_encoding,
131 const char *expected_content_type,
132 MessageContentStatus status)
134 const char *coding, *type;
136 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
137 debug_printf (1, " Unexpected status %d %s\n",
138 msg->status_code, msg->reason_phrase);
142 coding = soup_message_headers_get_one (msg->response_headers, "Content-Encoding");
143 if (expected_encoding) {
144 if (!coding || g_ascii_strcasecmp (coding, expected_encoding) != 0) {
145 debug_printf (1, " Unexpected Content-Encoding: %s\n",
146 coding ? coding : "(none)");
151 debug_printf (1, " Unexpected Content-Encoding: %s\n",
157 if (status != NO_CHECK) {
158 if (status == EXPECT_DECODED) {
159 if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED)) {
160 debug_printf (1, " SOUP_MESSAGE_CONTENT_DECODED not set!\n");
164 if (soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED) {
165 debug_printf (1, " SOUP_MESSAGE_CONTENT_DECODED set!\n");
171 type = soup_message_headers_get_one (msg->response_headers, "Content-Type");
172 if (!type || g_ascii_strcasecmp (type, expected_content_type) != 0) {
173 debug_printf (1, " Unexpected Content-Type: %s\n",
174 type ? type : "(none)");
180 check_msg_bodies (SoupMessage *msg1,
182 const char *msg1_type,
183 const char *msg2_type)
185 if (msg1->response_body->length != msg2->response_body->length) {
186 debug_printf (1, " Message length mismatch: %lu (%s) vs %lu (%s)\n",
187 (gulong)msg1->response_body->length,
189 (gulong)msg2->response_body->length,
192 } else if (memcmp (msg1->response_body->data,
193 msg2->response_body->data,
194 msg1->response_body->length) != 0) {
195 debug_printf (1, " Message data mismatch (%s/%s)\n",
196 msg1_type, msg2_type);
202 do_coding_test (void)
204 SoupSession *session;
205 SoupMessage *msg, *msgz, *msgj, *msge, *msgzl, *msgzlj, *msgzle, *msgzlr, *msgzlre;
208 debug_printf (1, "SoupMessage tests\n");
210 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
211 uri = soup_uri_new_with_base (base_uri, "/mbox");
213 /* Plain text data, no claim */
214 debug_printf (1, " GET /mbox, plain\n");
215 msg = soup_message_new_from_uri ("GET", uri);
216 soup_session_send_message (session, msg);
217 check_response (msg, NULL, "text/plain", EXPECT_NOT_DECODED);
219 /* Plain text data, claim gzip */
220 debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n");
221 soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
222 msgz = soup_message_new_from_uri ("GET", uri);
223 soup_session_send_message (session, msgz);
224 check_response (msgz, "gzip", "text/plain", EXPECT_DECODED);
225 check_msg_bodies (msg, msgz, "plain", "compressed");
227 /* Plain text data, claim gzip w/ junk */
228 debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
229 msgj = soup_message_new_from_uri ("GET", uri);
230 soup_message_headers_append (msgj->request_headers,
231 "X-Test-Options", "trailing-junk");
232 soup_session_send_message (session, msgj);
233 check_response (msgj, "gzip", "text/plain", EXPECT_DECODED);
234 check_msg_bodies (msg, msgj, "plain", "compressed w/ junk");
236 /* Plain text data, claim gzip with server error */
237 debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n");
238 msge = soup_message_new_from_uri ("GET", uri);
239 soup_message_headers_append (msge->request_headers,
240 "X-Test-Options", "force-encode");
241 soup_session_send_message (session, msge);
242 check_response (msge, "gzip", "text/plain", EXPECT_NOT_DECODED);
244 /* Failed content-decoding should have left the body untouched
245 * from what the server sent... which happens to be the
248 check_msg_bodies (msg, msge, "plain", "mis-encoded");
250 /* Plain text data, claim deflate */
251 debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n");
252 msgzl = soup_message_new_from_uri ("GET", uri);
253 soup_message_headers_append (msgzl->request_headers,
254 "X-Test-Options", "prefer-deflate-zlib");
255 soup_session_send_message (session, msgzl);
256 check_response (msgzl, "deflate", "text/plain", EXPECT_DECODED);
257 check_msg_bodies (msg, msgzl, "plain", "compressed");
259 /* Plain text data, claim deflate w/ junk */
260 debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n");
261 msgzlj = soup_message_new_from_uri ("GET", uri);
262 soup_message_headers_append (msgzlj->request_headers,
263 "X-Test-Options", "prefer-deflate-zlib, trailing-junk");
264 soup_session_send_message (session, msgzlj);
265 check_response (msgzlj, "deflate", "text/plain", EXPECT_DECODED);
266 check_msg_bodies (msg, msgzlj, "plain", "compressed w/ junk");
268 /* Plain text data, claim deflate with server error */
269 debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n");
270 msgzle = soup_message_new_from_uri ("GET", uri);
271 soup_message_headers_append (msgzle->request_headers,
272 "X-Test-Options", "force-encode, prefer-deflate-zlib");
273 soup_session_send_message (session, msgzle);
274 check_response (msgzle, "deflate", "text/plain", EXPECT_NOT_DECODED);
275 check_msg_bodies (msg, msgzle, "plain", "mis-encoded");
277 /* Plain text data, claim deflate (no zlib headers)*/
278 debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n");
279 msgzlr = soup_message_new_from_uri ("GET", uri);
280 soup_message_headers_append (msgzlr->request_headers,
281 "X-Test-Options", "prefer-deflate-raw");
282 soup_session_send_message (session, msgzlr);
283 check_response (msgzlr, "deflate", "text/plain", EXPECT_DECODED);
284 check_msg_bodies (msg, msgzlr, "plain", "compressed");
286 /* Plain text data, claim deflate with server error */
287 debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n");
288 msgzlre = soup_message_new_from_uri ("GET", uri);
289 soup_message_headers_append (msgzlre->request_headers,
290 "X-Test-Options", "force-encode, prefer-deflate-raw");
291 soup_session_send_message (session, msgzlre);
292 check_response (msgzlre, "deflate", "text/plain", EXPECT_NOT_DECODED);
293 check_msg_bodies (msg, msgzlre, "plain", "mis-encoded");
295 g_object_unref (msg);
296 g_object_unref (msgzlre);
297 g_object_unref (msgzlr);
298 g_object_unref (msgzlj);
299 g_object_unref (msgzle);
300 g_object_unref (msgzl);
301 g_object_unref (msgz);
302 g_object_unref (msgj);
303 g_object_unref (msge);
306 soup_test_session_abort_unref (session);
310 read_finished (GObject *stream, GAsyncResult *result, gpointer user_data)
312 gssize *nread = user_data;
313 GError *error = NULL;
315 *nread = g_input_stream_read_finish (G_INPUT_STREAM (stream),
318 debug_printf (1, " Error reading: %s\n",
320 g_error_free (error);
326 do_single_coding_req_test (SoupRequestHTTP *reqh,
327 const char *expected_encoding,
328 const char *expected_content_type,
329 MessageContentStatus status)
331 GInputStream *stream;
336 GError *error = NULL;
338 data = g_byte_array_new ();
340 stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, &error);
342 debug_printf (1, " Error sending request: %s\n",
344 g_error_free (error);
351 g_input_stream_read_async (stream, buf, sizeof (buf),
353 NULL, read_finished, &nread);
355 g_main_context_iteration (NULL, TRUE);
358 g_byte_array_append (data, buf, nread);
361 soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error);
363 debug_printf (1, " error closing stream: %s\n",
365 g_error_free (error);
368 g_object_unref (stream);
370 msg = soup_request_http_get_message (reqh);
371 check_response (msg, expected_encoding, expected_content_type, status);
372 g_object_unref (msg);
378 check_req_bodies (GByteArray *body1,
380 const char *msg1_type,
381 const char *msg2_type)
383 if (body1->len != body2->len) {
384 debug_printf (1, " Message length mismatch: %lu (%s) vs %lu (%s)\n",
385 (gulong)body1->len, msg1_type,
386 (gulong)body2->len, msg2_type);
388 } else if (memcmp (body1->data, body2->data, body1->len) != 0) {
389 debug_printf (1, " Message data mismatch (%s/%s)\n",
390 msg1_type, msg2_type);
396 do_coding_req_test (void)
398 SoupSession *session;
399 SoupRequestHTTP *reqh;
401 GByteArray *plain, *cmp;
403 debug_printf (1, "\nSoupRequest tests\n");
405 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
406 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
408 uri = soup_uri_new_with_base (base_uri, "/mbox");
410 /* Plain text data, no claim */
411 debug_printf (1, " GET /mbox, plain\n");
412 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
413 plain = do_single_coding_req_test (reqh, NULL, "text/plain", EXPECT_NOT_DECODED);
414 g_object_unref (reqh);
416 /* Plain text data, claim gzip */
417 debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n");
418 soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
419 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
420 cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_DECODED);
421 check_req_bodies (plain, cmp, "plain", "compressed");
422 g_byte_array_free (cmp, TRUE);
423 g_object_unref (reqh);
425 /* Plain text data, claim gzip w/ junk */
426 debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
427 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
428 soup_message_headers_append (reqh->request_headers,
429 "X-Test-Options", "trailing-junk");
430 cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_DECODED);
431 check_req_bodies (plain, cmp, "plain", "compressed w/ junk");
432 g_byte_array_free (cmp, TRUE);
433 g_object_unref (reqh);
435 /* Plain text data, claim gzip with server error */
436 debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n");
437 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
438 soup_message_headers_append (reqh->request_headers,
439 "X-Test-Options", "force-encode");
440 cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_NOT_DECODED);
442 /* Failed content-decoding should have left the body untouched
443 * from what the server sent... which happens to be the
446 check_req_bodies (plain, cmp, "plain", "mis-encoded");
447 g_byte_array_free (cmp, TRUE);
448 g_object_unref (reqh);
450 /* Plain text data, claim deflate */
451 debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n");
452 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
453 soup_message_headers_append (reqh->request_headers,
454 "X-Test-Options", "prefer-deflate-zlib");
455 cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED);
456 check_req_bodies (plain, cmp, "plain", "compressed");
457 g_byte_array_free (cmp, TRUE);
458 g_object_unref (reqh);
460 /* Plain text data, claim deflate w/ junk */
461 debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n");
462 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
463 soup_message_headers_append (reqh->request_headers,
464 "X-Test-Options", "prefer-deflate-zlib, trailing-junk");
465 cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED);
466 check_req_bodies (plain, cmp, "plain", "compressed w/ junk");
467 g_byte_array_free (cmp, TRUE);
468 g_object_unref (reqh);
470 /* Plain text data, claim deflate with server error */
471 debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n");
472 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
473 soup_message_headers_append (reqh->request_headers,
474 "X-Test-Options", "force-encode, prefer-deflate-zlib");
475 cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED);
476 check_req_bodies (plain, cmp, "plain", "mis-encoded");
477 g_byte_array_free (cmp, TRUE);
478 g_object_unref (reqh);
480 /* Plain text data, claim deflate (no zlib headers)*/
481 debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n");
482 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
483 soup_message_headers_append (reqh->request_headers,
484 "X-Test-Options", "prefer-deflate-raw");
485 cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED);
486 check_req_bodies (plain, cmp, "plain", "compressed");
487 g_byte_array_free (cmp, TRUE);
488 g_object_unref (reqh);
490 /* Plain text data, claim deflate with server error */
491 debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n");
492 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
493 soup_message_headers_append (reqh->request_headers,
494 "X-Test-Options", "force-encode, prefer-deflate-raw");
495 cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED);
496 check_req_bodies (plain, cmp, "plain", "mis-encoded");
497 g_byte_array_free (cmp, TRUE);
498 g_object_unref (reqh);
500 g_byte_array_free (plain, TRUE);
503 soup_test_session_abort_unref (session);
507 do_coding_empty_test (void)
509 SoupSession *session;
512 SoupRequestHTTP *reqh;
515 debug_printf (1, "\nEmpty allegedly-encoded body test\n");
517 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
518 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
519 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
521 uri = soup_uri_new_with_base (base_uri, "/mbox");
523 debug_printf (1, " SoupMessage\n");
524 msg = soup_message_new_from_uri ("GET", uri);
525 soup_message_headers_append (msg->request_headers,
526 "X-Test-Options", "empty");
527 soup_session_send_message (session, msg);
528 check_response (msg, "gzip", "text/plain", EXPECT_NOT_DECODED);
529 g_object_unref (msg);
531 debug_printf (1, " SoupRequest\n");
532 reqh = soup_session_request_http_uri (session, "GET", uri, NULL);
533 soup_message_headers_append (reqh->request_headers,
534 "X-Test-Options", "empty");
535 body = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_NOT_DECODED);
536 g_byte_array_free (body, TRUE);
537 g_object_unref (reqh);
540 soup_test_session_abort_unref (session);
545 main (int argc, char **argv)
547 test_init (argc, argv, NULL);
549 server = soup_test_server_new (TRUE);
550 soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
551 base_uri = soup_uri_new ("http://127.0.0.1/");
552 soup_uri_set_port (base_uri, soup_server_get_port (server));
555 do_coding_req_test ();
556 do_coding_empty_test ();
558 soup_uri_free (base_uri);
559 soup_test_server_quit_unref (server);