summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.am241
-rw-r--r--tests/auth-test.c474
-rw-r--r--tests/cache-test.c659
-rw-r--r--tests/chunk-io-test.c610
-rw-r--r--tests/chunk-test.c190
-rw-r--r--tests/coding-test.c689
-rw-r--r--tests/connection-test.c509
-rw-r--r--tests/context-test.c90
-rw-r--r--tests/continue-test.c107
-rw-r--r--tests/cookies-test.c73
-rw-r--r--tests/date.c376
-rw-r--r--tests/dns.c62
-rw-r--r--tests/forms-test.c164
-rw-r--r--tests/get.c189
-rw-r--r--tests/header-parsing.c472
-rw-r--r--tests/httpd.conf.22.in (renamed from tests/httpd.conf.in)81
-rw-r--r--tests/httpd.conf.24.in276
-rw-r--r--tests/libsoup.supp74
-rw-r--r--tests/misc-test.c588
-rw-r--r--tests/multipart-test.c521
-rw-r--r--tests/no-ssl-test.c151
-rw-r--r--tests/ntlm-test-helper.c103
-rw-r--r--tests/ntlm-test.c281
-rw-r--r--tests/proxy-test.c231
-rw-r--r--tests/pull-api.c180
-rw-r--r--tests/range-test.c216
-rw-r--r--tests/redirect-test.c416
-rw-r--r--tests/requester-test.c594
-rw-r--r--tests/resource-test.c220
-rw-r--r--tests/resources/feed.rdf32
-rw-r--r--tests/resources/home.jpgbin0 -> 1074 bytes
-rw-r--r--tests/resources/home.pngbin0 -> 313 bytes
-rw-r--r--tests/resources/html_binary.html2
-rw-r--r--tests/resources/leading_space.html12
-rw-r--r--tests/resources/test.aiffbin0 -> 384088 bytes
-rw-r--r--tests/resources/test.mp4bin0 -> 192844 bytes
-rw-r--r--tests/resources/test.oggbin0 -> 16994 bytes
-rw-r--r--tests/resources/test.wavbin0 -> 384080 bytes
-rw-r--r--tests/resources/test.webmbin0 -> 149879 bytes
-rw-r--r--tests/resources/text.txt1
-rw-r--r--tests/resources/tux.webpbin0 -> 17128 bytes
-rw-r--r--tests/server-auth-test.c274
-rw-r--r--tests/server-test.c329
-rw-r--r--tests/session-test.c396
-rw-r--r--tests/simple-httpd.c319
-rw-r--r--tests/simple-proxy.c179
-rw-r--r--tests/sniffing-test.c541
-rw-r--r--tests/socket-test.c124
-rw-r--r--tests/soup-tests.gresource.xml28
-rw-r--r--tests/ssl-test.c321
-rw-r--r--tests/streaming-test.c99
-rw-r--r--tests/test-utils.c405
-rw-r--r--tests/test-utils.h108
-rw-r--r--tests/timeout-test.c300
-rw-r--r--tests/tld-test.c278
-rw-r--r--tests/uri-parsing.c515
-rw-r--r--tests/xmlrpc-server-test.c167
-rw-r--r--tests/xmlrpc-server.php17
-rw-r--r--tests/xmlrpc-test.c305
59 files changed, 8451 insertions, 5138 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 995196c3..a8b9d019 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,143 +1,136 @@
-INCLUDES = \
+include $(top_srcdir)/glib-tap.mk
+
+AM_CPPFLAGS = \
-I$(top_srcdir) \
- -DSRCDIR=\""$(abs_srcdir)"\" \
- -DLIBSOUP_DISABLE_DEPRECATED \
- $(SOUP_MAINTAINER_FLAGS) \
- $(XML_CFLAGS) \
$(GLIB_CFLAGS)
LIBS = \
$(top_builddir)/libsoup/libsoup-2.4.la \
- $(LIBGNUTLS_LIBS) \
$(GLIB_LIBS)
-noinst_PROGRAMS = \
- chunk-test \
- coding-test \
- connection-test \
- context-test \
- continue-test \
- cookies-test \
- date \
- dns \
- forms-test \
- get \
- header-parsing \
- misc-test \
- ntlm-test \
- redirect-test \
- requester-test \
- simple-httpd \
- simple-proxy \
- sniffing-test \
- ssl-test \
- streaming-test \
- timeout-test \
- tld-test \
- uri-parsing \
- $(CURL_TESTS) \
- $(APACHE_TESTS) \
- $(XMLRPC_TESTS)
-
-TEST_SRCS = test-utils.c test-utils.h
-
-auth_test_SOURCES = auth-test.c $(TEST_SRCS)
-chunk_test_SOURCES = chunk-test.c $(TEST_SRCS)
-coding_test_SOURCES = coding-test.c $(TEST_SRCS)
-connection_test_SOURCES = connection-test.c $(TEST_SRCS)
-context_test_SOURCES = context-test.c $(TEST_SRCS)
-continue_test_SOURCES = continue-test.c $(TEST_SRCS)
-cookies_test_SOURCES = cookies-test.c $(TEST_SRCS)
-date_SOURCES = date.c $(TEST_SRCS)
-dns_SOURCES = dns.c
-forms_test_SOURCES = forms-test.c $(TEST_SRCS)
-get_SOURCES = get.c
-if BUILD_LIBSOUP_GNOME
-get_LDADD = $(top_builddir)/libsoup/libsoup-gnome-2.4.la
-endif
-header_parsing_SOURCES = header-parsing.c $(TEST_SRCS)
-misc_test_SOURCES = misc-test.c $(TEST_SRCS)
-ntlm_test_SOURCES = ntlm-test.c $(TEST_SRCS)
-proxy_test_SOURCES = proxy-test.c $(TEST_SRCS)
-pull_api_SOURCES = pull-api.c $(TEST_SRCS)
-range_test_SOURCES = range-test.c $(TEST_SRCS)
-redirect_test_SOURCES = redirect-test.c $(TEST_SRCS)
-requester_test_SOURCES = requester-test.c $(TEST_SRCS)
-server_auth_test_SOURCES = server-auth-test.c $(TEST_SRCS)
-simple_httpd_SOURCES = simple-httpd.c
-simple_proxy_SOURCES = simple-proxy.c
-sniffing_test_SOURCES = sniffing-test.c $(TEST_SRCS)
-ssl_test_SOURCES = ssl-test.c $(TEST_SRCS)
-streaming_test_SOURCES = streaming-test.c $(TEST_SRCS)
-timeout_test_SOURCES = timeout-test.c $(TEST_SRCS)
-tld_test_SOURCES = tld-test.c $(TEST_SRCS)
-uri_parsing_SOURCES = uri-parsing.c $(TEST_SRCS)
-xmlrpc_test_SOURCES = xmlrpc-test.c $(TEST_SRCS)
-xmlrpc_server_test_SOURCES = xmlrpc-server-test.c $(TEST_SRCS)
+test_programs = \
+ auth-test \
+ cache-test \
+ chunk-test \
+ chunk-io-test \
+ coding-test \
+ connection-test \
+ context-test \
+ continue-test \
+ cookies-test \
+ date \
+ forms-test \
+ header-parsing \
+ misc-test \
+ multipart-test \
+ no-ssl-test \
+ ntlm-test \
+ proxy-test \
+ pull-api \
+ range-test \
+ redirect-test \
+ requester-test \
+ resource-test \
+ session-test \
+ server-auth-test \
+ server-test \
+ sniffing-test \
+ socket-test \
+ ssl-test \
+ streaming-test \
+ timeout-test \
+ tld-test \
+ uri-parsing \
+ xmlrpc-server-test \
+ xmlrpc-test
+
+test_extra_programs = \
+ ntlm-test-helper \
+ $(TESTS)
+
+test_data = \
+ index.txt \
+ soup-tests.gresource \
+ test-cert.pem \
+ test-key.pem \
+ xmlrpc-server.php
+
+noinst_LTLIBRARIES += libtest.la
+
+libtest_la_SOURCES = \
+ test-utils.c \
+ test-utils.h
+
+LDADD = libtest.la
if HAVE_APACHE
-APACHE_TESTS = auth-test proxy-test pull-api range-test
-endif
-if HAVE_CURL
-CURL_TESTS = forms-test server-auth-test
-endif
-if HAVE_XMLRPC_EPI_PHP
-XMLRPC_TESTS = xmlrpc-test xmlrpc-server-test
+if HAVE_APACHE_2_2
+httpd_conf_in = httpd.conf.22.in
+else
+httpd_conf_in = httpd.conf.24.in
endif
+httpd.conf: $(httpd_conf_in)
+ $(AM_V_GEN) sed -e 's,[@]srcdir@,$(srcdir),' \
+ -e 's,[@]builddir@,$(builddir),' \
+ -e 's,[@]APACHE_MODULE_DIR@,$(APACHE_MODULE_DIR),' \
+ -e 's,[@]APACHE_PHP_MODULE_DIR@,$(APACHE_PHP_MODULE_DIR),' \
+ -e 's,[@]APACHE_PHP_MODULE@,$(APACHE_PHP_MODULE),' \
+ -e 's,[@]IF_HAVE_PHP@,$(IF_HAVE_PHP),' \
+ -e 's,[@]APACHE_SSL_MODULE_DIR@,$(APACHE_SSL_MODULE_DIR),' \
+ $< > $@ || rm -f $@
-TESTS = \
- chunk-test \
- coding-test \
- connection-test \
- context-test \
- continue-test \
- cookies-test \
- date \
- header-parsing \
- misc-test \
- ntlm-test \
- redirect-test \
- requester-test \
- sniffing-test \
- ssl-test \
- streaming-test \
- timeout-test \
- tld-test \
- uri-parsing \
- $(APACHE_TESTS) \
- $(CURL_TESTS) \
- $(XMLRPC_TESTS)
-
-RESOURCES = \
- resources/atom.xml \
- resources/home.gif \
- resources/html_binary.html \
- resources/mbox \
- resources/mbox.gz \
- resources/mbox.raw \
- resources/mbox.zlib \
- resources/ps_binary.ps \
- resources/rss20.xml \
- resources/test.html \
- resources/text_binary.txt
-
-EXTRA_DIST = \
+BUILT_SOURCES += httpd.conf
+test_data += \
htdigest \
htpasswd \
- httpd.conf.in \
- index.txt \
- libsoup.supp \
- test-cert.pem \
- test-key.pem \
- xmlrpc-server.php \
+ httpd.conf
+endif
+
+RESOURCES = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml)
+
+soup-tests.gresource: soup-tests.gresource.xml $(RESOURCES)
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $<
+
+EXTRA_DIST += \
+ htdigest \
+ htpasswd \
+ httpd.conf.22.in \
+ httpd.conf.24.in \
+ index.txt \
+ libsoup.supp \
+ soup-tests.gresource.xml \
+ test-cert.pem \
+ test-key.pem \
+ xmlrpc-server.php \
$(RESOURCES)
-if MISSING_REGRESSION_TEST_PACKAGES
+DISTCLEANFILES += soup-tests.gresource httpd.conf
+
+TESTS_ENVIRONMENT += SOUP_TESTS_IN_MAKE_CHECK=1
+
+check: start-httpd
+
check-local: check-TESTS
- @echo ""
- @echo "NOTE: some tests were not run due to missing packages:" $(MISSING_REGRESSION_TEST_PACKAGES)
- @echo ""
+ @$(MAKE) kill-httpd
+
+.PHONY: start-httpd kill-httpd
+
+start-httpd:
+if HAVE_APACHE_2_2
+ @$(APACHE_HTTPD) -d $(abs_srcdir) -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k start;
+endif
+if HAVE_APACHE_2_4
+ @$(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k start;
endif
kill-httpd:
- $(APACHE_HTTPD) -d `pwd` -f httpd.conf -k stop
+if HAVE_APACHE_2_2
+ @if [ -f httpd.pid ]; then \
+ $(APACHE_HTTPD) -d $(abs_srcdir) -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k stop; \
+ fi
+endif
+if HAVE_APACHE_2_4
+ @if [ -f httpd.pid ]; then \
+ $(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k stop; \
+ fi
+endif
diff --git a/tests/auth-test.c b/tests/auth-test.c
index 85c4d414..8ed5cead 100644
--- a/tests/auth-test.c
+++ b/tests/auth-test.c
@@ -2,6 +2,7 @@
#include "test-utils.h"
+static const char *base_uri;
static GMainLoop *loop;
typedef struct {
@@ -35,10 +36,6 @@ typedef struct {
guint final_status;
} SoupAuthTest;
-/* Will either point to main_tests or relogin_tests
- */
-static SoupAuthTest *current_tests;
-
static SoupAuthTest main_tests[] = {
{ "No auth available, should fail",
"Basic/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED },
@@ -146,7 +143,12 @@ static SoupAuthTest main_tests[] = {
"Digest/realm1/not/", "1", FALSE, /* should not be used */ "1", SOUP_STATUS_UNAUTHORIZED },
{ "Make sure we've forgotten it",
- "Digest/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED }
+ "Digest/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED },
+
+ { "Fail with URI-embedded password, then use right password in the authenticate signal",
+ "Basic/realm3/", "43", TRUE, "43", SOUP_STATUS_OK },
+
+ { NULL }
};
static const char *auths[] = {
@@ -202,14 +204,12 @@ handler (SoupMessage *msg, gpointer data)
if (*expected) {
exp = *expected - '0';
- if (auth != exp) {
- debug_printf (1, " expected %s!\n", auths[exp]);
- errors++;
- }
+ soup_test_assert (auth == exp,
+ "expected %s", auths[exp]);
memmove (expected, expected + 1, strlen (expected));
} else {
- debug_printf (1, " expected to be finished\n");
- errors++;
+ soup_test_assert (*expected,
+ "expected to be finished");
}
}
@@ -217,18 +217,18 @@ static void
authenticate (SoupSession *session, SoupMessage *msg,
SoupAuth *auth, gboolean retrying, gpointer data)
{
- int *i = data;
+ SoupAuthTest *test = data;
char *username, *password;
char num;
- if (!current_tests[*i].provided[0])
+ if (!test->provided[0])
return;
if (retrying) {
- if (!current_tests[*i].provided[1])
+ if (!test->provided[1])
return;
- num = current_tests[*i].provided[1];
+ num = test->provided[1];
} else
- num = current_tests[*i].provided[0];
+ num = test->provided[0];
username = g_strdup_printf ("user%c", num);
password = g_strdup_printf ("realm%c", num);
@@ -244,13 +244,10 @@ bug271540_sent (SoupMessage *msg, gpointer data)
gboolean *authenticated = data;
int auth = identify_auth (msg);
- if (!*authenticated && auth) {
- debug_printf (1, " using auth on message %d before authenticating!!??\n", n);
- errors++;
- } else if (*authenticated && !auth) {
- debug_printf (1, " sent unauthenticated message %d after authenticating!\n", n);
- errors++;
- }
+ soup_test_assert (*authenticated || !auth,
+ "using auth on message %d before authenticating", n);
+ soup_test_assert (!*authenticated || auth,
+ "sent unauthenticated message %d after authenticating", n);
}
static void
@@ -269,8 +266,8 @@ bug271540_authenticate (SoupSession *session, SoupMessage *msg,
soup_auth_authenticate (auth, "user1", "realm1");
*authenticated = TRUE;
} else {
- debug_printf (1, " asked to authenticate message %d after authenticating!\n", n);
- errors++;
+ soup_test_assert (!*authenticated,
+ "asked to authenticate message %d after authenticating", n);
}
}
@@ -278,13 +275,8 @@ static void
bug271540_finished (SoupSession *session, SoupMessage *msg, gpointer data)
{
int *left = data;
- int n = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "#"));
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " got status '%d %s' on message %d!\n",
- msg->status_code, msg->reason_phrase, n);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
(*left)--;
if (!*left)
@@ -292,7 +284,7 @@ bug271540_finished (SoupSession *session, SoupMessage *msg, gpointer data)
}
static void
-do_pipelined_auth_test (const char *base_uri)
+do_pipelined_auth_test (void)
{
SoupSession *session;
SoupMessage *msg;
@@ -300,7 +292,10 @@ do_pipelined_auth_test (const char *base_uri)
char *uri;
int i;
- debug_printf (1, "Testing pipelined auth (bug 271540):\n");
+ g_test_bug ("271540");
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
authenticated = FALSE;
@@ -437,28 +432,21 @@ do_digest_nonce_test (SoupSession *session,
&got_401);
got_401 = FALSE;
soup_session_send_message (session, msg);
- if (got_401 != expect_401) {
- debug_printf (1, " %s request %s a 401 Unauthorized!\n", nth,
- got_401 ? "got" : "did not get");
- errors++;
- }
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " %s request got status %d %s!\n", nth,
- msg->status_code, msg->reason_phrase);
- errors++;
- }
- if (errors == 0)
- debug_printf (1, " %s request succeeded\n", nth);
+ soup_test_assert (got_401 == expect_401,
+ "%s request %s a 401 Unauthorized!\n", nth,
+ got_401 ? "got" : "did not get");
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
g_object_unref (msg);
}
static void
-do_digest_expiration_test (const char *base_uri)
+do_digest_expiration_test (void)
{
SoupSession *session;
char *uri;
- debug_printf (1, "\nTesting digest nonce expiration:\n");
+ SOUP_TEST_SKIP_IF_NO_APACHE;
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
@@ -530,10 +518,8 @@ async_authenticate_assert_once (SoupSession *session, SoupMessage *msg,
debug_printf (2, " async_authenticate_assert_once\n");
- if (*been_here) {
- debug_printf (1, " ERROR: async_authenticate_assert_once called twice\n");
- errors++;
- }
+ soup_test_assert (!*been_here,
+ "async_authenticate_assert_once called twice");
*been_here = TRUE;
}
@@ -545,10 +531,8 @@ async_authenticate_assert_once_and_stop (SoupSession *session, SoupMessage *msg,
debug_printf (2, " async_authenticate_assert_once_and_stop\n");
- if (*been_here) {
- debug_printf (1, " ERROR: async_authenticate_assert_once called twice\n");
- errors++;
- }
+ soup_test_assert (!*been_here,
+ "async_authenticate_assert_once called twice");
*been_here = TRUE;
soup_session_pause_message (session, msg);
@@ -556,7 +540,7 @@ async_authenticate_assert_once_and_stop (SoupSession *session, SoupMessage *msg,
}
static void
-do_async_auth_test (const char *base_uri)
+do_async_auth_good_password_test (void)
{
SoupSession *session;
SoupMessage *msg1, *msg2, *msg3, msg2_bak;
@@ -564,15 +548,13 @@ do_async_auth_test (const char *base_uri)
char *uri;
SoupAuth *auth = NULL;
int remaining;
- gboolean been_there;
- debug_printf (1, "\nTesting async auth:\n");
+ SOUP_TEST_SKIP_IF_NO_APACHE;
loop = g_main_loop_new (NULL, TRUE);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- remaining = 0;
-
uri = g_strconcat (base_uri, "Basic/realm1/", NULL);
+ remaining = 0;
msg1 = soup_message_new ("GET", uri);
g_object_set_data (G_OBJECT (msg1), "id", GINT_TO_POINTER (1));
@@ -590,13 +572,7 @@ do_async_auth_test (const char *base_uri)
g_object_set_data (G_OBJECT (msg2), "id", GINT_TO_POINTER (2));
soup_session_send_message (session, msg2);
- if (msg2->status_code == SOUP_STATUS_UNAUTHORIZED)
- debug_printf (1, " msg2 failed as expected\n");
- else {
- debug_printf (1, " msg2 got wrong status! (%u)\n",
- msg2->status_code);
- errors++;
- }
+ soup_test_assert_message_status (msg2, SOUP_STATUS_UNAUTHORIZED);
/* msg2 should be done at this point; assuming everything is
* working correctly, the session won't look at it again; we
@@ -627,25 +603,11 @@ do_async_auth_test (const char *base_uri)
g_main_loop_run (loop);
/* async_finished will quit the loop */
- } else {
- debug_printf (1, " msg1 didn't get authenticate signal!\n");
- errors++;
- }
+ } else
+ soup_test_assert (auth, "msg1 didn't get authenticate signal");
- if (msg1->status_code == SOUP_STATUS_OK)
- debug_printf (1, " msg1 succeeded\n");
- else {
- debug_printf (1, " msg1 FAILED! (%u %s)\n",
- msg1->status_code, msg1->reason_phrase);
- errors++;
- }
- if (msg3->status_code == SOUP_STATUS_OK)
- debug_printf (1, " msg3 succeeded\n");
- else {
- debug_printf (1, " msg3 FAILED! (%u %s)\n",
- msg3->status_code, msg3->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg1, SOUP_STATUS_OK);
+ soup_test_assert_message_status (msg3, SOUP_STATUS_OK);
soup_test_session_abort_unref (session);
@@ -654,27 +616,46 @@ do_async_auth_test (const char *base_uri)
memcpy (msg2, &msg2_bak, sizeof (SoupMessage));
g_object_unref (msg2);
+ g_free (uri);
+ g_main_loop_unref (loop);
+}
+
+static void
+do_async_auth_bad_password_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ guint auth_id;
+ char *uri;
+ SoupAuth *auth = NULL;
+ int remaining;
+ gboolean been_there;
+
/* Test that giving the wrong password doesn't cause multiple
* authenticate signals the second time.
*/
- debug_printf (1, "\nTesting async auth with wrong password (#522601):\n");
+ g_test_bug ("522601");
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+ loop = g_main_loop_new (NULL, TRUE);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ uri = g_strconcat (base_uri, "Basic/realm1/", NULL);
remaining = 0;
auth = NULL;
- msg1 = soup_message_new ("GET", uri);
- g_object_set_data (G_OBJECT (msg1), "id", GINT_TO_POINTER (1));
+ msg = soup_message_new ("GET", uri);
+ g_object_set_data (G_OBJECT (msg), "id", GINT_TO_POINTER (1));
auth_id = g_signal_connect (session, "authenticate",
G_CALLBACK (async_authenticate), &auth);
- g_object_ref (msg1);
+ g_object_ref (msg);
remaining++;
- soup_session_queue_message (session, msg1, async_finished, &remaining);
+ soup_session_queue_message (session, msg, async_finished, &remaining);
g_main_loop_run (loop);
g_signal_handler_disconnect (session, auth_id);
soup_auth_authenticate (auth, "user1", "wrong");
g_object_unref (auth);
- soup_session_unpause_message (session, msg1);
+ soup_session_unpause_message (session, msg);
been_there = FALSE;
auth_id = g_signal_connect (session, "authenticate",
@@ -683,55 +664,71 @@ do_async_auth_test (const char *base_uri)
g_main_loop_run (loop);
g_signal_handler_disconnect (session, auth_id);
- if (!been_there) {
- debug_printf (1, " authenticate not emitted?\n");
- errors++;
- }
+ soup_test_assert (been_there,
+ "authenticate not emitted");
soup_test_session_abort_unref (session);
- g_object_unref (msg1);
+ g_object_unref (msg);
+
+ g_free (uri);
+ g_main_loop_unref (loop);
+}
+
+static void
+do_async_auth_no_password_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ guint auth_id;
+ char *uri;
+ int remaining;
+ gboolean been_there;
/* Test that giving no password doesn't cause multiple
* authenticate signals the second time.
*/
- debug_printf (1, "\nTesting async auth with no password (#583462):\n");
+ g_test_bug ("583462");
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+ loop = g_main_loop_new (NULL, TRUE);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ uri = g_strconcat (base_uri, "Basic/realm1/", NULL);
remaining = 0;
/* Send a message that doesn't actually authenticate
*/
- msg1 = soup_message_new ("GET", uri);
- g_object_set_data (G_OBJECT (msg1), "id", GINT_TO_POINTER (1));
+ msg = soup_message_new ("GET", uri);
+ g_object_set_data (G_OBJECT (msg), "id", GINT_TO_POINTER (1));
auth_id = g_signal_connect (session, "authenticate",
G_CALLBACK (async_authenticate), NULL);
- g_object_ref (msg1);
+ g_object_ref (msg);
remaining++;
- soup_session_queue_message (session, msg1, async_finished, &remaining);
+ soup_session_queue_message (session, msg, async_finished, &remaining);
g_main_loop_run (loop);
g_signal_handler_disconnect (session, auth_id);
- soup_session_unpause_message (session, msg1);
+ soup_session_unpause_message (session, msg);
g_main_loop_run (loop);
- g_object_unref(msg1);
+ g_object_unref(msg);
/* Now send a second message */
- msg1 = soup_message_new ("GET", uri);
- g_object_set_data (G_OBJECT (msg1), "id", GINT_TO_POINTER (2));
- g_object_ref (msg1);
+ msg = soup_message_new ("GET", uri);
+ g_object_set_data (G_OBJECT (msg), "id", GINT_TO_POINTER (2));
+ g_object_ref (msg);
been_there = FALSE;
auth_id = g_signal_connect (session, "authenticate",
G_CALLBACK (async_authenticate_assert_once_and_stop),
&been_there);
remaining++;
- soup_session_queue_message (session, msg1, async_finished, &remaining);
+ soup_session_queue_message (session, msg, async_finished, &remaining);
g_main_loop_run (loop);
- soup_session_unpause_message (session, msg1);
+ soup_session_unpause_message (session, msg);
g_main_loop_run (loop);
g_signal_handler_disconnect (session, auth_id);
soup_test_session_abort_unref (session);
- g_object_unref (msg1);
+ g_object_unref (msg);
g_free (uri);
g_main_loop_unref (loop);
@@ -795,41 +792,27 @@ select_auth_test_one (SoupURI *uri,
msg = soup_message_new_from_uri ("GET", uri);
soup_session_send_message (session, msg);
- if (strcmp (sad.round[0].headers, first_headers) != 0) {
- debug_printf (1, " Header order wrong: expected %s, got %s\n",
- first_headers, sad.round[0].headers);
- errors++;
- }
- if (strcmp (sad.round[0].response, first_response) != 0) {
- debug_printf (1, " Selected auth type wrong: expected %s, got %s\n",
- first_response, sad.round[0].response);
- errors++;
- }
-
- if (second_headers && !sad.round[1].headers) {
- debug_printf (1, " Expected a second round!\n");
- errors++;
- } else if (!second_headers && sad.round[1].headers) {
- debug_printf (1, " Didn't expect a second round!\n");
- errors++;
- } else if (second_headers) {
- if (strcmp (sad.round[1].headers, second_headers) != 0) {
- debug_printf (1, " Second round header order wrong: expected %s, got %s\n",
- second_headers, sad.round[1].headers);
- errors++;
- }
- if (strcmp (sad.round[1].response, second_response) != 0) {
- debug_printf (1, " Second round selected auth type wrong: expected %s, got %s\n",
- second_response, sad.round[1].response);
- errors++;
- }
+ soup_test_assert (strcmp (sad.round[0].headers, first_headers) == 0,
+ "Header order wrong: expected %s, got %s",
+ first_headers, sad.round[0].headers);
+ soup_test_assert (strcmp (sad.round[0].response, first_response) == 0,
+ "Selected auth type wrong: expected %s, got %s",
+ first_response, sad.round[0].response);
+
+ soup_test_assert (sad.round[1].headers || !second_headers,
+ "Expected a second round");
+ soup_test_assert (!sad.round[1].headers || second_headers,
+ "Didn't expect a second round");
+ if (second_headers && second_response) {
+ soup_test_assert (strcmp (sad.round[1].headers, second_headers) == 0,
+ "Second round header order wrong: expected %s, got %s\n",
+ second_headers, sad.round[1].headers);
+ soup_test_assert (strcmp (sad.round[1].response, second_response) == 0,
+ "Second round selected auth type wrong: expected %s, got %s\n",
+ second_response, sad.round[1].response);
}
- if (msg->status_code != final_status) {
- debug_printf (1, " Final status wrong: expected %u, got %u\n",
- final_status, msg->status_code);
- errors++;
- }
+ soup_test_assert_message_status (msg, final_status);
g_object_unref (msg);
soup_test_session_abort_unref (session);
@@ -873,7 +856,7 @@ do_select_auth_test (void)
SoupAuthDomain *basic_auth_domain, *digest_auth_domain;
SoupURI *uri;
- debug_printf (1, "\nTesting selection among multiple auths:\n");
+ g_test_bug ("562339");
/* It doesn't seem to be possible to configure Apache to serve
* multiple auth types for a single URL. So we have to use
@@ -1029,8 +1012,6 @@ do_auth_close_test (void)
SoupURI *uri;
AuthCloseData acd;
- debug_printf (1, "\nTesting auth when server times out connection:\n");
-
server = soup_test_server_new (FALSE);
soup_server_add_handler (server, NULL,
server_callback, NULL, NULL);
@@ -1057,18 +1038,130 @@ do_auth_close_test (void)
soup_uri_free (uri);
soup_session_send_message (acd.session, acd.msg);
- if (acd.msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Final status wrong: expected %u, got %u %s\n",
- SOUP_STATUS_OK, acd.msg->status_code,
- acd.msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (acd.msg, SOUP_STATUS_OK);
g_object_unref (acd.msg);
soup_test_session_abort_unref (acd.session);
soup_test_server_quit_unref (server);
}
+static gboolean
+infinite_cancel (gpointer session)
+{
+ soup_session_abort (session);
+ return FALSE;
+}
+
+static void
+infinite_authenticate (SoupSession *session, SoupMessage *msg,
+ SoupAuth *auth, gboolean retrying, gpointer data)
+{
+ soup_auth_authenticate (auth, "user", "bad");
+}
+
+static void
+do_infinite_auth_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ char *uri;
+ int timeout;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (infinite_authenticate), NULL);
+
+ uri = g_strconcat (base_uri, "Basic/realm1/", NULL);
+ msg = soup_message_new ("GET", uri);
+ g_free (uri);
+
+ timeout = g_timeout_add (500, infinite_cancel, session);
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*stuck in infinite loop*");
+ soup_session_send_message (session, msg);
+ g_test_assert_expected_messages ();
+
+ soup_test_assert (msg->status_code != SOUP_STATUS_CANCELLED,
+ "Got stuck in loop");
+ soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED);
+
+ g_source_remove (timeout);
+ soup_test_session_abort_unref (session);
+ g_object_unref (msg);
+}
+
+static void
+disappear_request_read (SoupServer *server, SoupMessage *msg,
+ SoupClientContext *context, gpointer user_data)
+{
+ /* Remove the WWW-Authenticate header if this was a failed attempt */
+ if (soup_message_headers_get_one (msg->request_headers, "Authorization") &&
+ msg->status_code == SOUP_STATUS_UNAUTHORIZED)
+ soup_message_headers_remove (msg->response_headers, "WWW-Authenticate");
+}
+
+static void
+disappear_authenticate (SoupSession *session, SoupMessage *msg,
+ SoupAuth *auth, gboolean retrying, gpointer data)
+{
+ int *counter = data;
+
+ (*counter)++;
+ if (!retrying)
+ soup_auth_authenticate (auth, "user", "bad");
+}
+
+static void
+do_disappearing_auth_test (void)
+{
+ SoupServer *server;
+ SoupAuthDomain *auth_domain;
+ SoupURI *uri;
+ SoupMessage *msg;
+ SoupSession *session;
+ int counter;
+
+ g_test_bug ("https://bugzilla.redhat.com/show_bug.cgi?id=916224");
+
+ server = soup_test_server_new (FALSE);
+ soup_server_add_handler (server, NULL,
+ server_callback, NULL, NULL);
+
+ uri = soup_uri_new ("http://127.0.0.1/");
+ soup_uri_set_port (uri, soup_server_get_port (server));
+
+ auth_domain = soup_auth_domain_basic_new (
+ SOUP_AUTH_DOMAIN_REALM, "auth-test",
+ SOUP_AUTH_DOMAIN_ADD_PATH, "/",
+ SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, server_basic_auth_callback,
+ NULL);
+ soup_server_add_auth_domain (server, auth_domain);
+ g_signal_connect (server, "request-read",
+ G_CALLBACK (disappear_request_read), NULL);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+
+ counter = 0;
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (disappear_authenticate), &counter);
+
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_session_send_message (session, msg);
+
+ soup_test_assert (counter <= 2,
+ "Got stuck in loop");
+ soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED);
+
+ g_object_unref (msg);
+ soup_test_session_abort_unref (session);
+
+ g_object_unref (auth_domain);
+ soup_uri_free (uri);
+ soup_test_server_quit_unref (server);
+}
+
static SoupAuthTest relogin_tests[] = {
{ "Auth provided via URL, should succeed",
"Basic/realm12/", "1", TRUE, "01", SOUP_STATUS_OK },
@@ -1090,25 +1183,28 @@ static SoupAuthTest relogin_tests[] = {
{ "Should fail with no auth, fail again with bad password, and give up",
"Basic/realm12/", "3", FALSE, "03", SOUP_STATUS_UNAUTHORIZED },
+
+ { NULL }
};
static void
-do_batch_tests (const gchar *base_uri_str, gint ntests)
+do_batch_tests (gconstpointer data)
{
+ const SoupAuthTest *current_tests = data;
SoupSession *session;
SoupMessage *msg;
char *expected, *uristr;
- SoupURI *base_uri;
+ SoupURI *base;
+ guint signal;
int i;
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- g_signal_connect (session, "authenticate",
- G_CALLBACK (authenticate), &i);
+ SOUP_TEST_SKIP_IF_NO_APACHE;
- base_uri = soup_uri_new (base_uri_str);
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ base = soup_uri_new (base_uri);
- for (i = 0; i < ntests; i++) {
- SoupURI *soup_uri = soup_uri_new_with_base (base_uri, current_tests[i].url);
+ for (i = 0; current_tests[i].url; i++) {
+ SoupURI *soup_uri = soup_uri_new_with_base (base, current_tests[i].url);
debug_printf (1, "Test %d: %s\n", i + 1, current_tests[i].explanation);
@@ -1139,30 +1235,24 @@ do_batch_tests (const gchar *base_uri_str, gint ntests)
soup_message_add_status_code_handler (
msg, "got_headers", SOUP_STATUS_OK,
G_CALLBACK (handler), expected);
+
+ signal = g_signal_connect (session, "authenticate",
+ G_CALLBACK (authenticate),
+ (gpointer)&current_tests[i]);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_UNAUTHORIZED &&
- msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " %d %s !\n", msg->status_code,
- msg->reason_phrase);
- errors++;
- }
- if (*expected) {
- debug_printf (1, " expected %d more round(s)\n",
- (int)strlen (expected));
- errors++;
- }
- g_free (expected);
+ g_signal_handler_disconnect (session, signal);
- if (msg->status_code != current_tests[i].final_status) {
- debug_printf (1, " expected %d\n",
- current_tests[i].final_status);
- }
+ soup_test_assert_message_status (msg, current_tests[i].final_status);
+ soup_test_assert (!*expected,
+ "expected %d more round(s)\n",
+ (int)strlen (expected));
+ g_free (expected);
debug_printf (1, "\n");
g_object_unref (msg);
}
- soup_uri_free (base_uri);
+ soup_uri_free (base);
soup_test_session_abort_unref (session);
}
@@ -1170,31 +1260,27 @@ do_batch_tests (const gchar *base_uri_str, gint ntests)
int
main (int argc, char **argv)
{
- const char *base_uri;
- int ntests;
+ int ret;
test_init (argc, argv, NULL);
apache_init ();
base_uri = "http://127.0.0.1:47524/";
- /* Main tests */
- current_tests = main_tests;
- ntests = G_N_ELEMENTS (main_tests);
- do_batch_tests (base_uri, ntests);
-
- /* Re-login tests */
- current_tests = relogin_tests;
- ntests = G_N_ELEMENTS (relogin_tests);
- do_batch_tests (base_uri, ntests);
+ g_test_add_data_func ("/auth/main-tests", main_tests, do_batch_tests);
+ g_test_add_data_func ("/auth/relogin-tests", relogin_tests, do_batch_tests);
+ g_test_add_func ("/auth/pipelined-auth", do_pipelined_auth_test);
+ g_test_add_func ("/auth/digest-expiration", do_digest_expiration_test);
+ g_test_add_func ("/auth/async-auth/good-password", do_async_auth_good_password_test);
+ g_test_add_func ("/auth/async-auth/bad-password", do_async_auth_bad_password_test);
+ g_test_add_func ("/auth/async-auth/no-password", do_async_auth_no_password_test);
+ g_test_add_func ("/auth/select-auth", do_select_auth_test);
+ g_test_add_func ("/auth/auth-close", do_auth_close_test);
+ g_test_add_func ("/auth/infinite-auth", do_infinite_auth_test);
+ g_test_add_func ("/auth/disappearing-auth", do_disappearing_auth_test);
- /* Other regression tests */
- do_pipelined_auth_test (base_uri);
- do_digest_expiration_test (base_uri);
- do_async_auth_test (base_uri);
- do_select_auth_test ();
- do_auth_close_test ();
+ ret = g_test_run ();
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/cache-test.c b/tests/cache-test.c
new file mode 100644
index 00000000..3478f377
--- /dev/null
+++ b/tests/cache-test.c
@@ -0,0 +1,659 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright 2012 Red Hat, Inc.
+ */
+
+#include "test-utils.h"
+
+static void
+server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ const char *last_modified, *etag;
+ const char *header;
+ guint status = SOUP_STATUS_OK;
+
+ if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) {
+ soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ header = soup_message_headers_get_one (msg->request_headers,
+ "Test-Set-Expires");
+ if (header) {
+ soup_message_headers_append (msg->response_headers,
+ "Expires",
+ header);
+ }
+
+ header = soup_message_headers_get_one (msg->request_headers,
+ "Test-Set-Cache-Control");
+ if (header) {
+ soup_message_headers_append (msg->response_headers,
+ "Cache-Control",
+ header);
+ }
+
+ last_modified = soup_message_headers_get_one (msg->request_headers,
+ "Test-Set-Last-Modified");
+ if (last_modified) {
+ soup_message_headers_append (msg->response_headers,
+ "Last-Modified",
+ last_modified);
+ }
+
+ etag = soup_message_headers_get_one (msg->request_headers,
+ "Test-Set-ETag");
+ if (etag) {
+ soup_message_headers_append (msg->response_headers,
+ "ETag",
+ etag);
+ }
+
+
+ header = soup_message_headers_get_one (msg->request_headers,
+ "If-Modified-Since");
+ if (header && last_modified) {
+ SoupDate *date;
+ time_t lastmod, check;
+
+ date = soup_date_new_from_string (last_modified);
+ lastmod = soup_date_to_time_t (date);
+ soup_date_free (date);
+
+ date = soup_date_new_from_string (header);
+ check = soup_date_to_time_t (date);
+ soup_date_free (date);
+
+ if (lastmod <= check)
+ status = SOUP_STATUS_NOT_MODIFIED;
+ }
+
+ header = soup_message_headers_get_one (msg->request_headers,
+ "If-None-Match");
+ if (header && etag) {
+ if (!strcmp (header, etag))
+ status = SOUP_STATUS_NOT_MODIFIED;
+ }
+
+ header = soup_message_headers_get_one (msg->request_headers,
+ "Test-Set-My-Header");
+ if (header) {
+ soup_message_headers_append (msg->response_headers,
+ "My-Header",
+ header);
+ }
+
+ if (status == SOUP_STATUS_OK) {
+ GChecksum *sum;
+ const char *body;
+
+ sum = g_checksum_new (G_CHECKSUM_SHA256);
+ g_checksum_update (sum, (guchar *)path, strlen (path));
+ if (last_modified)
+ g_checksum_update (sum, (guchar *)last_modified, strlen (last_modified));
+ if (etag)
+ g_checksum_update (sum, (guchar *)etag, strlen (etag));
+ body = g_checksum_get_string (sum);
+ soup_message_set_response (msg, "text/plain",
+ SOUP_MEMORY_COPY,
+ body, strlen (body) + 1);
+ g_checksum_free (sum);
+ }
+ soup_message_set_status (msg, status);
+}
+
+static gboolean
+is_network_stream (GInputStream *stream)
+{
+ while (G_IS_FILTER_INPUT_STREAM (stream))
+ stream = G_FILTER_INPUT_STREAM (stream)->base_stream;
+
+ return !G_IS_FILE_INPUT_STREAM (stream);
+}
+
+static char *do_request (SoupSession *session,
+ SoupURI *base_uri,
+ const char *method,
+ const char *path,
+ SoupMessageHeaders *response_headers,
+ ...) G_GNUC_NULL_TERMINATED;
+
+static gboolean last_request_hit_network;
+static gboolean last_request_validated;
+static guint cancelled_requests;
+
+static void
+copy_headers (const char *name,
+ const char *value,
+ gpointer user_data)
+{
+ SoupMessageHeaders *headers = (SoupMessageHeaders *) user_data;
+ soup_message_headers_append (headers, name, value);
+}
+
+static char *
+do_request (SoupSession *session,
+ SoupURI *base_uri,
+ const char *method,
+ const char *path,
+ SoupMessageHeaders *response_headers,
+ ...)
+{
+ SoupRequestHTTP *req;
+ SoupMessage *msg;
+ GInputStream *stream;
+ SoupURI *uri;
+ va_list ap;
+ const char *header, *value;
+ char buf[256];
+ gsize nread;
+ GError *error = NULL;
+
+ last_request_validated = last_request_hit_network = FALSE;
+
+ uri = soup_uri_new_with_base (base_uri, path);
+ req = soup_session_request_http_uri (session, method, uri, NULL);
+ soup_uri_free (uri);
+ msg = soup_request_http_get_message (req);
+
+ va_start (ap, response_headers);
+ while ((header = va_arg (ap, const char *))) {
+ value = va_arg (ap, const char *);
+ soup_message_headers_append (msg->request_headers,
+ header, value);
+ }
+ va_end (ap);
+
+ stream = soup_test_request_send (SOUP_REQUEST (req), NULL, 0, &error);
+ if (!stream) {
+ debug_printf (1, " could not send request: %s\n",
+ error->message);
+ g_error_free (error);
+ g_object_unref (req);
+ g_object_unref (msg);
+ return NULL;
+ }
+
+ if (response_headers)
+ soup_message_headers_foreach (msg->response_headers, copy_headers, response_headers);
+
+ g_object_unref (msg);
+
+ last_request_hit_network = is_network_stream (stream);
+
+ g_input_stream_read_all (stream, buf, sizeof (buf), &nread,
+ NULL, &error);
+ if (error) {
+ debug_printf (1, " could not read response: %s\n",
+ error->message);
+ g_clear_error (&error);
+ }
+ soup_test_request_close_stream (SOUP_REQUEST (req), stream,
+ NULL, &error);
+ if (error) {
+ debug_printf (1, " could not close stream: %s\n",
+ error->message);
+ g_clear_error (&error);
+ }
+ g_object_unref (stream);
+ g_object_unref (req);
+
+ /* Cache writes are G_PRIORITY_LOW, so they won't have happened yet... */
+ soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE));
+
+ return nread ? g_memdup (buf, nread) : g_strdup ("");
+}
+
+static void
+do_request_with_cancel (SoupSession *session,
+ SoupURI *base_uri,
+ const char *method,
+ const char *path,
+ SoupTestRequestFlags flags)
+{
+ SoupRequestHTTP *req;
+ GInputStream *stream;
+ SoupURI *uri;
+ GError *error = NULL;
+ GCancellable *cancellable;
+
+ last_request_validated = last_request_hit_network = FALSE;
+ cancelled_requests = 0;
+
+ uri = soup_uri_new_with_base (base_uri, path);
+ req = soup_session_request_http_uri (session, method, uri, NULL);
+ soup_uri_free (uri);
+ cancellable = flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE ? g_cancellable_new () : NULL;
+ stream = soup_test_request_send (SOUP_REQUEST (req), cancellable, flags, &error);
+ if (stream) {
+ debug_printf (1, " could not cancel the request\n");
+ g_object_unref (stream);
+ g_object_unref (req);
+ return;
+ }
+
+ g_clear_object (&cancellable);
+ g_clear_object (&stream);
+ g_clear_object (&req);
+
+ soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE));
+}
+
+static void
+request_started (SoupSession *session, SoupMessage *msg,
+ SoupSocket *socket)
+{
+ if (soup_message_headers_get_one (msg->request_headers,
+ "If-Modified-Since") ||
+ soup_message_headers_get_one (msg->request_headers,
+ "If-None-Match")) {
+ debug_printf (2, " Conditional request for %s\n",
+ soup_message_get_uri (msg)->path);
+ last_request_validated = TRUE;
+ }
+}
+
+static void
+request_unqueued (SoupSession *session, SoupMessage *msg,
+ gpointer data)
+{
+ if (msg->status_code == SOUP_STATUS_CANCELLED)
+ cancelled_requests++;
+}
+
+static void
+do_basics_test (gconstpointer data)
+{
+ SoupURI *base_uri = (SoupURI *)data;
+ SoupSession *session;
+ SoupCache *cache;
+ char *cache_dir;
+ char *body1, *body2, *body3, *body4, *body5, *cmp;
+
+ cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL);
+ debug_printf (2, " Caching to %s\n", cache_dir);
+ cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER);
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ SOUP_SESSION_ADD_FEATURE, cache,
+ NULL);
+ g_signal_connect (session, "request-started",
+ G_CALLBACK (request_started), NULL);
+
+ debug_printf (2, " Initial requests\n");
+ body1 = do_request (session, base_uri, "GET", "/1", NULL,
+ "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT",
+ NULL);
+ body2 = do_request (session, base_uri, "GET", "/2", NULL,
+ "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT",
+ NULL);
+ body3 = do_request (session, base_uri, "GET", "/3", NULL,
+ "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT",
+ "Test-Set-Cache-Control", "must-revalidate",
+ NULL);
+ body4 = do_request (session, base_uri, "GET", "/4", NULL,
+ "Test-Set-ETag", "\"abcdefg\"",
+ "Test-Set-Cache-Control", "must-revalidate",
+ NULL);
+ body5 = do_request (session, base_uri, "GET", "/5", NULL,
+ "Test-Set-Cache-Control", "no-cache",
+ NULL);
+
+
+ /* Resource with future Expires should have been cached */
+ debug_printf (1, " Fresh cached resource\n");
+ cmp = do_request (session, base_uri, "GET", "/1", NULL,
+ NULL);
+ soup_test_assert (!last_request_hit_network,
+ "Request for /1 not filled from cache");
+ g_assert_cmpstr (body1, ==, cmp);
+ g_free (cmp);
+
+
+ /* Resource with long-ago Last-Modified should have been cached */
+ debug_printf (1, " Heuristically-fresh cached resource\n");
+ cmp = do_request (session, base_uri, "GET", "/2", NULL,
+ NULL);
+ soup_test_assert (!last_request_hit_network,
+ "Request for /2 not filled from cache");
+ g_assert_cmpstr (body2, ==, cmp);
+ g_free (cmp);
+
+
+ /* Adding a query string should bypass the cache but not invalidate it */
+ debug_printf (1, " Fresh cached resource with a query\n");
+ cmp = do_request (session, base_uri, "GET", "/1?attr=value", NULL,
+ NULL);
+ soup_test_assert (last_request_hit_network,
+ "Request for /1?attr=value filled from cache");
+ g_free (cmp);
+ debug_printf (2, " Second request\n");
+ cmp = do_request (session, base_uri, "GET", "/1", NULL,
+ NULL);
+ soup_test_assert (!last_request_hit_network,
+ "Second request for /1 not filled from cache");
+ g_assert_cmpstr (body1, ==, cmp);
+ g_free (cmp);
+
+
+ /* Last-Modified + must-revalidate causes a conditional request */
+ debug_printf (1, " Unchanged must-revalidate resource w/ Last-Modified\n");
+ cmp = do_request (session, base_uri, "GET", "/3", NULL,
+ "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT",
+ "Test-Set-Cache-Control", "must-revalidate",
+ NULL);
+ soup_test_assert (last_request_validated,
+ "Request for /3 not validated");
+ soup_test_assert (!last_request_hit_network,
+ "Request for /3 not filled from cache");
+ g_assert_cmpstr (body3, ==, cmp);
+ g_free (cmp);
+
+
+ /* Validation failure should update cache */
+ debug_printf (1, " Changed must-revalidate resource w/ Last-Modified\n");
+ cmp = do_request (session, base_uri, "GET", "/3", NULL,
+ "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT",
+ "Test-Set-Cache-Control", "must-revalidate",
+ NULL);
+ soup_test_assert (last_request_validated,
+ "Request for /3 not validated");
+ soup_test_assert (last_request_hit_network,
+ "Request for /3 filled from cache");
+ g_assert_cmpstr (body3, !=, cmp);
+ g_free (cmp);
+
+ debug_printf (2, " Second request\n");
+ cmp = do_request (session, base_uri, "GET", "/3", NULL,
+ "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT",
+ "Test-Set-Cache-Control", "must-revalidate",
+ NULL);
+ soup_test_assert (last_request_validated,
+ "Second request for /3 not validated");
+ soup_test_assert (!last_request_hit_network,
+ "Second request for /3 not filled from cache");
+ g_assert_cmpstr (body3, !=, cmp);
+ g_free (cmp);
+
+ /* ETag + must-revalidate causes a conditional request */
+ debug_printf (1, " Unchanged must-revalidate resource w/ ETag\n");
+ cmp = do_request (session, base_uri, "GET", "/4", NULL,
+ "Test-Set-ETag", "\"abcdefg\"",
+ NULL);
+ soup_test_assert (last_request_validated,
+ "Request for /4 not validated");
+ soup_test_assert (!last_request_hit_network,
+ "Request for /4 not filled from cache");
+ g_assert_cmpstr (body4, ==, cmp);
+ g_free (cmp);
+
+
+ /* Cache-Control: no-cache prevents caching */
+ debug_printf (1, " Uncacheable resource\n");
+ cmp = do_request (session, base_uri, "GET", "/5", NULL,
+ "Test-Set-Cache-Control", "no-cache",
+ NULL);
+ soup_test_assert (last_request_hit_network,
+ "Request for /5 filled from cache");
+ g_assert_cmpstr (body5, ==, cmp);
+ g_free (cmp);
+
+
+ /* PUT to a URI invalidates the cache entry */
+ debug_printf (1, " Invalidating and re-requesting a cached resource\n");
+ cmp = do_request (session, base_uri, "PUT", "/1", NULL,
+ NULL);
+ soup_test_assert (last_request_hit_network,
+ "PUT filled from cache");
+ g_free (cmp);
+ cmp = do_request (session, base_uri, "GET", "/1", NULL,
+ NULL);
+ soup_test_assert (last_request_hit_network,
+ "PUT failed to invalidate cache entry");
+ g_assert_true (last_request_hit_network);
+ g_free (cmp);
+
+
+ soup_test_session_abort_unref (session);
+ g_object_unref (cache);
+
+ g_free (cache_dir);
+ g_free (body1);
+ g_free (body2);
+ g_free (body3);
+ g_free (body4);
+ g_free (body5);
+}
+
+static void
+do_cancel_test (gconstpointer data)
+{
+ SoupURI *base_uri = (SoupURI *)data;
+ SoupSession *session;
+ SoupCache *cache;
+ char *cache_dir;
+ char *body1, *body2;
+ guint flags;
+
+ g_test_bug ("692310");
+
+ cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL);
+ debug_printf (2, " Caching to %s\n", cache_dir);
+ cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER);
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ SOUP_SESSION_ADD_FEATURE, cache,
+ NULL);
+ g_signal_connect (session, "request-unqueued",
+ G_CALLBACK (request_unqueued), NULL);
+
+ debug_printf (2, " Initial requests\n");
+ body1 = do_request (session, base_uri, "GET", "/1", NULL,
+ "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT",
+ NULL);
+ body2 = do_request (session, base_uri, "GET", "/2", NULL,
+ "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT",
+ "Test-Set-Cache-Control", "must-revalidate",
+ NULL);
+
+ /* Check that messages are correctly processed on cancellations. */
+ debug_printf (1, " Cancel fresh resource with soup_session_message_cancel()\n");
+ flags = SOUP_TEST_REQUEST_CANCEL_MESSAGE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE;
+ do_request_with_cancel (session, base_uri, "GET", "/1", flags);
+ g_assert_cmpint (cancelled_requests, ==, 1);
+
+ debug_printf (1, " Cancel fresh resource with g_cancellable_cancel()\n");
+ flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE;
+ do_request_with_cancel (session, base_uri, "GET", "/1", flags);
+ g_assert_cmpint (cancelled_requests, ==, 1);
+
+ soup_test_session_abort_unref (session);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ SOUP_SESSION_ADD_FEATURE, cache,
+ NULL);
+ g_signal_connect (session, "request-unqueued",
+ G_CALLBACK (request_unqueued), NULL);
+
+ /* Check that messages are correctly processed on cancellations. */
+ debug_printf (1, " Cancel a revalidating resource with soup_session_message_cancel()\n");
+ flags = SOUP_TEST_REQUEST_CANCEL_MESSAGE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE;
+ do_request_with_cancel (session, base_uri, "GET", "/2", flags);
+ g_assert_cmpint (cancelled_requests, ==, 2);
+
+ debug_printf (1, " Cancel a revalidating resource with g_cancellable_cancel()\n");
+ flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE;
+ do_request_with_cancel (session, base_uri, "GET", "/2", flags);
+ g_assert_cmpint (cancelled_requests, ==, 2);
+
+ soup_test_session_abort_unref (session);
+
+ g_object_unref (cache);
+ g_free (cache_dir);
+ g_free (body1);
+ g_free (body2);
+}
+
+static gboolean
+unref_stream (gpointer stream)
+{
+ g_object_unref (stream);
+ return FALSE;
+}
+
+static void
+base_stream_unreffed (gpointer loop, GObject *ex_base_stream)
+{
+ g_main_loop_quit (loop);
+}
+
+static void
+do_refcounting_test (gconstpointer data)
+{
+ SoupURI *base_uri = (SoupURI *)data;
+ SoupSession *session;
+ SoupCache *cache;
+ char *cache_dir;
+ SoupRequestHTTP *req;
+ GInputStream *stream, *base_stream;
+ SoupURI *uri;
+ GError *error = NULL;
+ guint flags;
+ GMainLoop *loop;
+
+ g_test_bug ("682527");
+
+ cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL);
+ debug_printf (2, " Caching to %s\n", cache_dir);
+ cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER);
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ SOUP_SESSION_ADD_FEATURE, cache,
+ NULL);
+
+ last_request_validated = last_request_hit_network = FALSE;
+ cancelled_requests = 0;
+
+ uri = soup_uri_new_with_base (base_uri, "/1");
+ req = soup_session_request_http_uri (session, "GET", uri, NULL);
+ soup_uri_free (uri);
+
+ flags = SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH | SOUP_TEST_REQUEST_CANCEL_MESSAGE;
+ stream = soup_test_request_send (SOUP_REQUEST (req), NULL, flags, &error);
+ if (!stream) {
+ debug_printf (1, " could not send request: %s\n",
+ error->message);
+ g_error_free (error);
+ g_object_unref (req);
+ return;
+ }
+ g_object_unref (req);
+
+ base_stream = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream));
+
+ debug_printf (1, " Checking that the base stream is properly unref'ed\n");
+ loop = g_main_loop_new (NULL, FALSE);
+ g_object_weak_ref (G_OBJECT (base_stream), base_stream_unreffed, loop);
+ g_idle_add (unref_stream, stream);
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE));
+
+ soup_test_session_abort_unref (session);
+
+ g_object_unref (cache);
+ g_free (cache_dir);
+}
+
+static void
+do_headers_test (gconstpointer data)
+{
+ SoupURI *base_uri = (SoupURI *)data;
+ SoupSession *session;
+ SoupMessageHeaders *headers;
+ SoupCache *cache;
+ char *cache_dir;
+ char *body1, *cmp;
+ const char *header_value;
+
+ cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL);
+ debug_printf (2, " Caching to %s\n", cache_dir);
+ cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER);
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ SOUP_SESSION_ADD_FEATURE, cache,
+ NULL);
+
+ g_signal_connect (session, "request-started",
+ G_CALLBACK (request_started), NULL);
+
+ debug_printf (2, " Initial requests\n");
+ body1 = do_request (session, base_uri, "GET", "/1", NULL,
+ "Test-Set-Last-Modified", "Fri, 01 Jan 2100 00:00:00 GMT",
+ "Test-Set-My-Header", "My header value",
+ NULL);
+
+ /* My-Header new value should be updated in cache */
+ debug_printf (2, " Fresh cached resource which updates My-Header\n");
+ cmp = do_request (session, base_uri, "GET", "/1", NULL,
+ "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT",
+ "Test-Set-My-Header", "My header NEW value",
+ NULL);
+ soup_test_assert (last_request_validated,
+ "Request for /1 not validated");
+ soup_test_assert (!last_request_hit_network,
+ "Request for /1 not filled from cache");
+ g_free (cmp);
+
+ /* Check that cache returns the updated header */
+ debug_printf (2, " Fresh cached resource with new value for My-Header\n");
+ headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
+ cmp = do_request (session, base_uri, "GET", "/1", headers,
+ "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT",
+ NULL);
+ soup_test_assert (!last_request_hit_network,
+ "Request for /1 not filled from cache");
+ g_free (cmp);
+
+ header_value = soup_message_headers_get_list (headers, "My-Header");
+ g_assert_cmpstr (header_value, ==, "My header NEW value");
+ soup_message_headers_free (headers);
+
+ soup_test_session_abort_unref (session);
+ g_object_unref (cache);
+
+ g_free (cache_dir);
+ g_free (body1);
+}
+
+int
+main (int argc, char **argv)
+{
+ SoupServer *server;
+ SoupURI *base_uri;
+ int ret;
+
+ test_init (argc, argv, NULL);
+
+ server = soup_test_server_new (TRUE);
+ soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+ base_uri = soup_uri_new ("http://127.0.0.1/");
+ soup_uri_set_port (base_uri, soup_server_get_port (server));
+
+ g_test_add_data_func ("/cache/basics", base_uri, do_basics_test);
+ g_test_add_data_func ("/cache/cancellation", base_uri, do_cancel_test);
+ g_test_add_data_func ("/cache/refcounting", base_uri, do_refcounting_test);
+ g_test_add_data_func ("/cache/headers", base_uri, do_headers_test);
+
+ ret = g_test_run ();
+
+ soup_uri_free (base_uri);
+ soup_test_server_quit_unref (server);
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/chunk-io-test.c b/tests/chunk-io-test.c
new file mode 100644
index 00000000..1e53eef1
--- /dev/null
+++ b/tests/chunk-io-test.c
@@ -0,0 +1,610 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright 2013 Red Hat, Inc.
+ */
+
+#include "test-utils.h"
+
+static void
+force_io_streams_init (void)
+{
+ SoupServer *server;
+ SoupSession *session;
+ guint port;
+ SoupURI *base_uri;
+ SoupMessage *msg;
+
+ /* Poke libsoup enough to cause SoupBodyInputStream and
+ * SoupBodyOutputStream to get defined, so we can find them
+ * via g_type_from_name() later.
+ */
+
+ server = soup_test_server_new (TRUE);
+ port = soup_server_get_port (server);
+
+ base_uri = soup_uri_new ("http://127.0.0.1");
+ soup_uri_set_port (base_uri, port);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ msg = soup_message_new_from_uri ("POST", base_uri);
+ soup_session_send_message (session, msg);
+ g_object_unref (msg);
+ soup_test_session_abort_unref (session);
+
+ soup_uri_free (base_uri);
+ soup_test_server_quit_unref (server);
+}
+
+typedef struct {
+ GFilterInputStream grandparent;
+
+ gpointer *soup_filter_input_stream_private;
+
+ gboolean is_readable;
+} SlowInputStream;
+
+typedef struct {
+ GFilterInputStreamClass grandparent;
+} SlowInputStreamClass;
+
+GType slow_input_stream_get_type (void);
+static void slow_pollable_input_stream_init (GPollableInputStreamInterface *pollable_interface,
+ gpointer interface_data);
+
+G_DEFINE_TYPE_WITH_CODE (SlowInputStream, slow_input_stream,
+ g_type_from_name ("SoupFilterInputStream"),
+ G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, slow_pollable_input_stream_init);
+ )
+
+static void
+slow_input_stream_init (SlowInputStream *sis)
+{
+}
+
+static gssize
+slow_input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return g_input_stream_read (G_FILTER_INPUT_STREAM (stream)->base_stream,
+ buffer, 1, cancellable, error);
+}
+
+static void
+slow_input_stream_class_init (SlowInputStreamClass *sisclass)
+{
+ GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS (sisclass);
+
+ input_stream_class->read_fn = slow_input_stream_read;
+}
+
+static gboolean
+slow_input_stream_is_readable (GPollableInputStream *stream)
+{
+ return ((SlowInputStream *)stream)->is_readable;
+}
+
+static gssize
+slow_input_stream_read_nonblocking (GPollableInputStream *stream,
+ void *buffer,
+ gsize count,
+ GError **error)
+{
+ if (((SlowInputStream *)stream)->is_readable) {
+ ((SlowInputStream *)stream)->is_readable = FALSE;
+ return slow_input_stream_read (G_INPUT_STREAM (stream), buffer, count,
+ NULL, error);
+ } else {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+ "would block");
+ return -1;
+ }
+}
+
+static GSource *
+slow_input_stream_create_source (GPollableInputStream *stream,
+ GCancellable *cancellable)
+{
+ GSource *base_source, *pollable_source;
+
+ ((SlowInputStream *)stream)->is_readable = TRUE;
+ base_source = g_timeout_source_new (0);
+ g_source_set_dummy_callback (base_source);
+
+ pollable_source = g_pollable_source_new (G_OBJECT (stream));
+ g_source_add_child_source (pollable_source, base_source);
+ g_source_unref (base_source);
+
+ return pollable_source;
+}
+
+static void
+slow_pollable_input_stream_init (GPollableInputStreamInterface *pollable_interface,
+ gpointer interface_data)
+{
+ pollable_interface->is_readable = slow_input_stream_is_readable;
+ pollable_interface->read_nonblocking = slow_input_stream_read_nonblocking;
+ pollable_interface->create_source = slow_input_stream_create_source;
+}
+
+typedef struct {
+ GFilterOutputStream parent;
+
+ gboolean is_writable;
+} SlowOutputStream;
+
+typedef struct {
+ GFilterOutputStreamClass parent;
+} SlowOutputStreamClass;
+
+GType slow_output_stream_get_type (void);
+
+static void slow_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface,
+ gpointer interface_data);
+
+G_DEFINE_TYPE_WITH_CODE (SlowOutputStream, slow_output_stream,
+ g_type_from_name ("GFilterOutputStream"),
+ G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, slow_pollable_output_stream_init);
+ )
+
+static void
+slow_output_stream_init (SlowOutputStream *sis)
+{
+}
+
+static gssize
+slow_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return g_output_stream_write (G_FILTER_OUTPUT_STREAM (stream)->base_stream,
+ buffer, 1, cancellable, error);
+}
+
+static void
+slow_output_stream_class_init (SlowOutputStreamClass *sisclass)
+{
+ GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (sisclass);
+
+ output_stream_class->write_fn = slow_output_stream_write;
+}
+
+static gboolean
+slow_output_stream_is_writable (GPollableOutputStream *stream)
+{
+ return ((SlowOutputStream *)stream)->is_writable;
+}
+
+static gssize
+slow_output_stream_write_nonblocking (GPollableOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GError **error)
+{
+ if (((SlowOutputStream *)stream)->is_writable) {
+ ((SlowOutputStream *)stream)->is_writable = FALSE;
+ return slow_output_stream_write (G_OUTPUT_STREAM (stream), buffer, count,
+ NULL, error);
+ } else {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+ "would block");
+ return -1;
+ }
+}
+
+static GSource *
+slow_output_stream_create_source (GPollableOutputStream *stream,
+ GCancellable *cancellable)
+{
+ GSource *base_source, *pollable_source;
+
+ ((SlowOutputStream *)stream)->is_writable = TRUE;
+ base_source = g_timeout_source_new (0);
+ g_source_set_dummy_callback (base_source);
+
+ pollable_source = g_pollable_source_new (G_OBJECT (stream));
+ g_source_add_child_source (pollable_source, base_source);
+ g_source_unref (base_source);
+
+ return pollable_source;
+}
+
+static void
+slow_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface,
+ gpointer interface_data)
+{
+ pollable_interface->is_writable = slow_output_stream_is_writable;
+ pollable_interface->write_nonblocking = slow_output_stream_write_nonblocking;
+ pollable_interface->create_source = slow_output_stream_create_source;
+}
+
+typedef struct {
+ GFilterOutputStream parent;
+
+ gboolean is_broken;
+} BreakingOutputStream;
+
+typedef struct {
+ GFilterOutputStreamClass parent;
+} BreakingOutputStreamClass;
+
+GType breaking_output_stream_get_type (void);
+
+static void breaking_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface,
+ gpointer interface_data);
+
+G_DEFINE_TYPE_WITH_CODE (BreakingOutputStream, breaking_output_stream,
+ g_type_from_name ("GFilterOutputStream"),
+ G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, breaking_pollable_output_stream_init);
+ )
+
+static void
+breaking_output_stream_init (BreakingOutputStream *sis)
+{
+}
+
+static gssize
+breaking_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ if (((BreakingOutputStream *)stream)->is_broken) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "failed");
+ return -1;
+ }
+
+ if (count > 128) {
+ ((BreakingOutputStream *)stream)->is_broken = TRUE;
+ count /= 2;
+ }
+ return g_output_stream_write (G_FILTER_OUTPUT_STREAM (stream)->base_stream,
+ buffer, count, cancellable, error);
+}
+
+static void
+breaking_output_stream_class_init (BreakingOutputStreamClass *sisclass)
+{
+ GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (sisclass);
+
+ output_stream_class->write_fn = breaking_output_stream_write;
+}
+
+static gboolean
+breaking_output_stream_is_writable (GPollableOutputStream *stream)
+{
+ return TRUE;
+}
+
+static gssize
+breaking_output_stream_write_nonblocking (GPollableOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GError **error)
+{
+ if (((BreakingOutputStream *)stream)->is_broken) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "failed");
+ return -1;
+ }
+
+ if (count > 128) {
+ ((BreakingOutputStream *)stream)->is_broken = TRUE;
+ count /= 2;
+ }
+ return g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (G_FILTER_OUTPUT_STREAM (stream)->base_stream),
+ buffer, count, NULL, error);
+}
+
+static GSource *
+breaking_output_stream_create_source (GPollableOutputStream *stream,
+ GCancellable *cancellable)
+{
+ GSource *base_source, *pollable_source;
+
+ base_source = g_timeout_source_new (0);
+ g_source_set_dummy_callback (base_source);
+
+ pollable_source = g_pollable_source_new (G_OBJECT (stream));
+ g_source_add_child_source (pollable_source, base_source);
+ g_source_unref (base_source);
+
+ return pollable_source;
+}
+
+static void
+breaking_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface,
+ gpointer interface_data)
+{
+ pollable_interface->is_writable = breaking_output_stream_is_writable;
+ pollable_interface->write_nonblocking = breaking_output_stream_write_nonblocking;
+ pollable_interface->create_source = breaking_output_stream_create_source;
+}
+
+#define CHUNK_SIZE 1024
+
+static GString *
+chunkify (const char *str, gsize length)
+{
+ GString *gstr;
+ int i, size;
+
+ gstr = g_string_new (NULL);
+ for (i = 0; i < length; i += CHUNK_SIZE) {
+ size = MIN (CHUNK_SIZE, length - i);
+ g_string_append_printf (gstr, "%x\r\n", size);
+ g_string_append_len (gstr, str + i, size);
+ g_string_append (gstr, "\r\n");
+ }
+ g_string_append (gstr, "0\r\n\r\n");
+
+ return gstr;
+}
+
+static void
+do_io_tests (void)
+{
+ GInputStream *imem, *islow, *in;
+ GOutputStream *omem, *oslow, *out;
+ GMemoryOutputStream *mem;
+ SoupBuffer *raw_contents;
+ char *buf;
+ GString *chunkified;
+ GError *error = NULL;
+ gssize nread, nwrote, total;
+ gssize chunk_length, chunk_total;
+
+ raw_contents = soup_test_get_index ();
+ chunkified = chunkify (raw_contents->data, raw_contents->length);
+
+ debug_printf (1, " sync read\n");
+
+ imem = g_memory_input_stream_new_from_data (chunkified->str, chunkified->len, NULL);
+ islow = g_object_new (slow_input_stream_get_type (),
+ "base-stream", imem,
+ "close-base-stream", TRUE,
+ NULL);
+ in = g_object_new (g_type_from_name ("SoupBodyInputStream"),
+ "base-stream", islow,
+ "close-base-stream", TRUE,
+ "encoding", SOUP_ENCODING_CHUNKED,
+ NULL);
+ g_object_unref (imem);
+ g_object_unref (islow);
+
+ buf = g_malloc (raw_contents->length);
+ total = 0;
+ while (TRUE) {
+ nread = g_input_stream_read (in, buf + total,
+ raw_contents->length - total,
+ NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ if (nread > 0)
+ total += nread;
+ else
+ break;
+ }
+
+ g_input_stream_close (in, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ g_object_unref (in);
+
+ soup_assert_cmpmem (buf, total, raw_contents->data, raw_contents->length);
+ g_free (buf);
+
+ debug_printf (1, " async read\n");
+
+ imem = g_memory_input_stream_new_from_data (chunkified->str, chunkified->len, NULL);
+ islow = g_object_new (slow_input_stream_get_type (),
+ "base-stream", imem,
+ "close-base-stream", TRUE,
+ NULL);
+ in = g_object_new (g_type_from_name ("SoupBodyInputStream"),
+ "base-stream", islow,
+ "close-base-stream", TRUE,
+ "encoding", SOUP_ENCODING_CHUNKED,
+ NULL);
+ g_object_unref (imem);
+ g_object_unref (islow);
+
+ buf = g_malloc (raw_contents->length);
+ total = 0;
+ while (TRUE) {
+ nread = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (in),
+ buf + total,
+ raw_contents->length - total,
+ NULL, &error);
+ if (nread == -1 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
+ GSource *source;
+
+ g_clear_error (&error);
+ source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (in), NULL);
+ g_source_set_dummy_callback (source);
+ g_source_attach (source, NULL);
+ while (!g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (in)))
+ g_main_context_iteration (NULL, TRUE);
+ g_source_destroy (source);
+ g_source_unref (source);
+ continue;
+ } else if (nread == -1) {
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ break;
+ } else if (nread == 0)
+ break;
+ else
+ total += nread;
+ }
+
+ g_input_stream_close (in, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ g_object_unref (in);
+
+ soup_assert_cmpmem (buf, total, raw_contents->data, raw_contents->length);
+ g_free (buf);
+
+ debug_printf (1, " sync write\n");
+
+ buf = g_malloc (chunkified->len);
+ omem = g_memory_output_stream_new (buf, chunkified->len, NULL, NULL);
+ oslow = g_object_new (slow_output_stream_get_type (),
+ "base-stream", omem,
+ "close-base-stream", TRUE,
+ NULL);
+ out = g_object_new (g_type_from_name ("SoupBodyOutputStream"),
+ "base-stream", oslow,
+ "close-base-stream", TRUE,
+ "encoding", SOUP_ENCODING_CHUNKED,
+ NULL);
+ g_object_unref (omem);
+ g_object_unref (oslow);
+
+ total = chunk_length = chunk_total = 0;
+ while (total < raw_contents->length) {
+ if (chunk_total == chunk_length) {
+ chunk_length = MIN (CHUNK_SIZE, raw_contents->length - total);
+ chunk_total = 0;
+ }
+ nwrote = g_output_stream_write (out, raw_contents->data + total,
+ chunk_length - chunk_total, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ if (nwrote > 0) {
+ total += nwrote;
+ chunk_total += nwrote;
+ } else
+ break;
+ }
+
+ g_output_stream_close (out, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+
+ mem = G_MEMORY_OUTPUT_STREAM (omem);
+ soup_assert_cmpmem (g_memory_output_stream_get_data (mem),
+ g_memory_output_stream_get_data_size (mem),
+ chunkified->str, chunkified->len);
+
+ g_object_unref (out);
+ g_free (buf);
+
+ debug_printf (1, " async write\n");
+
+ buf = g_malloc (chunkified->len);
+ omem = g_memory_output_stream_new (buf, chunkified->len, NULL, NULL);
+ oslow = g_object_new (slow_output_stream_get_type (),
+ "base-stream", omem,
+ "close-base-stream", TRUE,
+ NULL);
+ out = g_object_new (g_type_from_name ("SoupBodyOutputStream"),
+ "base-stream", oslow,
+ "close-base-stream", TRUE,
+ "encoding", SOUP_ENCODING_CHUNKED,
+ NULL);
+ g_object_unref (omem);
+ g_object_unref (oslow);
+
+ total = chunk_length = chunk_total = 0;
+ while (total < raw_contents->length) {
+ if (chunk_total == chunk_length) {
+ chunk_length = MIN (CHUNK_SIZE, raw_contents->length - total);
+ chunk_total = 0;
+ }
+ nwrote = g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (out),
+ raw_contents->data + total,
+ chunk_length - chunk_total,
+ NULL, &error);
+ if (nwrote == -1 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
+ GSource *source;
+
+ g_clear_error (&error);
+ source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (out), NULL);
+ g_source_set_dummy_callback (source);
+ g_source_attach (source, NULL);
+ while (!g_pollable_output_stream_is_writable (G_POLLABLE_OUTPUT_STREAM (out)))
+ g_main_context_iteration (NULL, TRUE);
+ g_source_destroy (source);
+ g_source_unref (source);
+ continue;
+ } else if (nwrote == -1) {
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ break;
+ } else {
+ total += nwrote;
+ chunk_total += nwrote;
+ }
+ }
+
+ g_output_stream_close (out, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+
+ mem = G_MEMORY_OUTPUT_STREAM (omem);
+ soup_assert_cmpmem (g_memory_output_stream_get_data (mem),
+ g_memory_output_stream_get_data_size (mem),
+ chunkified->str, chunkified->len);
+
+ g_object_unref (out);
+ g_free (buf);
+
+ debug_printf (1, " failed write\n");
+ /* this succeeds if it doesn't critical */
+
+ buf = g_malloc (chunkified->len);
+ omem = g_memory_output_stream_new (buf, chunkified->len, NULL, NULL);
+ oslow = g_object_new (breaking_output_stream_get_type (),
+ "base-stream", omem,
+ "close-base-stream", TRUE,
+ NULL);
+ out = g_object_new (g_type_from_name ("SoupBodyOutputStream"),
+ "base-stream", oslow,
+ "close-base-stream", TRUE,
+ "encoding", SOUP_ENCODING_CHUNKED,
+ NULL);
+ g_object_unref (omem);
+ g_object_unref (oslow);
+
+ total = 0;
+ while (total < raw_contents->length) {
+ nwrote = g_output_stream_write (out, raw_contents->data + total,
+ raw_contents->length - total, NULL, NULL);
+ if (nwrote == -1)
+ break;
+ else
+ total += nwrote;
+ }
+
+ g_assert_cmpint (total, !=, raw_contents->length);
+
+ g_output_stream_close (out, NULL, NULL);
+ g_object_unref (out);
+
+ g_free (buf);
+
+ g_string_free (chunkified, TRUE);
+}
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+
+ test_init (argc, argv, NULL);
+
+ force_io_streams_init ();
+
+ g_test_add_func ("/chunk-io", do_io_tests);
+
+ ret = g_test_run ();
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/chunk-test.c b/tests/chunk-test.c
index cce7127f..864f8620 100644
--- a/tests/chunk-test.c
+++ b/tests/chunk-test.c
@@ -5,6 +5,9 @@
#include "test-utils.h"
+static SoupSession *session;
+static SoupURI *base_uri;
+
typedef struct {
SoupSession *session;
SoupBuffer *chunks[3];
@@ -19,9 +22,9 @@ write_next_chunk (SoupMessage *msg, gpointer user_data)
debug_printf (2, " writing chunk %d\n", ptd->next);
- if (ptd->streaming && ptd->next > 0 && ptd->chunks[ptd->next - 1]) {
- debug_printf (1, " error: next chunk requested before last one freed!\n");
- errors++;
+ if (ptd->streaming && ptd->next > 0) {
+ soup_test_assert (ptd->chunks[ptd->next - 1] == NULL,
+ "next chunk requested before last one freed");
}
if (ptd->next < G_N_ELEMENTS (ptd->chunks)) {
@@ -50,8 +53,8 @@ write_next_chunk_streaming_hack (SoupMessage *msg, gpointer user_data)
soup_message_body_wrote_chunk (msg->request_body, chunk);
soup_buffer_free (chunk);
} else {
- debug_printf (1, " error: written chunk does not exist!\n");
- errors++;
+ soup_test_assert (chunk,
+ "written chunk does not exist");
}
write_next_chunk (msg, user_data);
}
@@ -77,8 +80,8 @@ clear_buffer_ptr (gpointer data)
g_free ((char *)(*buffer_ptr)->data);
*buffer_ptr = NULL;
} else {
- debug_printf (2, " chunk is already clear!\n");
- errors++;
+ soup_test_assert (*buffer_ptr,
+ "chunk is already clear");
}
}
@@ -136,26 +139,20 @@ typedef enum {
} RequestTestFlags;
static void
-do_request_test (SoupSession *session, SoupURI *base_uri, RequestTestFlags flags)
+do_request_test (gconstpointer data)
{
- SoupURI *uri = base_uri;
+ RequestTestFlags flags = GPOINTER_TO_UINT (data);
+ SoupURI *uri;
PutTestData ptd;
SoupMessage *msg;
const char *client_md5, *server_md5;
GChecksum *check;
int i, length;
- debug_printf (1, "PUT");
- if (flags & HACKY_STREAMING)
- debug_printf (1, " w/ hacky streaming");
- else if (flags & PROPER_STREAMING)
- debug_printf (1, " w/ proper streaming");
- if (flags & RESTART) {
- debug_printf (1, " and restart");
+ if (flags & RESTART)
+ uri = soup_uri_new_with_base (base_uri, "/redirect");
+ else
uri = soup_uri_copy (base_uri);
- soup_uri_set_path (uri, "/redirect");
- }
- debug_printf (1, "\n");
ptd.session = session;
setup_request_body (&ptd);
@@ -199,35 +196,19 @@ do_request_test (SoupSession *session, SoupURI *base_uri, RequestTestFlags flags
G_CALLBACK (wrote_body_data), &ptd);
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " message failed: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
-
- if (msg->request_body->data) {
- debug_printf (1, " msg->request_body set!\n");
- errors++;
- }
- if (msg->request_body->length != length || length != ptd.nwrote) {
- debug_printf (1, " sent length mismatch: %d vs %d vs %d\n",
- (int)msg->request_body->length, length, ptd.nwrote);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_CREATED);
+ g_assert_null (msg->request_body->data);
+ g_assert_cmpint (msg->request_body->length, ==, length);
+ g_assert_cmpint (length, ==, ptd.nwrote);
server_md5 = soup_message_headers_get_one (msg->response_headers,
"Content-MD5");
- if (!server_md5 || strcmp (client_md5, server_md5) != 0) {
- debug_printf (1, " client/server data mismatch: %s vs %s\n",
- client_md5, server_md5 ? server_md5 : "(null)");
- errors++;
- }
+ g_assert_cmpstr (client_md5, ==, server_md5);
g_object_unref (msg);
g_checksum_free (check);
- if (uri != base_uri)
- soup_uri_free (uri);
+ soup_uri_free (uri);
}
typedef struct {
@@ -243,10 +224,8 @@ chunk_allocator (SoupMessage *msg, gsize max_len, gpointer user_data)
debug_printf (2, " allocating chunk\n");
- if (gtd->current_chunk) {
- debug_printf (1, " error: next chunk allocated before last one freed!\n");
- errors++;
- }
+ soup_test_assert (gtd->current_chunk == NULL,
+ "error: next chunk allocated before last one freed");
gtd->current_chunk = soup_buffer_new_with_owner (g_malloc (6), 6,
&gtd->current_chunk,
clear_buffer_ptr);
@@ -270,56 +249,40 @@ got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data)
}
static void
-do_response_test (SoupSession *session, SoupURI *base_uri)
+do_response_test (void)
{
GetTestData gtd;
SoupMessage *msg;
const char *client_md5, *server_md5;
- debug_printf (1, "GET\n");
-
gtd.current_chunk = NULL;
gtd.length = 0;
gtd.check = g_checksum_new (G_CHECKSUM_MD5);
msg = soup_message_new_from_uri ("GET", base_uri);
soup_message_body_set_accumulate (msg->response_body, FALSE);
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
soup_message_set_chunk_allocator (msg, chunk_allocator, &gtd, NULL);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
g_signal_connect (msg, "got_chunk",
G_CALLBACK (got_chunk), &gtd);
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " message failed: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
-
- if (msg->response_body->data) {
- debug_printf (1, " msg->response_body set!\n");
- errors++;
- }
- if (soup_message_headers_get_content_length (msg->response_headers) != gtd.length) {
- debug_printf (1, " received length mismatch: %d vs %d\n",
- (int)soup_message_headers_get_content_length (msg->response_headers), gtd.length);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_assert_null (msg->response_body->data);
+ g_assert_cmpint (soup_message_headers_get_content_length (msg->response_headers), ==, gtd.length);
client_md5 = g_checksum_get_string (gtd.check);
server_md5 = soup_message_headers_get_one (msg->response_headers,
"Content-MD5");
- if (!server_md5 || strcmp (client_md5, server_md5) != 0) {
- debug_printf (1, " client/server data mismatch: %s vs %s\n",
- client_md5, server_md5 ? server_md5 : "(null)");
- errors++;
- }
+ g_assert_cmpstr (client_md5, ==, server_md5);
g_object_unref (msg);
g_checksum_free (gtd.check);
}
/* Make sure TEMPORARY buffers are handled properly with non-accumulating
- * message bodies. Part of https://bugs.webkit.org/show_bug.cgi?id=18343
+ * message bodies.
*/
static void
@@ -334,24 +297,24 @@ temp_test_wrote_chunk (SoupMessage *msg, gpointer session)
* the I/O to stall since soup-message-io will think it's
* done, but it hasn't written Content-Length bytes yet.
*/
- if (!chunk) {
- debug_printf (1, " Lost second chunk!\n");
- errors++;
- soup_session_abort (session);
- } else
+ if (chunk)
soup_buffer_free (chunk);
+ else {
+ soup_test_assert (chunk, "Lost second chunk");
+ soup_session_abort (session);
+ }
g_signal_handlers_disconnect_by_func (msg, temp_test_wrote_chunk, session);
}
static void
-do_temporary_test (SoupSession *session, SoupURI *base_uri)
+do_temporary_test (void)
{
SoupMessage *msg;
char *client_md5;
const char *server_md5;
- debug_printf (1, "PUT w/ temporary buffers\n");
+ g_test_bug ("https://bugs.webkit.org/show_bug.cgi?id=18343");
msg = soup_message_new_from_uri ("PUT", base_uri);
soup_message_body_append (msg->request_body, SOUP_MEMORY_TEMPORARY,
@@ -366,19 +329,11 @@ do_temporary_test (SoupSession *session, SoupURI *base_uri)
G_CALLBACK (temp_test_wrote_chunk), session);
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " message failed: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_CREATED);
server_md5 = soup_message_headers_get_one (msg->response_headers,
"Content-MD5");
- if (!server_md5 || strcmp (client_md5, server_md5) != 0) {
- debug_printf (1, " client/server data mismatch: %s vs %s\n",
- client_md5, server_md5 ? server_md5 : "(null)");
- errors++;
- }
+ g_assert_cmpstr (client_md5, ==, server_md5);
g_free (client_md5);
g_object_unref (msg);
@@ -396,24 +351,20 @@ large_wrote_body_data (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data)
{
LargeChunkData *lcd = user_data;
- if (memcmp (chunk->data, lcd->buf->data + lcd->offset, chunk->length) != 0) {
- debug_printf (1, " chunk data mismatch at %ld\n", (long)lcd->offset);
- errors++;
- } else
- debug_printf (2, " chunk data match at %ld\n", (long)lcd->offset);
+ soup_assert_cmpmem (chunk->data, chunk->length,
+ lcd->buf->data + lcd->offset,
+ chunk->length);
lcd->offset += chunk->length;
}
static void
-do_large_chunk_test (SoupSession *session, SoupURI *base_uri)
+do_large_chunk_test (void)
{
SoupMessage *msg;
char *buf_data;
int i;
LargeChunkData lcd;
- debug_printf (1, "PUT w/ large chunk\n");
-
msg = soup_message_new_from_uri ("PUT", base_uri);
buf_data = g_malloc0 (LARGE_CHUNK_SIZE);
@@ -428,41 +379,13 @@ do_large_chunk_test (SoupSession *session, SoupURI *base_uri)
G_CALLBACK (large_wrote_body_data), &lcd);
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " message failed: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_CREATED);
soup_buffer_free (lcd.buf);
g_object_unref (msg);
}
static void
-do_chunk_tests (SoupURI *base_uri)
-{
- SoupSession *session;
-
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- do_request_test (session, base_uri, 0);
- debug_printf (2, "\n\n");
- do_request_test (session, base_uri, PROPER_STREAMING);
- debug_printf (2, "\n\n");
- do_request_test (session, base_uri, PROPER_STREAMING | RESTART);
- debug_printf (2, "\n\n");
- do_request_test (session, base_uri, HACKY_STREAMING);
- debug_printf (2, "\n\n");
- do_request_test (session, base_uri, HACKY_STREAMING | RESTART);
- debug_printf (2, "\n\n");
- do_response_test (session, base_uri);
- debug_printf (2, "\n\n");
- do_temporary_test (session, base_uri);
- debug_printf (2, "\n\n");
- do_large_chunk_test (session, base_uri);
- soup_test_session_abort_unref (session);
-}
-
-static void
server_callback (SoupServer *server, SoupMessage *msg,
const char *path, GHashTable *query,
SoupClientContext *context, gpointer data)
@@ -505,7 +428,7 @@ main (int argc, char **argv)
GMainLoop *loop;
SoupServer *server;
guint port;
- SoupURI *base_uri;
+ int ret;
test_init (argc, argv, NULL);
@@ -518,12 +441,27 @@ main (int argc, char **argv)
base_uri = soup_uri_new ("http://127.0.0.1");
soup_uri_set_port (base_uri, port);
- do_chunk_tests (base_uri);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+
+ g_test_add_data_func ("/chunks/request/unstreamed", GINT_TO_POINTER (0), do_request_test);
+ g_test_add_data_func ("/chunks/request/proper-streaming", GINT_TO_POINTER (PROPER_STREAMING), do_request_test);
+ g_test_add_data_func ("/chunks/request/proper-streaming/restart", GINT_TO_POINTER (PROPER_STREAMING | RESTART), do_request_test);
+ g_test_add_data_func ("/chunks/request/hacky-streaming", GINT_TO_POINTER (HACKY_STREAMING), do_request_test);
+ g_test_add_data_func ("/chunks/request/hacky-streaming/restart", GINT_TO_POINTER (HACKY_STREAMING | RESTART), do_request_test);
+ g_test_add_func ("/chunks/response", do_response_test);
+ g_test_add_func ("/chunks/temporary", do_temporary_test);
+ g_test_add_func ("/chunks/large", do_large_chunk_test);
+
+ ret = g_test_run ();
+
+ soup_test_session_abort_unref (session);
+
soup_uri_free (base_uri);
g_main_loop_unref (loop);
soup_test_server_quit_unref (server);
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/coding-test.c b/tests/coding-test.c
index cda4b89e..0445f632 100644
--- a/tests/coding-test.c
+++ b/tests/coding-test.c
@@ -16,8 +16,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
{
const char *accept_encoding, *options;
GSList *codings;
- char *file = NULL, *contents;
- gsize length;
+ SoupBuffer *response = NULL;
options = soup_message_headers_get_one (msg->request_headers,
"X-Test-Options");
@@ -33,7 +32,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
if (codings) {
gboolean claim_deflate, claim_gzip;
- const char *file_path = NULL, *encoding = NULL;
+ const char *extension = NULL, *encoding = NULL;
claim_deflate = g_slist_find_custom (codings, "deflate", (GCompareFunc)g_ascii_strcasecmp) != NULL;
claim_gzip = g_slist_find_custom (codings, "gzip", (GCompareFunc)g_ascii_strcasecmp) != NULL;
@@ -41,44 +40,44 @@ server_callback (SoupServer *server, SoupMessage *msg,
if (claim_gzip && (!claim_deflate ||
(!soup_header_contains (options, "prefer-deflate-zlib") &&
!soup_header_contains (options, "prefer-deflate-raw")))) {
- file_path = SRCDIR "/resources%s.gz";
+ extension = "gz";
encoding = "gzip";
} else if (claim_deflate) {
if (soup_header_contains (options, "prefer-deflate-raw")) {
- file_path = SRCDIR "/resources%s.raw";
+ extension = "raw";
encoding = "deflate";
} else {
- file_path = SRCDIR "/resources%s.zlib";
+ extension = "zlib";
encoding = "deflate";
}
}
- if (file_path && encoding) {
- file = g_strdup_printf (file_path, path);
- if (g_file_test (file, G_FILE_TEST_EXISTS)) {
+ if (extension && encoding) {
+ char *resource;
+
+ resource = g_strdup_printf ("%s.%s", path, extension);
+ response = soup_test_load_resource (resource, NULL);
+
+ if (response) {
soup_message_headers_append (msg->response_headers,
"Content-Encoding",
encoding);
- } else {
- g_free (file);
- file = NULL;
}
+ g_free (resource);
}
}
soup_header_free_list (codings);
- if (!file)
- file = g_strdup_printf (SRCDIR "/resources%s", path);
- if (!g_file_get_contents (file, &contents, &length, NULL)) {
+ if (!response)
+ response = soup_test_load_resource (path, NULL);
+ if (!response) {
/* If path.gz exists but can't be read, we'll send back
* the error with "Content-Encoding: gzip" but there's
* no body, so, eh.
*/
- g_free (file);
soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
return;
}
- g_free (file);
if (soup_header_contains (options, "force-encode")) {
const gchar *encoding = "gzip";
@@ -106,10 +105,9 @@ server_callback (SoupServer *server, SoupMessage *msg,
soup_message_set_status (msg, SOUP_STATUS_OK);
soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CHUNKED);
- if (!soup_header_contains (options, "empty")) {
- soup_message_body_append (msg->response_body,
- SOUP_MEMORY_TAKE, contents, length);
- }
+ if (!soup_header_contains (options, "empty"))
+ soup_message_body_append_buffer (msg->response_body, response);
+ soup_buffer_free (response);
if (soup_header_contains (options, "trailing-junk")) {
soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY,
@@ -118,6 +116,20 @@ server_callback (SoupServer *server, SoupMessage *msg,
soup_message_body_complete (msg->response_body);
}
+typedef struct {
+ SoupSession *session;
+ SoupMessage *msg;
+ SoupRequest *req;
+ SoupBuffer *response;
+} CodingTestData;
+
+typedef enum {
+ CODING_TEST_DEFAULT = 0,
+ CODING_TEST_NO_DECODER = (1 << 0),
+ CODING_TEST_REQUEST_API = (1 << 1),
+ CODING_TEST_EMPTY = (1 << 2)
+} CodingTestType;
+
typedef enum {
NO_CHECK,
EXPECT_DECODED,
@@ -125,184 +137,189 @@ typedef enum {
} MessageContentStatus;
static void
-check_response (SoupMessage *msg,
+check_response (CodingTestData *data,
const char *expected_encoding,
const char *expected_content_type,
- MessageContentStatus status)
+ MessageContentStatus status,
+ GByteArray *body)
{
const char *coding, *type;
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " Unexpected status %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (data->msg, SOUP_STATUS_OK);
- coding = soup_message_headers_get_one (msg->response_headers, "Content-Encoding");
- if (expected_encoding) {
- if (!coding || g_ascii_strcasecmp (coding, expected_encoding) != 0) {
- debug_printf (1, " Unexpected Content-Encoding: %s\n",
- coding ? coding : "(none)");
- errors++;
- }
- } else {
- if (coding) {
- debug_printf (1, " Unexpected Content-Encoding: %s\n",
- coding);
- errors++;
- }
- }
+ coding = soup_message_headers_get_one (data->msg->response_headers, "Content-Encoding");
+ g_assert_cmpstr (coding, ==, expected_encoding);
if (status != NO_CHECK) {
- if (status == EXPECT_DECODED) {
- if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED)) {
- debug_printf (1, " SOUP_MESSAGE_CONTENT_DECODED not set!\n");
- errors++;
- }
- } else {
- if (soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED) {
- debug_printf (1, " SOUP_MESSAGE_CONTENT_DECODED set!\n");
- errors++;
- }
- }
+ if (status == EXPECT_DECODED)
+ g_assert_true (soup_message_get_flags (data->msg) & SOUP_MESSAGE_CONTENT_DECODED);
+ else
+ g_assert_false (soup_message_get_flags (data->msg) & SOUP_MESSAGE_CONTENT_DECODED);
}
- type = soup_message_headers_get_one (msg->response_headers, "Content-Type");
- if (!type || g_ascii_strcasecmp (type, expected_content_type) != 0) {
- debug_printf (1, " Unexpected Content-Type: %s\n",
- type ? type : "(none)");
- errors++;
+ type = soup_message_headers_get_one (data->msg->response_headers, "Content-Type");
+ g_assert_cmpstr (type, ==, expected_content_type);
+
+ if (body) {
+ soup_assert_cmpmem (body->data,
+ body->len,
+ data->response->data,
+ data->response->length);
+ } else {
+ soup_assert_cmpmem (data->msg->response_body->data,
+ data->msg->response_body->length,
+ data->response->data,
+ data->response->length);
}
}
static void
-check_msg_bodies (SoupMessage *msg1,
- SoupMessage *msg2,
- const char *msg1_type,
- const char *msg2_type)
+setup_coding_test (CodingTestData *data, gconstpointer test_data)
{
- if (msg1->response_body->length != msg2->response_body->length) {
- debug_printf (1, " Message length mismatch: %lu (%s) vs %lu (%s)\n",
- (gulong)msg1->response_body->length,
- msg1_type,
- (gulong)msg2->response_body->length,
- msg2_type);
- errors++;
- } else if (memcmp (msg1->response_body->data,
- msg2->response_body->data,
- msg1->response_body->length) != 0) {
- debug_printf (1, " Message data mismatch (%s/%s)\n",
- msg1_type, msg2_type);
- errors++;
+ CodingTestType test_type = GPOINTER_TO_INT (test_data);
+ SoupMessage *msg;
+ SoupURI *uri;
+
+ data->session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
+
+ uri = soup_uri_new_with_base (base_uri, "/mbox");
+
+ if (test_type & CODING_TEST_EMPTY)
+ data->response = soup_buffer_new (SOUP_MEMORY_STATIC, "", 0);
+ else {
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_session_send_message (data->session, msg);
+
+ data->response = soup_message_body_flatten (msg->response_body);
+ g_object_unref (msg);
}
+
+ if (test_type & CODING_TEST_REQUEST_API) {
+ SoupRequestHTTP *reqh;
+
+ reqh = soup_session_request_http_uri (data->session, "GET", uri, NULL);
+ data->req = SOUP_REQUEST (reqh);
+ data->msg = soup_request_http_get_message (reqh);
+ } else
+ data->msg = soup_message_new_from_uri ("GET", uri);
+ soup_uri_free (uri);
+
+ if (! (test_type & CODING_TEST_NO_DECODER))
+ soup_session_add_feature_by_type (data->session, SOUP_TYPE_CONTENT_DECODER);
}
static void
-do_coding_test (void)
+teardown_coding_test (CodingTestData *data, gconstpointer test_data)
{
- SoupSession *session;
- SoupMessage *msg, *msgz, *msgj, *msge, *msgzl, *msgzlj, *msgzle, *msgzlr, *msgzlre;
- SoupURI *uri;
+ soup_buffer_free (data->response);
- debug_printf (1, "SoupMessage tests\n");
+ g_clear_object (&data->req);
+ g_object_unref (data->msg);
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- uri = soup_uri_new_with_base (base_uri, "/mbox");
+ soup_test_session_abort_unref (data->session);
+}
+
+static void
+do_coding_test_plain (CodingTestData *data, gconstpointer test_data)
+{
+ soup_session_send_message (data->session, data->msg);
+ check_response (data, NULL, "text/plain", EXPECT_NOT_DECODED, NULL);
+}
+
+static void
+do_coding_test_gzip (CodingTestData *data, gconstpointer test_data)
+{
+ soup_session_send_message (data->session, data->msg);
+ check_response (data, "gzip", "text/plain", EXPECT_DECODED, NULL);
+}
- /* Plain text data, no claim */
- debug_printf (1, " GET /mbox, plain\n");
- msg = soup_message_new_from_uri ("GET", uri);
- soup_session_send_message (session, msg);
- check_response (msg, NULL, "text/plain", EXPECT_NOT_DECODED);
-
- /* Plain text data, claim gzip */
- debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n");
- soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
- msgz = soup_message_new_from_uri ("GET", uri);
- soup_session_send_message (session, msgz);
- check_response (msgz, "gzip", "text/plain", EXPECT_DECODED);
- check_msg_bodies (msg, msgz, "plain", "compressed");
-
- /* Plain text data, claim gzip w/ junk */
- debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
- msgj = soup_message_new_from_uri ("GET", uri);
- soup_message_headers_append (msgj->request_headers,
+static void
+do_coding_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("606352");
+ g_test_bug ("676477");
+
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "trailing-junk");
- soup_session_send_message (session, msgj);
- check_response (msgj, "gzip", "text/plain", EXPECT_DECODED);
- check_msg_bodies (msg, msgj, "plain", "compressed w/ junk");
-
- /* Plain text data, claim gzip with server error */
- debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n");
- msge = soup_message_new_from_uri ("GET", uri);
- soup_message_headers_append (msge->request_headers,
+
+ soup_session_send_message (data->session, data->msg);
+ check_response (data, "gzip", "text/plain", EXPECT_DECODED, NULL);
+}
+
+static void
+do_coding_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("613361");
+
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "force-encode");
- soup_session_send_message (session, msge);
- check_response (msge, "gzip", "text/plain", EXPECT_NOT_DECODED);
+
+ soup_session_send_message (data->session, data->msg);
/* Failed content-decoding should have left the body untouched
* from what the server sent... which happens to be the
* uncompressed data.
*/
- check_msg_bodies (msg, msge, "plain", "mis-encoded");
+ check_response (data, "gzip", "text/plain", EXPECT_NOT_DECODED, NULL);
+}
- /* Plain text data, claim deflate */
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n");
- msgzl = soup_message_new_from_uri ("GET", uri);
- soup_message_headers_append (msgzl->request_headers,
+static void
+do_coding_test_deflate (CodingTestData *data, gconstpointer test_data)
+{
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "prefer-deflate-zlib");
- soup_session_send_message (session, msgzl);
- check_response (msgzl, "deflate", "text/plain", EXPECT_DECODED);
- check_msg_bodies (msg, msgzl, "plain", "compressed");
-
- /* Plain text data, claim deflate w/ junk */
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n");
- msgzlj = soup_message_new_from_uri ("GET", uri);
- soup_message_headers_append (msgzlj->request_headers,
+ soup_session_send_message (data->session, data->msg);
+
+ check_response (data, "deflate", "text/plain", EXPECT_DECODED, NULL);
+}
+
+static void
+do_coding_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("606352");
+ g_test_bug ("676477");
+
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "prefer-deflate-zlib, trailing-junk");
- soup_session_send_message (session, msgzlj);
- check_response (msgzlj, "deflate", "text/plain", EXPECT_DECODED);
- check_msg_bodies (msg, msgzlj, "plain", "compressed w/ junk");
-
- /* Plain text data, claim deflate with server error */
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n");
- msgzle = soup_message_new_from_uri ("GET", uri);
- soup_message_headers_append (msgzle->request_headers,
+ soup_session_send_message (data->session, data->msg);
+
+ check_response (data, "deflate", "text/plain", EXPECT_DECODED, NULL);
+}
+
+static void
+do_coding_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("613361");
+
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "force-encode, prefer-deflate-zlib");
- soup_session_send_message (session, msgzle);
- check_response (msgzle, "deflate", "text/plain", EXPECT_NOT_DECODED);
- check_msg_bodies (msg, msgzle, "plain", "mis-encoded");
-
- /* Plain text data, claim deflate (no zlib headers)*/
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n");
- msgzlr = soup_message_new_from_uri ("GET", uri);
- soup_message_headers_append (msgzlr->request_headers,
+ soup_session_send_message (data->session, data->msg);
+
+ check_response (data, "deflate", "text/plain", EXPECT_NOT_DECODED, NULL);
+}
+
+static void
+do_coding_test_deflate_raw (CodingTestData *data, gconstpointer test_data)
+{
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "prefer-deflate-raw");
- soup_session_send_message (session, msgzlr);
- check_response (msgzlr, "deflate", "text/plain", EXPECT_DECODED);
- check_msg_bodies (msg, msgzlr, "plain", "compressed");
-
- /* Plain text data, claim deflate with server error */
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n");
- msgzlre = soup_message_new_from_uri ("GET", uri);
- soup_message_headers_append (msgzlre->request_headers,
+ soup_session_send_message (data->session, data->msg);
+
+ check_response (data, "deflate", "text/plain", EXPECT_DECODED, NULL);
+}
+
+static void
+do_coding_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("613361");
+
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "force-encode, prefer-deflate-raw");
- soup_session_send_message (session, msgzlre);
- check_response (msgzlre, "deflate", "text/plain", EXPECT_NOT_DECODED);
- check_msg_bodies (msg, msgzlre, "plain", "mis-encoded");
-
- g_object_unref (msg);
- g_object_unref (msgzlre);
- g_object_unref (msgzlr);
- g_object_unref (msgzlj);
- g_object_unref (msgzle);
- g_object_unref (msgzl);
- g_object_unref (msgz);
- g_object_unref (msgj);
- g_object_unref (msge);
- soup_uri_free (uri);
+ soup_session_send_message (data->session, data->msg);
- soup_test_session_abort_unref (session);
+ check_response (data, "deflate", "text/plain", EXPECT_NOT_DECODED, NULL);
}
static void
@@ -313,38 +330,29 @@ read_finished (GObject *stream, GAsyncResult *result, gpointer user_data)
*nread = g_input_stream_read_finish (G_INPUT_STREAM (stream),
result, &error);
- if (error) {
- debug_printf (1, " Error reading: %s\n",
- error->message);
- g_error_free (error);
- errors++;
- }
+ g_assert_no_error (error);
+ g_clear_error (&error);
}
-static GByteArray *
-do_single_coding_req_test (SoupRequest *req,
+static void
+do_single_coding_req_test (CodingTestData *data,
const char *expected_encoding,
const char *expected_content_type,
MessageContentStatus status)
{
GInputStream *stream;
- SoupMessage *msg;
- GByteArray *data;
+ GByteArray *body;
guchar buf[1024];
gssize nread;
GError *error = NULL;
- data = g_byte_array_new ();
-
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+ body = g_byte_array_new ();
- stream = soup_test_request_send_async_as_sync (req, NULL, &error);
- if (error) {
- debug_printf (1, " Error sending request: %s\n",
- error->message);
+ stream = soup_test_request_send (data->req, NULL, 0, &error);
+ if (!stream) {
+ g_assert_no_error (error);
g_error_free (error);
- errors++;
- return data;
+ return;
}
do {
@@ -356,208 +364,126 @@ do_single_coding_req_test (SoupRequest *req,
g_main_context_iteration (NULL, TRUE);
if (nread > 0)
- g_byte_array_append (data, buf, nread);
+ g_byte_array_append (body, buf, nread);
} while (nread > 0);
- soup_test_stream_close_async_as_sync (stream, NULL, &error);
- if (error) {
- debug_printf (1, " error closing stream: %s\n",
- error->message);
- g_error_free (error);
- errors++;
- }
+ soup_test_request_close_stream (data->req, stream, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ g_object_unref (stream);
- check_response (msg, expected_encoding, expected_content_type, status);
- g_object_unref (msg);
+ check_response (data, expected_encoding, expected_content_type, status, body);
+ g_byte_array_free (body, TRUE);
+}
- return data;
+static void
+do_coding_req_test_plain (CodingTestData *data, gconstpointer test_data)
+{
+ do_single_coding_req_test (data, NULL, "text/plain", EXPECT_NOT_DECODED);
}
static void
-check_req_bodies (GByteArray *body1,
- GByteArray *body2,
- const char *msg1_type,
- const char *msg2_type)
+do_coding_req_test_gzip (CodingTestData *data, gconstpointer test_data)
{
- if (body1->len != body2->len) {
- debug_printf (1, " Message length mismatch: %lu (%s) vs %lu (%s)\n",
- (gulong)body1->len, msg1_type,
- (gulong)body2->len, msg2_type);
- errors++;
- } else if (memcmp (body1->data, body2->data, body1->len) != 0) {
- debug_printf (1, " Message data mismatch (%s/%s)\n",
- msg1_type, msg2_type);
- errors++;
- }
+ do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_DECODED);
}
static void
-do_coding_req_test (void)
+do_coding_req_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data)
{
- SoupSession *session;
- SoupRequester *requester;
- SoupRequest *req;
- SoupMessage *msg;
- SoupURI *uri;
- GByteArray *plain, *cmp;
+ g_test_bug ("606352");
+ g_test_bug ("676477");
- debug_printf (1, "\nSoupRequest tests\n");
+ soup_message_headers_append (data->msg->request_headers,
+ "X-Test-Options", "trailing-junk");
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
- NULL);
- requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
- uri = soup_uri_new_with_base (base_uri, "/mbox");
+ do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_DECODED);
+}
- /* Plain text data, no claim */
- debug_printf (1, " GET /mbox, plain\n");
- req = soup_requester_request_uri (requester, uri, NULL);
- plain = do_single_coding_req_test (req, NULL, "text/plain", EXPECT_NOT_DECODED);
- g_object_unref (req);
-
- /* Plain text data, claim gzip */
- debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n");
- soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
- req = soup_requester_request_uri (requester, uri, NULL);
- cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED);
- check_req_bodies (plain, cmp, "plain", "compressed");
- g_byte_array_free (cmp, TRUE);
- g_object_unref (req);
-
- /* Plain text data, claim gzip w/ junk */
- debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n");
- req = soup_requester_request_uri (requester, uri, NULL);
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- soup_message_headers_append (msg->request_headers,
- "X-Test-Options", "trailing-junk");
- cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED);
- check_req_bodies (plain, cmp, "plain", "compressed w/ junk");
- g_byte_array_free (cmp, TRUE);
- g_object_unref (req);
-
- /* Plain text data, claim gzip with server error */
- debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n");
- req = soup_requester_request_uri (requester, uri, NULL);
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- soup_message_headers_append (msg->request_headers,
+static void
+do_coding_req_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("613361");
+
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "force-encode");
- cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_NOT_DECODED);
+ do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_NOT_DECODED);
+}
- /* Failed content-decoding should have left the body untouched
- * from what the server sent... which happens to be the
- * uncompressed data.
- */
- check_req_bodies (plain, cmp, "plain", "mis-encoded");
- g_byte_array_free (cmp, TRUE);
- g_object_unref (req);
-
- /* Plain text data, claim deflate */
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n");
- req = soup_requester_request_uri (requester, uri, NULL);
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- soup_message_headers_append (msg->request_headers,
+static void
+do_coding_req_test_deflate (CodingTestData *data, gconstpointer test_data)
+{
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "prefer-deflate-zlib");
- cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED);
- check_req_bodies (plain, cmp, "plain", "compressed");
- g_byte_array_free (cmp, TRUE);
- g_object_unref (req);
-
- /* Plain text data, claim deflate w/ junk */
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n");
- req = soup_requester_request_uri (requester, uri, NULL);
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- soup_message_headers_append (msg->request_headers,
+ do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED);
+}
+
+static void
+do_coding_req_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("606352");
+ g_test_bug ("676477");
+
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "prefer-deflate-zlib, trailing-junk");
- cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED);
- check_req_bodies (plain, cmp, "plain", "compressed w/ junk");
- g_byte_array_free (cmp, TRUE);
- g_object_unref (req);
-
- /* Plain text data, claim deflate with server error */
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n");
- req = soup_requester_request_uri (requester, uri, NULL);
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- soup_message_headers_append (msg->request_headers,
- "X-Test-Options", "force-encode, prefer-deflate-zlib");
- cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED);
- check_req_bodies (plain, cmp, "plain", "mis-encoded");
- g_byte_array_free (cmp, TRUE);
- g_object_unref (req);
-
- /* Plain text data, claim deflate (no zlib headers)*/
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n");
- req = soup_requester_request_uri (requester, uri, NULL);
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- soup_message_headers_append (msg->request_headers,
- "X-Test-Options", "prefer-deflate-raw");
- cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED);
- check_req_bodies (plain, cmp, "plain", "compressed");
- g_byte_array_free (cmp, TRUE);
- g_object_unref (req);
-
- /* Plain text data, claim deflate with server error */
- debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n");
- req = soup_requester_request_uri (requester, uri, NULL);
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- soup_message_headers_append (msg->request_headers,
- "X-Test-Options", "force-encode, prefer-deflate-raw");
- cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED);
- check_req_bodies (plain, cmp, "plain", "mis-encoded");
- g_byte_array_free (cmp, TRUE);
- g_object_unref (req);
+ do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED);
+}
- g_byte_array_free (plain, TRUE);
- soup_uri_free (uri);
+static void
+do_coding_req_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("613361");
- soup_test_session_abort_unref (session);
+ soup_message_headers_append (data->msg->request_headers,
+ "X-Test-Options", "force-encode, prefer-deflate-zlib");
+ do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED);
}
static void
-do_coding_empty_test (void)
+do_coding_req_test_deflate_raw (CodingTestData *data, gconstpointer test_data)
{
- SoupSession *session;
- SoupMessage *msg;
- SoupURI *uri;
- SoupRequester *requester;
- SoupRequest *req;
- GByteArray *body;
+ soup_message_headers_append (data->msg->request_headers,
+ "X-Test-Options", "prefer-deflate-raw");
+ do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED);
+}
- debug_printf (1, "\nEmpty allegedly-encoded body test\n");
+static void
+do_coding_req_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("613361");
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
- SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
- NULL);
- requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
- uri = soup_uri_new_with_base (base_uri, "/mbox");
+ soup_message_headers_append (data->msg->request_headers,
+ "X-Test-Options", "force-encode, prefer-deflate-raw");
+ do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED);
+}
- debug_printf (1, " SoupMessage\n");
- msg = soup_message_new_from_uri ("GET", uri);
- soup_message_headers_append (msg->request_headers,
- "X-Test-Options", "empty");
- soup_session_send_message (session, msg);
- check_response (msg, "gzip", "text/plain", EXPECT_NOT_DECODED);
- g_object_unref (msg);
-
- debug_printf (1, " SoupRequest\n");
- req = soup_requester_request_uri (requester, uri, NULL);
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- soup_message_headers_append (msg->request_headers,
+static void
+do_coding_msg_empty_test (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("697527");
+
+ soup_message_headers_append (data->msg->request_headers,
"X-Test-Options", "empty");
- g_object_unref (msg);
- body = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_NOT_DECODED);
- g_byte_array_free (body, TRUE);
- g_object_unref (req);
+ soup_session_send_message (data->session, data->msg);
- soup_test_session_abort_unref (session);
+ check_response (data, "gzip", "text/plain", EXPECT_NOT_DECODED, NULL);
}
+static void
+do_coding_req_empty_test (CodingTestData *data, gconstpointer test_data)
+{
+ g_test_bug ("697527");
+
+ soup_message_headers_append (data->msg->request_headers,
+ "X-Test-Options", "empty");
+ do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_NOT_DECODED);
+}
int
main (int argc, char **argv)
{
+ int ret;
+
test_init (argc, argv, NULL);
server = soup_test_server_new (TRUE);
@@ -565,13 +491,74 @@ main (int argc, char **argv)
base_uri = soup_uri_new ("http://127.0.0.1/");
soup_uri_set_port (base_uri, soup_server_get_port (server));
- do_coding_test ();
- do_coding_req_test ();
- do_coding_empty_test ();
+ g_test_add ("/coding/message/plain", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_NO_DECODER),
+ setup_coding_test, do_coding_test_plain, teardown_coding_test);
+ g_test_add ("/coding/message/gzip", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_DEFAULT),
+ setup_coding_test, do_coding_test_gzip, teardown_coding_test);
+ g_test_add ("/coding/message/gzip/with-junk", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_DEFAULT),
+ setup_coding_test, do_coding_test_gzip_with_junk, teardown_coding_test);
+ g_test_add ("/coding/message/gzip/bad-server", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_DEFAULT),
+ setup_coding_test, do_coding_test_gzip_bad_server, teardown_coding_test);
+ g_test_add ("/coding/message/deflate", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_DEFAULT),
+ setup_coding_test, do_coding_test_deflate, teardown_coding_test);
+ g_test_add ("/coding/message/deflate/with-junk", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_DEFAULT),
+ setup_coding_test, do_coding_test_deflate_with_junk, teardown_coding_test);
+ g_test_add ("/coding/message/deflate/bad-server", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_DEFAULT),
+ setup_coding_test, do_coding_test_deflate_bad_server, teardown_coding_test);
+ g_test_add ("/coding/message/deflate-raw", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_DEFAULT),
+ setup_coding_test, do_coding_test_deflate_raw, teardown_coding_test);
+ g_test_add ("/coding/message/deflate-raw/bad-server", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_DEFAULT),
+ setup_coding_test, do_coding_test_deflate_raw_bad_server, teardown_coding_test);
+
+ g_test_add ("/coding/request/plain", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_NO_DECODER | CODING_TEST_REQUEST_API),
+ setup_coding_test, do_coding_req_test_plain, teardown_coding_test);
+ g_test_add ("/coding/request/gzip", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_REQUEST_API),
+ setup_coding_test, do_coding_req_test_gzip, teardown_coding_test);
+ g_test_add ("/coding/request/gzip/with-junk", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_REQUEST_API),
+ setup_coding_test, do_coding_req_test_gzip_with_junk, teardown_coding_test);
+ g_test_add ("/coding/request/gzip/bad-server", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_REQUEST_API),
+ setup_coding_test, do_coding_req_test_gzip_bad_server, teardown_coding_test);
+ g_test_add ("/coding/request/deflate", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_REQUEST_API),
+ setup_coding_test, do_coding_req_test_deflate, teardown_coding_test);
+ g_test_add ("/coding/request/deflate/with-junk", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_REQUEST_API),
+ setup_coding_test, do_coding_req_test_deflate_with_junk, teardown_coding_test);
+ g_test_add ("/coding/request/deflate/bad-server", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_REQUEST_API),
+ setup_coding_test, do_coding_req_test_deflate_bad_server, teardown_coding_test);
+ g_test_add ("/coding/request/deflate-raw", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_REQUEST_API),
+ setup_coding_test, do_coding_req_test_deflate_raw, teardown_coding_test);
+ g_test_add ("/coding/request/deflate-raw/bad-server", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_REQUEST_API),
+ setup_coding_test, do_coding_req_test_deflate_raw_bad_server, teardown_coding_test);
+
+ g_test_add ("/coding/message/empty", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_EMPTY),
+ setup_coding_test, do_coding_msg_empty_test, teardown_coding_test);
+ g_test_add ("/coding/request/empty", CodingTestData,
+ GINT_TO_POINTER (CODING_TEST_REQUEST_API | CODING_TEST_EMPTY),
+ setup_coding_test, do_coding_req_empty_test, teardown_coding_test);
+
+ ret = g_test_run ();
soup_uri_free (base_uri);
soup_test_server_quit_unref (server);
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/connection-test.c b/tests/connection-test.c
index ddf0c988..8f8c74be 100644
--- a/tests/connection-test.c
+++ b/tests/connection-test.c
@@ -5,6 +5,8 @@
#include "test-utils.h"
+#include <gio/gnetworking.h>
+
SoupServer *server;
SoupURI *base_uri;
GMutex server_mutex;
@@ -164,7 +166,7 @@ do_content_length_framing_test (void)
SoupURI *request_uri;
goffset declared_length;
- debug_printf (1, "\nInvalid Content-Length framing tests\n");
+ g_test_bug ("611481");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
@@ -172,21 +174,14 @@ do_content_length_framing_test (void)
request_uri = soup_uri_new_with_base (base_uri, "/content-length/long");
msg = soup_message_new_from_uri ("GET", request_uri);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- } else {
- declared_length = soup_message_headers_get_content_length (msg->response_headers);
- debug_printf (2, " Content-Length: %lu, body: %s\n",
- (gulong)declared_length, msg->response_body->data);
- if (msg->response_body->length >= declared_length) {
- debug_printf (1, " Body length %lu >= declared length %lu\n",
- (gulong)msg->response_body->length,
- (gulong)declared_length);
- errors++;
- }
- }
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
+ declared_length = soup_message_headers_get_content_length (msg->response_headers);
+ debug_printf (2, " Content-Length: %lu, body: %s\n",
+ (gulong)declared_length, msg->response_body->data);
+ g_assert_cmpint (msg->response_body->length, <, declared_length);
+
soup_uri_free (request_uri);
g_object_unref (msg);
@@ -194,21 +189,12 @@ do_content_length_framing_test (void)
request_uri = soup_uri_new_with_base (base_uri, "/content-length/noclose");
msg = soup_message_new_from_uri ("GET", request_uri);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- } else {
- declared_length = soup_message_headers_get_content_length (msg->response_headers);
- debug_printf (2, " Content-Length: %lu, body: %s\n",
- (gulong)declared_length, msg->response_body->data);
- if (msg->response_body->length != declared_length) {
- debug_printf (1, " Body length %lu != declared length %lu\n",
- (gulong)msg->response_body->length,
- (gulong)declared_length);
- errors++;
- }
- }
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
+ declared_length = soup_message_headers_get_content_length (msg->response_headers);
+ g_assert_cmpint (msg->response_body->length, ==, declared_length);
+
soup_uri_free (request_uri);
g_object_unref (msg);
@@ -232,12 +218,11 @@ request_started_socket_collector (SoupSession *session, SoupMessage *msg,
* two consecutive sockets.
*/
sockets[i] = g_object_ref (socket);
- return;
+ break;
}
}
- debug_printf (1, " socket queue overflowed!\n");
- errors++;
+ soup_test_assert (i < 4, "socket queue overflowed");
}
static void
@@ -257,14 +242,10 @@ do_timeout_test_for_session (SoupSession *session)
msg = soup_message_new_from_uri ("GET", timeout_uri);
soup_uri_free (timeout_uri);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
if (sockets[1]) {
- debug_printf (1, " Message was retried??\n");
- errors++;
+ soup_test_assert (sockets[1] == NULL, "Message was retried");
sockets[1] = sockets[2] = sockets[3] = NULL;
}
g_object_unref (msg);
@@ -272,24 +253,16 @@ do_timeout_test_for_session (SoupSession *session)
debug_printf (1, " Second message\n");
msg = soup_message_new_from_uri ("GET", base_uri);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
- if (sockets[1] != sockets[0]) {
- debug_printf (1, " Message was not retried on existing connection\n");
- errors++;
- } else if (!sockets[2]) {
- debug_printf (1, " Message was not retried after disconnect\n");
- errors++;
- } else if (sockets[2] == sockets[1]) {
- debug_printf (1, " Message was retried on closed connection??\n");
- errors++;
- } else if (sockets[3]) {
- debug_printf (1, " Message was retried again??\n");
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
+ soup_test_assert (sockets[1] == sockets[0],
+ "Message was not retried on existing connection");
+ soup_test_assert (sockets[2] != NULL,
+ "Message was not retried after disconnect");
+ soup_test_assert (sockets[2] != sockets[1],
+ "Message was retried on closed connection");
+ soup_test_assert (sockets[3] == NULL,
+ "Message was retried again");
g_object_unref (msg);
for (i = 0; sockets[i]; i++)
@@ -299,7 +272,6 @@ do_timeout_test_for_session (SoupSession *session)
static void
do_timeout_req_test_for_session (SoupSession *session)
{
- SoupRequester *requester;
SoupRequest *req;
SoupMessage *msg;
GInputStream *stream;
@@ -308,94 +280,67 @@ do_timeout_req_test_for_session (SoupSession *session)
GError *error = NULL;
int i;
- requester = soup_requester_new ();
- soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
- g_object_unref (requester);
-
g_signal_connect (session, "request-started",
G_CALLBACK (request_started_socket_collector),
&sockets);
debug_printf (1, " First request\n");
timeout_uri = soup_uri_new_with_base (base_uri, "/timeout-persistent");
- req = soup_requester_request_uri (requester, timeout_uri, NULL);
+ req = soup_session_request_uri (session, timeout_uri, NULL);
soup_uri_free (timeout_uri);
- if (SOUP_IS_SESSION_SYNC (session))
- stream = soup_request_send (req, NULL, &error);
- else
- stream = soup_test_request_send_async_as_sync (req, NULL, &error);
-
- if (!stream) {
- debug_printf (1, " Unexpected error on send: %s\n",
- error->message);
- errors++;
+ stream = soup_test_request_send (req, NULL, 0, &error);
+ if (error) {
+ g_assert_no_error (error);
g_clear_error (&error);
} else {
- if (SOUP_IS_SESSION_SYNC (session))
- g_input_stream_close (stream, NULL, &error);
- else
- soup_test_stream_close_async_as_sync (stream, NULL, &error);
+ soup_test_request_read_all (req, stream, NULL, &error);
+ if (error) {
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ }
+
+ soup_test_request_close_stream (req, stream, NULL, &error);
if (error) {
- debug_printf (1, " Unexpected error on close: %s\n",
- error->message);
- errors++;
+ g_assert_no_error (error);
g_clear_error (&error);
}
+ g_object_unref (stream);
}
if (sockets[1]) {
- debug_printf (1, " Message was retried??\n");
- errors++;
+ soup_test_assert (sockets[1] == NULL, "Message was retried");
sockets[1] = sockets[2] = sockets[3] = NULL;
}
g_object_unref (req);
debug_printf (1, " Second request\n");
- req = soup_requester_request_uri (requester, base_uri, NULL);
+ req = soup_session_request_uri (session, base_uri, NULL);
- if (SOUP_IS_SESSION_SYNC (session))
- stream = soup_request_send (req, NULL, &error);
- else
- stream = soup_test_request_send_async_as_sync (req, NULL, &error);
-
- if (!stream) {
- debug_printf (1, " Unexpected error on send: %s\n",
- error->message);
- errors++;
+ stream = soup_test_request_send (req, NULL, 0, &error);
+ if (error) {
+ g_assert_no_error (error);
g_clear_error (&error);
} else {
- if (SOUP_IS_SESSION_SYNC (session))
- g_input_stream_close (stream, NULL, &error);
- else
- soup_test_stream_close_async_as_sync (stream, NULL, &error);
+ soup_test_request_close_stream (req, stream, NULL, &error);
if (error) {
- debug_printf (1, " Unexpected error on close: %s\n",
- error->message);
- errors++;
+ g_assert_no_error (error);
g_clear_error (&error);
}
+ g_object_unref (stream);
}
msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
- if (sockets[1] != sockets[0]) {
- debug_printf (1, " Message was not retried on existing connection\n");
- errors++;
- } else if (!sockets[2]) {
- debug_printf (1, " Message was not retried after disconnect\n");
- errors++;
- } else if (sockets[2] == sockets[1]) {
- debug_printf (1, " Message was retried on closed connection??\n");
- errors++;
- } else if (sockets[3]) {
- debug_printf (1, " Message was retried again??\n");
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
+ soup_test_assert (sockets[1] == sockets[0],
+ "Message was not retried on existing connection");
+ soup_test_assert (sockets[2] != NULL,
+ "Message was not retried after disconnect");
+ soup_test_assert (sockets[2] != sockets[1],
+ "Message was retried on closed connection");
+ soup_test_assert (sockets[3] == NULL,
+ "Message was retried again");
g_object_unref (msg);
g_object_unref (req);
@@ -408,13 +353,14 @@ do_persistent_connection_timeout_test (void)
{
SoupSession *session;
- debug_printf (1, "\nUnexpected timing out of persistent connections\n");
+ g_test_bug ("631525");
debug_printf (1, " Async session, message API\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
do_timeout_test_for_session (session);
soup_test_session_abort_unref (session);
+ debug_printf (1, " Async session, request API\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
@@ -426,6 +372,7 @@ do_persistent_connection_timeout_test (void)
do_timeout_test_for_session (session);
soup_test_session_abort_unref (session);
+ debug_printf (1, " Sync session, request API\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
do_timeout_req_test_for_session (session);
soup_test_session_abort_unref (session);
@@ -491,26 +438,18 @@ do_max_conns_test_for_session (SoupSession *session)
}
g_main_loop_run (max_conns_loop);
- if (msgs_done != MAX_CONNS) {
- debug_printf (1, " Queued %d connections out of max %d?",
- msgs_done, MAX_CONNS);
- errors++;
- }
+ g_assert_cmpint (msgs_done, ==, MAX_CONNS);
g_signal_handlers_disconnect_by_func (session, max_conns_request_started, NULL);
msgs_done = 0;
g_idle_add (idle_start_server, NULL);
+ if (quit_loop_timeout)
+ g_source_remove (quit_loop_timeout);
quit_loop_timeout = g_timeout_add (1000, quit_loop, NULL);
g_main_loop_run (max_conns_loop);
- for (i = 0; i < TEST_CONNS; i++) {
- if (!SOUP_STATUS_IS_SUCCESSFUL (msgs[i]->status_code)) {
- debug_printf (1, " Message %d failed? %d %s\n",
- i, msgs[i]->status_code,
- msgs[i]->reason_phrase ? msgs[i]->reason_phrase : "-");
- errors++;
- }
- }
+ for (i = 0; i < TEST_CONNS; i++)
+ soup_test_assert_message_status (msgs[i], SOUP_STATUS_OK);
if (msgs_done != TEST_CONNS) {
/* Clean up so we don't get a spurious "Leaked
@@ -522,8 +461,10 @@ do_max_conns_test_for_session (SoupSession *session)
}
g_main_loop_unref (max_conns_loop);
- if (quit_loop_timeout)
+ if (quit_loop_timeout) {
g_source_remove (quit_loop_timeout);
+ quit_loop_timeout = 0;
+ }
for (i = 0; i < TEST_CONNS; i++)
g_object_unref (msgs[i]);
@@ -534,7 +475,7 @@ do_max_conns_test (void)
{
SoupSession *session;
- debug_printf (1, "\nExceeding max-conns\n");
+ g_test_bug ("634422");
debug_printf (1, " Async session\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
@@ -551,8 +492,6 @@ do_max_conns_test (void)
soup_test_session_abort_unref (session);
}
-GMainLoop *loop;
-
static void
np_request_started (SoupSession *session, SoupMessage *msg,
SoupSocket *socket, gpointer user_data)
@@ -568,10 +507,14 @@ np_request_unqueued (SoupSession *session, SoupMessage *msg,
{
SoupSocket *socket = *(SoupSocket **)user_data;
- if (soup_socket_is_connected (socket)) {
- debug_printf (1, " socket is still connected\n");
- errors++;
- }
+ g_assert_false (soup_socket_is_connected (socket));
+}
+
+static void
+np_request_finished (SoupSession *session, SoupMessage *msg,
+ gpointer user_data)
+{
+ GMainLoop *loop = user_data;
g_main_loop_quit (loop);
}
@@ -581,6 +524,7 @@ do_non_persistent_test_for_session (SoupSession *session)
{
SoupMessage *msg;
SoupSocket *socket = NULL;
+ GMainLoop *loop;
loop = g_main_loop_new (NULL, FALSE);
@@ -594,15 +538,15 @@ do_non_persistent_test_for_session (SoupSession *session)
msg = soup_message_new_from_uri ("GET", base_uri);
soup_message_headers_append (msg->request_headers, "Connection", "close");
g_object_ref (msg);
- soup_session_queue_message (session, msg, NULL, NULL);
+ soup_session_queue_message (session, msg,
+ np_request_finished, loop);
g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
g_object_unref (msg);
+ g_object_unref (socket);
}
static void
@@ -610,7 +554,7 @@ do_non_persistent_connection_test (void)
{
SoupSession *session;
- debug_printf (1, "\nNon-persistent connections are closed immediately\n");
+ g_test_bug ("578990");
debug_printf (1, " Async session\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
@@ -637,14 +581,9 @@ do_non_idempotent_test_for_session (SoupSession *session)
debug_printf (2, " GET\n");
msg = soup_message_new_from_uri ("GET", base_uri);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
if (sockets[1]) {
- debug_printf (1, " Message was retried??\n");
- errors++;
+ soup_test_assert (sockets[1] == NULL, "Message was retried");
sockets[1] = sockets[2] = sockets[3] = NULL;
}
g_object_unref (msg);
@@ -652,19 +591,12 @@ do_non_idempotent_test_for_session (SoupSession *session)
debug_printf (2, " POST\n");
msg = soup_message_new_from_uri ("POST", base_uri);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
- if (sockets[1] == sockets[0]) {
- debug_printf (1, " Message was sent on existing connection!\n");
- errors++;
- }
- if (sockets[2]) {
- debug_printf (1, " Too many connections used...\n");
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ soup_test_assert (sockets[1] != sockets[0],
+ "Message was sent on existing connection");
+ soup_test_assert (sockets[2] == NULL,
+ "Too many connections used");
+
g_object_unref (msg);
for (i = 0; sockets[i]; i++)
@@ -676,8 +608,6 @@ do_non_idempotent_connection_test (void)
{
SoupSession *session;
- debug_printf (1, "\nNon-idempotent methods are always sent on new connections\n");
-
debug_printf (1, " Async session\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
do_non_idempotent_test_for_session (session);
@@ -689,25 +619,254 @@ do_non_idempotent_connection_test (void)
soup_test_session_abort_unref (session);
}
+#define HTTP_SERVER "http://127.0.0.1:47524"
+#define HTTPS_SERVER "https://127.0.0.1:47525"
+#define HTTP_PROXY "http://127.0.0.1:47526"
+
+static SoupConnectionState state_transitions[] = {
+ /* NEW -> */ SOUP_CONNECTION_CONNECTING,
+ /* CONNECTING -> */ SOUP_CONNECTION_IN_USE,
+ /* IDLE -> */ SOUP_CONNECTION_DISCONNECTED,
+ /* IN_USE -> */ SOUP_CONNECTION_IDLE,
+
+ /* REMOTE_DISCONNECTED */ -1,
+ /* DISCONNECTED */ -1,
+};
+
+static const char *state_names[] = {
+ "NEW", "CONNECTING", "IDLE", "IN_USE",
+ "REMOTE_DISCONNECTED", "DISCONNECTED"
+};
+
+static void
+connection_state_changed (GObject *object, GParamSpec *param,
+ gpointer user_data)
+{
+ SoupConnectionState *state = user_data;
+ SoupConnectionState new_state;
+
+ g_object_get (object, "state", &new_state, NULL);
+ debug_printf (2, " %s -> %s\n",
+ state_names[*state], state_names[new_state]);
+ soup_test_assert (state_transitions[*state] == new_state,
+ "Unexpected transition: %s -> %s\n",
+ state_names[*state], state_names[new_state]);
+ *state = new_state;
+}
+
+static void
+connection_created (SoupSession *session, GObject *conn,
+ gpointer user_data)
+{
+ SoupConnectionState *state = user_data;
+
+ g_object_get (conn, "state", state, NULL);
+ g_assert_cmpint (*state, ==, SOUP_CONNECTION_NEW);
+
+ g_signal_connect (conn, "notify::state",
+ G_CALLBACK (connection_state_changed),
+ state);
+}
+
+static void
+do_one_connection_state_test (SoupSession *session, const char *uri)
+{
+ SoupMessage *msg;
+
+ msg = soup_message_new ("GET", uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_object_unref (msg);
+ soup_session_abort (session);
+}
+
+static void
+do_connection_state_test_for_session (SoupSession *session)
+{
+ SoupConnectionState state;
+ SoupURI *proxy_uri;
+
+ g_signal_connect (session, "connection-created",
+ G_CALLBACK (connection_created),
+ &state);
+
+ debug_printf (1, " http\n");
+ do_one_connection_state_test (session, HTTP_SERVER);
+
+ if (tls_available) {
+ debug_printf (1, " https\n");
+ do_one_connection_state_test (session, HTTPS_SERVER);
+ } else
+ debug_printf (1, " https -- SKIPPING\n");
+
+ proxy_uri = soup_uri_new (HTTP_PROXY);
+ g_object_set (G_OBJECT (session),
+ SOUP_SESSION_PROXY_URI, proxy_uri,
+ NULL);
+ soup_uri_free (proxy_uri);
+
+ debug_printf (1, " http with proxy\n");
+ do_one_connection_state_test (session, HTTP_SERVER);
+
+ if (tls_available) {
+ debug_printf (1, " https with proxy\n");
+ do_one_connection_state_test (session, HTTPS_SERVER);
+ } else
+ debug_printf (1, " https with proxy -- SKIPPING\n");
+}
+
+static void
+do_connection_state_test (void)
+{
+ SoupSession *session;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ debug_printf (1, " Async session\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ do_connection_state_test_for_session (session);
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " Sync session\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+ do_connection_state_test_for_session (session);
+ soup_test_session_abort_unref (session);
+}
+
+
+static const char *event_names[] = {
+ "RESOLVING", "RESOLVED", "CONNECTING", "CONNECTED",
+ "PROXY_NEGOTIATING", "PROXY_NEGOTIATED",
+ "TLS_HANDSHAKING", "TLS_HANDSHAKED", "COMPLETE"
+};
+
+static const char event_abbrevs[] = {
+ 'r', 'R', 'c', 'C', 'p', 'P', 't', 'T', 'x', '\0'
+};
+
+static const char *
+event_name_from_abbrev (char abbrev)
+{
+ int evt;
+
+ for (evt = 0; event_abbrevs[evt]; evt++) {
+ if (event_abbrevs[evt] == abbrev)
+ return event_names[evt];
+ }
+ return "???";
+}
+
+static void
+network_event (SoupMessage *msg, GSocketClientEvent event,
+ GIOStream *connection, gpointer user_data)
+{
+ const char **events = user_data;
+
+ debug_printf (2, " %s\n", event_name_from_abbrev (**events));
+ soup_test_assert (**events == event_abbrevs[event],
+ "Unexpected event: %s (expected %s)\n",
+ event_names[event],
+ event_name_from_abbrev (**events));
+ *events = *events + 1;
+}
+
+static void
+do_one_connection_event_test (SoupSession *session, const char *uri,
+ const char *events)
+{
+ SoupMessage *msg;
+
+ msg = soup_message_new ("GET", uri);
+ g_signal_connect (msg, "network-event",
+ G_CALLBACK (network_event),
+ &events);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ while (*events) {
+ soup_test_assert (!*events,
+ "Expected %s",
+ event_name_from_abbrev (*events));
+ events++;
+ }
+
+ g_object_unref (msg);
+ soup_session_abort (session);
+}
+
+static void
+do_connection_event_test_for_session (SoupSession *session)
+{
+ SoupURI *proxy_uri;
+
+ debug_printf (1, " http\n");
+ do_one_connection_event_test (session, HTTP_SERVER, "rRcCx");
+
+ if (tls_available) {
+ debug_printf (1, " https\n");
+ do_one_connection_event_test (session, HTTPS_SERVER, "rRcCtTx");
+ } else
+ debug_printf (1, " https -- SKIPPING\n");
+
+ proxy_uri = soup_uri_new (HTTP_PROXY);
+ g_object_set (G_OBJECT (session),
+ SOUP_SESSION_PROXY_URI, proxy_uri,
+ NULL);
+ soup_uri_free (proxy_uri);
+
+ debug_printf (1, " http with proxy\n");
+ do_one_connection_event_test (session, HTTP_SERVER, "rRcCx");
+
+ if (tls_available) {
+ debug_printf (1, " https with proxy\n");
+ do_one_connection_event_test (session, HTTPS_SERVER, "rRcCpPtTx");
+ } else
+ debug_printf (1, " https with proxy -- SKIPPING\n");
+}
+
+static void
+do_connection_event_test (void)
+{
+ SoupSession *session;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ debug_printf (1, " Async session\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ do_connection_event_test_for_session (session);
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " Sync session\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+ do_connection_event_test_for_session (session);
+ soup_test_session_abort_unref (session);
+}
+
int
main (int argc, char **argv)
{
+ int ret;
+
test_init (argc, argv, NULL);
+ apache_init ();
server = soup_test_server_new (TRUE);
soup_server_add_handler (server, NULL, server_callback, "http", NULL);
base_uri = soup_uri_new ("http://127.0.0.1/");
soup_uri_set_port (base_uri, soup_server_get_port (server));
- do_content_length_framing_test ();
- do_persistent_connection_timeout_test ();
- do_max_conns_test ();
- do_non_persistent_connection_test ();
- do_non_idempotent_connection_test ();
+ g_test_add_func ("/connection/content-length-framing", do_content_length_framing_test);
+ g_test_add_func ("/connection/persistent-connection-timeout", do_persistent_connection_timeout_test);
+ g_test_add_func ("/connection/max-conns", do_max_conns_test);
+ g_test_add_func ("/connection/non-persistent", do_non_persistent_connection_test);
+ g_test_add_func ("/connection/non-idempotent", do_non_idempotent_connection_test);
+ g_test_add_func ("/connection/state", do_connection_state_test);
+ g_test_add_func ("/connection/event", do_connection_event_test);
+
+ ret = g_test_run ();
soup_uri_free (base_uri);
soup_test_server_quit_unref (server);
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/context-test.c b/tests/context-test.c
index 97cd2c0c..727c63ba 100644
--- a/tests/context-test.c
+++ b/tests/context-test.c
@@ -84,13 +84,9 @@ static GMutex test1_mutex;
static GMainLoop *test1_loop;
static void
-do_test1 (int n, gboolean use_thread_context)
+do_test1 (gconstpointer data)
{
- debug_printf (1, "\nTest %d: blocking the main thread does not block other thread\n", n);
- if (use_thread_context)
- debug_printf (1, "(Using g_main_context_push_thread_default())\n");
- else
- debug_printf (1, "(Using SOUP_SESSION_ASYNC_CONTEXT)\n");
+ gboolean use_thread_context = GPOINTER_TO_INT (data);
test1_loop = g_main_loop_new (NULL, FALSE);
g_idle_add (idle_start_test1_thread, GINT_TO_POINTER (use_thread_context));
@@ -111,9 +107,8 @@ idle_start_test1_thread (gpointer use_thread_context)
if (g_cond_wait_until (&test1_cond, &test1_mutex, time))
g_thread_join (thread);
else {
- debug_printf (1, " timeout!\n");
+ soup_test_assert (FALSE, "timeout");
g_thread_unref (thread);
- errors++;
}
g_mutex_unlock (&test1_mutex);
@@ -158,11 +153,7 @@ test1_thread (gpointer use_thread_context)
debug_printf (1, " send_message\n");
msg = soup_message_new ("GET", uri);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " unexpected status: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
g_object_unref (msg);
debug_printf (1, " queue_message\n");
@@ -172,11 +163,7 @@ test1_thread (gpointer use_thread_context)
soup_session_queue_message (session, msg, test1_finished, loop);
g_main_loop_run (loop);
g_main_loop_unref (loop);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " unexpected status: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
g_object_unref (msg);
soup_test_session_abort_unref (session);
@@ -196,20 +183,15 @@ test1_thread (gpointer use_thread_context)
static gboolean idle_test2_fail (gpointer user_data);
static void
-do_test2 (int n, gboolean use_thread_context)
+do_test2 (gconstpointer data)
{
+ gboolean use_thread_context = GPOINTER_TO_INT (data);
guint idle;
GMainContext *async_context;
SoupSession *session;
char *uri;
SoupMessage *msg;
- debug_printf (1, "\nTest %d: a session with its own context is independent of the main loop.\n", n);
- if (use_thread_context)
- debug_printf (1, "(Using g_main_context_push_thread_default())\n");
- else
- debug_printf (1, "(Using SOUP_SESSION_ASYNC_CONTEXT)\n");
-
idle = g_idle_add_full (G_PRIORITY_HIGH, idle_test2_fail, NULL, NULL);
async_context = g_main_context_new ();
@@ -230,11 +212,7 @@ do_test2 (int n, gboolean use_thread_context)
debug_printf (1, " send_message\n");
msg = soup_message_new ("GET", uri);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " unexpected status: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
g_object_unref (msg);
soup_test_session_abort_unref (session);
@@ -249,8 +227,7 @@ do_test2 (int n, gboolean use_thread_context)
static gboolean
idle_test2_fail (gpointer user_data)
{
- debug_printf (1, " idle ran!\n");
- errors++;
+ soup_test_assert (FALSE, "idle ran");
return FALSE;
}
@@ -279,15 +256,13 @@ multi_msg_finished (SoupSession *session, SoupMessage *msg, gpointer user_data)
}
static void
-do_multicontext_test (int n)
+do_multicontext_test (void)
{
SoupSession *session;
SoupMessage *msg1, *msg2;
GMainContext *context1, *context2;
GMainLoop *loop1, *loop2;
- debug_printf (1, "\nTest %d: Using multiple async contexts\n", n);
-
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
@@ -318,36 +293,26 @@ do_multicontext_test (int n)
g_main_loop_run (loop1);
g_main_context_pop_thread_default (context1);
- if (!g_object_get_data (G_OBJECT (msg1), "started")) {
- debug_printf (1, " msg1 not started??\n");
- errors++;
- }
- if (g_object_get_data (G_OBJECT (msg2), "started")) {
- debug_printf (1, " msg2 started while loop1 was running!\n");
- errors++;
- }
+ if (!g_object_get_data (G_OBJECT (msg1), "started"))
+ soup_test_assert (FALSE, "msg1 not started");
+ if (g_object_get_data (G_OBJECT (msg2), "started"))
+ soup_test_assert (FALSE, "msg2 started while loop1 was running");
g_main_context_push_thread_default (context2);
g_main_loop_run (loop2);
g_main_context_pop_thread_default (context2);
- if (g_object_get_data (G_OBJECT (msg1), "finished")) {
- debug_printf (1, " msg1 finished while loop2 was running!\n");
- errors++;
- }
- if (!g_object_get_data (G_OBJECT (msg2), "finished")) {
- debug_printf (1, " msg2 not finished??\n");
- errors++;
- }
+ if (g_object_get_data (G_OBJECT (msg1), "finished"))
+ soup_test_assert (FALSE, "msg1 finished while loop2 was running");
+ if (!g_object_get_data (G_OBJECT (msg2), "finished"))
+ soup_test_assert (FALSE, "msg2 not finished");
g_main_context_push_thread_default (context1);
g_main_loop_run (loop1);
g_main_context_pop_thread_default (context1);
- if (!g_object_get_data (G_OBJECT (msg1), "finished")) {
- debug_printf (1, " msg1 not finished??\n");
- errors++;
- }
+ if (!g_object_get_data (G_OBJECT (msg1), "finished"))
+ soup_test_assert (FALSE, "msg1 not finished");
g_object_unref (msg1);
g_object_unref (msg2);
@@ -364,6 +329,7 @@ int
main (int argc, char **argv)
{
SoupServer *server;
+ int ret;
test_init (argc, argv, NULL);
@@ -372,15 +338,17 @@ main (int argc, char **argv)
base_uri = g_strdup_printf ("http://127.0.0.1:%u/",
soup_server_get_port (server));
- do_test1 (1, FALSE);
- do_test1 (2, TRUE);
- do_test2 (3, FALSE);
- do_test2 (4, TRUE);
- do_multicontext_test (5);
+ g_test_add_data_func ("/context/blocking/explicit", GINT_TO_POINTER (FALSE), do_test1);
+ g_test_add_data_func ("/context/blocking/thread-default", GINT_TO_POINTER (TRUE), do_test1);
+ g_test_add_data_func ("/context/nested/explicit", GINT_TO_POINTER (FALSE), do_test2);
+ g_test_add_data_func ("/context/nested/thread-default", GINT_TO_POINTER (TRUE), do_test2);
+ g_test_add_func ("/context/multiple", do_multicontext_test);
+
+ ret = g_test_run ();
g_free (base_uri);
soup_test_server_quit_unref (server);
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/continue-test.c b/tests/continue-test.c
index fa9ef809..b6a5805f 100644
--- a/tests/continue-test.c
+++ b/tests/continue-test.c
@@ -59,13 +59,6 @@ do_message (const char *path, gboolean long_body,
const char *expected_event;
char *actual_event;
int expected_status, actual_status;
- static int count = 1;
-
- debug_printf (1, "%d. /%s, %s body, %sExpect, %s password\n",
- count++, path,
- long_body ? "long" : "short",
- expect_continue ? "" : "no ",
- auth ? "with" : "without");
uri = g_strdup_printf ("http://%s127.0.0.1:%d/%s",
auth ? "user:pass@" : "",
@@ -106,17 +99,13 @@ do_message (const char *path, gboolean long_body,
while ((expected_event = va_arg (ap, const char *))) {
if (!events) {
- actual_event = g_strdup ("");
- debug_printf (1, " Expected '%s', got end of list\n",
- expected_event);
- errors++;
+ soup_test_assert (events != NULL,
+ "Expected '%s', got end of list",
+ expected_event);
+ continue;
} else {
actual_event = events->data;
- if (strcmp (expected_event, actual_event) != 0) {
- debug_printf (1, " Expected '%s', got '%s'\n",
- expected_event, actual_event);
- errors++;
- }
+ g_assert_cmpstr (expected_event, ==, actual_event);
events = g_slist_delete_link (events, events);
}
@@ -134,10 +123,10 @@ do_message (const char *path, gboolean long_body,
if (expected_status != -1 && actual_status != -1 &&
expected_status != actual_status) {
- debug_printf (1, " Expected status '%s', got '%s'\n",
- soup_status_get_phrase (expected_status),
- soup_status_get_phrase (actual_status));
- errors++;
+ soup_test_assert (expected_status == actual_status,
+ "Expected status '%s', got '%s'",
+ soup_status_get_phrase (expected_status),
+ soup_status_get_phrase (actual_status));
}
g_free (actual_event);
@@ -145,8 +134,8 @@ do_message (const char *path, gboolean long_body,
va_end (ap);
while (events) {
actual_event = events->data;
- debug_printf (1, " Expected to be done, got '%s'\n", actual_event);
- errors++;
+ soup_test_assert (events == NULL,
+ "Expected to be done, got '%s'", actual_event);
events = g_slist_delete_link (events, events);
if (!strcmp (actual_event, "server-wrote_headers") ||
@@ -157,7 +146,7 @@ do_message (const char *path, gboolean long_body,
}
static void
-run_tests (void)
+do_test_unauth_short_noexpect_nopass (void)
{
do_message ("unauth", FALSE, FALSE, FALSE,
"client-wrote_headers",
@@ -171,6 +160,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+
+static void
+do_test_unauth_long_noexpect_nopass (void)
+{
do_message ("unauth", TRUE, FALSE, FALSE,
"client-wrote_headers",
"client-wrote_body",
@@ -183,6 +177,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+
+static void
+do_test_unauth_short_expect_nopass (void)
+{
do_message ("unauth", FALSE, TRUE, FALSE,
"client-wrote_headers",
"server-got_headers",
@@ -197,6 +196,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+
+static void
+do_test_unauth_long_expect_nopass (void)
+{
do_message ("unauth", TRUE, TRUE, FALSE,
"client-wrote_headers",
"server-got_headers",
@@ -207,7 +211,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+static void
+do_test_auth_short_noexpect_nopass (void)
+{
do_message ("auth", FALSE, FALSE, FALSE,
"client-wrote_headers",
"client-wrote_body",
@@ -220,6 +228,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+
+static void
+do_test_auth_long_noexpect_nopass (void)
+{
do_message ("auth", TRUE, FALSE, FALSE,
"client-wrote_headers",
"client-wrote_body",
@@ -232,6 +245,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+
+static void
+do_test_auth_short_expect_nopass (void)
+{
do_message ("auth", FALSE, TRUE, FALSE,
"client-wrote_headers",
"server-got_headers",
@@ -242,6 +260,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+
+static void
+do_test_auth_long_expect_nopass (void)
+{
do_message ("auth", TRUE, TRUE, FALSE,
"client-wrote_headers",
"server-got_headers",
@@ -252,7 +275,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+static void
+do_test_auth_short_noexpect_pass (void)
+{
do_message ("auth", FALSE, FALSE, TRUE,
"client-wrote_headers",
"client-wrote_body",
@@ -274,6 +301,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+
+static void
+do_test_auth_long_noexpect_pass (void)
+{
do_message ("auth", TRUE, FALSE, TRUE,
"client-wrote_headers",
"client-wrote_body",
@@ -295,6 +327,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+
+static void
+do_test_auth_short_expect_pass (void)
+{
do_message ("auth", FALSE, TRUE, TRUE,
"client-wrote_headers",
"server-got_headers",
@@ -316,6 +353,11 @@ run_tests (void)
"client-got_body",
"client-finished",
NULL);
+}
+
+static void
+do_test_auth_long_expect_pass (void)
+{
do_message ("auth", TRUE, TRUE, TRUE,
"client-wrote_headers",
"server-got_headers",
@@ -434,15 +476,30 @@ int
main (int argc, char **argv)
{
SoupServer *server;
+ int ret;
test_init (argc, argv, NULL);
server = setup_server ();
port = soup_server_get_port (server);
- run_tests ();
+ g_test_add_func ("/continue/unauth_short_noexpect_nopass", do_test_unauth_short_noexpect_nopass);
+ g_test_add_func ("/continue/unauth_long_noexpect_nopass", do_test_unauth_long_noexpect_nopass);
+ g_test_add_func ("/continue/unauth_short_expect_nopass", do_test_unauth_short_expect_nopass);
+ g_test_add_func ("/continue/unauth_long_expect_nopass", do_test_unauth_long_expect_nopass);
+ g_test_add_func ("/continue/auth_short_noexpect_nopass", do_test_auth_short_noexpect_nopass);
+ g_test_add_func ("/continue/auth_long_noexpect_nopass", do_test_auth_long_noexpect_nopass);
+ g_test_add_func ("/continue/auth_short_expect_nopass", do_test_auth_short_expect_nopass);
+ g_test_add_func ("/continue/auth_long_expect_nopass", do_test_auth_long_expect_nopass);
+ g_test_add_func ("/continue/auth_short_noexpect_pass", do_test_auth_short_noexpect_pass);
+ g_test_add_func ("/continue/auth_long_noexpect_pass", do_test_auth_long_noexpect_pass);
+ g_test_add_func ("/continue/auth_short_expect_pass", do_test_auth_short_expect_pass);
+ g_test_add_func ("/continue/auth_long_expect_pass", do_test_auth_long_expect_pass);
+
+ ret = g_test_run ();
soup_test_server_quit_unref (server);
test_cleanup ();
- return errors != 0;
+
+ return ret;
}
diff --git a/tests/cookies-test.c b/tests/cookies-test.c
index 58f8052e..12529d81 100644
--- a/tests/cookies-test.c
+++ b/tests/cookies-test.c
@@ -55,8 +55,6 @@ do_cookies_accept_policy_test (void)
GSList *l, *p;
int i;
- debug_printf (1, "SoupCookieJarAcceptPolicy test\n");
-
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
soup_session_add_feature_by_type (session, SOUP_TYPE_COOKIE_JAR);
jar = SOUP_COOKIE_JAR (soup_session_get_feature (session, SOUP_TYPE_COOKIE_JAR));
@@ -83,13 +81,7 @@ do_cookies_accept_policy_test (void)
g_object_unref (msg);
l = soup_cookie_jar_all_cookies (jar);
- if (g_slist_length (l) < validResults[i].n_cookies) {
- debug_printf (1, " accepted less cookies than it should have\n");
- errors++;
- } else if (g_slist_length (l) > validResults[i].n_cookies) {
- debug_printf (1, " accepted more cookies than it should have\n");
- errors++;
- }
+ g_assert_cmpint (g_slist_length (l), ==, validResults[i].n_cookies);
for (p = l; p; p = p->next) {
soup_cookie_jar_delete_cookie (jar, p->data);
@@ -113,7 +105,7 @@ do_cookies_parsing_test (void)
SoupCookie *cookie;
gboolean got1, got2, got3;
- debug_printf (1, "\nSoupCookie parsing test\n");
+ g_test_bug ("678753");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
soup_session_add_feature_by_type (session, SOUP_TYPE_COOKIE_JAR);
@@ -146,56 +138,28 @@ do_cookies_parsing_test (void)
if (!strcmp (soup_cookie_get_name (cookie), "one")) {
got1 = TRUE;
- if (!soup_cookie_get_http_only (cookie)) {
- debug_printf (1, " cookie 1 is not HttpOnly!\n");
- errors++;
- }
- if (!soup_cookie_get_expires (cookie)) {
- debug_printf (1, " cookie 1 did not fully parse!\n");
- errors++;
- }
+ g_assert_true (soup_cookie_get_http_only (cookie));
+ g_assert_true (soup_cookie_get_expires (cookie) != NULL);
} else if (!strcmp (soup_cookie_get_name (cookie), "two")) {
got2 = TRUE;
- if (!soup_cookie_get_http_only (cookie)) {
- debug_printf (1, " cookie 2 is not HttpOnly!\n");
- errors++;
- }
- if (!soup_cookie_get_expires (cookie)) {
- debug_printf (1, " cookie 3 did not fully parse!\n");
- errors++;
- }
+ g_assert_true (soup_cookie_get_http_only (cookie));
+ g_assert_true (soup_cookie_get_expires (cookie) != NULL);
} else if (!strcmp (soup_cookie_get_name (cookie), "three")) {
got3 = TRUE;
- if (!soup_cookie_get_http_only (cookie)) {
- debug_printf (1, " cookie 3 is not HttpOnly!\n");
- errors++;
- }
- if (!soup_cookie_get_expires (cookie)) {
- debug_printf (1, " cookie 3 did not fully parse!\n");
- errors++;
- }
+ g_assert_true (soup_cookie_get_http_only (cookie));
+ g_assert_true (soup_cookie_get_expires (cookie) != NULL);
} else {
- debug_printf (1, " got unexpected cookie '%s'\n",
- soup_cookie_get_name (cookie));
- errors++;
+ soup_test_assert (FALSE, "got unexpected cookie '%s'",
+ soup_cookie_get_name (cookie));
}
soup_cookie_free (cookie);
}
g_slist_free (cookies);
- if (!got1) {
- debug_printf (1, " didn't get cookie 1\n");
- errors++;
- }
- if (!got2) {
- debug_printf (1, " didn't get cookie 2\n");
- errors++;
- }
- if (!got3) {
- debug_printf (1, " didn't get cookie 3\n");
- errors++;
- }
+ g_assert_true (got1);
+ g_assert_true (got2);
+ g_assert_true (got3);
soup_test_session_abort_unref (session);
}
@@ -203,6 +167,8 @@ do_cookies_parsing_test (void)
int
main (int argc, char **argv)
{
+ int ret;
+
test_init (argc, argv, NULL);
server = soup_test_server_new (TRUE);
@@ -212,14 +178,15 @@ main (int argc, char **argv)
soup_uri_set_port (first_party_uri, soup_server_get_port (server));
soup_uri_set_port (third_party_uri, soup_server_get_port (server));
- do_cookies_accept_policy_test ();
- do_cookies_parsing_test ();
+ g_test_add_func ("/cookies/accept-policy", do_cookies_accept_policy_test);
+ g_test_add_func ("/cookies/parsing", do_cookies_parsing_test);
+
+ ret = g_test_run ();
soup_uri_free (first_party_uri);
soup_uri_free (third_party_uri);
soup_test_server_quit_unref (server);
test_cleanup ();
-
- return errors != 0;
+ return ret;
}
diff --git a/tests/date.c b/tests/date.c
index 54a59f2b..e51fa57f 100644
--- a/tests/date.c
+++ b/tests/date.c
@@ -5,7 +5,7 @@
#include "test-utils.h"
-static gboolean check_ok (const char *strdate, SoupDate *date);
+static void check_ok (gconstpointer data);
static SoupDate *
make_date (const char *strdate)
@@ -24,178 +24,226 @@ make_date (const char *strdate)
return date;
}
-static const struct {
+static SoupDate *
+check_correct_date (const char *strdate)
+{
+ SoupDate *date;
+
+ date = make_date (strdate);
+ if (!date) {
+ g_assert_nonnull (date);
+ return NULL;
+ }
+
+ g_assert_cmpint (date->year, ==, 2004);
+ g_assert_cmpint (date->month, ==, 11);
+ g_assert_cmpint (date->day, ==, 6);
+ g_assert_cmpint (date->hour, ==, 8);
+ g_assert_cmpint (date->minute, ==, 9);
+ g_assert_cmpint (date->second, ==, 7);
+
+ return date;
+}
+
+typedef struct {
SoupDateFormat format;
const char *date;
-} good_dates[] = {
- { SOUP_DATE_HTTP, "Sat, 06 Nov 2004 08:09:07 GMT" },
- { SOUP_DATE_COOKIE, "Sat, 06-Nov-2004 08:09:07 GMT" },
- { SOUP_DATE_RFC2822, "Sat, 6 Nov 2004 08:09:07 -0430" },
- { SOUP_DATE_ISO8601_COMPACT, "20041106T080907" },
- { SOUP_DATE_ISO8601_FULL, "2004-11-06T08:09:07" },
- { SOUP_DATE_ISO8601_XMLRPC, "20041106T08:09:07" }
+ const char *bugref;
+} GoodDate;
+
+static const GoodDate good_dates[] = {
+ { SOUP_DATE_HTTP, "Sat, 06 Nov 2004 08:09:07 GMT", NULL },
+ { SOUP_DATE_COOKIE, "Sat, 06-Nov-2004 08:09:07 GMT", NULL },
+ { SOUP_DATE_RFC2822, "Sat, 6 Nov 2004 08:09:07 -0430", "579055" },
+ { SOUP_DATE_ISO8601_COMPACT, "20041106T080907", NULL },
+ { SOUP_DATE_ISO8601_FULL, "2004-11-06T08:09:07", NULL },
+ { SOUP_DATE_ISO8601_XMLRPC, "20041106T08:09:07", NULL }
};
static void
-check_good (SoupDateFormat format, const char *strdate)
+check_good (gconstpointer data)
{
+ GoodDate *good = (GoodDate *)data;
SoupDate *date;
char *strdate2;
- date = make_date (strdate);
- g_assert (date);
- strdate2 = soup_date_to_string (date, format);
- if (!check_ok (strdate, date))
+ if (good->bugref)
+ g_test_bug (good->bugref);
+
+ date = check_correct_date (good->date);
+ if (!date)
return;
- if (strcmp (strdate, strdate2) != 0) {
- debug_printf (1, " restringification failed: '%s' -> '%s'\n",
- strdate, strdate2);
- errors++;
- }
+ strdate2 = soup_date_to_string (date, good->format);
+ soup_date_free (date);
+
+ soup_test_assert (strcmp (good->date, strdate2) == 0,
+ "restringification failed: '%s' -> '%s'\n",
+ good->date, strdate2);
g_free (strdate2);
}
-static const char *ok_dates[] = {
+typedef struct {
+ const char *date;
+ const char *bugref;
+} OkDate;
+
+static const OkDate ok_dates[] = {
/* rfc1123-date, and broken variants */
- "Sat, 06 Nov 2004 08:09:07 GMT",
- "Sat, 6 Nov 2004 08:09:07 GMT",
- "Sat, 6 Nov 2004 08:09:07 GMT",
- "Sat, 06 Nov 2004 08:09:07",
- "06 Nov 2004 08:09:07 GMT",
- "SAT, 06 NOV 2004 08:09:07 +1000",
+ { "Sat, 06 Nov 2004 08:09:07 GMT", NULL },
+ { "Sat, 6 Nov 2004 08:09:07 GMT", NULL },
+ { "Sat, 6 Nov 2004 08:09:07 GMT", NULL },
+ { "Sat, 06 Nov 2004 08:09:07", NULL },
+ { "06 Nov 2004 08:09:07 GMT", NULL },
+ { "SAT, 06 NOV 2004 08:09:07 +1000", "644048" },
/* rfc850-date, and broken variants */
- "Saturday, 06-Nov-04 08:09:07 GMT",
- "Saturday, 6-Nov-04 08:09:07 GMT",
- "Saturday, 6-Nov-04 08:09:07 GMT",
- "Saturday, 06-Nov-104 08:09:07 GMT",
- "Saturday, 06-Nov-04 08:09:07",
- "06-Nov-04 08:09:07 GMT",
+ { "Saturday, 06-Nov-04 08:09:07 GMT", NULL },
+ { "Saturday, 6-Nov-04 08:09:07 GMT", NULL },
+ { "Saturday, 6-Nov-04 08:09:07 GMT", NULL },
+ { "Saturday, 06-Nov-104 08:09:07 GMT", NULL },
+ { "Saturday, 06-Nov-04 08:09:07", NULL },
+ { "06-Nov-04 08:09:07 GMT", NULL },
/* asctime-date, and broken variants */
- "Sat Nov 6 08:09:07 2004",
- "Sat Nov 06 08:09:07 2004",
- "Sat Nov 6 08:09:07 2004",
- "Sat Nov 6 08:09:07 2004 GMT",
+ { "Sat Nov 6 08:09:07 2004", NULL },
+ { "Sat Nov 06 08:09:07 2004", NULL },
+ { "Sat Nov 6 08:09:07 2004", NULL },
+ { "Sat Nov 6 08:09:07 2004 GMT", NULL },
/* ISO 8601 */
- "2004-11-06T08:09:07Z",
- "20041106T08:09:07Z",
- "20041106T08:09:07+00:00",
- "20041106T080907+00:00",
+ { "2004-11-06T08:09:07Z", NULL },
+ { "20041106T08:09:07Z", NULL },
+ { "20041106T08:09:07+00:00", NULL },
+ { "20041106T080907+00:00", NULL },
/* Netscape cookie spec date, and broken variants */
- "Sat, 06-Nov-2004 08:09:07 GMT",
- "Sat, 6-Nov-2004 08:09:07 GMT",
- "Sat, 6-Nov-2004 08:09:07 GMT",
- "Sat, 06-Nov-2004 08:09:07",
+ { "Sat, 06-Nov-2004 08:09:07 GMT", NULL },
+ { "Sat, 6-Nov-2004 08:09:07 GMT", NULL },
+ { "Sat, 6-Nov-2004 08:09:07 GMT", NULL },
+ { "Sat, 06-Nov-2004 08:09:07", NULL },
/* Original version of Netscape cookie spec, and broken variants */
- "Sat, 06-Nov-04 08:09:07 GMT",
- "Sat, 6-Nov-04 08:09:07 GMT",
- "Sat, 6-Nov-04 08:09:07 GMT",
- "Sat, 06-Nov-104 08:09:07 GMT",
- "Sat, 06-Nov-04 08:09:07",
+ { "Sat, 06-Nov-04 08:09:07 GMT", NULL },
+ { "Sat, 6-Nov-04 08:09:07 GMT", NULL },
+ { "Sat, 6-Nov-04 08:09:07 GMT", NULL },
+ { "Sat, 06-Nov-104 08:09:07 GMT", NULL },
+ { "Sat, 06-Nov-04 08:09:07", NULL },
/* Netscape cookie spec example syntax, and broken variants */
- "Saturday, 06-Nov-04 08:09:07 GMT",
- "Saturday, 6-Nov-04 08:09:07 GMT",
- "Saturday, 6-Nov-04 08:09:07 GMT",
- "Saturday, 06-Nov-104 08:09:07 GMT",
- "Saturday, 06-Nov-2004 08:09:07 GMT",
- "Saturday, 6-Nov-2004 08:09:07 GMT",
- "Saturday, 6-Nov-2004 08:09:07 GMT",
- "Saturday, 06-Nov-04 08:09:07",
+ { "Saturday, 06-Nov-04 08:09:07 GMT", NULL },
+ { "Saturday, 6-Nov-04 08:09:07 GMT", NULL },
+ { "Saturday, 6-Nov-04 08:09:07 GMT", NULL },
+ { "Saturday, 06-Nov-104 08:09:07 GMT", NULL },
+ { "Saturday, 06-Nov-2004 08:09:07 GMT", NULL },
+ { "Saturday, 6-Nov-2004 08:09:07 GMT", NULL },
+ { "Saturday, 6-Nov-2004 08:09:07 GMT", NULL },
+ { "Saturday, 06-Nov-04 08:09:07", NULL },
/* Miscellaneous broken formats seen on the web */
- "Sat 06-Nov-2004 08:9:07",
- "Saturday, 06-Nov-04 8:9:07 GMT",
- "Sat, 06 Nov 2004 08:09:7 GMT"
+ { "Sat 06-Nov-2004 08:9:07", NULL },
+ { "Saturday, 06-Nov-04 8:9:07 GMT", NULL },
+ { "Sat, 06 Nov 2004 08:09:7 GMT", NULL }
};
+static void
+check_ok (gconstpointer data)
+{
+ OkDate *ok = (OkDate *)data;
+ SoupDate *date;
+
+ if (ok->bugref)
+ g_test_bug (ok->bugref);
+
+ date = check_correct_date (ok->date);
+ if (!date)
+ return;
+ soup_date_free (date);
+}
+
#define TIME_T 1099728547L
#define TIME_T_STRING "1099728547"
-static gboolean
-check_ok (const char *strdate, SoupDate *date)
+static void
+check_ok_time_t (void)
{
- debug_printf (2, "%s\n", strdate);
+ SoupDate *date;
- if (date &&
- date->year == 2004 && date->month == 11 && date->day == 6 &&
- date->hour == 8 && date->minute == 9 && date->second == 7) {
- soup_date_free (date);
- return TRUE;
- }
+ date = soup_date_new_from_time_t (TIME_T);
- debug_printf (1, " date parsing failed for '%s'.\n", strdate);
- if (date) {
- debug_printf (1, " got: %d %d %d - %d %d %d\n\n",
- date->year, date->month, date->day,
- date->hour, date->minute, date->second);
- soup_date_free (date);
- }
- errors++;
- return FALSE;
+ g_assert_cmpint (date->year, ==, 2004);
+ g_assert_cmpint (date->month, ==, 11);
+ g_assert_cmpint (date->day, ==, 6);
+ g_assert_cmpint (date->hour, ==, 8);
+ g_assert_cmpint (date->minute, ==, 9);
+ g_assert_cmpint (date->second, ==, 7);
}
-static const char *bad_dates[] = {
+typedef struct {
+ const char *date;
+ const char *bugref;
+} BadDate;
+
+static const BadDate bad_dates[] = {
/* broken rfc1123-date */
- ", 06 Nov 2004 08:09:07 GMT",
- "Sat, Nov 2004 08:09:07 GMT",
- "Sat, 06 2004 08:09:07 GMT",
- "Sat, 06 Nov 08:09:07 GMT",
- "Sat, 06 Nov 2004 :09:07 GMT",
- "Sat, 06 Nov 2004 09:07 GMT",
- "Sat, 06 Nov 2004 08::07 GMT",
- "Sat, 06 Nov 2004 08:09: GMT",
+ { ", 06 Nov 2004 08:09:07 GMT", NULL },
+ { "Sat, Nov 2004 08:09:07 GMT", NULL },
+ { "Sat, 06 2004 08:09:07 GMT", NULL },
+ { "Sat, 06 Nov 08:09:07 GMT", NULL },
+ { "Sat, 06 Nov 2004 :09:07 GMT", NULL },
+ { "Sat, 06 Nov 2004 09:07 GMT", NULL },
+ { "Sat, 06 Nov 2004 08::07 GMT", NULL },
+ { "Sat, 06 Nov 2004 08:09: GMT", NULL },
/* broken rfc850-date */
- ", 06-Nov-04 08:09:07 GMT",
- "Saturday, -Nov-04 08:09:07 GMT",
- "Saturday, Nov-04 08:09:07 GMT",
- "Saturday, 06-04 08:09:07 GMT",
- "Saturday, 06--04 08:09:07 GMT",
- "Saturday, 06-Nov- 08:09:07 GMT",
- "Saturday, 06-Nov 08:09:07 GMT",
- "Saturday, 06-Nov-04 :09:07 GMT",
- "Saturday, 06-Nov-04 09:07 GMT",
- "Saturday, 06-Nov-04 08::07 GMT",
- "Saturday, 06-Nov-04 08:09: GMT",
+ { ", 06-Nov-04 08:09:07 GMT", NULL },
+ { "Saturday, -Nov-04 08:09:07 GMT", NULL },
+ { "Saturday, Nov-04 08:09:07 GMT", NULL },
+ { "Saturday, 06-04 08:09:07 GMT", NULL },
+ { "Saturday, 06--04 08:09:07 GMT", NULL },
+ { "Saturday, 06-Nov- 08:09:07 GMT", NULL },
+ { "Saturday, 06-Nov 08:09:07 GMT", NULL },
+ { "Saturday, 06-Nov-04 :09:07 GMT", NULL },
+ { "Saturday, 06-Nov-04 09:07 GMT", NULL },
+ { "Saturday, 06-Nov-04 08::07 GMT", NULL },
+ { "Saturday, 06-Nov-04 08:09: GMT", NULL },
/* broken asctime-date */
- "Nov 6 08:09:07 2004",
- "Sat 6 08:09:07 2004",
- "Sat Nov 08:09:07 2004",
- "Sat Nov 6 :09:07 2004",
- "Sat Nov 6 09:07 2004",
- "Sat Nov 6 08::07 2004",
- "Sat Nov 6 08:09: 2004",
- "Sat Nov 6 08:09:07",
- "Sat Nov 6 08:09:07 GMT 2004"
+ { "Nov 6 08:09:07 2004", NULL },
+ { "Sat 6 08:09:07 2004", NULL },
+ { "Sat Nov 08:09:07 2004", NULL },
+ { "Sat Nov 6 :09:07 2004", NULL },
+ { "Sat Nov 6 09:07 2004", NULL },
+ { "Sat Nov 6 08::07 2004", NULL },
+ { "Sat Nov 6 08:09: 2004", NULL },
+ { "Sat Nov 6 08:09:07", NULL },
+ { "Sat Nov 6 08:09:07 GMT 2004", NULL }
};
static void
-check_bad (const char *strdate, SoupDate *date)
+check_bad (gconstpointer data)
{
- debug_printf (2, "%s\n", strdate);
+ BadDate *bad = (BadDate *)data;
+ SoupDate *date;
- if (!date)
- return;
- errors++;
+ if (bad->bugref)
+ g_test_bug (bad->bugref);
- debug_printf (1, " date parsing succeeded for '%s'!\n", strdate);
- debug_printf (1, " got: %d %d %d - %d %d %d\n\n",
- date->year, date->month, date->day,
- date->hour, date->minute, date->second);
- soup_date_free (date);
+ date = make_date (bad->date);
+ soup_test_assert (date == NULL,
+ "date parsing succeeded for '%s': %d %d %d - %d %d %d",
+ bad->date,
+ date->year, date->month, date->day,
+ date->hour, date->minute, date->second);
+ g_clear_pointer (&date, soup_date_free);
}
-static const struct conversion {
+typedef struct {
const char *source;
const char *http, *cookie, *rfc2822, *compact, *full, *xmlrpc;
-} conversions[] = {
+} DateConversion;
+
+static const DateConversion conversions[] = {
/* SOUP_DATE_HTTP */
{ "Sat, 06 Nov 2004 08:09:07 GMT",
@@ -288,71 +336,40 @@ static const struct conversion {
};
static void
-check_conversion (const struct conversion *conv)
+check_conversion (gconstpointer data)
{
+ const DateConversion *conv = data;
SoupDate *date;
char *str;
- debug_printf (2, "%s\n", conv->source);
date = make_date (conv->source);
if (!date) {
- debug_printf (1, " date parsing failed for '%s'.\n", conv->source);
- errors++;
+ soup_test_assert (FALSE, "date parsing failed for '%s'.", conv->source);
return;
}
str = soup_date_to_string (date, SOUP_DATE_HTTP);
- if (!str || strcmp (str, conv->http) != 0) {
- debug_printf (1, " conversion of '%s' to HTTP failed:\n"
- " wanted: %s\n got: %s\n",
- conv->source, conv->http, str ? str : "(null)");
- errors++;
- }
+ g_assert_cmpstr (str, ==, conv->http);
g_free (str);
str = soup_date_to_string (date, SOUP_DATE_COOKIE);
- if (!str || strcmp (str, conv->cookie) != 0) {
- debug_printf (1, " conversion of '%s' to COOKIE failed:\n"
- " wanted: %s\n got: %s\n",
- conv->source, conv->cookie, str ? str : "(null)");
- errors++;
- }
+ g_assert_cmpstr (str, ==, conv->cookie);
g_free (str);
str = soup_date_to_string (date, SOUP_DATE_RFC2822);
- if (!str || strcmp (str, conv->rfc2822) != 0) {
- debug_printf (1, " conversion of '%s' to RFC2822 failed:\n"
- " wanted: %s\n got: %s\n",
- conv->source, conv->rfc2822, str ? str : "(null)");
- errors++;
- }
+ g_assert_cmpstr (str, ==, conv->rfc2822);
g_free (str);
str = soup_date_to_string (date, SOUP_DATE_ISO8601_COMPACT);
- if (!str || strcmp (str, conv->compact) != 0) {
- debug_printf (1, " conversion of '%s' to COMPACT failed:\n"
- " wanted: %s\n got: %s\n",
- conv->source, conv->compact, str ? str : "(null)");
- errors++;
- }
+ g_assert_cmpstr (str, ==, conv->compact);
g_free (str);
str = soup_date_to_string (date, SOUP_DATE_ISO8601_FULL);
- if (!str || strcmp (str, conv->full) != 0) {
- debug_printf (1, " conversion of '%s' to FULL failed:\n"
- " wanted: %s\n got: %s\n",
- conv->source, conv->full, str ? str : "(null)");
- errors++;
- }
+ g_assert_cmpstr (str, ==, conv->full);
g_free (str);
str = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
- if (!str || strcmp (str, conv->xmlrpc) != 0) {
- debug_printf (1, " conversion of '%s' to XMLRPC failed:\n"
- " wanted: %s\n got: %s\n",
- conv->source, conv->xmlrpc, str ? str : "(null)");
- errors++;
- }
+ g_assert_cmpstr (str, ==, conv->xmlrpc);
g_free (str);
soup_date_free (date);
@@ -361,27 +378,38 @@ check_conversion (const struct conversion *conv)
int
main (int argc, char **argv)
{
- int i;
+ int i, ret;
+ char *path;
test_init (argc, argv, NULL);
- debug_printf (1, "Good dates:\n");
- for (i = 0; i < G_N_ELEMENTS (good_dates); i++)
- check_good (good_dates[i].format, good_dates[i].date);
+ for (i = 0; i < G_N_ELEMENTS (good_dates); i++) {
+ path = g_strdup_printf ("/date/good/%s", good_dates[i].date);
+ g_test_add_data_func (path, &good_dates[i], check_good);
+ g_free (path);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (ok_dates); i++) {
+ path = g_strdup_printf ("/date/ok/%s", ok_dates[i].date);
+ g_test_add_data_func (path, &ok_dates[i], check_ok);
+ g_free (path);
+ }
+ g_test_add_func ("/date/ok/" TIME_T_STRING, check_ok_time_t);
- debug_printf (1, "\nOK dates:\n");
- for (i = 0; i < G_N_ELEMENTS (ok_dates); i++)
- check_ok (ok_dates[i], make_date (ok_dates[i]));
- check_ok (TIME_T_STRING, soup_date_new_from_time_t (TIME_T));
+ for (i = 0; i < G_N_ELEMENTS (bad_dates); i++) {
+ path = g_strdup_printf ("/date/bad/%s", bad_dates[i].date);
+ g_test_add_data_func (path, &bad_dates[i], check_bad);
+ g_free (path);
+ }
- debug_printf (1, "\nBad dates:\n");
- for (i = 0; i < G_N_ELEMENTS (bad_dates); i++)
- check_bad (bad_dates[i], make_date (bad_dates[i]));
+ for (i = 0; i < G_N_ELEMENTS (conversions); i++) {
+ path = g_strdup_printf ("/date/conversions/%s", conversions[i].source);
+ g_test_add_data_func (path, &conversions[i], check_conversion);
+ g_free (path);
+ }
- debug_printf (1, "\nConversions:\n");
- for (i = 0; i < G_N_ELEMENTS (conversions); i++)
- check_conversion (&conversions[i] );
+ ret = g_test_run ();
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/dns.c b/tests/dns.c
deleted file mode 100644
index f5940647..00000000
--- a/tests/dns.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-#include "test-utils.h"
-
-static GMainLoop *loop;
-static int nlookups = 0;
-
-static void
-resolve_callback (SoupAddress *addr, guint status, gpointer data)
-{
- if (status == SOUP_STATUS_OK) {
- g_print ("Name: %s\n", soup_address_get_name (addr));
- g_print ("Address: %s\n", soup_address_get_physical (addr));
- } else {
- g_print ("Name: %s\n", soup_address_get_name (addr));
- g_print ("Error: %s\n", soup_status_get_phrase (status));
- }
- g_print ("\n");
-
- g_object_unref (addr);
-
- nlookups--;
- if (nlookups == 0)
- g_main_loop_quit (loop);
-}
-
-static void
-usage (void)
-{
- g_printerr ("Usage: dns hostname ...\n");
- exit (1);
-}
-
-int
-main (int argc, char **argv)
-{
- SoupAddress *addr;
- int i;
-
- if (argc < 2)
- usage ();
-
- g_type_init ();
-
- for (i = 1; i < argc; i++) {
- addr = soup_address_new (argv[i], 0);
- if (!addr) {
- g_printerr ("Could not parse address %s\n", argv[1]);
- exit (1);
- }
-
- soup_address_resolve_async (addr, NULL, NULL,
- resolve_callback, NULL);
- nlookups++;
- }
-
- loop = g_main_loop_new (NULL, TRUE);
- g_main_loop_run (loop);
- g_main_loop_unref (loop);
-
- return 0;
-}
diff --git a/tests/forms-test.c b/tests/forms-test.c
index 1d254b12..3915b019 100644
--- a/tests/forms-test.c
+++ b/tests/forms-test.c
@@ -41,6 +41,7 @@ do_hello_test (int n, gboolean extra, const char *uri)
GPtrArray *args;
char *title_arg = NULL, *name_arg = NULL;
char *str_stdout = NULL;
+ GError *error = NULL;
debug_printf (1, "%2d. '%s' '%s'%s: ", n * 2 + (extra ? 2 : 1),
tests[n].title ? tests[n].title : "(null)",
@@ -49,6 +50,8 @@ do_hello_test (int n, gboolean extra, const char *uri)
args = g_ptr_array_new ();
g_ptr_array_add (args, "curl");
+ g_ptr_array_add (args, "--noproxy");
+ g_ptr_array_add (args, "*");
g_ptr_array_add (args, "-G");
if (tests[n].title) {
title_arg = soup_form_encode ("title", tests[n].title, NULL);
@@ -70,20 +73,12 @@ do_hello_test (int n, gboolean extra, const char *uri)
if (g_spawn_sync (NULL, (char **)args->pdata, NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
NULL, NULL,
- &str_stdout, NULL, NULL, NULL)) {
- if (str_stdout && !strcmp (str_stdout, tests[n].result))
- debug_printf (1, "OK!\n");
- else {
- debug_printf (1, "WRONG!\n");
- debug_printf (1, " expected '%s', got '%s'\n",
- tests[n].result,
- str_stdout ? str_stdout : "(error)");
- errors++;
- }
+ &str_stdout, NULL, NULL, &error)) {
+ g_assert_cmpstr (str_stdout, ==, tests[n].result);
g_free (str_stdout);
} else {
- debug_printf (1, "ERROR!\n");
- errors++;
+ g_assert_no_error (error);
+ g_error_free (error);
}
g_ptr_array_free (args, TRUE);
g_free (title_arg);
@@ -91,30 +86,75 @@ do_hello_test (int n, gboolean extra, const char *uri)
}
static void
-do_hello_tests (const char *uri)
+do_hello_tests (gconstpointer uri)
{
int n;
- debug_printf (1, "Hello tests (GET, application/x-www-form-urlencoded)\n");
+#ifndef HAVE_CURL
+ g_test_skip ("/usr/bin/curl is not available");
+ return;
+#endif
+
for (n = 0; n < G_N_ELEMENTS (tests); n++) {
do_hello_test (n, FALSE, uri);
do_hello_test (n, TRUE, uri);
}
}
+#define MD5_TEST_FILE (g_test_get_filename (G_TEST_DIST, "index.txt", NULL))
+#define MD5_TEST_FILE_BASENAME "index.txt"
+#define MD5_TEST_FILE_MIME_TYPE "text/plain"
+
+static char *
+get_md5_data (char **contents, gsize *length)
+{
+ char *my_contents, *md5;
+ gsize my_length;
+ GError *error = NULL;
+
+ if (!g_file_get_contents (MD5_TEST_FILE, &my_contents, &my_length, &error)) {
+ g_assert_no_error (error);
+ g_error_free (error);
+ return NULL;
+ }
+
+ md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, my_contents, my_length);
+
+ if (contents)
+ *contents = my_contents;
+ else
+ g_free (my_contents);
+ if (length)
+ *length = my_length;
+
+ return md5;
+}
+
static void
-do_md5_test_curl (const char *uri, const char *file, const char *md5)
+do_md5_test_curl (gconstpointer data)
{
+ const char *uri = data;
+ char *md5;
GPtrArray *args;
char *file_arg, *str_stdout;
+ GError *error = NULL;
- debug_printf (1, " via curl: ");
+#ifndef HAVE_CURL
+ g_test_skip ("/usr/bin/curl is not available");
+ return;
+#endif
+
+ md5 = get_md5_data (NULL, NULL);
+ if (!md5)
+ return;
args = g_ptr_array_new ();
g_ptr_array_add (args, "curl");
+ g_ptr_array_add (args, "--noproxy");
+ g_ptr_array_add (args, "*");
g_ptr_array_add (args, "-L");
g_ptr_array_add (args, "-F");
- file_arg = g_strdup_printf ("file=@%s", file);
+ file_arg = g_strdup_printf ("file=@%s", MD5_TEST_FILE);
g_ptr_array_add (args, file_arg);
g_ptr_array_add (args, "-F");
g_ptr_array_add (args, "fmt=txt");
@@ -125,37 +165,34 @@ do_md5_test_curl (const char *uri, const char *file, const char *md5)
G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
NULL, NULL,
&str_stdout, NULL, NULL, NULL)) {
- if (str_stdout && !strcmp (str_stdout, md5))
- debug_printf (1, "OK!\n");
- else {
- debug_printf (1, "WRONG!\n");
- debug_printf (1, " expected '%s', got '%s'\n",
- md5, str_stdout ? str_stdout : "(error)");
- errors++;
- }
+ g_assert_cmpstr (str_stdout, ==, md5);
g_free (str_stdout);
} else {
- debug_printf (1, "ERROR!\n");
- errors++;
+ g_assert_no_error (error);
+ g_error_free (error);
}
g_ptr_array_free (args, TRUE);
g_free (file_arg);
-}
-#define MD5_TEST_FILE SRCDIR "/resources/home.gif"
-#define MD5_TEST_FILE_BASENAME "home.gif"
-#define MD5_TEST_FILE_MIME_TYPE "image/gif"
+ g_free (md5);
+}
static void
-do_md5_test_libsoup (const char *uri, const char *contents,
- gsize length, const char *md5)
+do_md5_test_libsoup (gconstpointer data)
{
+ const char *uri = data;
+ char *contents, *md5;
+ gsize length;
SoupMultipart *multipart;
SoupBuffer *buffer;
SoupMessage *msg;
SoupSession *session;
- debug_printf (1, " via libsoup: ");
+ g_test_bug ("601640");
+
+ md5 = get_md5_data (&contents, &length);
+ if (!md5)
+ return;
multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
buffer = soup_buffer_new (SOUP_MEMORY_COPY, contents, length);
@@ -172,47 +209,16 @@ do_md5_test_libsoup (const char *uri, const char *contents,
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, "ERROR: Unexpected status %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- } else if (strcmp (msg->response_body->data, md5) != 0) {
- debug_printf (1, "ERROR: Incorrect response: expected '%s' got '%s'\n",
- md5, msg->response_body->data);
- errors++;
- } else
- debug_printf (1, "OK!\n");
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_assert_cmpstr (msg->response_body->data, ==, md5);
g_object_unref (msg);
soup_test_session_abort_unref (session);
-}
-
-static void
-do_md5_tests (const char *uri)
-{
- char *contents, *md5;
- gsize length;
- GError *error = NULL;
-
- debug_printf (1, "\nMD5 tests (POST, multipart/form-data)\n");
-
- if (!g_file_get_contents (MD5_TEST_FILE, &contents, &length, &error)) {
- debug_printf (1, " ERROR: Could not read " MD5_TEST_FILE ": %s\n", error->message);
- g_error_free (error);
- errors++;
- return;
- }
-
- md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, contents, length);
-
- do_md5_test_curl (uri, MD5_TEST_FILE, md5);
- do_md5_test_libsoup (uri, contents, length, md5);
g_free (contents);
g_free (md5);
}
-
static void
do_form_decode_test (void)
{
@@ -220,7 +226,10 @@ do_form_decode_test (void)
const gchar *value;
gchar *tmp;
- debug_printf (1, "\nDecode tests\n");
+#ifndef HAVE_CURL
+ g_test_skip ("/usr/bin/curl is not available");
+ return;
+#endif
/* Test that the code handles multiple values with the same key. */
table = soup_form_decode ("foo=first&foo=second&foo=third");
@@ -232,11 +241,7 @@ do_form_decode_test (void)
tmp = g_strdup ("other");
value = g_hash_table_lookup (table, "foo");
- if (g_strcmp0 (value, "third") != 0) {
- debug_printf (1, " ERROR: expected '%s', got '%s'\n",
- "third", value ? value : "(null)");
- errors++;
- }
+ g_assert_cmpstr (value, ==, "third");
g_free (tmp);
g_hash_table_destroy (table);
@@ -417,6 +422,7 @@ main (int argc, char **argv)
SoupServer *server;
guint port;
char *uri_str;
+ int ret = 0;
test_init (argc, argv, no_test_entry);
@@ -431,14 +437,16 @@ main (int argc, char **argv)
if (run_tests) {
uri_str = g_strdup_printf ("http://127.0.0.1:%u/hello", port);
- do_hello_tests (uri_str);
- g_free (uri_str);
+ g_test_add_data_func_full ("/forms/hello", uri_str, do_hello_tests, g_free);
uri_str = g_strdup_printf ("http://127.0.0.1:%u/md5", port);
- do_md5_tests (uri_str);
+ g_test_add_data_func_full ("/forms/md5/curl", g_strdup (uri_str), do_md5_test_curl, g_free);
+ g_test_add_data_func_full ("/forms/md5/libsoup", g_strdup (uri_str), do_md5_test_libsoup, g_free);
g_free (uri_str);
- do_form_decode_test ();
+ g_test_add_func ("/forms/decode", do_form_decode_test);
+
+ ret = g_test_run ();
} else {
g_print ("Listening on port %d\n", port);
g_main_loop_run (loop);
@@ -449,5 +457,5 @@ main (int argc, char **argv)
soup_test_server_quit_unref (server);
if (run_tests)
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/get.c b/tests/get.c
deleted file mode 100644
index 1d867155..00000000
--- a/tests/get.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2001-2003, Ximian, Inc.
- */
-
-#include "test-utils.h"
-#include <stdio.h>
-
-static SoupSession *session;
-static GMainLoop *loop;
-static gboolean debug = FALSE, quiet = FALSE;
-static const char *method;
-
-static void
-get_url (const char *url)
-{
- const char *name;
- SoupMessage *msg;
- const char *header;
-
- msg = soup_message_new (method, url);
- soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
-
- soup_session_send_message (session, msg);
-
- name = soup_message_get_uri (msg)->path;
-
- if (debug) {
- SoupMessageHeadersIter iter;
- const char *hname, *value;
- char *path = soup_uri_to_string (soup_message_get_uri (msg), TRUE);
-
- g_print ("%s %s HTTP/1.%d\n", method, path,
- soup_message_get_http_version (msg));
- soup_message_headers_iter_init (&iter, msg->request_headers);
- while (soup_message_headers_iter_next (&iter, &hname, &value))
- g_print ("%s: %s\r\n", hname, value);
- g_print ("\n");
-
- g_print ("HTTP/1.%d %d %s\n",
- soup_message_get_http_version (msg),
- msg->status_code, msg->reason_phrase);
-
- soup_message_headers_iter_init (&iter, msg->response_headers);
- while (soup_message_headers_iter_next (&iter, &hname, &value))
- g_print ("%s: %s\r\n", hname, value);
- g_print ("\n");
- } else if (msg->status_code == SOUP_STATUS_SSL_FAILED) {
- GTlsCertificateFlags flags;
-
- if (soup_message_get_https_status (msg, NULL, &flags))
- g_print ("%s: %d %s (0x%x)\n", name, msg->status_code, msg->reason_phrase, flags);
- else
- g_print ("%s: %d %s (no handshake status)\n", name, msg->status_code, msg->reason_phrase);
- } else if (!quiet || SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
- g_print ("%s: %d %s\n", name, msg->status_code, msg->reason_phrase);
-
- if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) {
- header = soup_message_headers_get_one (msg->response_headers,
- "Location");
- if (header) {
- SoupURI *uri;
- char *uri_string;
-
- if (!debug && !quiet)
- g_print (" -> %s\n", header);
-
- uri = soup_uri_new_with_base (soup_message_get_uri (msg), header);
- uri_string = soup_uri_to_string (uri, FALSE);
- get_url (uri_string);
- g_free (uri_string);
- soup_uri_free (uri);
- }
- } else if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- fwrite (msg->response_body->data, 1,
- msg->response_body->length, stdout);
- }
-}
-
-static void
-usage (void)
-{
- g_printerr ("Usage: get [-c CAfile] [-p proxy URL] [-h] [-d] URL\n");
- exit (1);
-}
-
-int
-main (int argc, char **argv)
-{
- const char *cafile = NULL, *url;
- SoupURI *proxy = NULL, *parsed;
- gboolean synchronous = FALSE, ntlm = FALSE;
- int opt;
-
- g_type_init ();
-
- method = SOUP_METHOD_GET;
-
- while ((opt = getopt (argc, argv, "c:dhnp:qs")) != -1) {
- switch (opt) {
- case 'c':
- cafile = optarg;
- break;
-
- case 'd':
- debug = TRUE;
- break;
-
- case 'h':
- method = SOUP_METHOD_HEAD;
- debug = TRUE;
- break;
-
- case 'n':
- ntlm = TRUE;
- break;
-
- case 'p':
- proxy = soup_uri_new (optarg);
- if (!proxy) {
- g_printerr ("Could not parse %s as URI\n",
- optarg);
- exit (1);
- }
- break;
-
- case 'q':
- quiet = TRUE;
- break;
-
- case 's':
- synchronous = TRUE;
- break;
-
- case '?':
- usage ();
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 1)
- usage ();
- url = argv[0];
- parsed = soup_uri_new (url);
- if (!parsed) {
- g_printerr ("Could not parse '%s' as a URL\n", url);
- exit (1);
- }
- soup_uri_free (parsed);
-
- if (synchronous) {
- session = soup_session_sync_new_with_options (
- SOUP_SESSION_SSL_CA_FILE, cafile,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
- SOUP_SESSION_USER_AGENT, "get ",
- SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
- SOUP_SESSION_USE_NTLM, ntlm,
- NULL);
- } else {
- session = soup_session_async_new_with_options (
- SOUP_SESSION_SSL_CA_FILE, cafile,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
- SOUP_SESSION_USER_AGENT, "get ",
- SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
- SOUP_SESSION_USE_NTLM, ntlm,
- NULL);
- }
-
- if (proxy) {
- g_object_set (G_OBJECT (session),
- SOUP_SESSION_PROXY_URI, proxy,
- NULL);
- } else
- soup_session_add_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_DEFAULT);
-
- if (!synchronous)
- loop = g_main_loop_new (NULL, TRUE);
-
- get_url (url);
-
- if (!synchronous)
- g_main_loop_unref (loop);
-
- return 0;
-}
diff --git a/tests/header-parsing.c b/tests/header-parsing.c
index e57d7d83..fdc7885d 100644
--- a/tests/header-parsing.c
+++ b/tests/header-parsing.c
@@ -8,6 +8,7 @@ typedef struct {
static struct RequestTest {
const char *description;
+ const char *bugref;
const char *request;
int length;
guint status;
@@ -19,14 +20,14 @@ static struct RequestTest {
/*** VALID REQUESTS ***/
/**********************/
- { "HTTP 1.0 request with no headers",
+ { "HTTP 1.0 request with no headers", NULL,
"GET / HTTP/1.0\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_0,
{ { NULL } }
},
- { "Req w/ 1 header",
+ { "Req w/ 1 header", NULL,
"GET / HTTP/1.1\r\nHost: example.com\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -35,7 +36,7 @@ static struct RequestTest {
}
},
- { "Req w/ 1 header, no leading whitespace",
+ { "Req w/ 1 header, no leading whitespace", NULL,
"GET / HTTP/1.1\r\nHost:example.com\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -44,7 +45,7 @@ static struct RequestTest {
}
},
- { "Req w/ 1 header including trailing whitespace",
+ { "Req w/ 1 header including trailing whitespace", NULL,
"GET / HTTP/1.1\r\nHost: example.com \r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -53,7 +54,7 @@ static struct RequestTest {
}
},
- { "Req w/ 1 header, wrapped",
+ { "Req w/ 1 header, wrapped", NULL,
"GET / HTTP/1.1\r\nFoo: bar\r\n baz\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -62,7 +63,7 @@ static struct RequestTest {
}
},
- { "Req w/ 1 header, wrapped with additional whitespace",
+ { "Req w/ 1 header, wrapped with additional whitespace", NULL,
"GET / HTTP/1.1\r\nFoo: bar \r\n baz\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -71,7 +72,7 @@ static struct RequestTest {
}
},
- { "Req w/ 1 header, wrapped with tab",
+ { "Req w/ 1 header, wrapped with tab", NULL,
"GET / HTTP/1.1\r\nFoo: bar\r\n\tbaz\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -80,7 +81,7 @@ static struct RequestTest {
}
},
- { "Req w/ 1 header, wrapped before value",
+ { "Req w/ 1 header, wrapped before value", NULL,
"GET / HTTP/1.1\r\nFoo:\r\n bar baz\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -89,7 +90,7 @@ static struct RequestTest {
}
},
- { "Req w/ 1 header with empty value",
+ { "Req w/ 1 header with empty value", NULL,
"GET / HTTP/1.1\r\nHost:\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -98,7 +99,7 @@ static struct RequestTest {
}
},
- { "Req w/ 2 headers",
+ { "Req w/ 2 headers", NULL,
"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -108,7 +109,7 @@ static struct RequestTest {
}
},
- { "Req w/ 3 headers",
+ { "Req w/ 3 headers", NULL,
"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\nBlah: blah\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -119,7 +120,7 @@ static struct RequestTest {
}
},
- { "Req w/ 3 headers, 1st wrapped",
+ { "Req w/ 3 headers, 1st wrapped", NULL,
"GET / HTTP/1.1\r\nFoo: bar\r\n baz\r\nConnection: close\r\nBlah: blah\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -130,7 +131,7 @@ static struct RequestTest {
}
},
- { "Req w/ 3 headers, 2nd wrapped",
+ { "Req w/ 3 headers, 2nd wrapped", NULL,
"GET / HTTP/1.1\r\nConnection: close\r\nBlah: blah\r\nFoo: bar\r\n baz\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -141,7 +142,7 @@ static struct RequestTest {
}
},
- { "Req w/ 3 headers, 3rd wrapped",
+ { "Req w/ 3 headers, 3rd wrapped", NULL,
"GET / HTTP/1.1\r\nConnection: close\r\nBlah: blah\r\nFoo: bar\r\n baz\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -152,7 +153,7 @@ static struct RequestTest {
}
},
- { "Req w/ same header multiple times",
+ { "Req w/ same header multiple times", NULL,
"GET / HTTP/1.1\r\nFoo: bar\r\nFoo: baz\r\nFoo: quux\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -161,7 +162,7 @@ static struct RequestTest {
}
},
- { "Connection header on HTTP/1.0 message",
+ { "Connection header on HTTP/1.0 message", NULL,
"GET / HTTP/1.0\r\nFoo: bar\r\nConnection: Bar, Quux\r\nBar: baz\r\nQuux: foo\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_0,
@@ -171,14 +172,14 @@ static struct RequestTest {
}
},
- { "GET with full URI",
+ { "GET with full URI", "667637",
"GET http://example.com HTTP/1.1\r\n", -1,
SOUP_STATUS_OK,
"GET", "http://example.com", SOUP_HTTP_1_1,
{ { NULL } }
},
- { "GET with full URI in upper-case",
+ { "GET with full URI in upper-case", "667637",
"GET HTTP://example.com HTTP/1.1\r\n", -1,
SOUP_STATUS_OK,
"GET", "HTTP://example.com", SOUP_HTTP_1_1,
@@ -188,7 +189,7 @@ static struct RequestTest {
/* It's better for this to be passed through: this means a SoupServer
* could implement ftp-over-http proxying, for instance
*/
- { "GET with full URI of unrecognised scheme",
+ { "GET with full URI of unrecognised scheme", "667637",
"GET AbOuT: HTTP/1.1\r\n", -1,
SOUP_STATUS_OK,
"GET", "AbOuT:", SOUP_HTTP_1_1,
@@ -201,7 +202,7 @@ static struct RequestTest {
/* RFC 2616 section 4.1 says we SHOULD accept this */
- { "Spurious leading CRLF",
+ { "Spurious leading CRLF", NULL,
"\r\nGET / HTTP/1.1\r\nHost: example.com\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -212,7 +213,7 @@ static struct RequestTest {
/* RFC 2616 section 3.1 says we MUST accept this */
- { "HTTP/01.01 request",
+ { "HTTP/01.01 request", NULL,
"GET / HTTP/01.01\r\nHost: example.com\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -223,7 +224,7 @@ static struct RequestTest {
/* RFC 2616 section 19.3 says we SHOULD accept these */
- { "LF instead of CRLF after header",
+ { "LF instead of CRLF after header", NULL,
"GET / HTTP/1.1\r\nHost: example.com\nConnection: close\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -233,7 +234,7 @@ static struct RequestTest {
}
},
- { "LF instead of CRLF after Request-Line",
+ { "LF instead of CRLF after Request-Line", NULL,
"GET / HTTP/1.1\nHost: example.com\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -242,7 +243,7 @@ static struct RequestTest {
}
},
- { "Mixed CRLF/LF",
+ { "Mixed CRLF/LF", "666316",
"GET / HTTP/1.1\r\na: b\r\nc: d\ne: f\r\ng: h\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -254,7 +255,7 @@ static struct RequestTest {
}
},
- { "Req w/ incorrect whitespace in Request-Line",
+ { "Req w/ incorrect whitespace in Request-Line", NULL,
"GET /\tHTTP/1.1\r\nHost: example.com\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -263,7 +264,7 @@ static struct RequestTest {
}
},
- { "Req w/ incorrect whitespace after Request-Line",
+ { "Req w/ incorrect whitespace after Request-Line", "475169",
"GET / HTTP/1.1 \r\nHost: example.com\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -274,10 +275,9 @@ static struct RequestTest {
/* If the request/status line is parseable, then we
* just ignore any invalid-looking headers after that.
- * (qv bug 579318).
*/
- { "Req w/ mangled header",
+ { "Req w/ mangled header", "579318",
"GET / HTTP/1.1\r\nHost: example.com\r\nFoo one\r\nBar: two\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -287,7 +287,7 @@ static struct RequestTest {
}
},
- { "First header line is continuation",
+ { "First header line is continuation", "666316",
"GET / HTTP/1.1\r\n b\r\nHost: example.com\r\nc: d\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -297,7 +297,7 @@ static struct RequestTest {
}
},
- { "Zero-length header name",
+ { "Zero-length header name", "666316",
"GET / HTTP/1.1\r\na: b\r\n: example.com\r\nc: d\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -307,7 +307,7 @@ static struct RequestTest {
}
},
- { "CR in header name",
+ { "CR in header name", "666316",
"GET / HTTP/1.1\r\na: b\r\na\rb: cd\r\nx\r: y\r\n\rz: w\r\nc: d\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -317,7 +317,7 @@ static struct RequestTest {
}
},
- { "CR in header value",
+ { "CR in header value", "666316",
"GET / HTTP/1.1\r\na: b\r\nHost: example\rcom\r\np: \rq\r\ns: t\r\r\nc: d\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -330,7 +330,7 @@ static struct RequestTest {
}
},
- { "Tab in header name",
+ { "Tab in header name", "666316",
"GET / HTTP/1.1\r\na: b\r\na\tb: cd\r\nx\t: y\r\np: q\r\n\tz: w\r\nc: d\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -345,7 +345,7 @@ static struct RequestTest {
}
},
- { "Tab in header value",
+ { "Tab in header value", "666316",
"GET / HTTP/1.1\r\na: b\r\nab: c\td\r\nx: \ty\r\nz: w\t\r\nc: d\r\n", -1,
SOUP_STATUS_OK,
"GET", "/", SOUP_HTTP_1_1,
@@ -362,84 +362,84 @@ static struct RequestTest {
/*** INVALID REQUESTS ***/
/************************/
- { "HTTP 0.9 request; not supported",
+ { "HTTP 0.9 request; not supported", NULL,
"GET /\r\n", -1,
SOUP_STATUS_BAD_REQUEST,
NULL, NULL, -1,
{ { NULL } }
},
- { "HTTP 1.2 request (no such thing)",
+ { "HTTP 1.2 request (no such thing)", NULL,
"GET / HTTP/1.2\r\n", -1,
SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED,
NULL, NULL, -1,
{ { NULL } }
},
- { "HTTP 2000 request (no such thing)",
+ { "HTTP 2000 request (no such thing)", NULL,
"GET / HTTP/2000.0\r\n", -1,
SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED,
NULL, NULL, -1,
{ { NULL } }
},
- { "Non-HTTP request",
+ { "Non-HTTP request", NULL,
"GET / SOUP/1.1\r\nHost: example.com\r\n", -1,
SOUP_STATUS_BAD_REQUEST,
NULL, NULL, -1,
{ { NULL } }
},
- { "Junk after Request-Line",
+ { "Junk after Request-Line", NULL,
"GET / HTTP/1.1 blah\r\nHost: example.com\r\n", -1,
SOUP_STATUS_BAD_REQUEST,
NULL, NULL, -1,
{ { NULL } }
},
- { "NUL in Method",
+ { "NUL in Method", NULL,
"G\x00T / HTTP/1.1\r\nHost: example.com\r\n", 37,
SOUP_STATUS_BAD_REQUEST,
NULL, NULL, -1,
{ { NULL } }
},
- { "NUL at beginning of Method",
+ { "NUL at beginning of Method", "666316",
"\x00 / HTTP/1.1\r\nHost: example.com\r\n", 35,
SOUP_STATUS_BAD_REQUEST,
NULL, NULL, -1,
{ { NULL } }
},
- { "NUL in Path",
+ { "NUL in Path", NULL,
"GET /\x00 HTTP/1.1\r\nHost: example.com\r\n", 38,
SOUP_STATUS_BAD_REQUEST,
NULL, NULL, -1,
{ { NULL } }
},
- { "NUL in header name",
+ { "NUL in header name", "666316",
"GET / HTTP/1.1\r\n\x00: silly\r\n", 37,
SOUP_STATUS_BAD_REQUEST,
NULL, NULL, -1,
{ { NULL } }
},
- { "NUL in header value",
+ { "NUL in header value", NULL,
"GET / HTTP/1.1\r\nHost: example\x00com\r\n", 37,
SOUP_STATUS_BAD_REQUEST,
NULL, NULL, -1,
{ { NULL } }
},
- { "No terminating CRLF",
+ { "No terminating CRLF", NULL,
"GET / HTTP/1.1\r\nHost: example.com", -1,
SOUP_STATUS_BAD_REQUEST,
NULL, NULL, -1,
{ { NULL } }
},
- { "Unrecognized expectation",
+ { "Unrecognized expectation", NULL,
"GET / HTTP/1.1\r\nHost: example.com\r\nExpect: the-impossible\r\n", -1,
SOUP_STATUS_EXPECTATION_FAILED,
NULL, NULL, -1,
@@ -450,36 +450,37 @@ static const int num_reqtests = G_N_ELEMENTS (reqtests);
static struct ResponseTest {
const char *description;
+ const char *bugref;
const char *response;
int length;
SoupHTTPVersion version;
guint status_code;
const char *reason_phrase;
- Header headers[4];
+ Header headers[10];
} resptests[] = {
/***********************/
/*** VALID RESPONSES ***/
/***********************/
- { "HTTP 1.0 response w/ no headers",
+ { "HTTP 1.0 response w/ no headers", NULL,
"HTTP/1.0 200 ok\r\n", -1,
SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok",
{ { NULL } }
},
- { "HTTP 1.1 response w/ no headers",
+ { "HTTP 1.1 response w/ no headers", NULL,
"HTTP/1.1 200 ok\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { NULL } }
},
- { "Response w/ multi-word Reason-Phrase",
+ { "Response w/ multi-word Reason-Phrase", NULL,
"HTTP/1.1 400 bad request\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_BAD_REQUEST, "bad request",
{ { NULL } }
},
- { "Response w/ 1 header",
+ { "Response w/ 1 header", NULL,
"HTTP/1.1 200 ok\r\nFoo: bar\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { "Foo", "bar" },
@@ -487,7 +488,7 @@ static struct ResponseTest {
}
},
- { "Response w/ 2 headers",
+ { "Response w/ 2 headers", NULL,
"HTTP/1.1 200 ok\r\nFoo: bar\r\nBaz: quux\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { "Foo", "bar" },
@@ -496,7 +497,7 @@ static struct ResponseTest {
}
},
- { "Response w/ same header multiple times",
+ { "Response w/ same header multiple times", NULL,
"HTTP/1.1 200 ok\r\nFoo: bar\r\nFoo: baz\r\nFoo: quux\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { "Foo", "bar, baz, quux" },
@@ -504,7 +505,7 @@ static struct ResponseTest {
}
},
- { "Response w/ no reason phrase",
+ { "Response w/ no reason phrase", NULL,
"HTTP/1.1 200 \r\nFoo: bar\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "",
{ { "Foo", "bar" },
@@ -512,7 +513,7 @@ static struct ResponseTest {
}
},
- { "Connection header on HTTP/1.0 message",
+ { "Connection header on HTTP/1.0 message", NULL,
"HTTP/1.0 200 ok\r\nFoo: bar\r\nConnection: Bar\r\nBar: quux\r\n", -1,
SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok",
{ { "Foo", "bar" },
@@ -521,13 +522,26 @@ static struct ResponseTest {
}
},
+ /* Tests from Cockpit */
+
+ { "Response w/ 3 headers, check case-insensitivity", "722341",
+ "HTTP/1.0 200 ok\r\nHeader1: value3\r\nHeader2: field\r\nHead3: Another \r\n", -1,
+ SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok",
+ { { "header1", "value3" },
+ { "Header2", "field" },
+ { "hEAD3", "Another" },
+ { "Something else", NULL },
+ { NULL }
+ }
+ },
+
/*****************************/
/*** RECOVERABLE RESPONSES ***/
/*****************************/
/* RFC 2616 section 3.1 says we MUST accept this */
- { "HTTP/01.01 response",
+ { "HTTP/01.01 response", NULL,
"HTTP/01.01 200 ok\r\nFoo: bar\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { "Foo", "bar" },
@@ -537,7 +551,7 @@ static struct ResponseTest {
/* RFC 2616 section 19.3 says we SHOULD accept these */
- { "Response w/ LF instead of CRLF after Status-Line",
+ { "Response w/ LF instead of CRLF after Status-Line", NULL,
"HTTP/1.1 200 ok\nFoo: bar\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { "Foo", "bar" },
@@ -545,7 +559,7 @@ static struct ResponseTest {
}
},
- { "Response w/ incorrect spacing in Status-Line",
+ { "Response w/ incorrect spacing in Status-Line", NULL,
"HTTP/1.1 200\tok\r\nFoo: bar\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { "Foo", "bar" },
@@ -553,7 +567,7 @@ static struct ResponseTest {
}
},
- { "Response w/ no reason phrase or preceding SP",
+ { "Response w/ no reason phrase or preceding SP", NULL,
"HTTP/1.1 200\r\nFoo: bar\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "",
{ { "Foo", "bar" },
@@ -561,7 +575,7 @@ static struct ResponseTest {
}
},
- { "Response w/ no whitespace after status code",
+ { "Response w/ no whitespace after status code", NULL,
"HTTP/1.1 200ok\r\nFoo: bar\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { "Foo", "bar" },
@@ -570,7 +584,7 @@ static struct ResponseTest {
},
/* Shoutcast support */
- { "Shoutcast server not-quite-HTTP",
+ { "Shoutcast server not-quite-HTTP", "502325",
"ICY 200 OK\r\nFoo: bar\r\n", -1,
SOUP_HTTP_1_0, SOUP_STATUS_OK, "OK",
{ { "Foo", "bar" },
@@ -578,8 +592,7 @@ static struct ResponseTest {
}
},
- /* qv bug 579318, do_bad_header_tests() below */
- { "Response w/ mangled header",
+ { "Response w/ mangled header", "579318",
"HTTP/1.1 200 ok\r\nFoo: one\r\nBar two:2\r\nBaz: three\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { "Foo", "one" },
@@ -588,8 +601,7 @@ static struct ResponseTest {
}
},
- /* qv bug 602863 */
- { "HTTP 1.1 response with leading line break",
+ { "HTTP 1.1 response with leading line break", "602863",
"\nHTTP/1.1 200 ok\r\nFoo: bar\r\n", -1,
SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok",
{ { "Foo", "bar" },
@@ -600,79 +612,79 @@ static struct ResponseTest {
/*** INVALID RESPONSES ***/
/*************************/
- { "Invalid HTTP version",
+ { "Invalid HTTP version", NULL,
"HTTP/1.2 200 OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "Non-HTTP response",
+ { "Non-HTTP response", NULL,
"SOUP/1.1 200 OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "Non-numeric status code",
+ { "Non-numeric status code", NULL,
"HTTP/1.1 XXX OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "No status code",
+ { "No status code", NULL,
"HTTP/1.1 OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "One-digit status code",
+ { "One-digit status code", NULL,
"HTTP/1.1 2 OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "Two-digit status code",
+ { "Two-digit status code", NULL,
"HTTP/1.1 20 OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "Four-digit status code",
+ { "Four-digit status code", NULL,
"HTTP/1.1 2000 OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "Status code < 100",
+ { "Status code < 100", NULL,
"HTTP/1.1 001 OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "Status code > 599",
+ { "Status code > 599", NULL,
"HTTP/1.1 600 OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "NUL at start",
+ { "NUL at start", "666316",
"\x00HTTP/1.1 200 OK\r\nFoo: bar\r\n", 28,
-1, 0, NULL,
{ { NULL } }
},
- { "NUL in Reason Phrase",
+ { "NUL in Reason Phrase", NULL,
"HTTP/1.1 200 O\x00K\r\nFoo: bar\r\n", 28,
-1, 0, NULL,
{ { NULL } }
},
- { "NUL in header name",
+ { "NUL in header name", NULL,
"HTTP/1.1 200 OK\r\nF\x00oo: bar\r\n", 28,
-1, 0, NULL,
{ { NULL } }
},
- { "NUL in header value",
+ { "NUL in header value", NULL,
"HTTP/1.1 200 OK\r\nFoo: b\x00ar\r\n", 28,
-1, 0, NULL,
{ { NULL } }
@@ -704,18 +716,11 @@ static struct QValueTest {
static const int num_qvaluetests = G_N_ELEMENTS (qvaluetests);
static void
-print_header (const char *name, const char *value, gpointer data)
-{
- debug_printf (1, " '%s': '%s'\n", name, value);
-}
-
-static gboolean
check_headers (Header *headers, SoupMessageHeaders *hdrs)
{
GSList *header_names, *h;
SoupMessageHeadersIter iter;
const char *name, *value;
- gboolean ok = TRUE;
int i;
header_names = NULL;
@@ -727,36 +732,33 @@ check_headers (Header *headers, SoupMessageHeaders *hdrs)
}
for (i = 0, h = header_names; headers[i].name && h; i++, h = h->next) {
- if (strcmp (h->data, headers[i].name) != 0) {
- ok = FALSE;
- break;
- }
+ g_assert (g_ascii_strcasecmp (h->data, headers[i].name) == 0);
+
value = soup_message_headers_get_list (hdrs, headers[i].name);
- if (strcmp (value, headers[i].value) != 0) {
- ok = FALSE;
- break;
- }
+ g_assert_cmpstr (value, ==, headers[i].value);
+ }
+ /* If we have remaining fields to check, they should return NULL */
+ for (; headers[i].name; i++) {
+ value = soup_message_headers_get_list (hdrs, headers[i].name);
+ g_assert_null (value);
}
- if (headers[i].name || h)
- ok = FALSE;
+ g_assert_null (headers[i].name);
+ g_assert_null (h);
+
g_slist_free (header_names);
- return ok;
}
static void
do_request_tests (void)
{
- int i, len, h;
+ int i, len;
char *method, *path;
SoupHTTPVersion version;
SoupMessageHeaders *headers;
guint status;
- debug_printf (1, "Request tests\n");
for (i = 0; i < num_reqtests; i++) {
- gboolean ok = TRUE;
-
- debug_printf (1, "%2d. %s (%s): ", i + 1, reqtests[i].description,
+ debug_printf (1, "%2d. %s (%s)\n", i + 1, reqtests[i].description,
soup_status_get_phrase (reqtests[i].status));
headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_REQUEST);
@@ -769,71 +771,32 @@ do_request_tests (void)
status = soup_headers_parse_request (reqtests[i].request, len,
headers, &method, &path,
&version);
+ g_assert_cmpint (status, ==, reqtests[i].status);
if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
- if ((reqtests[i].method && strcmp (reqtests[i].method, method) != 0) || !reqtests[i].method)
- ok = FALSE;
- if ((reqtests[i].path && strcmp (reqtests[i].path, path) != 0) || !reqtests[i].path)
- ok = FALSE;
- if (reqtests[i].version != version)
- ok = FALSE;
-
- if (!check_headers (reqtests[i].headers, headers))
- ok = FALSE;
- } else {
- if (status != reqtests[i].status)
- ok = FALSE;
- }
+ g_assert_cmpstr (method, ==, reqtests[i].method);
+ g_assert_cmpstr (path, ==, reqtests[i].path);
+ g_assert_cmpint (version, ==, reqtests[i].version);
- if (ok)
- debug_printf (1, "OK!\n");
- else {
- debug_printf (1, "BAD!\n");
- errors++;
- if (reqtests[i].method) {
- debug_printf (1, " expected: '%s' '%s' 'HTTP/1.%d'\n",
- reqtests[i].method,
- reqtests[i].path,
- reqtests[i].version);
- for (h = 0; reqtests[i].headers[h].name; h++) {
- debug_printf (1, " '%s': '%s'\n",
- reqtests[i].headers[h].name,
- reqtests[i].headers[h].value);
- }
- } else {
- debug_printf (1, " expected: %s\n",
- soup_status_get_phrase (reqtests[i].status));
- }
- if (method) {
- debug_printf (1, " got: '%s' '%s' 'HTTP/1.%d'\n",
- method, path, version);
- soup_message_headers_foreach (headers, print_header, NULL);
- } else {
- debug_printf (1, " got: %s\n",
- soup_status_get_phrase (status));
- }
+ check_headers (reqtests[i].headers, headers);
}
g_free (method);
g_free (path);
soup_message_headers_free (headers);
}
- debug_printf (1, "\n");
}
static void
do_response_tests (void)
{
- int i, len, h;
+ int i, len;
guint status_code;
char *reason_phrase;
SoupHTTPVersion version;
SoupMessageHeaders *headers;
- debug_printf (1, "Response tests\n");
for (i = 0; i < num_resptests; i++) {
- gboolean ok = TRUE;
-
- debug_printf (1, "%2d. %s (%s): ", i + 1, resptests[i].description,
+ debug_printf (1, "%2d. %s (%s)\n", i + 1, resptests[i].description,
resptests[i].reason_phrase ? "should parse" : "should NOT parse");
headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
@@ -846,49 +809,17 @@ do_response_tests (void)
if (soup_headers_parse_response (resptests[i].response, len,
headers, &version,
&status_code, &reason_phrase)) {
- if (resptests[i].version != version)
- ok = FALSE;
- if (resptests[i].status_code != status_code)
- ok = FALSE;
- if ((resptests[i].reason_phrase && strcmp (resptests[i].reason_phrase, reason_phrase) != 0) || !resptests[i].reason_phrase)
- ok = FALSE;
-
- if (!check_headers (resptests[i].headers, headers))
- ok = FALSE;
- } else {
- if (resptests[i].reason_phrase)
- ok = FALSE;
- }
+ g_assert_cmpint (version, ==, resptests[i].version);
+ g_assert_cmpint (status_code, ==, resptests[i].status_code);
+ g_assert_cmpstr (reason_phrase, ==, resptests[i].reason_phrase);
- if (ok)
- debug_printf (1, "OK!\n");
- else {
- debug_printf (1, "BAD!\n");
- errors++;
- if (resptests[i].reason_phrase) {
- debug_printf (1, " expected: 'HTTP/1.%d' '%03d' '%s'\n",
- resptests[i].version,
- resptests[i].status_code,
- resptests[i].reason_phrase);
- for (h = 0; resptests[i].headers[h].name; h++) {
- debug_printf (1, " '%s': '%s'\n",
- resptests[i].headers[h].name,
- resptests[i].headers[h].value);
- }
- } else
- debug_printf (1, " expected: parse error\n");
- if (reason_phrase) {
- debug_printf (1, " got: 'HTTP/1.%d' '%03d' '%s'\n",
- version, status_code, reason_phrase);
- soup_message_headers_foreach (headers, print_header, NULL);
- } else
- debug_printf (1, " got: parse error\n");
- }
+ check_headers (resptests[i].headers, headers);
+ } else
+ g_assert_null (resptests[i].reason_phrase);
g_free (reason_phrase);
soup_message_headers_free (headers);
}
- debug_printf (1, "\n");
}
static void
@@ -896,9 +827,7 @@ do_qvalue_tests (void)
{
int i, j;
GSList *acceptable, *unacceptable, *iter;
- gboolean wrong;
- debug_printf (1, "qvalue tests\n");
for (i = 0; i < num_qvaluetests; i++) {
debug_printf (1, "%2d. %s:\n", i + 1, qvaluetests[i].header_value);
@@ -907,48 +836,26 @@ do_qvalue_tests (void)
&unacceptable);
debug_printf (1, " acceptable: ");
- wrong = FALSE;
if (acceptable) {
for (iter = acceptable, j = 0; iter; iter = iter->next, j++) {
debug_printf (1, "%s ", (char *)iter->data);
- if (!qvaluetests[i].acceptable[j] ||
- strcmp (iter->data, qvaluetests[i].acceptable[j]) != 0)
- wrong = TRUE;
+ g_assert_cmpstr (iter->data, ==, qvaluetests[i].acceptable[j]);
}
debug_printf (1, "\n");
soup_header_free_list (acceptable);
} else
debug_printf (1, "(none)\n");
- if (wrong) {
- debug_printf (1, " WRONG! expected: ");
- for (j = 0; qvaluetests[i].acceptable[j]; j++)
- debug_printf (1, "%s ", qvaluetests[i].acceptable[j]);
- debug_printf (1, "\n");
- errors++;
- }
debug_printf (1, " unacceptable: ");
- wrong = FALSE;
if (unacceptable) {
for (iter = unacceptable, j = 0; iter; iter = iter->next, j++) {
debug_printf (1, "%s ", (char *)iter->data);
- if (!qvaluetests[i].unacceptable[j] ||
- strcmp (iter->data, qvaluetests[i].unacceptable[j]) != 0)
- wrong = TRUE;
+ g_assert_cmpstr (iter->data, ==, qvaluetests[i].unacceptable[j]);
}
debug_printf (1, "\n");
soup_header_free_list (unacceptable);
} else
debug_printf (1, "(none)\n");
- if (wrong) {
- debug_printf (1, " WRONG! expected: ");
- for (j = 0; qvaluetests[i].unacceptable[j]; j++)
- debug_printf (1, "%s ", qvaluetests[i].unacceptable[j]);
- debug_printf (1, "\n");
- errors++;
- }
-
- debug_printf (1, "\n");
}
}
@@ -972,8 +879,6 @@ do_content_disposition_tests (void)
SoupMultipart *multipart;
SoupMessageBody *body;
- debug_printf (1, "Content-Disposition tests\n");
-
hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART);
params = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (params, "filename", RFC5987_TEST_FILENAME);
@@ -981,13 +886,7 @@ do_content_disposition_tests (void)
g_hash_table_destroy (params);
header = soup_message_headers_get_one (hdrs, "Content-Disposition");
- if (!strcmp (header, RFC5987_TEST_HEADER_ENCODED))
- debug_printf (1, " encoded OK\n");
- else {
- debug_printf (1, " encoding FAILED!\n expected: %s\n got: %s\n",
- RFC5987_TEST_HEADER_ENCODED, header);
- errors++;
- }
+ g_assert_cmpstr (header, ==, RFC5987_TEST_HEADER_ENCODED);
/* UTF-8 decoding */
soup_message_headers_clear (hdrs);
@@ -996,22 +895,13 @@ do_content_disposition_tests (void)
if (!soup_message_headers_get_content_disposition (hdrs,
&disposition,
&params)) {
- debug_printf (1, " UTF-8 decoding FAILED!\n could not parse\n");
- errors++;
+ soup_test_assert (FALSE, "UTF-8 decoding FAILED");
return;
}
g_free (disposition);
filename = g_hash_table_lookup (params, "filename");
- if (!filename) {
- debug_printf (1, " UTF-8 decoding FAILED!\n could not find filename\n");
- errors++;
- } else if (strcmp (filename, RFC5987_TEST_FILENAME) != 0) {
- debug_printf (1, " UTF-8 decoding FAILED!\n expected: %s\n got: %s\n",
- RFC5987_TEST_FILENAME, filename);
- errors++;
- } else
- debug_printf (1, " UTF-8 decoded OK\n");
+ g_assert_cmpstr (filename, ==, RFC5987_TEST_FILENAME);
g_hash_table_destroy (params);
/* ISO-8859-1 decoding */
@@ -1021,22 +911,13 @@ do_content_disposition_tests (void)
if (!soup_message_headers_get_content_disposition (hdrs,
&disposition,
&params)) {
- debug_printf (1, " iso-8859-1 decoding FAILED!\n could not parse\n");
- errors++;
+ soup_test_assert (FALSE, "iso-8859-1 decoding FAILED");
return;
}
g_free (disposition);
filename = g_hash_table_lookup (params, "filename");
- if (!filename) {
- debug_printf (1, " iso-8859-1 decoding FAILED!\n could not find filename\n");
- errors++;
- } else if (strcmp (filename, RFC5987_TEST_FILENAME) != 0) {
- debug_printf (1, " iso-8859-1 decoding FAILED!\n expected: %s\n got: %s\n",
- RFC5987_TEST_FILENAME, filename);
- errors++;
- } else
- debug_printf (1, " iso-8859-1 decoded OK\n");
+ g_assert_cmpstr (filename, ==, RFC5987_TEST_FILENAME);
g_hash_table_destroy (params);
/* Fallback */
@@ -1046,27 +927,19 @@ do_content_disposition_tests (void)
if (!soup_message_headers_get_content_disposition (hdrs,
&disposition,
&params)) {
- debug_printf (1, " fallback decoding FAILED!\n could not parse\n");
- errors++;
+ soup_test_assert (FALSE, "fallback decoding FAILED");
return;
}
g_free (disposition);
filename = g_hash_table_lookup (params, "filename");
- if (!filename) {
- debug_printf (1, " fallback decoding FAILED!\n could not find filename\n");
- errors++;
- } else if (strcmp (filename, RFC5987_TEST_FALLBACK_FILENAME) != 0) {
- debug_printf (1, " fallback decoding FAILED!\n expected: %s\n got: %s\n",
- RFC5987_TEST_FALLBACK_FILENAME, filename);
- errors++;
- } else
- debug_printf (1, " fallback decoded OK\n");
+ g_assert_cmpstr (filename, ==, RFC5987_TEST_FALLBACK_FILENAME);
g_hash_table_destroy (params);
soup_message_headers_free (hdrs);
- /* Ensure that soup-multipart always quotes filename (bug 641280) */
+ /* Ensure that soup-multipart always quotes filename */
+ g_test_bug ("641280");
multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
buffer = soup_buffer_new (SOUP_MEMORY_STATIC, "foo", 3);
soup_multipart_append_form_file (multipart, "test", "token",
@@ -1082,15 +955,9 @@ do_content_disposition_tests (void)
buffer = soup_message_body_flatten (body);
soup_message_body_free (body);
- if (strstr (buffer->data, "filename=\"token\""))
- debug_printf (1, " SoupMultipart encoded filename correctly\n");
- else {
- debug_printf (1, " SoupMultipart encoded filename incorrectly!\n");
- errors++;
- }
- soup_buffer_free (buffer);
+ g_assert_true (strstr (buffer->data, "filename=\"token\""));
- debug_printf (1, "\n");
+ soup_buffer_free (buffer);
}
#define CONTENT_TYPE_TEST_MIME_TYPE "text/plain"
@@ -1107,7 +974,7 @@ do_content_type_tests (void)
GHashTable *params;
const char *header, *mime_type;
- debug_printf (1, "Content-Type tests\n");
+ g_test_bug ("576760");
hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART);
params = g_hash_table_new (g_str_hash, g_str_equal);
@@ -1117,13 +984,7 @@ do_content_type_tests (void)
g_hash_table_destroy (params);
header = soup_message_headers_get_one (hdrs, "Content-Type");
- if (!strcmp (header, CONTENT_TYPE_TEST_HEADER))
- debug_printf (1, " encoded OK\n");
- else {
- debug_printf (1, " encoding FAILED!\n expected: %s\n got: %s\n",
- CONTENT_TYPE_TEST_HEADER, header);
- errors++;
- }
+ g_assert_cmpstr (header, ==, CONTENT_TYPE_TEST_HEADER);
soup_message_headers_clear (hdrs);
soup_message_headers_append (hdrs, "Content-Type",
@@ -1133,38 +994,20 @@ do_content_type_tests (void)
CONTENT_TYPE_TEST_MIME_TYPE);
mime_type = soup_message_headers_get_content_type (hdrs, &params);
- if (!mime_type) {
- debug_printf (1, " decoding FAILED!\n could not parse\n");
- errors++;
- }
-
- if (mime_type && strcmp (mime_type, CONTENT_TYPE_TEST_MIME_TYPE) != 0) {
- debug_printf (1, " decoding FAILED!\n bad returned MIME type: %s\n",
- mime_type);
- errors++;
- } else if (params && g_hash_table_size (params) != 0) {
- debug_printf (1, " decoding FAILED!\n params contained %d params (should be 0)\n",
- g_hash_table_size (params));
- errors++;
- } else
- debug_printf (1, " decoded OK\n");
-
+ g_assert_cmpstr (mime_type, ==, CONTENT_TYPE_TEST_MIME_TYPE);
+ g_assert_cmpint (g_hash_table_size (params), ==, 0);
if (params)
g_hash_table_destroy (params);
+ g_test_bug ("577630");
+
soup_message_headers_clear (hdrs);
soup_message_headers_append (hdrs, "Content-Type",
CONTENT_TYPE_BAD_HEADER);
mime_type = soup_message_headers_get_content_type (hdrs, &params);
- if (mime_type) {
- debug_printf (1, " Bad content rejection FAILED!\n");
- errors++;
- } else
- debug_printf (1, " Bad content rejection OK\n");
+ g_assert_null (mime_type);
soup_message_headers_free (hdrs);
-
- debug_printf (1, "\n");
}
struct {
@@ -1185,7 +1028,7 @@ do_append_param_tests (void)
GString *params;
int i;
- debug_printf (1, "soup_header_g_string_append_param() tests\n");
+ g_test_bug ("577728");
params = g_string_new (NULL);
for (i = 0; i < G_N_ELEMENTS (test_params); i++) {
@@ -1195,15 +1038,8 @@ do_append_param_tests (void)
test_params[i].name,
test_params[i].value);
}
- if (strcmp (params->str, TEST_PARAMS_RESULT) != 0) {
- debug_printf (1, " FAILED!\n expected: %s\n got: %s\n",
- TEST_PARAMS_RESULT, params->str);
- errors++;
- } else
- debug_printf (1, " OK\n");
+ g_assert_cmpstr (params->str, ==, TEST_PARAMS_RESULT);
g_string_free (params, TRUE);
-
- debug_printf (1, "\n");
}
static const struct {
@@ -1226,19 +1062,15 @@ do_bad_header_tests (void)
SoupMessageHeaders *hdrs;
int i;
- debug_printf (1, "bad header rejection tests\n");
-
hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART);
for (i = 0; i < G_N_ELEMENTS (bad_headers); i++) {
debug_printf (1, " %s\n", bad_headers[i].description);
- expect_warning = TRUE;
+
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_CRITICAL,
+ "*soup_message_headers_append*assertion*failed*");
soup_message_headers_append (hdrs, bad_headers[i].name,
bad_headers[i].value);
- if (expect_warning) {
- expect_warning = FALSE;
- debug_printf (1, " FAILED: soup_message_headers_append() did not reject it\n");
- errors++;
- }
+ g_test_assert_expected_messages ();
}
soup_message_headers_free (hdrs);
}
@@ -1246,16 +1078,20 @@ do_bad_header_tests (void)
int
main (int argc, char **argv)
{
+ int ret;
+
test_init (argc, argv, NULL);
- do_request_tests ();
- do_response_tests ();
- do_qvalue_tests ();
- do_content_disposition_tests ();
- do_content_type_tests ();
- do_append_param_tests ();
- do_bad_header_tests ();
+ g_test_add_func ("/header-parsing/request", do_request_tests);
+ g_test_add_func ("/header-parsing/response", do_response_tests);
+ g_test_add_func ("/header-parsing/qvalue", do_qvalue_tests);
+ g_test_add_func ("/header-parsing/content-disposition", do_content_disposition_tests);
+ g_test_add_func ("/header-parsing/content-type", do_content_type_tests);
+ g_test_add_func ("/header-parsing/append-param", do_append_param_tests);
+ g_test_add_func ("/header-parsing/bad", do_bad_header_tests);
+
+ ret = g_test_run ();
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/httpd.conf.in b/tests/httpd.conf.22.in
index de0b75fa..b912ca36 100644
--- a/tests/httpd.conf.in
+++ b/tests/httpd.conf.22.in
@@ -3,8 +3,7 @@
ServerName 127.0.0.1
Listen 127.0.0.1:47524
-PidFile @builddir@/httpd.pid
-DocumentRoot @srcdir@
+DocumentRoot .
# The tests shut down apache with "graceful-stop", because that makes
# it close its listening socket right away. But it seems to sometimes
@@ -83,7 +82,7 @@ Listen 127.0.0.1:47527
AuthType Basic
AuthName realm1
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require valid-user
</Proxy>
@@ -94,7 +93,7 @@ Listen 127.0.0.1:47527
AuthType Basic
AuthName realm1
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require valid-user
</Proxy>
@@ -124,7 +123,7 @@ Listen 127.0.0.1:47528
AuthType Basic
AuthName realm1
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require user no-such-user
</Proxy>
@@ -135,7 +134,7 @@ Listen 127.0.0.1:47528
AuthType Basic
AuthName realm1
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require user no-such-user
</Proxy>
@@ -154,89 +153,89 @@ Listen 127.0.0.1:47528
<VirtualHost 127.0.0.1:47525>
SSLEngine on
- SSLCertificateFile @srcdir@/test-cert.pem
- SSLCertificateKeyFile @srcdir@/test-key.pem
+ SSLCertificateFile ./test-cert.pem
+ SSLCertificateKeyFile ./test-key.pem
</VirtualHost>
</IfModule>
# Basic auth tests
-Alias /Basic/realm1/realm2/realm1 @srcdir@
-Alias /Basic/realm1/realm2 @srcdir@
-Alias /Basic/realm1/subdir @srcdir@
-Alias /Basic/realm1/not @srcdir@
-Alias /Basic/realm1 @srcdir@
-Alias /Basic/realm12/subdir @srcdir@
-Alias /Basic/realm12 @srcdir@
-Alias /Basic/realm2 @srcdir@
-Alias /Basic/realm3 @srcdir@
-Alias /Basic @srcdir@
+Alias /Basic/realm1/realm2/realm1 .
+Alias /Basic/realm1/realm2 .
+Alias /Basic/realm1/subdir .
+Alias /Basic/realm1/not .
+Alias /Basic/realm1 .
+Alias /Basic/realm12/subdir .
+Alias /Basic/realm12 .
+Alias /Basic/realm2 .
+Alias /Basic/realm3 .
+Alias /Basic .
<Location /Basic/realm1>
AuthType Basic
AuthName realm1
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require user user1
</Location>
<Location /Basic/realm1/not>
AuthType Basic
AuthName realm1
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require user user2
</Location>
<Location /Basic/realm12>
AuthType Basic
AuthName realm12
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require user user1 user2
</Location>
<Location /Basic/realm1/realm2>
AuthType Basic
AuthName realm2
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require user user2
</Location>
<Location /Basic/realm1/realm2/realm1>
AuthType Basic
AuthName realm1
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require user user1
</Location>
<Location /Basic/realm2>
AuthType Basic
AuthName realm2
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require user user2
</Location>
<Location /Basic/realm3>
AuthType Basic
AuthName realm3
- AuthUserFile @srcdir@/htpasswd
+ AuthUserFile ./htpasswd
Require user user3
</Location>
# Digest auth tests
-Alias /Digest/realm1/realm2/realm1 @srcdir@
-Alias /Digest/realm1/realm2 @srcdir@
-Alias /Digest/realm1/subdir @srcdir@
-Alias /Digest/realm1/expire @srcdir@
-Alias /Digest/realm1/not @srcdir@
-Alias /Digest/realm1 @srcdir@
-Alias /Digest/realm2 @srcdir@
-Alias /Digest/realm3 @srcdir@
-Alias /Digest @srcdir@
+Alias /Digest/realm1/realm2/realm1 .
+Alias /Digest/realm1/realm2 .
+Alias /Digest/realm1/subdir .
+Alias /Digest/realm1/expire .
+Alias /Digest/realm1/not .
+Alias /Digest/realm1 .
+Alias /Digest/realm2 .
+Alias /Digest/realm3 .
+Alias /Digest .
<Location /Digest/realm1>
AuthType Digest
AuthName realm1
- AuthUserFile @srcdir@/htdigest
+ AuthUserFile ./htdigest
AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1
Require valid-user
</Location>
@@ -244,7 +243,7 @@ Alias /Digest @srcdir@
<Location /Digest/realm1/expire>
AuthType Digest
AuthName realm1
- AuthUserFile @srcdir@/htdigest
+ AuthUserFile ./htdigest
AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1
AuthDigestNonceLifetime 2
Require valid-user
@@ -253,7 +252,7 @@ Alias /Digest @srcdir@
<Location /Digest/realm1/not>
AuthType Digest
AuthName realm1
- AuthUserFile @srcdir@/htdigest
+ AuthUserFile ./htdigest
AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1
Require user user2
</Location>
@@ -261,7 +260,7 @@ Alias /Digest @srcdir@
<Location /Digest/realm1/realm2>
AuthType Digest
AuthName realm2
- AuthUserFile @srcdir@/htdigest
+ AuthUserFile ./htdigest
AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2
Require valid-user
</Location>
@@ -269,7 +268,7 @@ Alias /Digest @srcdir@
<Location /Digest/realm1/realm2/realm1>
AuthType Digest
AuthName realm1
- AuthUserFile @srcdir@/htdigest
+ AuthUserFile ./htdigest
AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1
Require valid-user
</Location>
@@ -277,7 +276,7 @@ Alias /Digest @srcdir@
<Location /Digest/realm2>
AuthType Digest
AuthName realm2
- AuthUserFile @srcdir@/htdigest
+ AuthUserFile ./htdigest
AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2
Require valid-user
</Location>
@@ -285,7 +284,7 @@ Alias /Digest @srcdir@
<Location /Digest/realm3>
AuthType Digest
AuthName realm3
- AuthUserFile @srcdir@/htdigest
+ AuthUserFile ./htdigest
AuthDigestDomain /Digest/realm3
Require valid-user
# test RFC2069-style Digest
diff --git a/tests/httpd.conf.24.in b/tests/httpd.conf.24.in
new file mode 100644
index 00000000..850b8393
--- /dev/null
+++ b/tests/httpd.conf.24.in
@@ -0,0 +1,276 @@
+# http.conf used for testing auth-test
+
+ServerName 127.0.0.1
+Listen 127.0.0.1:47524
+
+DocumentRoot .
+
+# The tests shut down apache with "graceful-stop", because that makes
+# it close its listening socket right away. But it seems to sometimes
+# result in apache never fully exiting. This fixes that.
+GracefulShutdownTimeout 1
+
+# Change this to "./error.log" if it's failing and you don't know why
+ErrorLog /dev/null
+
+LoadModule mpm_prefork_module @APACHE_MODULE_DIR@/mod_mpm_prefork.so
+LoadModule alias_module @APACHE_MODULE_DIR@/mod_alias.so
+LoadModule auth_basic_module @APACHE_MODULE_DIR@/mod_auth_basic.so
+LoadModule auth_digest_module @APACHE_MODULE_DIR@/mod_auth_digest.so
+LoadModule authn_core_module @APACHE_MODULE_DIR@/mod_authn_core.so
+LoadModule authn_file_module @APACHE_MODULE_DIR@/mod_authn_file.so
+LoadModule authz_core_module @APACHE_MODULE_DIR@/mod_authz_core.so
+LoadModule authz_host_module @APACHE_MODULE_DIR@/mod_authz_host.so
+LoadModule authz_user_module @APACHE_MODULE_DIR@/mod_authz_user.so
+LoadModule dir_module @APACHE_MODULE_DIR@/mod_dir.so
+LoadModule mime_module @APACHE_MODULE_DIR@/mod_mime.so
+@IF_HAVE_PHP@LoadModule php5_module @APACHE_PHP_MODULE_DIR@/@APACHE_PHP_MODULE@
+LoadModule proxy_module @APACHE_MODULE_DIR@/mod_proxy.so
+LoadModule proxy_http_module @APACHE_MODULE_DIR@/mod_proxy_http.so
+LoadModule proxy_connect_module @APACHE_MODULE_DIR@/mod_proxy_connect.so
+LoadModule ssl_module @APACHE_SSL_MODULE_DIR@/mod_ssl.so
+LoadModule unixd_module @APACHE_SSL_MODULE_DIR@/mod_unixd.so
+
+DirectoryIndex index.txt
+TypesConfig /dev/null
+AddType application/x-httpd-php .php
+Redirect permanent /redirected /index.txt
+
+# Proxy #1: unauthenticated
+Listen 127.0.0.1:47526
+<VirtualHost 127.0.0.1:47526>
+ ProxyRequests On
+ AllowCONNECT 47525
+
+ # Deny proxying by default
+ <Proxy *>
+ Require all denied
+ </Proxy>
+
+ # Allow local http connections
+ <Proxy http://127.0.0.1*>
+ Require all granted
+ </Proxy>
+
+ # Allow CONNECT to local https port
+ <Proxy 127.0.0.1:47525>
+ Require all granted
+ </Proxy>
+
+ # Deny non-proxy requests
+ <Directory />
+ Require all denied
+ </Directory>
+</VirtualHost>
+
+# Proxy #2: authenticated
+Listen 127.0.0.1:47527
+<VirtualHost 127.0.0.1:47527>
+ ProxyRequests On
+ AllowCONNECT 47525
+
+ # Deny proxying by default
+ <Proxy *>
+ Require all denied
+ </Proxy>
+
+ # Allow local http connections with authentication
+ <Proxy http://127.0.0.1:47524*>
+ AuthType Basic
+ AuthName realm1
+ AuthUserFile ./htpasswd
+ Require valid-user
+ </Proxy>
+
+ # Allow CONNECT to local https port with authentication
+ <Proxy 127.0.0.1:47525>
+ AuthType Basic
+ AuthName realm1
+ AuthUserFile ./htpasswd
+ Require valid-user
+ </Proxy>
+
+ # Fail non-proxy requests
+ <Directory />
+ Require all denied
+ </Directory>
+</VirtualHost>
+
+# Proxy #3: unauthenticatable-to
+Listen 127.0.0.1:47528
+<VirtualHost 127.0.0.1:47528>
+ ProxyRequests On
+ AllowCONNECT 47525
+
+ # Deny proxying by default
+ <Proxy *>
+ Require all denied
+ </Proxy>
+
+ # Allow local http connections with authentication
+ <Proxy http://127.0.0.1:47524*>
+ AuthType Basic
+ AuthName realm1
+ AuthUserFile ./htpasswd
+ Require user no-such-user
+ </Proxy>
+
+ # Allow CONNECT to local https port with authentication
+ <Proxy 127.0.0.1:47525>
+ AuthType Basic
+ AuthName realm1
+ AuthUserFile ./htpasswd
+ Require user no-such-user
+ </Proxy>
+
+ # Fail non-proxy requests
+ <Directory />
+ Require all denied
+ </Directory>
+</VirtualHost>
+
+
+# SSL setup
+<IfModule mod_ssl.c>
+ Listen 127.0.0.1:47525
+
+ <VirtualHost 127.0.0.1:47525>
+ SSLEngine on
+
+ SSLCertificateFile ./test-cert.pem
+ SSLCertificateKeyFile ./test-key.pem
+
+ </VirtualHost>
+</IfModule>
+
+
+# Basic auth tests
+Alias /Basic/realm1/realm2/realm1 .
+Alias /Basic/realm1/realm2 .
+Alias /Basic/realm1/subdir .
+Alias /Basic/realm1/not .
+Alias /Basic/realm1 .
+Alias /Basic/realm12/subdir .
+Alias /Basic/realm12 .
+Alias /Basic/realm2 .
+Alias /Basic/realm3 .
+Alias /Basic .
+
+<Location /Basic/realm1>
+ AuthType Basic
+ AuthName realm1
+ AuthUserFile ./htpasswd
+ Require user user1
+</Location>
+
+<Location /Basic/realm1/not>
+ AuthType Basic
+ AuthName realm1
+ AuthUserFile ./htpasswd
+ Require user user2
+</Location>
+
+<Location /Basic/realm12>
+ AuthType Basic
+ AuthName realm12
+ AuthUserFile ./htpasswd
+ Require user user1 user2
+</Location>
+
+<Location /Basic/realm1/realm2>
+ AuthType Basic
+ AuthName realm2
+ AuthUserFile ./htpasswd
+ Require user user2
+</Location>
+
+<Location /Basic/realm1/realm2/realm1>
+ AuthType Basic
+ AuthName realm1
+ AuthUserFile ./htpasswd
+ Require user user1
+</Location>
+
+<Location /Basic/realm2>
+ AuthType Basic
+ AuthName realm2
+ AuthUserFile ./htpasswd
+ Require user user2
+</Location>
+
+<Location /Basic/realm3>
+ AuthType Basic
+ AuthName realm3
+ AuthUserFile ./htpasswd
+ Require user user3
+</Location>
+
+# Digest auth tests
+Alias /Digest/realm1/realm2/realm1 .
+Alias /Digest/realm1/realm2 .
+Alias /Digest/realm1/subdir .
+Alias /Digest/realm1/expire .
+Alias /Digest/realm1/not .
+Alias /Digest/realm1 .
+Alias /Digest/realm2 .
+Alias /Digest/realm3 .
+Alias /Digest .
+
+<Location /Digest/realm1>
+ AuthType Digest
+ AuthName realm1
+ AuthUserFile ./htdigest
+ AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1
+ Require valid-user
+</Location>
+
+<Location /Digest/realm1/expire>
+ AuthType Digest
+ AuthName realm1
+ AuthUserFile ./htdigest
+ AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1
+ AuthDigestNonceLifetime 2
+ Require valid-user
+</Location>
+
+<Location /Digest/realm1/not>
+ AuthType Digest
+ AuthName realm1
+ AuthUserFile ./htdigest
+ AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1
+ Require user user2
+</Location>
+
+<Location /Digest/realm1/realm2>
+ AuthType Digest
+ AuthName realm2
+ AuthUserFile ./htdigest
+ AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2
+ Require valid-user
+</Location>
+
+<Location /Digest/realm1/realm2/realm1>
+ AuthType Digest
+ AuthName realm1
+ AuthUserFile ./htdigest
+ AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1
+ Require valid-user
+</Location>
+
+<Location /Digest/realm2>
+ AuthType Digest
+ AuthName realm2
+ AuthUserFile ./htdigest
+ AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2
+ Require valid-user
+</Location>
+
+<Location /Digest/realm3>
+ AuthType Digest
+ AuthName realm3
+ AuthUserFile ./htdigest
+ AuthDigestDomain /Digest/realm3
+ Require valid-user
+ # test RFC2069-style Digest
+ AuthDigestQop none
+</Location>
diff --git a/tests/libsoup.supp b/tests/libsoup.supp
index 24c6516a..ae8bda38 100644
--- a/tests/libsoup.supp
+++ b/tests/libsoup.supp
@@ -321,7 +321,7 @@
...
fun:_dl_allocate_tls
...
- fun:g_thread_create_posix_impl
+ fun:g_system_thread_new
}
{
glib/filenamecharsets
@@ -342,12 +342,78 @@
fun:g_tls_backend_gnutls_store_session
}
{
+ glib/gtlssessioncache_client
+ Memcheck:Leak
+ ...
+ fun:gnutls_session_get_data2
+ fun:g_tls_client_connection_gnutls_finish_handshake
+}
+{
+ glib/gtlssessioncache_client2
+ Memcheck:Leak
+ ...
+ fun:g_bytes_new_with_free_func
+ fun:g_tls_client_connection_gnutls_finish_handshake
+}
+{
+ glib/gtlssessioncache_client3
+ Memcheck:Leak
+ ...
+ fun:g_bytes_new_take
+ fun:g_tls_client_connection_gnutls_constructed
+}
+{
+ glib/gtlssessioncache_client4
+ Memcheck:Leak
+ ...
+ fun:g_strdup_printf
+ fun:g_tls_client_connection_gnutls_constructed
+}
+{
+ glib/gtlssessioncache_server
+ Memcheck:Leak
+ ...
+ fun:g_tls_server_connection_gnutls_db_store
+}
+{
glib/cached_poll_array
Memcheck:Leak
...
fun:g_malloc_n
fun:g_main_context_iterate
}
+{
+ glib/rand
+ Memcheck:Leak
+ ...
+ fun:g_rand_new
+ fun:g_random_int_range
+}
+{
+ glib/g_cancellable_push_current
+ Memcheck:Leak
+ ...
+ fun:g_cancellable_push_current
+}
+{
+ glib/slice_thread_local
+ Memcheck:Leak
+ ...
+ fun:thread_memory_from_self
+}
+{
+ glib/gobjectinit
+ Memcheck:Leak
+ ...
+ fun:gobject_init_ctor
+}
+{
+ glib/gtask threadpool
+ Memcheck:Leak
+ ...
+ fun:g_thread_pool_new
+ fun:g_task_thread_pool_init
+}
# probably inlines the aggressive memcpy/memcmp
{
@@ -421,6 +487,12 @@
...
fun:intern_header_name
}
+{
+ libsoup/tlds
+ Memcheck:Leak
+ ...
+ fun:soup_tld_ensure_rules_hash_table
+}
# fixme?
diff --git a/tests/misc-test.c b/tests/misc-test.c
index 605fa216..00559a03 100644
--- a/tests/misc-test.c
+++ b/tests/misc-test.c
@@ -32,16 +32,6 @@ server_callback (SoupServer *server, SoupMessage *msg,
SoupURI *uri = soup_message_get_uri (msg);
const char *server_protocol = data;
- soup_message_headers_append (msg->response_headers,
- "X-Handled-By", "server_callback");
-
- if (!strcmp (path, "*")) {
- debug_printf (1, " default server_callback got request for '*'!\n");
- errors++;
- soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
- return;
- }
-
if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) {
soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
return;
@@ -99,32 +89,8 @@ server_callback (SoupServer *server, SoupMessage *msg,
}
}
-static void
-server_star_callback (SoupServer *server, SoupMessage *msg,
- const char *path, GHashTable *query,
- SoupClientContext *context, gpointer data)
-{
- soup_message_headers_append (msg->response_headers,
- "X-Handled-By", "star_callback");
-
- if (strcmp (path, "*") != 0) {
- debug_printf (1, " server_star_callback got request for '%s'!\n", path);
- errors++;
- soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
- return;
- }
-
- if (msg->method != SOUP_METHOD_OPTIONS) {
- soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED);
- return;
- }
-
- soup_message_set_status (msg, SOUP_STATUS_OK);
-}
-
/* Host header handling: client must be able to override the default
* value, server must be able to recognize different Host values.
- * #539803.
*/
static void
do_host_test (void)
@@ -132,7 +98,7 @@ do_host_test (void)
SoupSession *session;
SoupMessage *one, *two;
- debug_printf (1, "Host handling\n");
+ g_test_bug ("539803");
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
@@ -145,42 +111,24 @@ do_host_test (void)
soup_test_session_abort_unref (session);
- if (!SOUP_STATUS_IS_SUCCESSFUL (one->status_code)) {
- debug_printf (1, " Message 1 failed: %d %s\n",
- one->status_code, one->reason_phrase);
- errors++;
- } else if (strcmp (one->response_body->data, "index") != 0) {
- debug_printf (1, " Unexpected response to message 1: '%s'\n",
- one->response_body->data);
- errors++;
- }
+ soup_test_assert_message_status (one, SOUP_STATUS_OK);
+ g_assert_cmpstr (one->response_body->data, ==, "index");
g_object_unref (one);
- if (!SOUP_STATUS_IS_SUCCESSFUL (two->status_code)) {
- debug_printf (1, " Message 2 failed: %d %s\n",
- two->status_code, two->reason_phrase);
- errors++;
- } else if (strcmp (two->response_body->data, "foo-index") != 0) {
- debug_printf (1, " Unexpected response to message 2: '%s'\n",
- two->response_body->data);
- errors++;
- }
+ soup_test_assert_message_status (two, SOUP_STATUS_OK);
+ g_assert_cmpstr (two->response_body->data, ==, "foo-index");
g_object_unref (two);
}
/* Dropping the application's ref on the session from a callback
* should not cause the session to be freed at an incorrect time.
- * (This test will crash if it fails.) #533473
+ * (This test will crash if it fails.)
*/
static void
cu_one_completed (SoupSession *session, SoupMessage *msg, gpointer loop)
{
debug_printf (2, " Message 1 completed\n");
- if (msg->status_code != SOUP_STATUS_CANT_CONNECT) {
- debug_printf (1, " Unexpected status on Message 1: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_CANT_CONNECT);
g_object_unref (session);
}
@@ -195,11 +143,7 @@ static void
cu_two_completed (SoupSession *session, SoupMessage *msg, gpointer loop)
{
debug_printf (2, " Message 2 completed\n");
- if (msg->status_code != SOUP_STATUS_CANT_CONNECT) {
- debug_printf (1, " Unexpected status on Message 2: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_CANT_CONNECT);
g_idle_add (cu_idle_quit, loop);
}
@@ -213,7 +157,7 @@ do_callback_unref_test (void)
GMainLoop *loop;
char *bad_uri;
- debug_printf (1, "\nCallback unref handling (msg api)\n");
+ g_test_bug ("533473");
/* Get a guaranteed-bad URI */
addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT);
@@ -243,22 +187,19 @@ do_callback_unref_test (void)
g_main_loop_run (loop);
g_main_loop_unref (loop);
+ g_assert_null (session);
if (session) {
g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session);
- debug_printf (1, " Session not destroyed?\n");
- errors++;
g_object_unref (session);
}
+ g_assert_null (one);
if (one) {
g_object_remove_weak_pointer (G_OBJECT (one), (gpointer *)&one);
- debug_printf (1, " Message 1 not destroyed?\n");
- errors++;
g_object_unref (one);
}
+ g_assert_null (two);
if (two) {
g_object_remove_weak_pointer (G_OBJECT (two), (gpointer *)&two);
- debug_printf (1, " Message 2 not destroyed?\n");
- errors++;
g_object_unref (two);
}
@@ -272,14 +213,8 @@ cur_one_completed (GObject *source, GAsyncResult *result, gpointer session)
GError *error = NULL;
debug_printf (2, " Request 1 completed\n");
- if (soup_request_send_finish (one, result, &error)) {
- debug_printf (1, " Request 1 succeeded?\n");
- errors++;
- } else if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_CONNECT)) {
- debug_printf (1, " Unexpected error on Request 1: %s\n",
- error->message);
- errors++;
- }
+ soup_request_send_finish (one, result, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED);
g_clear_error (&error);
g_object_unref (session);
@@ -299,14 +234,8 @@ cur_two_completed (GObject *source, GAsyncResult *result, gpointer loop)
GError *error = NULL;
debug_printf (2, " Request 2 completed\n");
- if (soup_request_send_finish (two, result, &error)) {
- debug_printf (1, " Request 2 succeeded?\n");
- errors++;
- } else if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_CONNECT)) {
- debug_printf (1, " Unexpected error on Request 2: %s\n",
- error->message);
- errors++;
- }
+ soup_request_send_finish (two, result, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED);
g_clear_error (&error);
g_idle_add (cur_idle_quit, loop);
@@ -318,13 +247,10 @@ do_callback_unref_req_test (void)
SoupServer *bad_server;
SoupAddress *addr;
SoupSession *session;
- SoupRequester *requester;
SoupRequest *one, *two;
GMainLoop *loop;
char *bad_uri;
- debug_printf (1, "\nCallback unref handling (request api)\n");
-
/* Get a guaranteed-bad URI */
addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT);
soup_address_resolve_sync (addr, NULL);
@@ -337,18 +263,15 @@ do_callback_unref_req_test (void)
g_object_unref (bad_server);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session);
- requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
-
loop = g_main_loop_new (NULL, TRUE);
- one = soup_requester_request (requester, bad_uri, NULL);
+ one = soup_session_request (session, bad_uri, NULL);
g_object_add_weak_pointer (G_OBJECT (one), (gpointer *)&one);
- two = soup_requester_request (requester, bad_uri, NULL);
+ two = soup_session_request (session, bad_uri, NULL);
g_object_add_weak_pointer (G_OBJECT (two), (gpointer *)&two);
g_free (bad_uri);
@@ -360,22 +283,19 @@ do_callback_unref_req_test (void)
g_main_loop_run (loop);
g_main_loop_unref (loop);
+ g_assert_null (session);
if (session) {
g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session);
- debug_printf (1, " Session not destroyed?\n");
- errors++;
g_object_unref (session);
}
+ g_assert_null (one);
if (one) {
g_object_remove_weak_pointer (G_OBJECT (one), (gpointer *)&one);
- debug_printf (1, " Request 1 not destroyed?\n");
- errors++;
g_object_unref (one);
}
+ g_assert_null (two);
if (two) {
g_object_remove_weak_pointer (G_OBJECT (two), (gpointer *)&two);
- debug_printf (1, " Request 2 not destroyed?\n");
- errors++;
g_object_unref (two);
}
@@ -384,20 +304,19 @@ do_callback_unref_req_test (void)
/* SoupSession should clean up all signal handlers on a message after
* it is finished, allowing the message to be reused if desired.
- * #559054
*/
static void
ensure_no_signal_handlers (SoupMessage *msg, guint *signal_ids, guint n_signal_ids)
{
int i;
+ guint id;
for (i = 0; i < n_signal_ids; i++) {
- if (g_signal_handler_find (msg, G_SIGNAL_MATCH_ID, signal_ids[i],
- 0, NULL, NULL, NULL)) {
- debug_printf (1, " Message has handler for '%s'\n",
- g_signal_name (signal_ids[i]));
- errors++;
- }
+ id = g_signal_handler_find (msg, G_SIGNAL_MATCH_ID, signal_ids[i],
+ 0, NULL, NULL, NULL);
+ soup_test_assert (id == 0,
+ "message has handler for '%s'",
+ g_signal_name (signal_ids[i]));
}
}
@@ -420,7 +339,7 @@ do_msg_reuse_test (void)
SoupURI *uri;
guint *signal_ids, n_signal_ids;
- debug_printf (1, "\nSoupMessage reuse\n");
+ g_test_bug ("559054");
signal_ids = g_signal_list_ids (SOUP_TYPE_MESSAGE, &n_signal_ids);
@@ -438,10 +357,7 @@ do_msg_reuse_test (void)
soup_message_set_uri (msg, uri);
soup_uri_free (uri);
soup_session_send_message (session, msg);
- if (!soup_uri_equal (soup_message_get_uri (msg), base_uri)) {
- debug_printf (1, " Message did not get redirected!\n");
- errors++;
- }
+ g_assert_true (soup_uri_equal (soup_message_get_uri (msg), base_uri));
ensure_no_signal_handlers (msg, signal_ids, n_signal_ids);
debug_printf (1, " Auth message\n");
@@ -449,10 +365,7 @@ do_msg_reuse_test (void)
soup_message_set_uri (msg, uri);
soup_uri_free (uri);
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " Message did not get authenticated!\n");
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
ensure_no_signal_handlers (msg, signal_ids, n_signal_ids);
/* One last try to make sure the auth stuff got cleaned up */
@@ -466,79 +379,12 @@ do_msg_reuse_test (void)
g_free (signal_ids);
}
-/* Server handlers for "*" work but are separate from handlers for
- * all other URIs. #590751
- */
-static void
-do_star_test (void)
-{
- SoupSession *session;
- SoupMessage *msg;
- SoupURI *star_uri;
- const char *handled_by;
-
- debug_printf (1, "\nOPTIONS *\n");
-
- session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
- star_uri = soup_uri_copy (base_uri);
- soup_uri_set_path (star_uri, "*");
-
- debug_printf (1, " Testing with no handler\n");
- msg = soup_message_new_from_uri ("OPTIONS", star_uri);
- soup_session_send_message (session, msg);
-
- if (msg->status_code != SOUP_STATUS_NOT_FOUND) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
- handled_by = soup_message_headers_get_one (msg->response_headers,
- "X-Handled-By");
- if (handled_by) {
- /* Should have been rejected by SoupServer directly */
- debug_printf (1, " Message reached handler '%s'\n",
- handled_by);
- errors++;
- }
- g_object_unref (msg);
-
- soup_server_add_handler (server, "*", server_star_callback, NULL, NULL);
-
- debug_printf (1, " Testing with handler\n");
- msg = soup_message_new_from_uri ("OPTIONS", star_uri);
- soup_session_send_message (session, msg);
-
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
- handled_by = soup_message_headers_get_one (msg->response_headers,
- "X-Handled-By");
- if (!handled_by) {
- debug_printf (1, " Message did not reach handler!\n");
- errors++;
- } else if (strcmp (handled_by, "star_callback") != 0) {
- debug_printf (1, " Message reached incorrect handler '%s'\n",
- handled_by);
- errors++;
- }
- g_object_unref (msg);
-
- soup_test_session_abort_unref (session);
- soup_uri_free (star_uri);
-}
-
-/* Handle unexpectedly-early aborts. #596074, #618641 */
+/* Handle unexpectedly-early aborts. */
static void
ea_msg_completed_one (SoupSession *session, SoupMessage *msg, gpointer loop)
{
debug_printf (2, " Message 1 completed\n");
- if (msg->status_code != SOUP_STATUS_CANCELLED) {
- debug_printf (1, " Unexpected status on Message 1: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
g_main_loop_quit (loop);
}
@@ -585,7 +431,8 @@ do_early_abort_test (void)
GMainContext *context;
GMainLoop *loop;
- debug_printf (1, "\nAbort with pending connection (msg api)\n");
+ g_test_bug ("596074");
+ g_test_bug ("618641");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
msg = soup_message_new_from_uri ("GET", base_uri);
@@ -609,11 +456,7 @@ do_early_abort_test (void)
soup_session_send_message (session, msg);
debug_printf (2, " Message 2 completed\n");
- if (msg->status_code != SOUP_STATUS_CANCELLED) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
g_object_unref (msg);
while (g_main_context_pending (context))
@@ -621,6 +464,8 @@ do_early_abort_test (void)
soup_test_session_abort_unref (session);
+ g_test_bug ("668098");
+
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
msg = soup_message_new_from_uri ("GET", base_uri);
@@ -629,11 +474,7 @@ do_early_abort_test (void)
soup_session_send_message (session, msg);
debug_printf (2, " Message 3 completed\n");
- if (msg->status_code != SOUP_STATUS_CANCELLED) {
- debug_printf (1, " Unexpected response: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
g_object_unref (msg);
while (g_main_context_pending (context))
@@ -648,14 +489,8 @@ ear_one_completed (GObject *source, GAsyncResult *result, gpointer user_data)
GError *error = NULL;
debug_printf (2, " Request 1 completed\n");
- if (soup_request_send_finish (SOUP_REQUEST (source), result, &error)) {
- debug_printf (1, " Request 1 succeeded?\n");
- errors++;
- } else if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED)) {
- debug_printf (1, " Unexpected error on Request 1: %s\n",
- error->message);
- errors++;
- }
+ soup_request_send_finish (SOUP_REQUEST (source), result, &error);
+ g_assert_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED);
g_clear_error (&error);
}
@@ -665,14 +500,8 @@ ear_two_completed (GObject *source, GAsyncResult *result, gpointer loop)
GError *error = NULL;
debug_printf (2, " Request 2 completed\n");
- if (soup_request_send_finish (SOUP_REQUEST (source), result, &error)) {
- debug_printf (1, " Request 2 succeeded?\n");
- errors++;
- } else if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED)) {
- debug_printf (1, " Unexpected error on Request 2: %s\n",
- error->message);
- errors++;
- }
+ soup_request_send_finish (SOUP_REQUEST (source), result, &error);
+ g_assert_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED);
g_clear_error (&error);
g_main_loop_quit (loop);
@@ -684,14 +513,8 @@ ear_three_completed (GObject *source, GAsyncResult *result, gpointer loop)
GError *error = NULL;
debug_printf (2, " Request 3 completed\n");
- if (soup_request_send_finish (SOUP_REQUEST (source), result, &error)) {
- debug_printf (1, " Request 3 succeeded?\n");
- errors++;
- } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- debug_printf (1, " Unexpected error on Request 3: %s\n",
- error->message);
- errors++;
- }
+ soup_request_send_finish (SOUP_REQUEST (source), result, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
g_clear_error (&error);
g_main_loop_quit (loop);
@@ -708,20 +531,15 @@ static void
do_early_abort_req_test (void)
{
SoupSession *session;
- SoupRequester *requester;
SoupRequest *req;
GMainContext *context;
GMainLoop *loop;
GCancellable *cancellable;
- debug_printf (1, "\nAbort with pending connection (request api)\n");
-
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
- requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
- req = soup_requester_request_uri (requester, base_uri, NULL);
+ req = soup_session_request_uri (session, base_uri, NULL);
context = g_main_context_default ();
loop = g_main_loop_new (context, TRUE);
@@ -735,11 +553,9 @@ do_early_abort_req_test (void)
soup_test_session_abort_unref (session);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
- requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
- req = soup_requester_request_uri (requester, base_uri, NULL);
+ req = soup_session_request_uri (session, base_uri, NULL);
g_signal_connect (session, "connection-created",
G_CALLBACK (ea_connection_created), NULL);
@@ -753,11 +569,9 @@ do_early_abort_req_test (void)
soup_test_session_abort_unref (session);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
- requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
- req = soup_requester_request_uri (requester, base_uri, NULL);
+ req = soup_session_request_uri (session, base_uri, NULL);
cancellable = g_cancellable_new ();
g_signal_connect (session, "request-started",
@@ -790,21 +604,10 @@ do_one_accept_language_test (const char *language, const char *expected_header)
soup_session_send_message (session, msg);
soup_test_session_abort_unref (session);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " Message failed? %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
val = soup_message_headers_get_list (msg->request_headers,
"Accept-Language");
- if (!val) {
- debug_printf (1, " No Accept-Language set!\n");
- errors++;
- } else if (strcmp (val, expected_header) != 0) {
- debug_printf (1, " Wrong Accept-Language: expected '%s', got '%s'\n",
- expected_header, val);
- errors++;
- }
+ g_assert_cmpstr (val, ==, expected_header);
g_object_unref (msg);
}
@@ -814,7 +617,7 @@ do_accept_language_test (void)
{
const char *orig_language;
- debug_printf (1, "\nAutomatic Accept-Language processing\n");
+ g_test_bug ("602547");
orig_language = g_getenv ("LANGUAGE");
do_one_accept_language_test ("C", "en");
@@ -887,11 +690,7 @@ do_cancel_while_reading_test_for_session (SoupSession *session)
while (!done)
g_main_context_iteration (NULL, TRUE);
- if (msg->status_code != SOUP_STATUS_CANCELLED) {
- debug_printf (1, " FAILED: %d %s (expected Cancelled)\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
g_object_unref (msg);
if (thread)
@@ -903,7 +702,8 @@ do_cancel_while_reading_test (void)
{
SoupSession *session;
- debug_printf (1, "\nCancelling message while reading response (msg api)\n");
+ g_test_bug ("637741");
+ g_test_bug ("676038");
debug_printf (1, " Async session\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
@@ -916,23 +716,9 @@ do_cancel_while_reading_test (void)
soup_test_session_abort_unref (session);
}
-static gboolean
-cancel_request_timeout (gpointer cancellable)
-{
- g_cancellable_cancel (cancellable);
- return FALSE;
-}
-
-static gpointer
-cancel_request_thread (gpointer cancellable)
-{
- g_usleep (100000); /* .1s */
- g_cancellable_cancel (cancellable);
- return NULL;
-}
-
static void
-do_cancel_while_reading_req_test_for_session (SoupRequester *requester)
+do_cancel_while_reading_req_test_for_session (SoupSession *session,
+ guint flags)
{
SoupRequest *req;
SoupURI *uri;
@@ -940,30 +726,12 @@ do_cancel_while_reading_req_test_for_session (SoupRequester *requester)
GError *error = NULL;
uri = soup_uri_new_with_base (base_uri, "/slow");
- req = soup_requester_request_uri (requester, uri, NULL);
+ req = soup_session_request_uri (session, uri, NULL);
soup_uri_free (uri);
cancellable = g_cancellable_new ();
-
- if (SOUP_IS_SESSION_ASYNC (soup_request_get_session (req))) {
- g_timeout_add (100, cancel_request_timeout, cancellable);
- soup_test_request_send_async_as_sync (req, cancellable, &error);
- } else {
- GThread *thread;
-
- thread = g_thread_new ("cancel_request_thread", cancel_request_thread, cancellable);
- soup_request_send (req, cancellable, &error);
- g_thread_unref (thread);
- }
-
- if (!error) {
- debug_printf (1, " Request succeeded?\n");
- errors++;
- } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- debug_printf (1, " Unexpected error: %s\n",
- error->message);
- errors++;
- }
+ soup_test_request_send (req, cancellable, flags, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
g_clear_error (&error);
g_object_unref (req);
@@ -971,169 +739,128 @@ do_cancel_while_reading_req_test_for_session (SoupRequester *requester)
}
static void
-do_cancel_while_reading_req_test (void)
+do_cancel_while_reading_immediate_req_test (void)
{
SoupSession *session;
- SoupRequester *requester;
+ guint flags;
- debug_printf (1, "\nCancelling message while reading response (request api)\n");
+ g_test_bug ("692310");
+
+ flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE;
debug_printf (1, " Async session\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
- requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
- do_cancel_while_reading_req_test_for_session (requester);
+ do_cancel_while_reading_req_test_for_session (session, flags);
soup_test_session_abort_unref (session);
debug_printf (1, " Sync session\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
NULL);
- requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
- do_cancel_while_reading_req_test_for_session (requester);
+ do_cancel_while_reading_req_test_for_session (session, flags);
soup_test_session_abort_unref (session);
}
static void
-do_aliases_test_for_session (SoupSession *session,
- const char *redirect_protocol)
+do_cancel_while_reading_delayed_req_test (void)
{
- SoupMessage *msg;
- SoupURI *uri;
- const char *redirected_protocol;
-
- uri = soup_uri_new_with_base (base_uri, "/alias-redirect");
- msg = soup_message_new_from_uri ("GET", uri);
- if (redirect_protocol)
- soup_message_headers_append (msg->request_headers, "X-Redirect-Protocol", redirect_protocol);
- soup_uri_free (uri);
- soup_session_send_message (session, msg);
+ SoupSession *session;
+ guint flags;
- redirected_protocol = soup_message_headers_get_one (msg->response_headers, "X-Redirected-Protocol");
+ flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_SOON;
- if (g_strcmp0 (redirect_protocol, redirected_protocol)) {
- debug_printf (1, " redirect went to %s, should have gone to %s!\n",
- redirected_protocol ? redirected_protocol : "(none)",
- redirect_protocol ? redirect_protocol : "(none)");
- errors++;
- } else if (redirect_protocol && !SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " msg failed? (%d %s)\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- } else if (!redirect_protocol && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " msg succeeded? (%d %s)\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ debug_printf (1, " Async session\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
+ do_cancel_while_reading_req_test_for_session (session, flags);
+ soup_test_session_abort_unref (session);
- g_object_unref (msg);
+ debug_printf (1, " Sync session\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
+ NULL);
+ do_cancel_while_reading_req_test_for_session (session, flags);
+ soup_test_session_abort_unref (session);
}
static void
-do_aliases_test (void)
+do_cancel_while_reading_preemptive_req_test (void)
{
SoupSession *session;
- char *aliases[] = { "foo", NULL };
+ guint flags;
- debug_printf (1, "\nhttp-aliases / https-aliases\n");
+ g_test_bug ("637039");
- debug_printf (1, " Default behavior\n");
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- do_aliases_test_for_session (session, "http");
- soup_test_session_abort_unref (session);
+ flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE;
- debug_printf (1, " foo-means-https\n");
+ debug_printf (1, " Async session\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_HTTPS_ALIASES, aliases,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
- do_aliases_test_for_session (session, "https");
+ do_cancel_while_reading_req_test_for_session (session, flags);
soup_test_session_abort_unref (session);
- debug_printf (1, " foo-means-nothing\n");
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_HTTP_ALIASES, NULL,
+ debug_printf (1, " Sync session\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
NULL);
- do_aliases_test_for_session (session, NULL);
+ do_cancel_while_reading_req_test_for_session (session, flags);
soup_test_session_abort_unref (session);
}
static void
-do_dot_dot_test (void)
+do_aliases_test_for_session (SoupSession *session,
+ const char *redirect_protocol)
{
- SoupSession *session;
SoupMessage *msg;
SoupURI *uri;
+ const char *redirected_protocol;
- debug_printf (1, "\n'..' smuggling test\n");
-
- session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
-
- uri = soup_uri_new_with_base (base_uri, "/..%2ftest");
+ uri = soup_uri_new_with_base (base_uri, "/alias-redirect");
msg = soup_message_new_from_uri ("GET", uri);
+ if (redirect_protocol)
+ soup_message_headers_append (msg->request_headers, "X-Redirect-Protocol", redirect_protocol);
soup_uri_free (uri);
-
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_BAD_REQUEST) {
- debug_printf (1, " FAILED: %d %s (expected Bad Request)\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
- g_object_unref (msg);
+ redirected_protocol = soup_message_headers_get_one (msg->response_headers, "X-Redirected-Protocol");
- soup_test_session_abort_unref (session);
+ g_assert_cmpstr (redirect_protocol, ==, redirected_protocol);
+ if (redirect_protocol)
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ else
+ soup_test_assert_message_status (msg, SOUP_STATUS_FOUND);
+
+ g_object_unref (msg);
}
static void
-do_ipv6_test (void)
+do_aliases_test (void)
{
- SoupServer *ipv6_server;
- SoupURI *ipv6_uri;
- SoupAddress *ipv6_addr;
SoupSession *session;
- SoupMessage *msg;
-
- debug_printf (1, "\nIPv6 server test\n");
-
- ipv6_addr = soup_address_new ("::1", SOUP_ADDRESS_ANY_PORT);
- soup_address_resolve_sync (ipv6_addr, NULL);
- ipv6_server = soup_server_new (SOUP_SERVER_INTERFACE, ipv6_addr,
- NULL);
- g_object_unref (ipv6_addr);
- soup_server_add_handler (ipv6_server, NULL, server_callback, NULL, NULL);
- soup_server_run_async (ipv6_server);
-
- ipv6_uri = soup_uri_new ("http://[::1]/");
- soup_uri_set_port (ipv6_uri, soup_server_get_port (ipv6_server));
+ char *aliases[] = { "foo", NULL };
+ debug_printf (1, " Default behavior\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ do_aliases_test_for_session (session, "http");
+ soup_test_session_abort_unref (session);
- debug_printf (1, " HTTP/1.1\n");
- msg = soup_message_new_from_uri ("GET", ipv6_uri);
- soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " request failed: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
- g_object_unref (msg);
-
- debug_printf (1, " HTTP/1.0\n");
- msg = soup_message_new_from_uri ("GET", ipv6_uri);
- soup_message_set_http_version (msg, SOUP_HTTP_1_0);
- soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " request failed: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
- g_object_unref (msg);
+ if (tls_available) {
+ debug_printf (1, " foo-means-https\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_HTTPS_ALIASES, aliases,
+ NULL);
+ do_aliases_test_for_session (session, "https");
+ soup_test_session_abort_unref (session);
+ } else
+ debug_printf (1, " foo-means-https -- SKIPPING\n");
- soup_uri_free (ipv6_uri);
+ debug_printf (1, " foo-means-nothing\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_HTTP_ALIASES, NULL,
+ NULL);
+ do_aliases_test_for_session (session, NULL);
soup_test_session_abort_unref (session);
- soup_test_server_quit_unref (ipv6_server);
}
static void
@@ -1143,7 +870,7 @@ do_idle_on_dispose_test (void)
SoupMessage *msg;
GMainContext *async_context;
- debug_printf (1, "\nTesting SoupSessionAsync dispose behavior\n");
+ g_test_bug ("667364");
async_context = g_main_context_new ();
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
@@ -1159,10 +886,8 @@ do_idle_on_dispose_test (void)
g_object_run_dispose (G_OBJECT (session));
- if (g_main_context_iteration (async_context, FALSE)) {
- debug_printf (1, " idle was queued!\n");
- errors++;
- }
+ if (g_main_context_iteration (async_context, FALSE))
+ soup_test_assert (FALSE, "idle was queued");
g_object_unref (session);
g_main_context_unref (async_context);
@@ -1175,7 +900,7 @@ do_pause_abort_test (void)
SoupMessage *msg;
gpointer ptr;
- debug_printf (1, "\nTesting paused messages don't get leaked on abort\n");
+ g_test_bug ("673905");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
@@ -1186,16 +911,14 @@ do_pause_abort_test (void)
g_object_add_weak_pointer (G_OBJECT (msg), &ptr);
soup_test_session_abort_unref (session);
- if (ptr) {
- debug_printf (1, " msg was leaked\n");
- errors++;
- }
+ g_assert_null (ptr);
}
int
main (int argc, char **argv)
{
SoupAuthDomain *auth_domain;
+ int ret;
test_init (argc, argv, NULL);
@@ -1212,32 +935,37 @@ main (int argc, char **argv)
soup_server_add_auth_domain (server, auth_domain);
g_object_unref (auth_domain);
- ssl_server = soup_test_server_new_ssl (TRUE);
- soup_server_add_handler (ssl_server, NULL, server_callback, "https", NULL);
- ssl_base_uri = soup_uri_new ("https://127.0.0.1/");
- soup_uri_set_port (ssl_base_uri, soup_server_get_port (ssl_server));
-
- do_host_test ();
- do_callback_unref_test ();
- do_callback_unref_req_test ();
- do_msg_reuse_test ();
- do_star_test ();
- do_early_abort_test ();
- do_early_abort_req_test ();
- do_accept_language_test ();
- do_cancel_while_reading_test ();
- do_cancel_while_reading_req_test ();
- do_aliases_test ();
- do_dot_dot_test ();
- do_ipv6_test ();
- do_idle_on_dispose_test ();
- do_pause_abort_test ();
+ if (tls_available) {
+ ssl_server = soup_test_server_new_ssl (TRUE);
+ soup_server_add_handler (ssl_server, NULL, server_callback, "https", NULL);
+ ssl_base_uri = soup_uri_new ("https://127.0.0.1/");
+ soup_uri_set_port (ssl_base_uri, soup_server_get_port (ssl_server));
+ }
+
+ g_test_add_func ("/misc/host", do_host_test);
+ g_test_add_func ("/misc/callback-unref/msg", do_callback_unref_test);
+ g_test_add_func ("/misc/callback-unref/req", do_callback_unref_req_test);
+ g_test_add_func ("/misc/msg-reuse", do_msg_reuse_test);
+ g_test_add_func ("/misc/early-abort/msg", do_early_abort_test);
+ g_test_add_func ("/misc/early-abort/req", do_early_abort_req_test);
+ g_test_add_func ("/misc/accept-language", do_accept_language_test);
+ g_test_add_func ("/misc/cancel-while-reading/msg", do_cancel_while_reading_test);
+ g_test_add_func ("/misc/cancel-while-reading/req/immediate", do_cancel_while_reading_immediate_req_test);
+ g_test_add_func ("/misc/cancel-while-reading/req/delayed", do_cancel_while_reading_delayed_req_test);
+ g_test_add_func ("/misc/cancel-while-reading/req/preemptive", do_cancel_while_reading_preemptive_req_test);
+ g_test_add_func ("/misc/aliases", do_aliases_test);
+ g_test_add_func ("/misc/idle-on-dispose", do_idle_on_dispose_test);
+ g_test_add_func ("/misc/pause-abort", do_pause_abort_test);
+
+ ret = g_test_run ();
soup_uri_free (base_uri);
- soup_uri_free (ssl_base_uri);
soup_test_server_quit_unref (server);
- soup_test_server_quit_unref (ssl_server);
- test_cleanup ();
- return errors != 0;
+ if (tls_available) {
+ soup_uri_free (ssl_base_uri);
+ soup_test_server_quit_unref (ssl_server);
+ }
+
+ return ret;
}
diff --git a/tests/multipart-test.c b/tests/multipart-test.c
new file mode 100644
index 00000000..e057412e
--- /dev/null
+++ b/tests/multipart-test.c
@@ -0,0 +1,521 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "test-utils.h"
+
+#define READ_BUFFER_SIZE 8192
+
+typedef enum {
+ NO_MULTIPART,
+ SYNC_MULTIPART,
+ ASYNC_MULTIPART,
+ ASYNC_MULTIPART_SMALL_READS
+} MultipartMode;
+
+char *buffer;
+SoupSession *session;
+char *base_uri_string;
+SoupURI *base_uri;
+SoupMultipartInputStream *multipart;
+unsigned passes;
+
+
+/* This payload contains 4 different responses.
+ *
+ * First, a text/html response with a Content-Length (31);
+ * Second, a response lacking Content-Type with Content-Length (11);
+ * Third, a text/css response with no Content-Length;
+ * Fourth, same as the third, but with different content;
+ */
+const char *payload = \
+ "--cut-here\r\n" \
+ "Content-Type: text/html\n"
+ "Content-Length: 30\r\n" \
+ "\r\n" \
+ "<html><body>Hey!</body></html>" \
+ "\r\n--cut-here\r\n" \
+ "Content-Length: 10\r\n" \
+ "\r\n" \
+ "soup rocks" \
+ "\r\n--cut-here\r\n" \
+ "Content-Type: text/css\r\n" \
+ "\r\n" \
+ ".soup { before: rocks; }" \
+ "\r\n--cut-here\n" /* Tests boundary ending in a single \n. */ \
+ "Content-Type: text/css\r\n" \
+ "\r\n" \
+ "#soup { background-color: black; }" \
+ "\r\n--cut-here--";
+
+static void
+server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ if (msg->method != SOUP_METHOD_GET) {
+ soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+
+ soup_message_headers_append (msg->response_headers,
+ "Content-Type", "multipart/x-mixed-replace; boundary=cut-here");
+
+ soup_message_body_append (msg->response_body,
+ SOUP_MEMORY_STATIC,
+ payload,
+ strlen (payload));
+
+ soup_message_body_complete (msg->response_body);
+}
+
+static void
+content_sniffed (SoupMessage *msg, char *content_type, GHashTable *params, int *sniffed_count)
+{
+ *sniffed_count = *sniffed_count + 1;
+ debug_printf (2, " content-sniffed -> %s\n", content_type);
+}
+
+static void
+check_is_next (gboolean is_next)
+{
+ soup_test_assert (is_next,
+ "expected a header, but there are no more headers");
+}
+
+static void
+got_headers (SoupMessage *msg, int *headers_count)
+{
+ SoupMessageHeadersIter iter;
+ gboolean is_next;
+ const char* name, *value;
+
+ *headers_count = *headers_count + 1;
+
+ soup_message_headers_iter_init (&iter, msg->response_headers);
+
+ is_next = soup_message_headers_iter_next (&iter, &name, &value);
+ check_is_next (is_next);
+
+ if (g_str_equal (name, "Date")) {
+ is_next = soup_message_headers_iter_next (&iter, &name, &value);
+ check_is_next (is_next);
+ }
+
+ g_assert_cmpstr (name, ==, "Content-Type");
+ g_assert_cmpstr (value, ==, "multipart/x-mixed-replace; boundary=cut-here");
+}
+
+static void
+read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop*)data;
+ GInputStream *stream = G_INPUT_STREAM (source);
+ GError *error = NULL;
+ gssize bytes_read;
+
+ bytes_read = g_input_stream_read_finish (stream, asyncResult, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_object_unref (stream);
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ if (!bytes_read) {
+ g_input_stream_close (stream, NULL, &error);
+ g_assert_no_error (error);
+ g_object_unref (stream);
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ g_input_stream_read_async (stream, buffer, READ_BUFFER_SIZE,
+ G_PRIORITY_DEFAULT, NULL,
+ read_cb, data);
+}
+
+static void
+no_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop*)data;
+ SoupRequest *request = SOUP_REQUEST (source);
+ GError *error = NULL;
+ GInputStream* in;
+
+ in = soup_request_send_finish (request, res, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ g_input_stream_read_async (in, buffer, READ_BUFFER_SIZE,
+ G_PRIORITY_DEFAULT, NULL,
+ read_cb, data);
+}
+
+static void
+multipart_close_part_cb (GObject *source, GAsyncResult *res, gpointer data)
+{
+ GInputStream *in = G_INPUT_STREAM (source);
+ GError *error = NULL;
+
+ g_input_stream_close_finish (in, res, &error);
+ g_assert_no_error (error);
+}
+
+static void multipart_next_part_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer data);
+
+static void
+check_read (gsize nread, unsigned passes)
+{
+ switch (passes) {
+ case 0:
+ g_assert_cmpint (nread, ==, 30);
+ break;
+ case 1:
+ g_assert_cmpint (nread, ==, 10);
+ break;
+ case 2:
+ g_assert_cmpint (nread, ==, 24);
+ break;
+ case 3:
+ g_assert_cmpint (nread, ==, 34);
+ break;
+ default:
+ soup_test_assert (FALSE, "unexpected read of size: %d", (int)nread);
+ break;
+ }
+}
+
+static void
+multipart_read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop*)data;
+ GInputStream *in = G_INPUT_STREAM (source);
+ GError *error = NULL;
+ static gssize bytes_read_for_part = 0;
+ gssize bytes_read;
+
+ bytes_read = g_input_stream_read_finish (in, asyncResult, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL,
+ multipart_close_part_cb, NULL);
+ g_object_unref (in);
+
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ /* Read 0 bytes - try to start reading another part. */
+ if (!bytes_read) {
+ check_read (bytes_read_for_part, passes);
+ bytes_read_for_part = 0;
+ passes++;
+
+ g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL,
+ multipart_close_part_cb, NULL);
+ g_object_unref (in);
+
+ soup_multipart_input_stream_next_part_async (multipart, G_PRIORITY_DEFAULT, NULL,
+ multipart_next_part_cb, data);
+ return;
+ }
+
+ bytes_read_for_part += bytes_read;
+ g_input_stream_read_async (in, buffer, READ_BUFFER_SIZE,
+ G_PRIORITY_DEFAULT, NULL,
+ multipart_read_cb, data);
+}
+
+static void
+check_headers (SoupMultipartInputStream* multipart, unsigned passes)
+{
+ SoupMessageHeaders *headers;
+ SoupMessageHeadersIter iter;
+ gboolean is_next;
+ const char *name, *value;
+
+ headers = soup_multipart_input_stream_get_headers (multipart);
+ soup_message_headers_iter_init (&iter, headers);
+
+ switch (passes) {
+ case 0:
+ is_next = soup_message_headers_iter_next (&iter, &name, &value);
+ check_is_next (is_next);
+
+ g_assert_cmpstr (name, ==, "Content-Type");
+ g_assert_cmpstr (value, ==, "text/html");
+
+ is_next = soup_message_headers_iter_next (&iter, &name, &value);
+ check_is_next (is_next);
+
+ g_assert_cmpstr (name, ==, "Content-Length");
+ g_assert_cmpstr (value, ==, "30");
+
+ break;
+ case 1:
+ is_next = soup_message_headers_iter_next (&iter, &name, &value);
+ check_is_next (is_next);
+
+ g_assert_cmpstr (name, ==, "Content-Length");
+ g_assert_cmpstr (value, ==, "10");
+
+ break;
+ case 2:
+ case 3:
+ is_next = soup_message_headers_iter_next (&iter, &name, &value);
+ check_is_next (is_next);
+
+ g_assert_cmpstr (name, ==, "Content-Type");
+ g_assert_cmpstr (value, ==, "text/css");
+
+ break;
+ default:
+ soup_test_assert (FALSE, "unexpected part received");
+ break;
+ }
+}
+
+static void
+multipart_next_part_cb (GObject *source, GAsyncResult *res, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop*)data;
+ GError *error = NULL;
+ GInputStream *in;
+ gsize read_size = READ_BUFFER_SIZE;
+
+ g_assert (SOUP_MULTIPART_INPUT_STREAM (source) == multipart);
+
+ in = soup_multipart_input_stream_next_part_finish (multipart, res, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_clear_error (&error);
+ g_object_unref (multipart);
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ if (!in) {
+ g_assert_cmpint (passes, ==, 4);
+ g_object_unref (multipart);
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ check_headers (multipart, passes);
+
+ if (g_object_get_data (G_OBJECT (multipart), "multipart-small-reads"))
+ read_size = 4;
+
+ g_input_stream_read_async (in, buffer, read_size,
+ G_PRIORITY_DEFAULT, NULL,
+ multipart_read_cb, data);
+}
+
+static void
+multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop*)data;
+ SoupRequest *request = SOUP_REQUEST (source);
+ GError *error = NULL;
+ GInputStream *in;
+ SoupMessage *message;
+
+ in = soup_request_send_finish (request, res, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
+ multipart = soup_multipart_input_stream_new (message, in);
+ g_object_unref (message);
+ g_object_unref (in);
+
+ if (g_object_get_data (source, "multipart-small-reads"))
+ g_object_set_data (G_OBJECT (multipart), "multipart-small-reads", GINT_TO_POINTER(1));
+
+ soup_multipart_input_stream_next_part_async (multipart, G_PRIORITY_DEFAULT, NULL,
+ multipart_next_part_cb, data);
+}
+
+static void
+sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop*)data;
+ SoupRequest *request = SOUP_REQUEST (source);
+ GError *error = NULL;
+ GInputStream *in;
+ SoupMessage *message;
+ char buffer[READ_BUFFER_SIZE];
+ gsize bytes_read;
+
+ in = soup_request_send_finish (request, res, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_main_loop_quit (loop);
+ return;
+ }
+
+ message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
+ multipart = soup_multipart_input_stream_new (message, in);
+ g_object_unref (message);
+ g_object_unref (in);
+
+ while (TRUE) {
+ in = soup_multipart_input_stream_next_part (multipart, NULL, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_clear_error (&error);
+ break;
+ }
+
+ if (!in)
+ break;
+
+ check_headers (multipart, passes);
+
+ g_input_stream_read_all (in, (void*)buffer, sizeof (buffer), &bytes_read, NULL, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_clear_error (&error);
+ g_object_unref (in);
+ break;
+ }
+
+ check_read (bytes_read, passes);
+
+ passes++;
+ g_object_unref (in);
+ }
+
+ g_assert_cmpint (passes, ==, 4);
+
+ g_main_loop_quit (loop);
+ g_object_unref (multipart);
+}
+
+static void
+test_multipart (gconstpointer data)
+{
+ int headers_expected = 1, sniffed_expected = 1;
+ MultipartMode multipart_mode = GPOINTER_TO_INT (data);
+ SoupRequest* request;
+ SoupMessage *msg;
+ GMainLoop *loop;
+ int headers_count = 0;
+ int sniffed_count = 0;
+ GHashTable *params;
+ const char *content_type;
+ gboolean message_is_multipart = FALSE;
+ GError* error = NULL;
+
+ request = soup_session_request (session, base_uri_string, &error);
+ g_assert_no_error (error);
+ if (error)
+ return;
+
+ msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
+
+ /* This is used to track the number of parts. */
+ passes = 0;
+
+ /* Force the server to close the connection. */
+ soup_message_headers_append (msg->request_headers,
+ "Connection", "close");
+
+ g_signal_connect (msg, "got_headers",
+ G_CALLBACK (got_headers), &headers_count);
+
+ g_signal_connect (msg, "content-sniffed",
+ G_CALLBACK (content_sniffed), &sniffed_count);
+
+ loop = g_main_loop_new (NULL, TRUE);
+
+ if (multipart_mode == ASYNC_MULTIPART)
+ soup_request_send_async (request, NULL, multipart_handling_cb, loop);
+ else if (multipart_mode == ASYNC_MULTIPART_SMALL_READS) {
+ g_object_set_data (G_OBJECT (request), "multipart-small-reads", GINT_TO_POINTER(1));
+ soup_request_send_async (request, NULL, multipart_handling_cb, loop);
+ } else if (multipart_mode == SYNC_MULTIPART)
+ soup_request_send_async (request, NULL, sync_multipart_handling_cb, loop);
+ else
+ soup_request_send_async (request, NULL, no_multipart_handling_cb, loop);
+
+ g_main_loop_run (loop);
+
+ content_type = soup_message_headers_get_content_type (msg->response_headers, &params);
+
+ if (content_type &&
+ g_str_has_prefix (content_type, "multipart/") &&
+ g_hash_table_lookup (params, "boundary")) {
+ message_is_multipart = TRUE;
+ }
+ g_clear_pointer (&params, g_hash_table_unref);
+
+ g_assert_true (message_is_multipart);
+ g_assert_cmpint (headers_count, ==, headers_expected);
+ g_assert_cmpint (sniffed_count, ==, sniffed_expected);
+
+ g_object_unref (msg);
+ g_object_unref (request);
+ g_main_loop_unref (loop);
+}
+
+int
+main (int argc, char **argv)
+{
+ SoupServer *server;
+ int ret;
+
+ test_init (argc, argv, NULL);
+
+ buffer = g_malloc (READ_BUFFER_SIZE);
+
+ server = soup_test_server_new (FALSE);
+ soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+ base_uri = soup_uri_new ("http://127.0.0.1");
+ soup_uri_set_port (base_uri, soup_server_get_port (server));
+ base_uri_string = soup_uri_to_string (base_uri, FALSE);
+
+ /* FIXME: I had to raise the number of connections allowed here, otherwise I
+ * was hitting the limit, which indicates some connections are not dying.
+ */
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ "use-thread-context", TRUE,
+ "max-conns", 20,
+ "max-conns-per-host", 20,
+ NULL);
+ soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
+
+ g_test_add_data_func ("/multipart/no", GINT_TO_POINTER (NO_MULTIPART), test_multipart);
+ g_test_add_data_func ("/multipart/sync", GINT_TO_POINTER (SYNC_MULTIPART), test_multipart);
+ g_test_add_data_func ("/multipart/async", GINT_TO_POINTER (ASYNC_MULTIPART), test_multipart);
+ g_test_add_data_func ("/multipart/async-small-reads", GINT_TO_POINTER (ASYNC_MULTIPART_SMALL_READS), test_multipart);
+
+ ret = g_test_run ();
+
+ soup_uri_free (base_uri);
+ g_free (base_uri_string);
+ g_free (buffer);
+
+ soup_test_session_abort_unref (session);
+ soup_test_server_quit_unref (server);
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c
new file mode 100644
index 00000000..82532c74
--- /dev/null
+++ b/tests/no-ssl-test.c
@@ -0,0 +1,151 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include "test-utils.h"
+
+static void
+do_ssl_test_for_session (SoupSession *session, const char *uri)
+{
+ SoupMessage *msg;
+ GTlsCertificate *cert = NULL;
+ GTlsCertificateFlags flags;
+ gboolean is_https;
+
+ msg = soup_message_new ("GET", uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_SSL_FAILED);
+
+ is_https = soup_message_get_https_status (msg, &cert, &flags);
+ soup_test_assert (!is_https, "get_http_status() returned TRUE? (flags %x)", flags);
+
+ g_assert_null (cert);
+ g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED);
+
+ g_object_unref (msg);
+}
+
+static void
+do_ssl_tests (gconstpointer uri)
+{
+ SoupSession *session;
+
+ g_test_bug ("700518");
+
+ debug_printf (1, " plain\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ do_ssl_test_for_session (session, uri);
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " async\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ do_ssl_test_for_session (session, uri);
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " sync\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+ do_ssl_test_for_session (session, uri);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_session_property_tests (void)
+{
+ gboolean use_system;
+ GTlsDatabase *tlsdb;
+ char *ca_file;
+ SoupSession *session;
+
+ g_test_bug ("700518");
+
+ session = soup_session_async_new ();
+
+ g_object_get (G_OBJECT (session),
+ "ssl-use-system-ca-file", &use_system,
+ "tls-database", &tlsdb,
+ "ssl-ca-file", &ca_file,
+ NULL);
+ soup_test_assert (!use_system, "ssl-use-system-ca-file defaults to TRUE");
+ soup_test_assert (tlsdb == NULL, "tls-database set by default");
+ soup_test_assert (ca_file == NULL, "ca-file set by default");
+
+ g_object_set (G_OBJECT (session),
+ "ssl-use-system-ca-file", TRUE,
+ NULL);
+ g_object_get (G_OBJECT (session),
+ "ssl-ca-file", &ca_file,
+ NULL);
+ soup_test_assert (ca_file == NULL, "setting ssl-use-system-ca-file set ssl-ca-file");
+
+ g_object_set (G_OBJECT (session),
+ "ssl-ca-file",
+ g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL),
+ NULL);
+ g_object_get (G_OBJECT (session),
+ "ssl-use-system-ca-file", &use_system,
+ "tls-database", &tlsdb,
+ "ssl-ca-file", &ca_file,
+ NULL);
+ soup_test_assert (ca_file == NULL, "setting ssl-ca-file did not fail");
+ soup_test_assert (!use_system, "setting ssl-ca-file set ssl-use-system-ca-file");
+ soup_test_assert (tlsdb == NULL, "setting ssl-ca-file set tls-database");
+
+ g_object_set (G_OBJECT (session),
+ "tls-database", NULL,
+ NULL);
+ g_object_get (G_OBJECT (session),
+ "ssl-use-system-ca-file", &use_system,
+ "tls-database", &tlsdb,
+ "ssl-ca-file", &ca_file,
+ NULL);
+ soup_test_assert (tlsdb == NULL, "setting tls-database NULL failed");
+ soup_test_assert (!use_system, "setting tls-database NULL set ssl-use-system-ca-file");
+ soup_test_assert (ca_file == NULL, "setting tls-database NULL set ssl-ca-file");
+
+ soup_test_session_abort_unref (session);
+}
+
+static void
+server_handler (SoupServer *server,
+ SoupMessage *msg,
+ const char *path,
+ GHashTable *query,
+ SoupClientContext *client,
+ gpointer user_data)
+{
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ soup_message_set_response (msg, "text/plain",
+ SOUP_MEMORY_STATIC,
+ "ok\r\n", 4);
+}
+
+int
+main (int argc, char **argv)
+{
+ SoupServer *server;
+ char *uri;
+ int ret;
+
+ /* Force this test to use the dummy TLS backend */
+ g_setenv ("GIO_USE_TLS", "dummy", TRUE);
+
+ test_init (argc, argv, NULL);
+
+ /* Make a non-SSL server and pretend that it's ssl, which is fine
+ * since we won't ever actually talk to it anyway. We don't
+ * currently test that failing to construct an SSL server works.
+ */
+ server = soup_test_server_new (TRUE);
+ soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
+ uri = g_strdup_printf ("https://127.0.0.1:%u/",
+ soup_server_get_port (server));
+
+ g_test_add_func ("/no-ssl/session-properties", do_session_property_tests);
+ g_test_add_data_func ("/no-ssl/request-error", uri, do_ssl_tests);
+
+ ret = g_test_run ();
+
+ g_free (uri);
+ soup_test_server_quit_unref (server);
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/ntlm-test-helper.c b/tests/ntlm-test-helper.c
new file mode 100644
index 00000000..f2450cae
--- /dev/null
+++ b/tests/ntlm-test-helper.c
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright 2012 Red Hat, Inc.
+ */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include "libsoup/soup.h"
+
+const char *helper_protocol, *username, *domain;
+gboolean use_cached_creds;
+
+static GOptionEntry entries[] = {
+ { "helper-protocol", 0, 0,
+ G_OPTION_ARG_STRING, &helper_protocol,
+ NULL, NULL },
+ { "use-cached-creds", 0, 0,
+ G_OPTION_ARG_NONE, &use_cached_creds,
+ NULL, NULL },
+ { "username", 0, 0,
+ G_OPTION_ARG_STRING, &username,
+ NULL, NULL },
+ { "domain", 0, 0,
+ G_OPTION_ARG_STRING, &domain,
+ NULL, NULL },
+ { NULL }
+};
+
+int
+main (int argc, char **argv)
+{
+ GOptionContext *opts;
+ char buf[256], *header;
+ SoupMessage *msg;
+ SoupAuth *auth;
+
+ /* Don't recurse */
+ g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE);
+
+ setlocale (LC_ALL, "");
+
+ opts = g_option_context_new (NULL);
+ g_option_context_add_main_entries (opts, entries, NULL);
+ if (!g_option_context_parse (opts, &argc, &argv, NULL)) {
+ g_printerr ("Bad arguments\n");
+ exit (1);
+ }
+ g_option_context_free (opts);
+
+ if (!username || !use_cached_creds || !helper_protocol ||
+ !g_str_equal (helper_protocol, "ntlmssp-client-1")) {
+ g_printerr ("Wrong arguments; this program is only intended for use by ntlm-test\n");
+ exit (1);
+ }
+
+ msg = soup_message_new ("GET", "http://localhost/");
+ auth = NULL;
+
+ while (fgets (buf, sizeof (buf), stdin)) {
+ if (strchr (buf, '\n'))
+ *strchr (buf, '\n') = '\0';
+ if (!strcmp (buf, "YR")) {
+ if (g_getenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS")) {
+ g_print ("PW\n");
+ continue;
+ }
+
+ g_clear_object (&auth);
+ auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL);
+ header = soup_auth_get_authorization (auth, msg);
+ g_print ("YR %s\n", header + 5);
+ g_free (header);
+ } else if (g_str_has_prefix (buf, "TT ")) {
+ header = g_strdup_printf ("NTLM %s\n", buf + 3);
+ if (!soup_auth_update (auth, msg, header)) {
+ g_printerr ("Bad challenge\n");
+ exit (1);
+ }
+ g_free (header);
+
+ soup_auth_authenticate (auth, username, "password");
+ header = soup_auth_get_authorization (auth, msg);
+ if (!header) {
+ g_printerr ("Internal authentication failure\n");
+ exit (1);
+ }
+ g_print ("KK %s\n", header + 5);
+ g_free (header);
+ } else {
+ g_printerr ("Unexpected command\n");
+ exit (1);
+ }
+ }
+
+ g_object_unref (msg);
+ g_clear_object (&auth);
+
+ return 0;
+}
diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c
index 00222e87..24a0f2e4 100644
--- a/tests/ntlm-test.c
+++ b/tests/ntlm-test.c
@@ -11,6 +11,8 @@
#include "test-utils.h"
+static SoupURI *uri;
+
typedef enum {
NTLM_UNAUTHENTICATED,
NTLM_RECEIVED_REQUEST,
@@ -19,12 +21,16 @@ typedef enum {
NTLM_AUTHENTICATED_BOB
} NTLMServerState;
+static const char *state_name[] = {
+ "unauth", "recv", "sent", "alice", "bob"
+};
+
#define NTLM_REQUEST_START "TlRMTVNTUAABAAAA"
#define NTLM_RESPONSE_START "TlRMTVNTUAADAAAA"
#define NTLM_CHALLENGE "TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA="
-#define NTLM_RESPONSE_USER(response) ((response)[102] == 'E' ? NTLM_AUTHENTICATED_ALICE : NTLM_AUTHENTICATED_BOB)
+#define NTLM_RESPONSE_USER(response) ((response)[86] == 'E' ? NTLM_AUTHENTICATED_ALICE : ((response)[86] == 'I' ? NTLM_AUTHENTICATED_BOB : NTLM_UNAUTHENTICATED))
static void
clear_state (gpointer connections, GObject *ex_connection)
@@ -134,16 +140,22 @@ server_callback (SoupServer *server, SoupMessage *msg,
}
}
+ debug_printf (2, " (S:%s)", state_name[state]);
g_hash_table_insert (connections, socket, GINT_TO_POINTER (state));
g_object_weak_ref (G_OBJECT (socket), clear_state, connections);
}
+static gboolean authenticated_ntlm = FALSE;
+
static void
authenticate (SoupSession *session, SoupMessage *msg,
SoupAuth *auth, gboolean retrying, gpointer user)
{
- if (!retrying)
+ if (!retrying) {
soup_auth_authenticate (auth, user, "password");
+ if (g_str_equal (soup_auth_get_scheme_name (auth), "NTLM"))
+ authenticated_ntlm = TRUE;
+ }
}
typedef struct {
@@ -238,82 +250,65 @@ do_message (SoupSession *session, SoupURI *base_uri, const char *path,
if (state.got_ntlm_prompt) {
debug_printf (1, " NTLM_PROMPT");
- if (!get_ntlm_prompt) {
+ if (!get_ntlm_prompt)
debug_printf (1, "???");
- errors++;
- }
- } else if (get_ntlm_prompt) {
+ } else if (get_ntlm_prompt)
debug_printf (1, " no-ntlm-prompt???");
- errors++;
- }
if (state.got_basic_prompt) {
debug_printf (1, " BASIC_PROMPT");
- if (!get_basic_prompt) {
+ if (!get_basic_prompt)
debug_printf (1, "???");
- errors++;
- }
- } else if (get_basic_prompt) {
+ } else if (get_basic_prompt)
debug_printf (1, " no-basic-prompt???");
- errors++;
- }
if (state.sent_ntlm_request) {
debug_printf (1, " REQUEST");
- if (!do_ntlm) {
+ if (!do_ntlm)
debug_printf (1, "???");
- errors++;
- }
- } else if (do_ntlm) {
+ } else if (do_ntlm)
debug_printf (1, " no-request???");
- errors++;
- }
if (state.got_ntlm_challenge) {
debug_printf (1, " CHALLENGE");
- if (!do_ntlm) {
+ if (!do_ntlm)
debug_printf (1, "???");
- errors++;
- }
- } else if (do_ntlm) {
+ } else if (do_ntlm)
debug_printf (1, " no-challenge???");
- errors++;
- }
if (state.sent_ntlm_response) {
debug_printf (1, " NTLM_RESPONSE");
- if (!do_ntlm) {
+ if (!do_ntlm)
debug_printf (1, "???");
- errors++;
- }
- } else if (do_ntlm) {
+ } else if (do_ntlm)
debug_printf (1, " no-ntlm-response???");
- errors++;
- }
if (state.sent_basic_response) {
debug_printf (1, " BASIC_RESPONSE");
- if (!do_basic) {
+ if (!do_basic)
debug_printf (1, "???");
- errors++;
- }
- } else if (do_basic) {
+ } else if (do_basic)
debug_printf (1, " no-basic-response???");
- errors++;
- }
debug_printf (1, " -> %s", msg->reason_phrase);
- if (msg->status_code != status_code) {
+ if (msg->status_code != status_code)
debug_printf (1, "???");
- errors++;
- }
debug_printf (1, "\n");
+ g_assert_true (state.got_ntlm_prompt == get_ntlm_prompt);
+ g_assert_true (state.got_basic_prompt == get_basic_prompt);
+ g_assert_true (state.sent_ntlm_request == do_ntlm);
+ g_assert_true (state.got_ntlm_challenge == do_ntlm);
+ g_assert_true (state.sent_ntlm_response == do_ntlm);
+ g_assert_true (state.sent_basic_response == do_basic);
+ soup_test_assert_message_status (msg, status_code);
+
g_object_unref (msg);
}
static void
-do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, const char *user)
+do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm,
+ const char *user, gboolean use_builtin_ntlm)
{
SoupSession *session;
gboolean alice = !g_strcmp0 (user, "alice");
@@ -322,13 +317,23 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, const char *user)
gboolean bob_via_ntlm = use_ntlm && bob;
gboolean alice_via_basic = !use_ntlm && alice;
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- if (use_ntlm)
- soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM);
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
if (user) {
g_signal_connect (session, "authenticate",
G_CALLBACK (authenticate), (char *)user);
+ if (use_ntlm && !use_builtin_ntlm)
+ g_setenv ("NTLMUSER", user, TRUE);
+ }
+ if (use_ntlm) {
+ SoupAuthManager *auth_manager;
+ SoupAuth *ntlm;
+
+ soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM);
+ auth_manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER));
+ ntlm = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL);
+ soup_auth_manager_use_auth (auth_manager, base_uri, ntlm);
+ g_object_unref (ntlm);
}
/* 1. Server doesn't request auth, so both get_ntlm_prompt and
@@ -336,11 +341,17 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, const char *user)
* if we're using NTLM we'll try that even without the server
* asking.
*/
+ authenticated_ntlm = FALSE;
do_message (session, base_uri, "/noauth",
FALSE, use_ntlm,
FALSE, FALSE,
SOUP_STATUS_OK);
+ soup_test_assert (authenticated_ntlm == (use_ntlm && use_builtin_ntlm),
+ "%s built-in NTLM support, but authenticate signal %s emitted\n",
+ use_builtin_ntlm ? "Using" : "Not using",
+ authenticated_ntlm ? "was" : "wasn't");
+
/* 2. Server requires auth as Alice, so it will request that
* if we didn't already authenticate the connection to her in
* the previous step. If we authenticated as Bob in the
@@ -421,46 +432,190 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, const char *user)
soup_test_session_abort_unref (session);
}
+typedef enum {
+ BUILTIN,
+ WINBIND,
+ FALLBACK
+} NtlmType;
+
+typedef struct {
+ const char *name, *user;
+ gboolean conn_uses_ntlm;
+ NtlmType ntlm_type;
+} NtlmTest;
+
+static const NtlmTest ntlm_tests[] = {
+ { "/ntlm/builtin/none", NULL, FALSE, BUILTIN },
+ { "/ntlm/builtin/alice", "alice", TRUE, BUILTIN },
+ { "/ntlm/builtin/bob", "bob", TRUE, BUILTIN },
+ { "/ntlm/builtin/basic", "alice", FALSE, BUILTIN },
+
+ { "/ntlm/winbind/none", NULL, FALSE, WINBIND },
+ { "/ntlm/winbind/alice", "alice", TRUE, WINBIND },
+ { "/ntlm/winbind/bob", "bob", TRUE, WINBIND },
+ { "/ntlm/winbind/basic", "alice", FALSE, WINBIND },
+
+ { "/ntlm/fallback/none", NULL, FALSE, FALLBACK },
+ { "/ntlm/fallback/alice", "alice", TRUE, FALLBACK },
+ { "/ntlm/fallback/bob", "bob", TRUE, FALLBACK },
+ { "/ntlm/fallback/basic", "alice", FALSE, FALLBACK }
+};
+
static void
-do_ntlm_tests (SoupURI *base_uri)
+do_ntlm_test (gconstpointer data)
{
- debug_printf (1, "Round 1: Non-NTLM Connection, no auth\n");
- do_ntlm_round (base_uri, FALSE, NULL);
- debug_printf (1, "Round 2: NTLM Connection, user=alice\n");
- do_ntlm_round (base_uri, TRUE, "alice");
- debug_printf (1, "Round 3: NTLM Connection, user=bob\n");
- do_ntlm_round (base_uri, TRUE, "bob");
- debug_printf (1, "Round 4: Non-NTLM Connection, user=alice\n");
- do_ntlm_round (base_uri, FALSE, "alice");
+ const NtlmTest *test = data;
+ gboolean use_builtin_ntlm = TRUE;
+
+ switch (test->ntlm_type) {
+ case BUILTIN:
+ /* Built-in NTLM auth support. (We set SOUP_NTLM_AUTH_DEBUG to
+ * an empty string to ensure that the built-in support is
+ * being used, even if /usr/bin/ntlm_auth is available.)
+ */
+ g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE);
+ break;
+
+ case WINBIND:
+#ifndef USE_NTLM_AUTH
+ g_test_skip ("/usr/bin/ntlm_auth is not available");
+ return;
+#endif
+
+ /* Samba winbind /usr/bin/ntlm_auth helper support (via a
+ * helper program that emulates its interface).
+ */
+ g_setenv ("SOUP_NTLM_AUTH_DEBUG",
+ g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL),
+ TRUE);
+ g_unsetenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS");
+ use_builtin_ntlm = FALSE;
+ break;
+
+ case FALLBACK:
+#ifndef USE_NTLM_AUTH
+ g_test_skip ("/usr/bin/ntlm_auth is not available");
+ return;
+#endif
+
+ /* Support for when ntlm_auth is installed, but the user has
+ * no cached credentials (and thus we have to fall back to
+ * libsoup's built-in NTLM support).
+ */
+ g_setenv ("SOUP_NTLM_AUTH_DEBUG",
+ g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL),
+ TRUE);
+ g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE);
+ break;
+ }
+
+ do_ntlm_round (uri, test->conn_uses_ntlm, test->user, use_builtin_ntlm);
+}
+
+static void
+retry_test_authenticate (SoupSession *session, SoupMessage *msg,
+ SoupAuth *auth, gboolean retrying,
+ gpointer user_data)
+{
+ gboolean *retried = user_data;
+
+ if (!retrying) {
+ /* server_callback doesn't actually verify the password,
+ * only the username. So we pass an incorrect username
+ * rather than an incorrect password.
+ */
+ soup_auth_authenticate (auth, "wrong", "password");
+ } else if (!*retried) {
+ soup_auth_authenticate (auth, "alice", "password");
+ *retried = TRUE;
+ }
+}
+
+static void
+do_retrying_test (gconstpointer data)
+{
+ SoupURI *base_uri = (SoupURI *)data;
+ SoupSession *session;
+ SoupMessage *msg;
+ SoupURI *uri;
+ gboolean retried = FALSE;
+
+ g_test_bug ("693222");
+
+ g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE);
+
+ debug_printf (1, " /alice\n");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_NTLM,
+ NULL);
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (retry_test_authenticate), &retried);
+
+ uri = soup_uri_new_with_base (base_uri, "/alice");
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_uri_free (uri);
+
+ soup_session_send_message (session, msg);
+
+ g_assert_true (retried);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
+ g_object_unref (msg);
+
+ soup_test_session_abort_unref (session);
+
+ debug_printf (1, " /bob\n");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_NTLM,
+ NULL);
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (retry_test_authenticate), &retried);
+ retried = FALSE;
+
+ uri = soup_uri_new_with_base (base_uri, "/bob");
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_uri_free (uri);
+
+ soup_session_send_message (session, msg);
+
+ g_assert_true (retried);
+ soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED);
+
+ g_object_unref (msg);
+
+ soup_test_session_abort_unref (session);
}
int
main (int argc, char **argv)
{
- GMainLoop *loop;
SoupServer *server;
GHashTable *connections;
- SoupURI *uri;
+ int i, ret;
test_init (argc, argv, NULL);
- server = soup_test_server_new (FALSE);
+ server = soup_test_server_new (TRUE);
connections = g_hash_table_new (NULL, NULL);
soup_server_add_handler (server, NULL,
server_callback, connections, NULL);
- loop = g_main_loop_new (NULL, TRUE);
-
uri = soup_uri_new ("http://127.0.0.1/");
soup_uri_set_port (uri, soup_server_get_port (server));
- do_ntlm_tests (uri);
- soup_uri_free (uri);
- g_main_loop_unref (loop);
+ for (i = 0; i < G_N_ELEMENTS (ntlm_tests); i++)
+ g_test_add_data_func (ntlm_tests[i].name, &ntlm_tests[i], do_ntlm_test);
+ g_test_add_data_func ("/ntlm/retry", uri, do_retrying_test);
+
+ ret = g_test_run ();
+
+ soup_uri_free (uri);
soup_test_server_quit_unref (server);
test_cleanup ();
g_hash_table_destroy (connections);
- return errors != 0;
+ return ret;
}
diff --git a/tests/proxy-test.c b/tests/proxy-test.c
index 85aac9f5..4b6679b3 100644
--- a/tests/proxy-test.c
+++ b/tests/proxy-test.c
@@ -6,16 +6,18 @@ typedef struct {
const char *explanation;
const char *url;
const guint final_status;
+ const char *bugref;
} SoupProxyTest;
static SoupProxyTest tests[] = {
- { "GET -> 200", "", SOUP_STATUS_OK },
- { "GET -> 404", "/not-found", SOUP_STATUS_NOT_FOUND },
- { "GET -> 401 -> 200", "/Basic/realm1/", SOUP_STATUS_OK },
- { "GET -> 401 -> 401", "/Basic/realm2/", SOUP_STATUS_UNAUTHORIZED },
- { "GET -> 403", "http://no-such-hostname.xx/", SOUP_STATUS_FORBIDDEN },
+ { "GET -> 200", "", SOUP_STATUS_OK, NULL },
+ { "GET -> 404", "/not-found", SOUP_STATUS_NOT_FOUND, NULL },
+ { "GET -> 401 -> 200", "/Basic/realm1/", SOUP_STATUS_OK, NULL },
+ { "GET -> 401 -> 401", "/Basic/realm2/", SOUP_STATUS_UNAUTHORIZED, NULL },
+ { "GET -> 403", "http://no-such-hostname.xx/", SOUP_STATUS_FORBIDDEN, "577532" },
+ { "GET -> 200 (unproxied)", "http://localhost:47524/", SOUP_STATUS_OK, "700472" },
};
-static int ntests = sizeof (tests) / sizeof (tests[0]);
+static const int ntests = sizeof (tests) / sizeof (tests[0]);
#define HTTP_SERVER "http://127.0.0.1:47524"
#define HTTPS_SERVER "https://127.0.0.1:47525"
@@ -35,25 +37,23 @@ static const char *proxy_names[] = {
"authenticated proxy",
"unauthenticatable-to proxy"
};
+static GProxyResolver *proxy_resolvers[3];
+static const char *ignore_hosts[] = { "localhost", NULL };
static void
authenticate (SoupSession *session, SoupMessage *msg,
SoupAuth *auth, gboolean retrying, gpointer data)
{
if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
- if (soup_auth_is_for_proxy (auth)) {
- debug_printf (1, " got proxy auth object for 401!\n");
- errors++;
- }
+ soup_test_assert (!soup_auth_is_for_proxy (auth),
+ "got proxy auth object for 401");
} else if (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) {
- if (!soup_auth_is_for_proxy (auth)) {
- debug_printf (1, " got regular auth object for 407!\n");
- errors++;
- }
+ soup_test_assert (soup_auth_is_for_proxy (auth),
+ "got regular auth object for 407");
} else {
- debug_printf (1, " got authenticate signal with status %d\n",
- msg->status_code);
- errors++;
+ soup_test_assert (FALSE,
+ "got authenticate signal with status %d\n",
+ msg->status_code);
}
if (!retrying)
@@ -80,28 +80,29 @@ test_url (const char *url, int proxy, guint expected,
gboolean sync, gboolean close)
{
SoupSession *session;
- SoupURI *proxy_uri;
SoupMessage *msg;
+ gboolean noproxy = !!strstr (url, "localhost");
if (!tls_available && g_str_has_prefix (url, "https:"))
return;
debug_printf (1, " GET %s via %s%s\n", url, proxy_names[proxy],
close ? " (with Connection: close)" : "");
- if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN)
+ if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN && !noproxy)
expected = SOUP_STATUS_PROXY_UNAUTHORIZED;
/* We create a new session for each request to ensure that
* connections/auth aren't cached between tests.
*/
- proxy_uri = soup_uri_new (proxies[proxy]);
session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_PROXY_URI, proxy_uri,
+ SOUP_SESSION_PROXY_RESOLVER, proxy_resolvers[proxy],
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ SOUP_SESSION_SSL_STRICT, FALSE,
NULL);
- soup_uri_free (proxy_uri);
g_signal_connect (session, "authenticate",
G_CALLBACK (authenticate), NULL);
if (close) {
+ /* FIXME g_test_bug ("611663") */
g_signal_connect (session, "request-started",
G_CALLBACK (set_close_on_connect), NULL);
}
@@ -115,10 +116,7 @@ test_url (const char *url, int proxy, guint expected,
soup_session_send_message (session, msg);
debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase);
- if (msg->status_code != expected) {
- debug_printf (1, " EXPECTED %d!\n", expected);
- errors++;
- }
+ soup_test_assert_message_status (msg, expected);
g_object_unref (msg);
soup_test_session_abort_unref (session);
@@ -129,73 +127,54 @@ test_url_new_api (const char *url, int proxy, guint expected,
gboolean sync, gboolean close)
{
SoupSession *session;
- SoupURI *proxy_uri;
SoupMessage *msg;
- SoupRequester *requester;
SoupRequest *request;
GInputStream *stream;
GError *error = NULL;
+ gboolean noproxy = !!strstr (url, "localhost");
+ /* FIXME g_test_skip() FIXME g_test_bug ("675865") */
if (!tls_available && g_str_has_prefix (url, "https:"))
return;
- debug_printf (1, " GET (requester API) %s via %s%s\n", url, proxy_names[proxy],
+ debug_printf (1, " GET (request API) %s via %s%s\n", url, proxy_names[proxy],
close ? " (with Connection: close)" : "");
- if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN)
+ if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN && !noproxy)
expected = SOUP_STATUS_PROXY_UNAUTHORIZED;
/* We create a new session for each request to ensure that
* connections/auth aren't cached between tests.
*/
- proxy_uri = soup_uri_new (proxies[proxy]);
session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
- SOUP_SESSION_PROXY_URI, proxy_uri,
+ SOUP_SESSION_PROXY_RESOLVER, proxy_resolvers[proxy],
+ SOUP_SESSION_SSL_STRICT, FALSE,
NULL);
- soup_uri_free (proxy_uri);
g_signal_connect (session, "authenticate",
G_CALLBACK (authenticate), NULL);
if (close) {
+ /* FIXME g_test_bug ("611663") */
g_signal_connect (session, "request-started",
G_CALLBACK (set_close_on_connect), NULL);
}
- requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
- request = soup_requester_request (requester, url, NULL);
+ request = soup_session_request (session, url, NULL);
msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
- if (sync)
- stream = soup_request_send (request, NULL, &error);
- else
- stream = soup_test_request_send_async_as_sync (request, NULL, &error);
-
- if (!stream) {
- debug_printf (1, " Unexpected error on Request: %s\n",
- error->message);
- errors++;
- g_clear_error (&error);
- }
+ stream = soup_test_request_send (request, NULL, 0, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
if (stream) {
- if (sync)
- g_input_stream_close (stream, NULL, NULL);
- else
- soup_test_stream_close_async_as_sync (stream, NULL, NULL);
- if (error) {
- debug_printf (1, " Unexpected error on close: %s\n",
- error->message);
- errors++;
- g_clear_error (&error);
- }
+ soup_test_request_close_stream (request, stream, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ g_object_unref (stream);
}
debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase);
- if (msg->status_code != expected) {
- debug_printf (1, " EXPECTED %d!\n", expected);
- errors++;
- }
+ soup_test_assert_message_status (msg, expected);
g_object_unref (msg);
g_object_unref (request);
@@ -204,42 +183,70 @@ test_url_new_api (const char *url, int proxy, guint expected,
}
static void
-run_test (int i, gboolean sync)
+do_proxy_test (SoupProxyTest *test, gboolean sync)
{
char *http_url, *https_url;
- debug_printf (1, "Test %d: %s (%s)\n", i + 1, tests[i].explanation,
- sync ? "sync" : "async");
+ if (test->bugref)
+ g_test_bug (test->bugref);
+
+ if (!strncmp (test->url, "http", 4)) {
+ SoupURI *uri;
+ guint port;
- if (!strncmp (tests[i].url, "http", 4)) {
- http_url = g_strdup (tests[i].url);
- https_url = g_strdup_printf ("https%s", tests[i].url + 4);
+ http_url = g_strdup (test->url);
+
+ uri = soup_uri_new (test->url);
+ port = uri->port;
+ soup_uri_set_scheme (uri, "https");
+ if (port)
+ soup_uri_set_port (uri, port + 1);
+ https_url = soup_uri_to_string (uri, FALSE);
+ soup_uri_free (uri);
} else {
- http_url = g_strconcat (HTTP_SERVER, tests[i].url, NULL);
- https_url = g_strconcat (HTTPS_SERVER, tests[i].url, NULL);
+ http_url = g_strconcat (HTTP_SERVER, test->url, NULL);
+ https_url = g_strconcat (HTTPS_SERVER, test->url, NULL);
}
- test_url (http_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
- test_url_new_api (http_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
- test_url (https_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
- test_url_new_api (https_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE);
+ test_url (http_url, SIMPLE_PROXY, test->final_status, sync, FALSE);
+ test_url_new_api (http_url, SIMPLE_PROXY, test->final_status, sync, FALSE);
+ test_url (https_url, SIMPLE_PROXY, test->final_status, sync, FALSE);
+ test_url_new_api (https_url, SIMPLE_PROXY, test->final_status, sync, FALSE);
- test_url (http_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
- test_url_new_api (http_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
- test_url (https_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
- test_url_new_api (https_url, AUTH_PROXY, tests[i].final_status, sync, FALSE);
- test_url (https_url, AUTH_PROXY, tests[i].final_status, sync, TRUE);
- test_url_new_api (https_url, AUTH_PROXY, tests[i].final_status, sync, TRUE);
+ test_url (http_url, AUTH_PROXY, test->final_status, sync, FALSE);
+ test_url_new_api (http_url, AUTH_PROXY, test->final_status, sync, FALSE);
+ test_url (https_url, AUTH_PROXY, test->final_status, sync, FALSE);
+ test_url_new_api (https_url, AUTH_PROXY, test->final_status, sync, FALSE);
+ test_url (https_url, AUTH_PROXY, test->final_status, sync, TRUE);
+ test_url_new_api (https_url, AUTH_PROXY, test->final_status, sync, TRUE);
- test_url (http_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
- test_url_new_api (http_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
- test_url (https_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
- test_url_new_api (https_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE);
+ test_url (http_url, UNAUTH_PROXY, test->final_status, sync, FALSE);
+ test_url_new_api (http_url, UNAUTH_PROXY, test->final_status, sync, FALSE);
+ test_url (https_url, UNAUTH_PROXY, test->final_status, sync, FALSE);
+ test_url_new_api (https_url, UNAUTH_PROXY, test->final_status, sync, FALSE);
g_free (http_url);
g_free (https_url);
+}
+
+static void
+do_async_proxy_test (gconstpointer data)
+{
+ SoupProxyTest *test = (SoupProxyTest *)data;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
- debug_printf (1, "\n");
+ do_proxy_test (test, FALSE);
+}
+
+static void
+do_sync_proxy_test (gconstpointer data)
+{
+ SoupProxyTest *test = (SoupProxyTest *)data;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ do_proxy_test (test, TRUE);
}
static void
@@ -253,13 +260,14 @@ server_callback (SoupServer *server, SoupMessage *msg,
}
static void
-do_proxy_fragment_test (SoupURI *base_uri)
+do_proxy_fragment_test (gconstpointer data)
{
+ SoupURI *base_uri = (SoupURI *)data;
SoupSession *session;
SoupURI *proxy_uri, *req_uri;
SoupMessage *msg;
- debug_printf (1, "\nTesting request with fragment via proxy\n");
+ SOUP_TEST_SKIP_IF_NO_APACHE;
proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
@@ -272,11 +280,7 @@ do_proxy_fragment_test (SoupURI *base_uri)
soup_uri_free (req_uri);
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " unexpected status %d %s!\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
g_object_unref (msg);
soup_test_session_abort_unref (session);
@@ -289,7 +293,10 @@ do_proxy_redirect_test (void)
SoupURI *proxy_uri, *req_uri, *new_uri;
SoupMessage *msg;
- debug_printf (1, "\nTesting redirection through proxy\n");
+ g_test_bug ("631368");
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+ SOUP_TEST_SKIP_IF_NO_TLS;
proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
@@ -305,17 +312,11 @@ do_proxy_redirect_test (void)
soup_session_send_message (session, msg);
new_uri = soup_message_get_uri (msg);
- if (!strcmp (req_uri->path, new_uri->path)) {
- debug_printf (1, " message was not redirected!\n");
- errors++;
- }
+ soup_test_assert (strcmp (req_uri->path, new_uri->path) != 0,
+ "message was not redirected");
soup_uri_free (req_uri);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " unexpected status %d %s!\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
g_object_unref (msg);
soup_test_session_abort_unref (session);
@@ -326,14 +327,15 @@ main (int argc, char **argv)
{
SoupServer *server;
SoupURI *base_uri;
- int i;
+ char *path;
+ int i, ret;
test_init (argc, argv, NULL);
apache_init ();
- for (i = 0; i < ntests; i++) {
- run_test (i, FALSE);
- run_test (i, TRUE);
+ for (i = 0; i < 3; i++) {
+ proxy_resolvers[i] =
+ g_simple_proxy_resolver_new (proxies[i], (char **) ignore_hosts);
}
server = soup_test_server_new (TRUE);
@@ -341,12 +343,25 @@ main (int argc, char **argv)
base_uri = soup_uri_new ("http://127.0.0.1/");
soup_uri_set_port (base_uri, soup_server_get_port (server));
- do_proxy_fragment_test (base_uri);
- do_proxy_redirect_test ();
+ for (i = 0; i < ntests; i++) {
+ path = g_strdup_printf ("/proxy/async/%s", tests[i].explanation);
+ g_test_add_data_func (path, &tests[i], do_async_proxy_test);
+ g_free (path);
+ }
+ for (i = 0; i < ntests; i++) {
+ path = g_strdup_printf ("/proxy/sync/%s", tests[i].explanation);
+ g_test_add_data_func (path, &tests[i], do_sync_proxy_test);
+ g_free (path);
+ }
+
+ g_test_add_data_func ("/proxy/fragment", base_uri, do_proxy_fragment_test);
+ g_test_add_func ("/proxy/redirect", do_proxy_redirect_test);
+
+ ret = g_test_run ();
soup_uri_free (base_uri);
soup_test_server_quit_unref (server);
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/pull-api.c b/tests/pull-api.c
index 512d1768..2915b9e4 100644
--- a/tests/pull-api.c
+++ b/tests/pull-api.c
@@ -12,6 +12,7 @@ authenticate (SoupSession *session, SoupMessage *msg,
soup_auth_authenticate (auth, "user2", "realm2");
}
+#if HAVE_APACHE
static void
get_correct_response (const char *uri)
{
@@ -32,6 +33,7 @@ get_correct_response (const char *uri)
g_object_unref (msg);
soup_test_session_abort_unref (session);
}
+#endif
/* Pull API version 1: fully-async. More like a "poke" API. Rather
* than having SoupMessage emit "got_chunk" signals whenever it wants,
@@ -161,9 +163,7 @@ fully_async_got_headers (SoupMessage *msg, gpointer user_data)
*/
return;
} else if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " unexpected status: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
return;
}
@@ -192,18 +192,10 @@ fully_async_got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data)
* test program, that means comparing it against
* correct_response to make sure that we got the right data.
*/
- if (ad->read_so_far + chunk->length > correct_response->length) {
- debug_printf (1, " read too far! (%lu > %lu)\n",
- (unsigned long) (ad->read_so_far + chunk->length),
- (unsigned long) correct_response->length);
- errors++;
- } else if (memcmp (chunk->data,
- correct_response->data + ad->read_so_far,
- chunk->length) != 0) {
- debug_printf (1, " data mismatch in block starting at %lu\n",
- (unsigned long) ad->read_so_far);
- errors++;
- }
+ g_assert_cmpint (ad->read_so_far + chunk->length, <=, correct_response->length);
+ soup_assert_cmpmem (chunk->data, chunk->length,
+ correct_response->data + ad->read_so_far,
+ chunk->length);
ad->read_so_far += chunk->length;
/* Now pause I/O, and prepare to read another chunk later.
@@ -224,11 +216,7 @@ fully_async_finished (SoupSession *session, SoupMessage *msg,
{
FullyAsyncData *ad = user_data;
- if (msg->status_code != ad->expected_status) {
- debug_printf (1, " unexpected final status: %d %s !\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, ad->expected_status);
if (ad->timeout != 0)
g_source_remove (ad->timeout);
@@ -240,6 +228,45 @@ fully_async_finished (SoupSession *session, SoupMessage *msg,
g_main_loop_quit (ad->loop);
}
+static void
+do_fast_async_test (gconstpointer data)
+{
+ const char *base_uri = data;
+ SoupSession *session;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (authenticate), NULL);
+ do_fully_async_test (session, base_uri, "/",
+ TRUE, SOUP_STATUS_OK);
+ do_fully_async_test (session, base_uri, "/Basic/realm1/",
+ TRUE, SOUP_STATUS_UNAUTHORIZED);
+ do_fully_async_test (session, base_uri, "/Basic/realm2/",
+ TRUE, SOUP_STATUS_OK);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_slow_async_test (gconstpointer data)
+{
+ const char *base_uri = data;
+ SoupSession *session;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (authenticate), NULL);
+ do_fully_async_test (session, base_uri, "/",
+ FALSE, SOUP_STATUS_OK);
+ do_fully_async_test (session, base_uri, "/Basic/realm1/",
+ FALSE, SOUP_STATUS_UNAUTHORIZED);
+ do_fully_async_test (session, base_uri, "/Basic/realm2/",
+ FALSE, SOUP_STATUS_OK);
+ soup_test_session_abort_unref (session);
+}
/* Pull API version 2: synchronous pull API via async I/O. */
@@ -284,14 +311,12 @@ do_synchronously_async_test (SoupSession *session,
/* Send the message, get back headers */
sync_async_send (session, msg);
- if (sync_async_is_finished (msg) &&
- expected_status == SOUP_STATUS_OK) {
- debug_printf (1, " finished without reading response!\n");
- errors++;
- } else if (!sync_async_is_finished (msg) &&
- expected_status != SOUP_STATUS_OK) {
- debug_printf (1, " request failed to fail!\n");
- errors++;
+ if (expected_status == SOUP_STATUS_OK) {
+ soup_test_assert (!sync_async_is_finished (msg),
+ "finished without reading response");
+ } else {
+ soup_test_assert (sync_async_is_finished (msg),
+ "request failed to fail");
}
/* Now we're ready to read the response body (though we could
@@ -303,32 +328,19 @@ do_synchronously_async_test (SoupSession *session,
(unsigned long) read_so_far,
(unsigned long) read_so_far + chunk->length);
- if (read_so_far + chunk->length > correct_response->length) {
- debug_printf (1, " read too far! (%lu > %lu)\n",
- (unsigned long) read_so_far + chunk->length,
- (unsigned long) correct_response->length);
- errors++;
- } else if (memcmp (chunk->data,
- correct_response->data + read_so_far,
- chunk->length) != 0) {
- debug_printf (1, " data mismatch in block starting at %lu\n",
- (unsigned long) read_so_far);
- errors++;
- }
+ g_assert_cmpint (read_so_far + chunk->length, <=, correct_response->length);
+ soup_assert_cmpmem (chunk->data, chunk->length,
+ correct_response->data + read_so_far,
+ chunk->length);
+
read_so_far += chunk->length;
soup_buffer_free (chunk);
}
- if (!sync_async_is_finished (msg) ||
- (msg->status_code == SOUP_STATUS_OK &&
- read_so_far != correct_response->length)) {
- debug_printf (1, " loop ended before message was fully read!\n");
- errors++;
- } else if (msg->status_code != expected_status) {
- debug_printf (1, " unexpected final status: %d %s !\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ g_assert_true (sync_async_is_finished (msg));
+ soup_test_assert_message_status (msg, expected_status);
+ if (msg->status_code == SOUP_STATUS_OK)
+ g_assert_cmpint (read_so_far, ==, correct_response->length);
sync_async_cleanup (msg);
g_object_unref (msg);
@@ -393,9 +405,7 @@ sync_async_got_headers (SoupMessage *msg, gpointer user_data)
*/
return;
} else if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " unexpected status: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
return;
}
@@ -473,44 +483,14 @@ sync_async_cleanup (SoupMessage *msg)
g_free (ad);
}
-
-int
-main (int argc, char **argv)
+static void
+do_sync_async_test (gconstpointer data)
{
+ const char *base_uri = data;
SoupSession *session;
- const char *base_uri;
- test_init (argc, argv, NULL);
- apache_init ();
-
- base_uri = "http://127.0.0.1:47524/";
- get_correct_response (base_uri);
-
- debug_printf (1, "\nFully async, fast requests\n");
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- g_signal_connect (session, "authenticate",
- G_CALLBACK (authenticate), NULL);
- do_fully_async_test (session, base_uri, "/",
- TRUE, SOUP_STATUS_OK);
- do_fully_async_test (session, base_uri, "/Basic/realm1/",
- TRUE, SOUP_STATUS_UNAUTHORIZED);
- do_fully_async_test (session, base_uri, "/Basic/realm2/",
- TRUE, SOUP_STATUS_OK);
- soup_test_session_abort_unref (session);
-
- debug_printf (1, "\nFully async, slow requests\n");
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- g_signal_connect (session, "authenticate",
- G_CALLBACK (authenticate), NULL);
- do_fully_async_test (session, base_uri, "/",
- FALSE, SOUP_STATUS_OK);
- do_fully_async_test (session, base_uri, "/Basic/realm1/",
- FALSE, SOUP_STATUS_UNAUTHORIZED);
- do_fully_async_test (session, base_uri, "/Basic/realm2/",
- FALSE, SOUP_STATUS_OK);
- soup_test_session_abort_unref (session);
+ SOUP_TEST_SKIP_IF_NO_APACHE;
- debug_printf (1, "\nSynchronously async\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
g_signal_connect (session, "authenticate",
G_CALLBACK (authenticate), NULL);
@@ -521,9 +501,33 @@ main (int argc, char **argv)
do_synchronously_async_test (session, base_uri, "/Basic/realm2/",
SOUP_STATUS_OK);
soup_test_session_abort_unref (session);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ const char *base_uri;
+ int ret;
+
+ test_init (argc, argv, NULL);
+ apache_init ();
+
+ base_uri = "http://127.0.0.1:47524/";
+#if HAVE_APACHE
+ get_correct_response (base_uri);
+#endif
+
+ g_test_add_data_func ("/pull-api/async/fast", base_uri, do_fast_async_test);
+ g_test_add_data_func ("/pull-api/async/slow", base_uri, do_slow_async_test);
+ g_test_add_data_func ("/pull-api/sync-async", base_uri, do_sync_async_test);
+
+ ret = g_test_run ();
+#if HAVE_APACHE
soup_buffer_free (correct_response);
+#endif
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/range-test.c b/tests/range-test.c
index 98f56450..c23ba462 100644
--- a/tests/range-test.c
+++ b/tests/range-test.c
@@ -7,23 +7,6 @@ int total_length;
char *test_response;
static void
-get_full_response (void)
-{
- char *contents;
- gsize length;
- GError *error = NULL;
-
- if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) {
- g_printerr ("Could not read index.txt: %s\n",
- error->message);
- exit (1);
- }
-
- full_response = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length);
- debug_printf (1, "Total response length is %d\n\n", (int)length);
-}
-
-static void
check_part (SoupMessageHeaders *headers, const char *body, gsize body_len,
gboolean check_start_end, int expected_start, int expected_end)
{
@@ -33,41 +16,39 @@ check_part (SoupMessageHeaders *headers, const char *body, gsize body_len,
soup_message_headers_get_one (headers, "Content-Range"));
if (!soup_message_headers_get_content_range (headers, &start, &end, &total_length)) {
- debug_printf (1, " Could not find/parse Content-Range\n");
- errors++;
+ soup_test_assert (FALSE, "Could not find/parse Content-Range");
return;
}
if (total_length != full_response->length && total_length != -1) {
- debug_printf (1, " Unexpected total length %" G_GINT64_FORMAT " in response\n",
- total_length);
- errors++;
+ soup_test_assert (FALSE,
+ "Unexpected total length %" G_GINT64_FORMAT " in response\n",
+ total_length);
return;
}
if (check_start_end) {
if ((expected_start >= 0 && start != expected_start) ||
(expected_start < 0 && start != full_response->length + expected_start)) {
- debug_printf (1, " Unexpected range start %" G_GINT64_FORMAT " in response\n",
- start);
- errors++;
+ soup_test_assert (FALSE,
+ "Unexpected range start %" G_GINT64_FORMAT " in response\n",
+ start);
return;
}
if ((expected_end >= 0 && end != expected_end) ||
(expected_end < 0 && end != full_response->length - 1)) {
- debug_printf (1, " Unexpected range end %" G_GINT64_FORMAT " in response\n",
- end);
- errors++;
+ soup_test_assert (FALSE,
+ "Unexpected range end %" G_GINT64_FORMAT " in response\n",
+ end);
return;
}
}
if (end - start + 1 != body_len) {
- debug_printf (1, " Range length (%d) does not match body length (%d)\n",
- (int)(end - start) + 1,
- (int)body_len);
- errors++;
+ soup_test_assert (FALSE, "Range length (%d) does not match body length (%d)\n",
+ (int)(end - start) + 1,
+ (int)body_len);
return;
}
@@ -76,7 +57,7 @@ check_part (SoupMessageHeaders *headers, const char *body, gsize body_len,
static void
do_single_range (SoupSession *session, SoupMessage *msg,
- int start, int end)
+ int start, int end, gboolean succeed)
{
const char *content_type;
@@ -85,22 +66,26 @@ do_single_range (SoupSession *session, SoupMessage *msg,
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) {
- debug_printf (1, " Unexpected status %d %s\n",
- msg->status_code, msg->reason_phrase);
+ if (!succeed) {
+ soup_test_assert_message_status (msg, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
+ if (msg->status_code != SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) {
+ const char *content_range;
+
+ content_range = soup_message_headers_get_one (msg->response_headers,
+ "Content-Range");
+ if (content_range)
+ debug_printf (1, " Content-Range: %s\n", content_range);
+ }
+
g_object_unref (msg);
- errors++;
return;
}
+ soup_test_assert_message_status (msg, SOUP_STATUS_PARTIAL_CONTENT);
+
content_type = soup_message_headers_get_content_type (
msg->response_headers, NULL);
- if (content_type && !strcmp (content_type, "multipart/byteranges")) {
- debug_printf (1, " Response body should not have been multipart/byteranges\n");
- g_object_unref (msg);
- errors++;
- return;
- }
+ g_assert_cmpstr (content_type, !=, "multipart/byteranges");
check_part (msg->response_headers, msg->response_body->data,
msg->response_body->length, TRUE, start, end);
@@ -109,13 +94,13 @@ do_single_range (SoupSession *session, SoupMessage *msg,
static void
request_single_range (SoupSession *session, const char *uri,
- int start, int end)
+ int start, int end, gboolean succeed)
{
SoupMessage *msg;
msg = soup_message_new ("GET", uri);
soup_message_headers_set_range (msg->request_headers, start, end);
- do_single_range (session, msg, start, end);
+ do_single_range (session, msg, start, end, succeed);
}
static void
@@ -131,38 +116,21 @@ do_multi_range (SoupSession *session, SoupMessage *msg,
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) {
- debug_printf (1, " Unexpected status %d %s\n",
- msg->status_code, msg->reason_phrase);
- g_object_unref (msg);
- errors++;
- return;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_PARTIAL_CONTENT);
content_type = soup_message_headers_get_content_type (msg->response_headers, NULL);
- if (!content_type || strcmp (content_type, "multipart/byteranges") != 0) {
- debug_printf (1, " Response Content-Type (%s) was not multipart/byteranges\n",
- content_type);
- g_object_unref (msg);
- errors++;
- return;
- }
+ g_assert_cmpstr (content_type, ==, "multipart/byteranges");
multipart = soup_multipart_new_from_message (msg->response_headers,
msg->response_body);
if (!multipart) {
- debug_printf (1, " Could not parse multipart\n");
+ soup_test_assert (FALSE, "Could not parse multipart");
g_object_unref (msg);
- errors++;
return;
}
length = soup_multipart_get_length (multipart);
- if (length != expected_return_ranges) {
- debug_printf (1, " Expected %d ranges, got %d\n",
- expected_return_ranges, length);
- errors++;
- }
+ g_assert_cmpint (length, ==, expected_return_ranges);
for (i = 0; i < length; i++) {
SoupMessageHeaders *headers;
@@ -196,7 +164,8 @@ request_double_range (SoupSession *session, const char *uri,
if (expected_return_ranges == 1) {
do_single_range (session, msg,
MIN (first_start, second_start),
- MAX (first_end, second_end));
+ MAX (first_end, second_end),
+ TRUE);
} else
do_multi_range (session, msg, expected_return_ranges);
}
@@ -223,13 +192,36 @@ request_triple_range (SoupSession *session, const char *uri,
if (expected_return_ranges == 1) {
do_single_range (session, msg,
MIN (first_start, MIN (second_start, third_start)),
- MAX (first_end, MAX (second_end, third_end)));
+ MAX (first_end, MAX (second_end, third_end)),
+ TRUE);
} else
do_multi_range (session, msg, expected_return_ranges);
}
static void
-do_range_test (SoupSession *session, const char *uri, gboolean expect_coalesce)
+request_semi_invalid_range (SoupSession *session, const char *uri,
+ int first_good_start, int first_good_end,
+ int bad_start, int bad_end,
+ int second_good_start, int second_good_end)
+{
+ SoupMessage *msg;
+ SoupRange ranges[3];
+
+ msg = soup_message_new ("GET", uri);
+ ranges[0].start = first_good_start;
+ ranges[0].end = first_good_end;
+ ranges[1].start = bad_start;
+ ranges[1].end = bad_end;
+ ranges[2].start = second_good_start;
+ ranges[2].end = second_good_end;
+ soup_message_headers_set_ranges (msg->request_headers, ranges, 3);
+
+ do_multi_range (session, msg, 2);
+}
+
+static void
+do_range_test (SoupSession *session, const char *uri,
+ gboolean expect_coalesce, gboolean expect_partial_coalesce)
{
int twelfths = full_response->length / 12;
@@ -255,7 +247,8 @@ do_range_test (SoupSession *session, const char *uri, gboolean expect_coalesce)
/* A: 0, simple request */
debug_printf (1, "Requesting %d-%d\n", 0 * twelfths, 1 * twelfths);
request_single_range (session, uri,
- 0 * twelfths, 1 * twelfths);
+ 0 * twelfths, 1 * twelfths,
+ TRUE);
/* B: 11, end-relative request. These two are mostly redundant
* in terms of data coverage, but they may still catch
@@ -263,10 +256,12 @@ do_range_test (SoupSession *session, const char *uri, gboolean expect_coalesce)
*/
debug_printf (1, "Requesting %d-\n", 11 * twelfths);
request_single_range (session, uri,
- 11 * twelfths, -1);
+ 11 * twelfths, -1,
+ TRUE);
debug_printf (1, "Requesting -%d\n", 1 * twelfths);
request_single_range (session, uri,
- -1 * twelfths, -1);
+ -1 * twelfths, -1,
+ TRUE);
/* C: 2 and 5 */
debug_printf (1, "Requesting %d-%d,%d-%d\n",
@@ -309,12 +304,43 @@ do_range_test (SoupSession *session, const char *uri, gboolean expect_coalesce)
9 * twelfths, 10 * twelfths + 5,
4 * twelfths, 5 * twelfths,
10 * twelfths - 5, 11 * twelfths,
- expect_coalesce ? 2 : 3);
+ expect_partial_coalesce ? 2 : 3);
- if (memcmp (full_response->data, test_response, full_response->length) != 0) {
- debug_printf (1, "\nfull_response and test_response don't match\n");
- errors++;
- }
+ soup_assert_cmpmem (full_response->data, full_response->length,
+ test_response, full_response->length);
+
+ debug_printf (1, "Requesting (invalid) %d-%d\n",
+ (int) full_response->length + 1,
+ (int) full_response->length + 100);
+ request_single_range (session, uri,
+ full_response->length + 1, full_response->length + 100,
+ FALSE);
+
+ debug_printf (1, "Requesting (semi-invalid) 1-10,%d-%d,20-30\n",
+ (int) full_response->length + 1,
+ (int) full_response->length + 100);
+ request_semi_invalid_range (session, uri,
+ 1, 10,
+ full_response->length + 1, full_response->length + 100,
+ 20, 30);
+}
+
+static void
+do_apache_range_test (void)
+{
+ SoupSession *session;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+
+#if HAVE_APACHE_2_2
+ do_range_test (session, "http://127.0.0.1:47524/", FALSE, FALSE);
+#else
+ do_range_test (session, "http://127.0.0.1:47524/", TRUE, FALSE);
+#endif
+
+ soup_test_session_abort_unref (session);
}
static void
@@ -330,38 +356,44 @@ server_handler (SoupServer *server,
full_response);
}
-int
-main (int argc, char **argv)
+static void
+do_libsoup_range_test (void)
{
SoupSession *session;
SoupServer *server;
char *base_uri;
- test_init (argc, argv, NULL);
- apache_init ();
-
- get_full_response ();
- test_response = g_malloc0 (full_response->length);
-
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- debug_printf (1, "1. Testing against apache\n");
- do_range_test (session, "http://127.0.0.1:47524/", FALSE);
-
- debug_printf (1, "\n2. Testing against SoupServer\n");
server = soup_test_server_new (FALSE);
soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
base_uri = g_strdup_printf ("http://127.0.0.1:%u/",
soup_server_get_port (server));
- do_range_test (session, base_uri, TRUE);
+ do_range_test (session, base_uri, TRUE, TRUE);
g_free (base_uri);
soup_test_server_quit_unref (server);
soup_test_session_abort_unref (session);
+}
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+
+ test_init (argc, argv, NULL);
+ apache_init ();
+
+ full_response = soup_test_get_index ();
+ test_response = g_malloc0 (full_response->length);
+
+ g_test_add_func ("/ranges/apache", do_apache_range_test);
+ g_test_add_func ("/ranges/libsoup", do_libsoup_range_test);
+
+ ret = g_test_run ();
- soup_buffer_free (full_response);
g_free (test_response);
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/redirect-test.c b/tests/redirect-test.c
index 59a2f077..ad8dabaa 100644
--- a/tests/redirect-test.c
+++ b/tests/redirect-test.c
@@ -5,7 +5,9 @@
#include "test-utils.h"
+SoupURI *base_uri;
char *server2_uri;
+SoupSession *async_session, *sync_session;
typedef struct {
const char *method;
@@ -14,104 +16,106 @@ typedef struct {
gboolean repeat;
} TestRequest;
-static struct {
+typedef struct {
TestRequest requests[3];
guint final_status;
- guint request_api_final_status;
-} tests[] = {
+ const char *bugref;
+} TestCase;
+
+static TestCase tests[] = {
/* A redirecty response to a GET or HEAD should cause a redirect */
{ { { "GET", "/301", 301 },
{ "GET", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, NULL },
{ { { "GET", "/302", 302 },
{ "GET", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, NULL },
{ { { "GET", "/303", 303 },
{ "GET", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, NULL },
{ { { "GET", "/307", 307 },
{ "GET", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, NULL },
{ { { "HEAD", "/301", 301 },
{ "HEAD", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, "551190" },
{ { { "HEAD", "/302", 302 },
{ "HEAD", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, "551190" },
/* 303 is a nonsensical response to HEAD, but some sites do
* it anyway. :-/
*/
{ { { "HEAD", "/303", 303 },
{ "HEAD", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, "600830" },
{ { { "HEAD", "/307", 307 },
{ "HEAD", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, "551190" },
/* A non-redirecty response to a GET or HEAD should not */
{ { { "GET", "/300", 300 },
- { NULL } }, 300 },
+ { NULL } }, 300, NULL },
{ { { "GET", "/304", 304 },
- { NULL } }, 304 },
+ { NULL } }, 304, NULL },
{ { { "GET", "/305", 305 },
- { NULL } }, 305 },
+ { NULL } }, 305, NULL },
{ { { "GET", "/306", 306 },
- { NULL } }, 306 },
+ { NULL } }, 306, NULL },
{ { { "GET", "/308", 308 },
- { NULL } }, 308 },
+ { NULL } }, 308, NULL },
{ { { "HEAD", "/300", 300 },
- { NULL } }, 300 },
+ { NULL } }, 300, "551190" },
{ { { "HEAD", "/304", 304 },
- { NULL } }, 304 },
+ { NULL } }, 304, "551190" },
{ { { "HEAD", "/305", 305 },
- { NULL } }, 305 },
+ { NULL } }, 305, "551190" },
{ { { "HEAD", "/306", 306 },
- { NULL } }, 306 },
+ { NULL } }, 306, "551190" },
{ { { "HEAD", "/308", 308 },
- { NULL } }, 308 },
+ { NULL } }, 308, "551190" },
/* Test double-redirect */
{ { { "GET", "/301/302", 301 },
{ "GET", "/302", 302 },
- { "GET", "/", 200 } }, 200 },
+ { "GET", "/", 200 } }, 200, NULL },
{ { { "HEAD", "/301/302", 301 },
{ "HEAD", "/302", 302 },
- { "HEAD", "/", 200 } }, 200 },
+ { "HEAD", "/", 200 } }, 200, "551190" },
/* POST should only automatically redirect on 301, 302 and 303 */
{ { { "POST", "/301", 301 },
{ "GET", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, "586692" },
{ { { "POST", "/302", 302 },
{ "GET", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, NULL },
{ { { "POST", "/303", 303 },
{ "GET", "/", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, NULL },
{ { { "POST", "/307", 307 },
- { NULL } }, 307 },
+ { NULL } }, 307, NULL },
/* Test behavior with recoverably-bad Location header */
{ { { "GET", "/bad", 302 },
{ "GET", "/bad%20with%20spaces", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, "566530" },
/* Test behavior with irrecoverably-bad Location header */
{ { { "GET", "/bad-no-host", 302 },
- { NULL } }, SOUP_STATUS_MALFORMED, 302 },
+ { NULL } }, SOUP_STATUS_MALFORMED, "528882" },
/* Test infinite redirection */
{ { { "GET", "/bad-recursive", 302, TRUE },
- { NULL } }, SOUP_STATUS_TOO_MANY_REDIRECTS },
+ { NULL } }, SOUP_STATUS_TOO_MANY_REDIRECTS, "604383" },
/* Test redirection to a different server */
{ { { "GET", "/server2", 302 },
{ "GET", "/on-server2", 200 },
- { NULL } }, 200 },
+ { NULL } }, 200, NULL },
};
static const int n_tests = G_N_ELEMENTS (tests);
@@ -131,11 +135,7 @@ got_headers (SoupMessage *msg, gpointer user_data)
if (!(*treq)->method)
return;
- if (msg->status_code != (*treq)->status_code) {
- debug_printf (1, " - Expected %d !\n",
- (*treq)->status_code);
- errors++;
- }
+ soup_test_assert_message_status (msg, (*treq)->status_code);
}
static void
@@ -149,35 +149,25 @@ restarted (SoupMessage *msg, gpointer user_data)
if ((*treq)->method && !(*treq)->repeat)
(*treq)++;
- if (!(*treq)->method) {
- debug_printf (1, " - Expected to be done!\n");
- errors++;
- return;
- }
+ soup_test_assert ((*treq)->method,
+ "Expected to be done");
- if (strcmp (msg->method, (*treq)->method) != 0) {
- debug_printf (1, " - Expected %s !\n", (*treq)->method);
- errors++;
- }
- if (strcmp (uri->path, (*treq)->path) != 0) {
- debug_printf (1, " - Expected %s !\n", (*treq)->path);
- errors++;
- }
+ g_assert_cmpstr (msg->method, ==, (*treq)->method);
+ g_assert_cmpstr (uri->path, ==, (*treq)->path);
}
static void
-do_message_api_test (SoupSession *session, SoupURI *base_uri, int n)
+do_message_api_test (SoupSession *session, TestCase *test)
{
SoupURI *uri;
SoupMessage *msg;
TestRequest *treq;
- debug_printf (1, "%2d. %s %s\n", n + 1,
- tests[n].requests[0].method,
- tests[n].requests[0].path);
+ if (test->bugref)
+ g_test_bug (test->bugref);
- uri = soup_uri_new_with_base (base_uri, tests[n].requests[0].path);
- msg = soup_message_new_from_uri (tests[n].requests[0].method, uri);
+ uri = soup_uri_new_with_base (base_uri, test->requests[0].path);
+ msg = soup_message_new_from_uri (test->requests[0].method, uri);
soup_uri_free (uri);
if (msg->method == SOUP_METHOD_POST) {
@@ -187,7 +177,7 @@ do_message_api_test (SoupSession *session, SoupURI *base_uri, int n)
strlen ("post body"));
}
- treq = &tests[n].requests[0];
+ treq = &test->requests[0];
g_signal_connect (msg, "got_headers",
G_CALLBACK (got_headers), &treq);
g_signal_connect (msg, "restarted",
@@ -195,53 +185,36 @@ do_message_api_test (SoupSession *session, SoupURI *base_uri, int n)
soup_session_send_message (session, msg);
- if (msg->status_code != tests[n].final_status) {
- debug_printf (1, " - Expected final status of %d, got %d !\n",
- tests[n].final_status, msg->status_code);
- errors++;
- }
+ soup_test_assert_message_status (msg, test->final_status);
g_object_unref (msg);
- debug_printf (2, "\n");
}
static void
-do_request_api_test (SoupSession *session, SoupURI *base_uri, int n)
+do_request_api_test (SoupSession *session, TestCase *test)
{
- SoupRequester *requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
SoupURI *uri;
- SoupRequest *req;
+ SoupRequestHTTP *reqh;
SoupMessage *msg;
TestRequest *treq;
GInputStream *stream;
GError *error = NULL;
- guint final_status;
-
- debug_printf (1, "%2d. %s %s\n", n + 1,
- tests[n].requests[0].method,
- tests[n].requests[0].path);
- final_status = tests[n].request_api_final_status;
- if (!final_status)
- final_status = tests[n].final_status;
+ if (test->bugref)
+ g_test_bug (test->bugref);
- uri = soup_uri_new_with_base (base_uri, tests[n].requests[0].path);
- req = soup_requester_request_uri (requester, uri, &error);
+ uri = soup_uri_new_with_base (base_uri, test->requests[0].path);
+ reqh = soup_session_request_http_uri (session,
+ test->requests[0].method,
+ uri, &error);
soup_uri_free (uri);
- if (!req) {
- debug_printf (1, " could not create request: %s\n",
- error->message);
+ g_assert_no_error (error);
+ if (error) {
g_error_free (error);
- errors++;
- debug_printf (2, "\n");
return;
}
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
- g_object_set (G_OBJECT (msg),
- SOUP_MESSAGE_METHOD, tests[n].requests[0].method,
- NULL);
-
+ msg = soup_request_http_get_message (reqh);
if (msg->method == SOUP_METHOD_POST) {
soup_message_set_request (msg, "text/plain",
SOUP_MEMORY_STATIC,
@@ -249,208 +222,75 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n)
strlen ("post body"));
}
- treq = &tests[n].requests[0];
+ treq = &test->requests[0];
g_signal_connect (msg, "got_headers",
G_CALLBACK (got_headers), &treq);
g_signal_connect (msg, "restarted",
G_CALLBACK (restarted), &treq);
- if (SOUP_IS_SESSION_SYNC (session))
- stream = soup_request_send (req, NULL, &error);
- else
- stream = soup_test_request_send_async_as_sync (req, NULL, &error);
-
- if (SOUP_STATUS_IS_TRANSPORT_ERROR (final_status)) {
- if (stream) {
- debug_printf (1, " expected failure (%s) but succeeded",
- soup_status_get_phrase (final_status));
- errors++;
- g_object_unref (stream);
- }
- if (error->domain != SOUP_HTTP_ERROR ||
- error->code != final_status) {
- debug_printf (1, " expected '%s' but got '%s'",
- soup_status_get_phrase (final_status),
- error->message);
- errors++;
- }
+ stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, 0, &error);
- g_error_free (error);
- g_object_unref (req);
- debug_printf (2, "\n");
- return;
- } else if (!stream) {
- debug_printf (1, " could not send request: %s\n",
- error->message);
- g_error_free (error);
- g_object_unref (req);
- errors++;
- debug_printf (2, "\n");
+ if (SOUP_STATUS_IS_TRANSPORT_ERROR (test->final_status) &&
+ test->final_status != SOUP_STATUS_MALFORMED) {
+ g_assert_error (error, SOUP_HTTP_ERROR, test->final_status);
+ g_clear_error (&error);
+
+ g_assert_null (stream);
+ g_clear_object (&stream);
+
+ g_object_unref (msg);
+ g_object_unref (reqh);
return;
}
- if (SOUP_IS_SESSION_SYNC (session))
- g_input_stream_close (stream, NULL, &error);
- else
- soup_test_stream_close_async_as_sync (stream, NULL, &error);
+ g_assert_no_error (error);
if (error) {
- debug_printf (1, " could not close stream: %s\n",
- error->message);
g_error_free (error);
- errors++;
+ g_object_unref (msg);
+ g_object_unref (reqh);
+ return;
}
- if (msg->status_code != final_status) {
- debug_printf (1, " - Expected final status of %d, got %d !\n",
- final_status, msg->status_code);
- errors++;
- }
+ soup_test_request_read_all (SOUP_REQUEST (reqh), stream, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
- g_object_unref (req);
- debug_printf (2, "\n");
-}
+ soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ g_object_unref (stream);
-static void
-do_redirect_tests (SoupURI *base_uri)
-{
- SoupSession *session;
- int n;
-
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
- SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
- NULL);
- debug_printf (1, "Async session, SoupMessage\n");
- for (n = 0; n < n_tests; n++)
- do_message_api_test (session, base_uri, n);
- debug_printf (1, "\nAsync session, SoupRequest\n");
- for (n = 0; n < n_tests; n++)
- do_request_api_test (session, base_uri, n);
- soup_test_session_abort_unref (session);
-
- session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
- SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
- NULL);
- debug_printf (1, "\nSync session, SoupMessage\n");
- for (n = 0; n < n_tests; n++)
- do_message_api_test (session, base_uri, n);
- debug_printf (1, "\nSync session, SoupRequest\n");
- for (n = 0; n < n_tests; n++)
- do_request_api_test (session, base_uri, n);
- soup_test_session_abort_unref (session);
-}
-
-typedef struct {
- SoupSession *session;
- SoupMessage *msg1, *msg2;
- SoupURI *uri1, *uri2;
- SoupSocket *sock1, *sock2;
-} ConnectionTestData;
+ if (test->final_status == SOUP_STATUS_MALFORMED)
+ g_assert_cmpint (msg->status_code, ==, test->requests[0].status_code);
+ else
+ g_assert_cmpint (msg->status_code, ==, test->final_status);
-static void
-msg2_finished (SoupSession *session, SoupMessage *msg2, gpointer user_data)
-{
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg2->status_code)) {
- debug_printf (1, " msg2 failed: %d %s\n",
- msg2->status_code, msg2->reason_phrase);
- errors++;
- }
+ g_object_unref (msg);
+ g_object_unref (reqh);
}
static void
-unpause_msg1 (SoupMessage *msg2, gpointer user_data)
+do_async_msg_api_test (gconstpointer test)
{
- ConnectionTestData *data = user_data;
-
- if (!data->sock1) {
- debug_printf (1, " msg1 has no connection?\n");
- errors++;
- } else if (!data->sock2) {
- debug_printf (1, " msg2 has no connection?\n");
- errors++;
- } else if (data->sock1 == data->sock2) {
- debug_printf (1, " Both messages sharing the same connection\n");
- errors++;
- }
-
- soup_session_unpause_message (data->session, data->msg1);
-}
-
-static gboolean
-msg1_just_restarted (gpointer user_data)
-{
- ConnectionTestData *data = user_data;
-
- soup_session_pause_message (data->session, data->msg1);
-
- data->msg2 = soup_message_new_from_uri ("GET", data->uri2);
-
- g_signal_connect (data->msg2, "got_body",
- G_CALLBACK (unpause_msg1), data);
-
- soup_session_queue_message (data->session, data->msg2, msg2_finished, data);
- return FALSE;
+ do_message_api_test (async_session, (TestCase *)test);
}
static void
-msg1_about_to_restart (SoupMessage *msg1, gpointer user_data)
+do_async_req_api_test (gconstpointer test)
{
- ConnectionTestData *data = user_data;
-
- /* Do nothing when loading the redirected-to resource */
- if (!SOUP_STATUS_IS_REDIRECTION (data->msg1->status_code))
- return;
-
- /* We have to pause msg1 after the I/O finishes, but before
- * the queue runs again.
- */
- g_idle_add_full (G_PRIORITY_HIGH, msg1_just_restarted, data, NULL);
+ do_request_api_test (async_session, (TestCase *)test);
}
static void
-request_started (SoupSession *session, SoupMessage *msg,
- SoupSocket *socket, gpointer user_data)
+do_sync_msg_api_test (gconstpointer test)
{
- ConnectionTestData *data = user_data;
-
- if (msg == data->msg1)
- data->sock1 = socket;
- else if (msg == data->msg2)
- data->sock2 = socket;
- else
- g_warn_if_reached ();
+ do_message_api_test (sync_session, (TestCase *)test);
}
static void
-do_connection_test (SoupURI *base_uri)
+do_sync_req_api_test (gconstpointer test)
{
- ConnectionTestData data;
-
- debug_printf (1, "\nConnection reuse\n");
- memset (&data, 0, sizeof (data));
-
- data.session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- g_signal_connect (data.session, "request-started",
- G_CALLBACK (request_started), &data);
-
- data.uri1 = soup_uri_new_with_base (base_uri, "/301");
- data.uri2 = soup_uri_new_with_base (base_uri, "/");
- data.msg1 = soup_message_new_from_uri ("GET", data.uri1);
-
- g_signal_connect (data.msg1, "got-body",
- G_CALLBACK (msg1_about_to_restart), &data);
- soup_session_send_message (data.session, data.msg1);
-
- if (!SOUP_STATUS_IS_SUCCESSFUL (data.msg1->status_code)) {
- debug_printf (1, " msg1 failed: %d %s\n",
- data.msg1->status_code, data.msg1->reason_phrase);
- errors++;
- }
- g_object_unref (data.msg1);
- soup_uri_free (data.uri1);
- soup_uri_free (data.uri2);
-
- soup_test_session_abort_unref (data.session);
+ do_request_api_test (sync_session, (TestCase *)test);
}
static void
@@ -550,29 +390,23 @@ server2_callback (SoupServer *server, SoupMessage *msg,
soup_message_set_status (msg, SOUP_STATUS_OK);
}
-static gboolean run_tests = TRUE;
-
-static GOptionEntry no_test_entry[] = {
- { "no-tests", 'n', G_OPTION_FLAG_REVERSE,
- G_OPTION_ARG_NONE, &run_tests,
- "Don't run tests, just run the test server", NULL },
- { NULL }
-};
-
int
main (int argc, char **argv)
{
GMainLoop *loop;
SoupServer *server, *server2;
guint port;
- SoupURI *base_uri;
+ char *path;
+ int n, ret;
- test_init (argc, argv, no_test_entry);
+ test_init (argc, argv, NULL);
server = soup_test_server_new (TRUE);
soup_server_add_handler (server, NULL,
server_callback, NULL, NULL);
port = soup_server_get_port (server);
+ base_uri = soup_uri_new ("http://127.0.0.1");
+ soup_uri_set_port (base_uri, port);
server2 = soup_test_server_new (TRUE);
soup_server_add_handler (server2, NULL,
@@ -582,23 +416,47 @@ main (int argc, char **argv)
loop = g_main_loop_new (NULL, TRUE);
- if (run_tests) {
- base_uri = soup_uri_new ("http://127.0.0.1");
- soup_uri_set_port (base_uri, port);
- do_redirect_tests (base_uri);
- do_connection_test (base_uri);
- soup_uri_free (base_uri);
- } else {
- g_print ("Listening on port %d\n", port);
- g_main_loop_run (loop);
+ async_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
+ sync_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+
+ for (n = 0; n < n_tests; n++) {
+ path = g_strdup_printf ("/redirect/async/msg/%d-%s-%d", n
+ , tests[n].requests[0].method,
+ tests[n].requests[0].status_code);
+ g_test_add_data_func (path, &tests[n], do_async_msg_api_test);
+ g_free (path);
+
+ path = g_strdup_printf ("/redirect/async/req/%d-%s-%d", n,
+ tests[n].requests[0].method,
+ tests[n].requests[0].status_code);
+ g_test_add_data_func (path, &tests[n], do_async_req_api_test);
+ g_free (path);
+
+ path = g_strdup_printf ("/redirect/sync/msg/%d-%s-%d", n,
+ tests[n].requests[0].method,
+ tests[n].requests[0].status_code);
+ g_test_add_data_func (path, &tests[n], do_sync_msg_api_test);
+ g_free (path);
+
+ path = g_strdup_printf ("/redirect/sync/req/%d-%s-%d", n,
+ tests[n].requests[0].method,
+ tests[n].requests[0].status_code);
+ g_test_add_data_func (path, &tests[n], do_sync_req_api_test);
+ g_free (path);
}
+ ret = g_test_run ();
+
g_main_loop_unref (loop);
- g_free (server2_uri);
+ soup_uri_free (base_uri);
soup_test_server_quit_unref (server);
+ g_free (server2_uri);
soup_test_server_quit_unref (server2);
- if (run_tests)
- test_cleanup ();
- return errors != 0;
+ soup_test_session_abort_unref (async_session);
+ soup_test_session_abort_unref (sync_session);
+
+ return ret;
}
diff --git a/tests/requester-test.c b/tests/requester-test.c
index b4e86ea6..39b30bd5 100644
--- a/tests/requester-test.c
+++ b/tests/requester-test.c
@@ -3,6 +3,9 @@
* Copyright (C) 2011 Red Hat, Inc.
*/
+/* Kill SoupRequester-related deprecation warnings */
+#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_40
+
#include "test-utils.h"
SoupServer *server;
@@ -14,24 +17,21 @@ SoupBuffer *response, *auth_response;
#define REDIRECT_HTML_BODY "<html><body>Try again</body></html>\r\n"
#define AUTH_HTML_BODY "<html><body>Unauthorized</body></html>\r\n"
-static void
-get_index (void)
+static gboolean
+slow_finish_message (gpointer msg)
{
- char *contents;
- gsize length;
- GError *error = NULL;
-
- if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) {
- g_printerr ("Could not read index.txt: %s\n",
- error->message);
- exit (1);
- }
+ SoupServer *server = g_object_get_data (G_OBJECT (msg), "server");
- response = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length);
+ soup_server_unpause_message (server, msg);
+ return FALSE;
+}
- auth_response = soup_buffer_new (SOUP_MEMORY_STATIC,
- AUTH_HTML_BODY,
- strlen (AUTH_HTML_BODY));
+static void
+slow_pause_message (SoupMessage *msg, gpointer server)
+{
+ soup_server_pause_message (server, msg);
+ soup_add_timeout (soup_server_get_async_context (server),
+ 1000, slow_finish_message, msg);
}
static void
@@ -67,6 +67,10 @@ server_callback (SoupServer *server, SoupMessage *msg,
} else if (strcmp (path, "/non-persistent") == 0) {
soup_message_headers_append (msg->response_headers,
"Connection", "close");
+ } else if (!strcmp (path, "/slow")) {
+ g_object_set_data (G_OBJECT (msg), "server", server);
+ g_signal_connect (msg, "wrote-headers",
+ G_CALLBACK (slow_pause_message), server);
}
soup_message_set_status (msg, SOUP_STATUS_OK);
@@ -99,11 +103,8 @@ stream_closed (GObject *source, GAsyncResult *res, gpointer user_data)
GInputStream *stream = G_INPUT_STREAM (source);
GError *error = NULL;
- if (!g_input_stream_close_finish (stream, res, &error)) {
- debug_printf (1, " close failed: %s\n", error->message);
- g_error_free (error);
- errors++;
- }
+ g_input_stream_close_finish (stream, res, &error);
+ g_assert_no_error (error);
g_main_loop_quit (loop);
g_object_unref (stream);
}
@@ -119,9 +120,8 @@ test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data)
nread = g_input_stream_read_finish (stream, res, &error);
if (nread == -1) {
- debug_printf (1, " read_async failed: %s\n", error->message);
+ g_assert_no_error (error);
g_error_free (error);
- errors++;
g_input_stream_close (stream, NULL, NULL);
g_object_unref (stream);
g_main_loop_quit (loop);
@@ -150,28 +150,18 @@ auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error);
if (!stream) {
- debug_printf (1, " send_async failed: %s\n", error->message);
- errors++;
+ g_assert_no_error (error);
+ g_clear_error (&error);
g_main_loop_quit (loop);
return;
}
msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (source));
- if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) {
- debug_printf (1, " GET failed: %d %s\n", msg->status_code,
- msg->reason_phrase);
- errors++;
- g_main_loop_quit (loop);
- return;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED);
g_object_unref (msg);
content_type = soup_request_get_content_type (SOUP_REQUEST (source));
- if (g_strcmp0 (content_type, "text/html") != 0) {
- debug_printf (1, " failed to sniff Content-Type: got %s\n",
- content_type ? content_type : "(NULL)");
- errors++;
- }
+ g_assert_cmpstr (content_type, ==, "text/html");
g_input_stream_read_async (stream, buf, sizeof (buf),
G_PRIORITY_DEFAULT, NULL,
@@ -188,22 +178,13 @@ test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error);
if (data->cancel) {
- if (stream) {
- debug_printf (1, " send_async succeeded??\n");
- errors++;
- g_input_stream_close (stream, NULL, NULL);
- g_object_unref (stream);
- } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- debug_printf (1, " send_async failed with wrong error: %s\n", error->message);
- errors++;
- g_clear_error (&error);
- }
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_clear_error (&error);
g_main_loop_quit (loop);
return;
} else {
+ g_assert_no_error (error);
if (!stream) {
- debug_printf (1, " send_async failed: %s\n", error->message);
- errors++;
g_main_loop_quit (loop);
g_clear_error (&error);
return;
@@ -211,11 +192,7 @@ test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
}
content_type = soup_request_get_content_type (SOUP_REQUEST (source));
- if (g_strcmp0 (content_type, "text/plain") != 0) {
- debug_printf (1, " failed to sniff Content-Type: got %s\n",
- content_type ? content_type : "(NULL)");
- errors++;
- }
+ g_assert_cmpstr (content_type, ==, "text/plain");
g_input_stream_read_async (stream, buf, sizeof (buf),
G_PRIORITY_DEFAULT, NULL,
@@ -234,6 +211,7 @@ request_started (SoupSession *session, SoupMessage *msg,
{
SoupSocket **save_socket = user_data;
+ g_clear_object (save_socket);
*save_socket = g_object_ref (socket);
}
@@ -250,11 +228,17 @@ do_async_test (SoupSession *session, SoupURI *uri,
SoupMessage *msg;
RequestData data;
- requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER));
+ if (SOUP_IS_SESSION_ASYNC (session))
+ requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER));
+ else
+ requester = NULL;
data.body = g_string_new (NULL);
data.cancel = cancel;
- request = soup_requester_request_uri (requester, uri, NULL);
+ if (requester)
+ request = soup_requester_request_uri (requester, uri, NULL);
+ else
+ request = soup_session_request_uri (session, uri, NULL);
msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
if (cancel) {
@@ -275,43 +259,20 @@ do_async_test (SoupSession *session, SoupURI *uri,
g_signal_handler_disconnect (session, started_id);
- if (msg->status_code != expected_status) {
- debug_printf (1, " GET failed: %d %s (expected %d)\n",
- msg->status_code, msg->reason_phrase,
- expected_status);
- g_object_unref (msg);
- errors++;
- return;
- }
+ soup_test_assert_message_status (msg, expected_status);
g_object_unref (msg);
- if (!expected_response) {
- if (data.body->len) {
- debug_printf (1, " body length mismatch: expected 0, got %d\n",
- (int)data.body->len);
- errors++;
- }
- } else if (data.body->len != expected_response->length) {
- debug_printf (1, " body length mismatch: expected %d, got %d\n",
- (int)expected_response->length, (int)data.body->len);
- errors++;
- } else if (memcmp (data.body->str, expected_response->data,
- expected_response->length) != 0) {
- debug_printf (1, " body data mismatch\n");
- errors++;
- }
+ if (expected_response) {
+ soup_assert_cmpmem (data.body->str, data.body->len,
+ expected_response->data, expected_response->length);
+ } else
+ g_assert_cmpint (data.body->len, ==, 0);
+
+ if (persistent)
+ g_assert_true (soup_socket_is_connected (socket));
+ else
+ g_assert_false (soup_socket_is_connected (socket));
- if (persistent) {
- if (!soup_socket_is_connected (socket)) {
- debug_printf (1, " socket not still connected!\n");
- errors++;
- }
- } else {
- if (soup_socket_is_connected (socket)) {
- debug_printf (1, " socket still connected!\n");
- errors++;
- }
- }
g_object_unref (socket);
g_string_free (data.body, TRUE);
@@ -323,19 +284,21 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri)
SoupRequester *requester;
SoupURI *uri;
- requester = soup_requester_new ();
- soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
- g_object_unref (requester);
+ if (SOUP_IS_SESSION_ASYNC (session)) {
+ requester = soup_requester_new ();
+ soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
+ g_object_unref (requester);
+ }
soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
- debug_printf (1, " basic test\n");
+ debug_printf (1, " basic test\n");
uri = soup_uri_new (base_uri);
do_async_test (session, uri, test_sent,
SOUP_STATUS_OK, response,
TRUE, FALSE);
soup_uri_free (uri);
- debug_printf (1, " chunked test\n");
+ debug_printf (1, " chunked test\n");
uri = soup_uri_new (base_uri);
soup_uri_set_path (uri, "/chunked");
do_async_test (session, uri, test_sent,
@@ -343,7 +306,7 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri)
TRUE, FALSE);
soup_uri_free (uri);
- debug_printf (1, " auth test\n");
+ debug_printf (1, " auth test\n");
uri = soup_uri_new (base_uri);
soup_uri_set_path (uri, "/auth");
do_async_test (session, uri, auth_test_sent,
@@ -351,7 +314,7 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri)
TRUE, FALSE);
soup_uri_free (uri);
- debug_printf (1, " non-persistent test\n");
+ debug_printf (1, " non-persistent test\n");
uri = soup_uri_new (base_uri);
soup_uri_set_path (uri, "/non-persistent");
do_async_test (session, uri, test_sent,
@@ -359,7 +322,7 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri)
FALSE, FALSE);
soup_uri_free (uri);
- debug_printf (1, " cancellation test\n");
+ debug_printf (1, " cancellation test\n");
uri = soup_uri_new (base_uri);
soup_uri_set_path (uri, "/");
do_async_test (session, uri, test_sent,
@@ -369,11 +332,23 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri)
}
static void
-do_simple_test (const char *uri)
+do_simple_plain_test (gconstpointer uri)
+{
+ SoupSession *session;
+
+ g_test_bug ("653707");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ do_test_for_thread_and_context (session, uri);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_simple_async_test (gconstpointer uri)
{
SoupSession *session;
- debug_printf (1, "Simple streaming test\n");
+ g_test_bug ("653707");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
@@ -382,16 +357,18 @@ do_simple_test (const char *uri)
soup_test_session_abort_unref (session);
}
-static gpointer
-do_test_with_context (const char *uri)
+static void
+do_test_with_context_and_type (const char *uri, gboolean plain_session)
{
GMainContext *async_context;
SoupSession *session;
+ g_test_bug ("653707");
+
async_context = g_main_context_new ();
g_main_context_push_thread_default (async_context);
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_ASYNC,
SOUP_SESSION_ASYNC_CONTEXT, async_context,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
@@ -401,25 +378,52 @@ do_test_with_context (const char *uri)
g_main_context_pop_thread_default (async_context);
g_main_context_unref (async_context);
- return NULL;
}
static void
-do_context_test (const char *uri)
+do_async_test_with_context (gconstpointer uri)
+{
+ do_test_with_context_and_type (uri, FALSE);
+}
+
+static void
+do_plain_test_with_context (gconstpointer uri)
+{
+ do_test_with_context_and_type (uri, TRUE);
+}
+
+static gpointer
+async_test_thread (gpointer uri)
{
- debug_printf (1, "Streaming with a non-default-context\n");
- do_test_with_context (uri);
+ do_test_with_context_and_type (uri, TRUE);
+ return NULL;
+}
+
+static gpointer
+plain_test_thread (gpointer uri)
+{
+ do_test_with_context_and_type (uri, FALSE);
+ return NULL;
}
static void
-do_thread_test (const char *uri)
+do_async_test_in_thread (gconstpointer uri)
{
GThread *thread;
- debug_printf (1, "Streaming in another thread\n");
+ thread = g_thread_new ("do_async_test_in_thread",
+ async_test_thread,
+ (gpointer)uri);
+ g_thread_join (thread);
+}
- thread = g_thread_new ("do_test_with_context",
- (GThreadFunc)do_test_with_context,
+static void
+do_plain_test_in_thread (gconstpointer uri)
+{
+ GThread *thread;
+
+ thread = g_thread_new ("do_plain_test_in_thread",
+ plain_test_thread,
(gpointer)uri);
g_thread_join (thread);
}
@@ -451,173 +455,381 @@ do_sync_request (SoupSession *session, SoupRequest *request,
in = soup_request_send (request, NULL, &error);
g_signal_handler_disconnect (session, started_id);
if (cancel) {
- if (in) {
- debug_printf (1, " send succeeded??\n");
- errors++;
- g_input_stream_close (in, NULL, NULL);
- g_object_unref (in);
- } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- debug_printf (1, " send failed with wrong error: %s\n", error->message);
- errors++;
- g_clear_error (&error);
- }
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_clear_error (&error);
g_object_unref (msg);
+ g_object_unref (socket);
return;
} else if (!in) {
- debug_printf (1, " soup_request_send failed: %s\n",
- error->message);
- g_object_unref (msg);
+ g_assert_no_error (error);
g_clear_error (&error);
- errors++;
- return;
- }
-
- if (msg->status_code != expected_status) {
- debug_printf (1, " GET failed: %d %s\n", msg->status_code,
- msg->reason_phrase);
g_object_unref (msg);
- g_object_unref (in);
- errors++;
+ g_object_unref (socket);
return;
}
+
+ soup_test_assert_message_status (msg, expected_status);
g_object_unref (msg);
body = g_string_new (NULL);
do {
nread = g_input_stream_read (in, buf, sizeof (buf),
NULL, &error);
+ g_assert_no_error (error);
if (nread == -1) {
- debug_printf (1, " g_input_stream_read failed: %s\n",
- error->message);
g_clear_error (&error);
- errors++;
break;
}
g_string_append_len (body, buf, nread);
} while (nread > 0);
- if (!g_input_stream_close (in, NULL, &error)) {
- debug_printf (1, " g_input_stream_close failed: %s\n",
- error->message);
- g_clear_error (&error);
- errors++;
- }
+ g_input_stream_close (in, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
g_object_unref (in);
- if (!expected_response) {
- if (body->len) {
- debug_printf (1, " body length mismatch: expected 0, got %d\n",
- (int)body->len);
- errors++;
- }
- } else if (body->len != expected_response->length) {
- debug_printf (1, " body length mismatch: expected %d, got %d\n",
- (int)expected_response->length, (int)body->len);
- errors++;
- } else if (memcmp (body->str, expected_response->data, body->len) != 0) {
- debug_printf (1, " body data mismatch\n");
- errors++;
- }
+ if (expected_response) {
+ soup_assert_cmpmem (body->str, body->len,
+ expected_response->data, expected_response->length);
+ } else
+ g_assert_cmpint (body->len, ==, 0);
- if (persistent) {
- if (!soup_socket_is_connected (socket)) {
- debug_printf (1, " socket not still connected!\n");
- errors++;
- }
- } else {
- if (soup_socket_is_connected (socket)) {
- debug_printf (1, " socket still connected!\n");
- errors++;
- }
- }
+ if (persistent)
+ g_assert_true (soup_socket_is_connected (socket));
+ else
+ g_assert_false (soup_socket_is_connected (socket));
g_object_unref (socket);
g_string_free (body, TRUE);
}
static void
-do_sync_test (const char *uri_string)
+do_sync_tests_for_session (SoupSession *session, const char *uri_string)
{
- SoupSession *session;
SoupRequester *requester;
SoupRequest *request;
SoupURI *uri;
- debug_printf (1, "Sync streaming\n");
-
- session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
- requester = soup_requester_new ();
- soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
- g_object_unref (requester);
+ requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER));
uri = soup_uri_new (uri_string);
- debug_printf (1, " basic test\n");
- request = soup_requester_request_uri (requester, uri, NULL);
+ debug_printf (1, " basic test\n");
+ if (requester)
+ request = soup_requester_request_uri (requester, uri, NULL);
+ else
+ request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_OK, response,
TRUE, FALSE);
g_object_unref (request);
- debug_printf (1, " chunked test\n");
+ debug_printf (1, " chunked test\n");
soup_uri_set_path (uri, "/chunked");
- request = soup_requester_request_uri (requester, uri, NULL);
+ if (requester)
+ request = soup_requester_request_uri (requester, uri, NULL);
+ else
+ request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_OK, response,
TRUE, FALSE);
g_object_unref (request);
- debug_printf (1, " auth test\n");
+ debug_printf (1, " auth test\n");
soup_uri_set_path (uri, "/auth");
- request = soup_requester_request_uri (requester, uri, NULL);
+ if (requester)
+ request = soup_requester_request_uri (requester, uri, NULL);
+ else
+ request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_UNAUTHORIZED, auth_response,
TRUE, FALSE);
g_object_unref (request);
- debug_printf (1, " non-persistent test\n");
+ debug_printf (1, " non-persistent test\n");
soup_uri_set_path (uri, "/non-persistent");
- request = soup_requester_request_uri (requester, uri, NULL);
+ if (requester)
+ request = soup_requester_request_uri (requester, uri, NULL);
+ else
+ request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_OK, response,
FALSE, FALSE);
g_object_unref (request);
- debug_printf (1, " cancel test\n");
+ debug_printf (1, " cancel test\n");
soup_uri_set_path (uri, "/");
- request = soup_requester_request_uri (requester, uri, NULL);
+ if (requester)
+ request = soup_requester_request_uri (requester, uri, NULL);
+ else
+ request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_FORBIDDEN, NULL,
TRUE, TRUE);
g_object_unref (request);
+ soup_uri_free (uri);
+}
+
+static void
+do_plain_sync_test (gconstpointer uri)
+{
+ SoupSession *session;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ do_sync_tests_for_session (session, uri);
soup_test_session_abort_unref (session);
+}
+
+static void
+do_sync_sync_test (gconstpointer uri)
+{
+ SoupSession *session;
+ SoupRequester *requester;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+ requester = soup_requester_new ();
+ soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
+ g_object_unref (requester);
+ do_sync_tests_for_session (session, uri);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_null_char_request (SoupSession *session, const char *encoded_data,
+ const char *expected_data, int expected_len)
+{
+ GError *error = NULL;
+ GInputStream *stream;
+ SoupRequest *request;
+ SoupURI *uri;
+ char *uri_string, buf[256];
+ gsize nread;
+
+ uri_string = g_strdup_printf ("data:text/html,%s", encoded_data);
+ uri = soup_uri_new (uri_string);
+ g_free (uri_string);
+
+ request = soup_session_request_uri (session, uri, NULL);
+ stream = soup_test_request_send (request, NULL, 0, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_error_free (error);
+ g_object_unref (request);
+ soup_uri_free (uri);
+ return;
+ }
+
+ g_input_stream_read_all (stream, buf, sizeof (buf), &nread, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+
+ soup_test_request_close_stream (request, stream, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+
+ soup_assert_cmpmem (buf, nread, expected_data, expected_len);
+
+ g_object_unref (stream);
+ g_object_unref (request);
soup_uri_free (uri);
}
+static void
+do_null_char_test_for_session (SoupSession *session)
+{
+ static struct {
+ const char *encoded_data;
+ const char *expected_data;
+ int expected_len;
+ } test_cases[] = {
+ { "%3Cscript%3Ea%3D'%00'%3C%2Fscript%3E", "<script>a='\0'</script>", 22 },
+ { "%00%3Cscript%3Ea%3D42%3C%2Fscript%3E", "\0<script>a=42</script>", 22 },
+ { "%3Cscript%3E%00%3Cbr%2F%3E%3C%2Fscript%3E%00", "<script>\0<br/></script>\0", 24 },
+ };
+ static int num_test_cases = G_N_ELEMENTS(test_cases);
+ int i;
+
+ for (i = 0; i < num_test_cases; i++) {
+ do_null_char_request (session, test_cases[i].encoded_data,
+ test_cases[i].expected_data, test_cases[i].expected_len);
+ }
+}
+
+static void
+do_plain_null_char_test (void)
+{
+ SoupSession *session;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ do_null_char_test_for_session (session);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_async_null_char_test (void)
+{
+ SoupSession *session;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
+ do_null_char_test_for_session (session);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+close_test_msg_finished (SoupMessage *msg,
+ gpointer user_data)
+{
+ gboolean *finished = user_data;
+
+ *finished = TRUE;
+}
+
+static void
+do_close_test_for_session (SoupSession *session,
+ SoupURI *uri)
+{
+ GError *error = NULL;
+ GInputStream *stream;
+ SoupRequest *request;
+ guint64 start, end;
+ GCancellable *cancellable;
+ SoupMessage *msg;
+ gboolean finished = FALSE;
+
+ debug_printf (1, " normal close\n");
+
+ request = soup_session_request_uri (session, uri, NULL);
+ stream = soup_test_request_send (request, NULL, 0, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_error_free (error);
+ g_object_unref (request);
+ return;
+ }
+
+ start = g_get_monotonic_time ();
+ soup_test_request_close_stream (request, stream, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ end = g_get_monotonic_time ();
+
+ g_assert_cmpint (end - start, <=, 500000);
+
+ g_object_unref (stream);
+ g_object_unref (request);
+
+
+ debug_printf (1, " error close\n");
+
+ request = soup_session_request_uri (session, uri, NULL);
+ msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
+ g_signal_connect (msg, "finished", G_CALLBACK (close_test_msg_finished), &finished);
+ g_object_unref (msg);
+
+ stream = soup_test_request_send (request, NULL, 0, &error);
+ g_assert_no_error (error);
+ if (error) {
+ g_error_free (error);
+ g_object_unref (request);
+ return;
+ }
+
+ cancellable = g_cancellable_new ();
+ g_cancellable_cancel (cancellable);
+ soup_test_request_close_stream (request, stream, cancellable, &error);
+ if (error)
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_clear_error (&error);
+
+ g_assert_true (finished);
+
+ g_object_unref (stream);
+ g_object_unref (request);
+}
+
+static void
+do_async_close_test (gconstpointer uri)
+{
+ SoupSession *session;
+ SoupURI *slow_uri;
+
+ g_test_bug ("695652");
+ g_test_bug ("711260");
+
+ slow_uri = soup_uri_new (uri);
+ soup_uri_set_path (slow_uri, "/slow");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
+ do_close_test_for_session (session, slow_uri);
+ soup_test_session_abort_unref (session);
+
+ soup_uri_free (slow_uri);
+}
+
+static void
+do_sync_close_test (gconstpointer uri)
+{
+ SoupSession *session;
+ SoupURI *slow_uri;
+
+ g_test_bug ("695652");
+ g_test_bug ("711260");
+
+ slow_uri = soup_uri_new (uri);
+ soup_uri_set_path (slow_uri, "/slow");
+
+ debug_printf (1, " SoupSessionSync\n");
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
+ do_close_test_for_session (session, slow_uri);
+ soup_test_session_abort_unref (session);
+
+ soup_uri_free (slow_uri);
+}
+
int
main (int argc, char **argv)
{
char *uri;
+ int ret;
test_init (argc, argv, NULL);
- get_index ();
+
+ response = soup_test_get_index ();
+ auth_response = soup_buffer_new (SOUP_MEMORY_STATIC,
+ AUTH_HTML_BODY,
+ strlen (AUTH_HTML_BODY));
server = soup_test_server_new (TRUE);
soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
uri = g_strdup_printf ("http://127.0.0.1:%u/foo", soup_server_get_port (server));
- do_simple_test (uri);
- do_thread_test (uri);
- do_context_test (uri);
- do_sync_test (uri);
+ g_test_add_data_func ("/requester/simple/SoupSession", uri, do_simple_plain_test);
+ g_test_add_data_func ("/requester/simple/SoupSessionAsync", uri, do_simple_async_test);
+ g_test_add_data_func ("/requester/threaded/SoupSession", uri, do_plain_test_in_thread);
+ g_test_add_data_func ("/requester/threaded/SoupSessionAsync", uri, do_async_test_in_thread);
+ g_test_add_data_func ("/requester/context/SoupSession", uri, do_plain_test_with_context);
+ g_test_add_data_func ("/requester/context/SoupSessionAsync", uri, do_async_test_with_context);
+ g_test_add_data_func ("/requester/sync/SoupSession", uri, do_plain_sync_test);
+ g_test_add_data_func ("/requester/sync/SoupSessionSync", uri, do_sync_sync_test);
+ g_test_add_func ("/requester/null-char/SoupSession", do_plain_null_char_test);
+ g_test_add_func ("/requester/null-char/SoupSessionAsync", do_async_null_char_test);
+ g_test_add_data_func ("/requester/close/SoupSessionAsync", uri, do_async_close_test);
+ g_test_add_data_func ("/requester/close/SoupSessionSync", uri, do_sync_close_test);
+
+ ret = g_test_run ();
g_free (uri);
- soup_buffer_free (response);
soup_buffer_free (auth_response);
soup_test_server_quit_unref (server);
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/resource-test.c b/tests/resource-test.c
new file mode 100644
index 00000000..6fcb899e
--- /dev/null
+++ b/tests/resource-test.c
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ */
+
+#include "test-utils.h"
+
+SoupBuffer *index_buffer;
+
+typedef struct {
+ GString *body;
+ char buffer[1024];
+ GMainLoop *loop;
+} AsyncRequestData;
+
+static void
+stream_closed (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GInputStream *in = G_INPUT_STREAM (source);
+ AsyncRequestData *data = user_data;
+ GError *error = NULL;
+
+ g_input_stream_close_finish (in, result, &error);
+ g_assert_no_error (error);
+ g_main_loop_quit (data->loop);
+ g_object_unref (in);
+}
+
+static void
+test_read_ready (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GInputStream *in = G_INPUT_STREAM (source);
+ AsyncRequestData *data = user_data;
+ gssize nread;
+ GError *error = NULL;
+
+ nread = g_input_stream_read_finish (in, result, &error);
+ if (nread == -1) {
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ g_input_stream_close (in, NULL, NULL);
+ g_object_unref (in);
+ return;
+ } else if (nread == 0) {
+ g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL,
+ stream_closed, data);
+ return;
+ }
+
+ g_string_append_len (data->body, data->buffer, nread);
+ g_input_stream_read_async (in, data->buffer, sizeof (data->buffer),
+ G_PRIORITY_DEFAULT, NULL,
+ test_read_ready, data);
+}
+
+static void
+async_request_sent (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GInputStream *in;
+ AsyncRequestData *data = user_data;
+ GError *error = NULL;
+
+ in = soup_request_send_finish (SOUP_REQUEST (source), result, &error);
+ if (!in) {
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ return;
+ }
+
+ g_input_stream_read_async (in, data->buffer, sizeof (data->buffer),
+ G_PRIORITY_DEFAULT, NULL,
+ test_read_ready, data);
+}
+
+static void
+do_async_request (SoupRequest *request)
+{
+ AsyncRequestData data;
+
+ data.body = g_string_new (NULL);
+ soup_request_send_async (request, NULL, async_request_sent, &data);
+
+ data.loop = g_main_loop_new (soup_session_get_async_context (soup_request_get_session (request)), TRUE);
+ g_main_loop_run (data.loop);
+ g_main_loop_unref (data.loop);
+
+ soup_assert_cmpmem (data.body->str, data.body->len,
+ index_buffer->data, index_buffer->length);
+ g_string_free (data.body, TRUE);
+}
+
+static void
+do_sync_request (SoupRequest *request)
+{
+ GInputStream *in;
+ GString *body;
+ char buffer[1024];
+ gssize nread;
+ GError *error = NULL;
+
+ in = soup_request_send (request, NULL, &error);
+ if (!in) {
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ return;
+ }
+
+ body = g_string_new (NULL);
+ do {
+ nread = g_input_stream_read (in, buffer, sizeof (buffer),
+ NULL, &error);
+ if (nread == -1) {
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ break;
+ }
+ g_string_append_len (body, buffer, nread);
+ } while (nread > 0);
+
+ g_input_stream_close (in, NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ g_object_unref (in);
+
+ soup_assert_cmpmem (body->str, body->len, index_buffer->data, index_buffer->length);
+ g_string_free (body, TRUE);
+}
+
+static void
+do_request (const char *uri_string, gconstpointer type)
+{
+ SoupSession *session;
+ SoupRequest *request;
+ GError *error = NULL;
+
+ session = soup_test_session_new (GPOINTER_TO_SIZE (type),
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
+
+ request = soup_session_request (session, uri_string, &error);
+ g_assert_no_error (error);
+
+ if (SOUP_IS_SESSION_ASYNC (session))
+ do_async_request (request);
+ else
+ do_sync_request (request);
+
+ g_object_unref (request);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_request_file_test (gconstpointer type)
+{
+ GFile *index;
+ char *uri_string;
+
+ index = g_file_new_for_path (g_test_get_filename (G_TEST_DIST, "index.txt", NULL));
+ uri_string = g_file_get_uri (index);
+ g_object_unref (index);
+
+ do_request (uri_string, type);
+ g_free (uri_string);
+}
+
+static void
+do_request_data_test (gconstpointer type)
+{
+ gchar *base64;
+ char *uri_string;
+
+ base64 = g_base64_encode ((const guchar *)index_buffer->data, index_buffer->length);
+ uri_string = g_strdup_printf ("data:text/plain;charset=utf8;base64,%s", base64);
+ g_free (base64);
+
+ do_request (uri_string, type);
+ g_free (uri_string);
+}
+
+static void
+do_request_gresource_test (gconstpointer type)
+{
+ do_request ("resource:///org/gnome/libsoup/tests/index.txt", type);
+}
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+
+ test_init (argc, argv, NULL);
+
+ index_buffer = soup_test_get_index ();
+ soup_test_register_resources ();
+
+ g_test_add_data_func ("/resource/sync/file",
+ GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC),
+ do_request_file_test);
+ g_test_add_data_func ("/resource/sync/data",
+ GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC),
+ do_request_data_test);
+ g_test_add_data_func ("/resource/sync/gresource",
+ GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC),
+ do_request_gresource_test);
+
+ g_test_add_data_func ("/resource/async/file",
+ GSIZE_TO_POINTER (SOUP_TYPE_SESSION_ASYNC),
+ do_request_file_test);
+ g_test_add_data_func ("/resource/async/data",
+ GSIZE_TO_POINTER (SOUP_TYPE_SESSION_ASYNC),
+ do_request_data_test);
+ g_test_add_data_func ("/resource/async/gresource",
+ GSIZE_TO_POINTER (SOUP_TYPE_SESSION_ASYNC),
+ do_request_gresource_test);
+
+ ret = g_test_run ();
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/resources/feed.rdf b/tests/resources/feed.rdf
new file mode 100644
index 00000000..f3d9e276
--- /dev/null
+++ b/tests/resources/feed.rdf
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+
+<!-- RDF Site Summary (RSS) 1.0
+ http://groups.yahoo.com/group/rss-dev/files/specification.html
+ Section 5.3
+ -->
+
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/">
+
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>XML.com</title>
+ <link>http://xml.com/pub</link>
+ <description>
+ XML.com features a rich mix of information and services
+ for the XML community.
+ </description>
+
+ <image rdf:resource="http://xml.com/universal/images/xml_tiny.gif" />
+
+ <items>
+ <rdf:Seq>
+ <rdf:li resource="http://xml.com/pub/2000/08/09/xslt/xslt.html" />
+ <rdf:li resource="http://xml.com/pub/2000/08/09/rdfdb/index.html" />
+ </rdf:Seq>
+ </items>
+
+ <textinput rdf:resource="http://search.xml.com" />
+ </channel>
+
+</rdf:RDF>
diff --git a/tests/resources/home.jpg b/tests/resources/home.jpg
new file mode 100644
index 00000000..ac1f3bbc
--- /dev/null
+++ b/tests/resources/home.jpg
Binary files differ
diff --git a/tests/resources/home.png b/tests/resources/home.png
new file mode 100644
index 00000000..0bb82bac
--- /dev/null
+++ b/tests/resources/home.png
Binary files differ
diff --git a/tests/resources/html_binary.html b/tests/resources/html_binary.html
index 9200dd42..d443048c 100644
--- a/tests/resources/html_binary.html
+++ b/tests/resources/html_binary.html
@@ -1 +1 @@
-<HTML 
+<HTML
diff --git a/tests/resources/leading_space.html b/tests/resources/leading_space.html
new file mode 100644
index 00000000..a640d653
--- /dev/null
+++ b/tests/resources/leading_space.html
@@ -0,0 +1,12 @@
+
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title></title>
+</head>
+<body>
+<h1>GNOME!</h1>
+</body>
+</html>
diff --git a/tests/resources/test.aiff b/tests/resources/test.aiff
new file mode 100644
index 00000000..9a1ecbb2
--- /dev/null
+++ b/tests/resources/test.aiff
Binary files differ
diff --git a/tests/resources/test.mp4 b/tests/resources/test.mp4
new file mode 100644
index 00000000..d278c8ad
--- /dev/null
+++ b/tests/resources/test.mp4
Binary files differ
diff --git a/tests/resources/test.ogg b/tests/resources/test.ogg
new file mode 100644
index 00000000..e8f49ac3
--- /dev/null
+++ b/tests/resources/test.ogg
Binary files differ
diff --git a/tests/resources/test.wav b/tests/resources/test.wav
new file mode 100644
index 00000000..11660b29
--- /dev/null
+++ b/tests/resources/test.wav
Binary files differ
diff --git a/tests/resources/test.webm b/tests/resources/test.webm
new file mode 100644
index 00000000..7e53d0b4
--- /dev/null
+++ b/tests/resources/test.webm
Binary files differ
diff --git a/tests/resources/text.txt b/tests/resources/text.txt
new file mode 100644
index 00000000..ff7066f6
--- /dev/null
+++ b/tests/resources/text.txt
@@ -0,0 +1 @@
+This is just text.
diff --git a/tests/resources/tux.webp b/tests/resources/tux.webp
new file mode 100644
index 00000000..8764f066
--- /dev/null
+++ b/tests/resources/tux.webp
Binary files differ
diff --git a/tests/server-auth-test.c b/tests/server-auth-test.c
index 757e065a..f386f526 100644
--- a/tests/server-auth-test.c
+++ b/tests/server-auth-test.c
@@ -5,6 +5,8 @@
#include "test-utils.h"
+static SoupURI *base_uri;
+
static struct {
gboolean client_sent_basic, client_sent_digest;
gboolean server_requested_basic, server_requested_digest;
@@ -21,7 +23,7 @@ curl_exited (GPid pid, int status, gpointer data)
}
static void
-do_test (int n, SoupURI *base_uri, const char *path,
+do_test (SoupURI *base_uri, const char *path,
gboolean good_user, gboolean good_password,
gboolean offer_basic, gboolean offer_digest,
gboolean client_sends_basic, gboolean client_sends_digest,
@@ -34,18 +36,14 @@ do_test (int n, SoupURI *base_uri, const char *path,
GPid pid;
gboolean done;
- debug_printf (1, "%2d. %s, %soffer Basic, %soffer Digest, %s user, %s password\n",
- n, path, offer_basic ? "" : "don't ",
- offer_digest ? "" : "don't ",
- good_user ? "good" : "bad",
- good_password ? "good" : "bad");
-
uri = soup_uri_new_with_base (base_uri, path);
uri_str = soup_uri_to_string (uri, FALSE);
soup_uri_free (uri);
args = g_ptr_array_new ();
g_ptr_array_add (args, "curl");
+ g_ptr_array_add (args, "--noproxy");
+ g_ptr_array_add (args, "*");
g_ptr_array_add (args, "-f");
g_ptr_array_add (args, "-s");
if (offer_basic || offer_digest) {
@@ -86,135 +84,103 @@ do_test (int n, SoupURI *base_uri, const char *path,
g_ptr_array_free (args, TRUE);
g_free (uri_str);
- if (server_requests_basic != test_data.server_requested_basic) {
- errors++;
- if (test_data.server_requested_basic)
- debug_printf (1, " Server sent WWW-Authenticate: Basic, but shouldn't have!\n");
- else
- debug_printf (1, " Server didn't send WWW-Authenticate: Basic, but should have!\n");
- }
- if (server_requests_digest != test_data.server_requested_digest) {
- errors++;
- if (test_data.server_requested_digest)
- debug_printf (1, " Server sent WWW-Authenticate: Digest, but shouldn't have!\n");
- else
- debug_printf (1, " Server didn't send WWW-Authenticate: Digest, but should have!\n");
- }
- if (client_sends_basic != test_data.client_sent_basic) {
- errors++;
- if (test_data.client_sent_basic)
- debug_printf (1, " Client sent Authorization: Basic, but shouldn't have!\n");
- else
- debug_printf (1, " Client didn't send Authorization: Basic, but should have!\n");
- }
- if (client_sends_digest != test_data.client_sent_digest) {
- errors++;
- if (test_data.client_sent_digest)
- debug_printf (1, " Client sent Authorization: Digest, but shouldn't have!\n");
- else
- debug_printf (1, " Client didn't send Authorization: Digest, but should have!\n");
- }
- if (success && !test_data.succeeded) {
- errors++;
- debug_printf (1, " Should have succeeded, but didn't!\n");
- } else if (!success && test_data.succeeded) {
- errors++;
- debug_printf (1, " Should not have succeeded, but did!\n");
- }
+ g_assert_cmpint (server_requests_basic, ==, test_data.server_requested_basic);
+ g_assert_cmpint (server_requests_digest, ==, test_data.server_requested_digest);
+ g_assert_cmpint (client_sends_basic, ==, test_data.client_sent_basic);
+ g_assert_cmpint (client_sends_digest, ==, test_data.client_sent_digest);
+
+ g_assert_cmpint (success, ==, test_data.succeeded);
}
+#define TEST_USES_BASIC(t) (((t) & 1) == 1)
+#define TEST_USES_DIGEST(t) (((t) & 2) == 2)
+#define TEST_GOOD_USER(t) (((t) & 4) == 4)
+#define TEST_GOOD_PASSWORD(t) (((t) & 8) == 8)
+
+#define TEST_GOOD_AUTH(t) (TEST_GOOD_USER (t) && TEST_GOOD_PASSWORD (t))
+#define TEST_PREEMPTIVE_BASIC(t) (TEST_USES_BASIC (t) && !TEST_USES_DIGEST (t))
+
static void
-do_auth_tests (SoupURI *base_uri)
+do_server_auth_test (gconstpointer data)
{
- int i, n = 1;
- gboolean use_basic, use_digest, good_user, good_password;
- gboolean preemptive_basic, good_auth;
-
- for (i = 0; i < 16; i++) {
- use_basic = (i & 1) == 1;
- use_digest = (i & 2) == 2;
- good_user = (i & 4) == 4;
- good_password = (i & 8) == 8;
-
- good_auth = good_user && good_password;
-
- /* Curl will preemptively send Basic if it's told to
- * use Basic but not Digest.
- */
- preemptive_basic = use_basic && !use_digest;
-
- /* 1. No auth required. The server will ignore the
- * Authorization headers completely, and the request
- * will always succeed.
- */
- do_test (n++, base_uri, "/foo",
- good_user, good_password,
- /* request */
- use_basic, use_digest,
- /* expected from client */
- preemptive_basic, FALSE,
- /* expected from server */
- FALSE, FALSE,
- /* success? */
- TRUE);
-
- /* 2. Basic auth required. The server will send
- * "WWW-Authenticate: Basic" if the client fails to
- * send an Authorization: Basic on the first request,
- * or if it sends a bad password.
- */
- do_test (n++, base_uri, "/Basic/foo",
- good_user, good_password,
- /* request */
- use_basic, use_digest,
- /* expected from client */
- use_basic, FALSE,
- /* expected from server */
- !preemptive_basic || !good_auth, FALSE,
- /* success? */
- use_basic && good_auth);
-
- /* 3. Digest auth required. Simpler than the basic
- * case because the client can't send Digest auth
- * premptively.
- */
- do_test (n++, base_uri, "/Digest/foo",
- good_user, good_password,
- /* request */
- use_basic, use_digest,
- /* expected from client */
- preemptive_basic, use_digest,
- /* expected from server */
- FALSE, TRUE,
- /* success? */
- use_digest && good_auth);
-
- /* 4. Any auth required. */
- do_test (n++, base_uri, "/Any/foo",
- good_user, good_password,
- /* request */
- use_basic, use_digest,
- /* expected from client */
- preemptive_basic, use_digest,
- /* expected from server */
- !preemptive_basic || !good_auth, !preemptive_basic || !good_auth,
- /* success? */
- (use_basic || use_digest) && good_auth);
-
- /* 5. No auth required again. (Makes sure that
- * SOUP_AUTH_DOMAIN_REMOVE_PATH works.)
- */
- do_test (n++, base_uri, "/Any/Not/foo",
- good_user, good_password,
- /* request */
- use_basic, use_digest,
- /* expected from client */
- preemptive_basic, FALSE,
- /* expected from server */
- FALSE, FALSE,
- /* success? */
- TRUE);
- }
+ int i = GPOINTER_TO_INT (data);
+
+#ifndef HAVE_CURL
+ g_test_skip ("/usr/bin/curl is not available");
+ return;
+#endif
+
+ /* 1. No auth required. The server will ignore the
+ * Authorization headers completely, and the request
+ * will always succeed.
+ */
+ do_test (base_uri, "/foo",
+ TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i),
+ /* request */
+ TEST_USES_BASIC (i), TEST_USES_DIGEST (i),
+ /* expected from client */
+ TEST_PREEMPTIVE_BASIC (i), FALSE,
+ /* expected from server */
+ FALSE, FALSE,
+ /* success? */
+ TRUE);
+
+ /* 2. Basic auth required. The server will send
+ * "WWW-Authenticate: Basic" if the client fails to
+ * send an Authorization: Basic on the first request,
+ * or if it sends a bad password.
+ */
+ do_test (base_uri, "/Basic/foo",
+ TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i),
+ /* request */
+ TEST_USES_BASIC (i), TEST_USES_DIGEST (i),
+ /* expected from client */
+ TEST_USES_BASIC (i), FALSE,
+ /* expected from server */
+ !TEST_PREEMPTIVE_BASIC (i) || !TEST_GOOD_AUTH (i), FALSE,
+ /* success? */
+ TEST_USES_BASIC (i) && TEST_GOOD_AUTH (i));
+
+ /* 3. Digest auth required. Simpler than the basic
+ * case because the client can't send Digest auth
+ * premptively.
+ */
+ do_test (base_uri, "/Digest/foo",
+ TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i),
+ /* request */
+ TEST_USES_BASIC (i), TEST_USES_DIGEST (i),
+ /* expected from client */
+ TEST_PREEMPTIVE_BASIC (i), TEST_USES_DIGEST (i),
+ /* expected from server */
+ FALSE, TRUE,
+ /* success? */
+ TEST_USES_DIGEST (i) && TEST_GOOD_AUTH (i));
+
+ /* 4. Any auth required. */
+ do_test (base_uri, "/Any/foo",
+ TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i),
+ /* request */
+ TEST_USES_BASIC (i), TEST_USES_DIGEST (i),
+ /* expected from client */
+ TEST_PREEMPTIVE_BASIC (i), TEST_USES_DIGEST (i),
+ /* expected from server */
+ !TEST_PREEMPTIVE_BASIC (i) || !TEST_GOOD_AUTH (i), !TEST_PREEMPTIVE_BASIC (i) || !TEST_GOOD_AUTH (i),
+ /* success? */
+ (TEST_USES_BASIC (i) || TEST_USES_DIGEST (i)) && TEST_GOOD_AUTH (i));
+
+ /* 5. No auth required again. (Makes sure that
+ * SOUP_AUTH_DOMAIN_REMOVE_PATH works.)
+ */
+ do_test (base_uri, "/Any/Not/foo",
+ TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i),
+ /* request */
+ TEST_USES_BASIC (i), TEST_USES_DIGEST (i),
+ /* expected from client */
+ TEST_PREEMPTIVE_BASIC (i), FALSE,
+ /* expected from server */
+ FALSE, FALSE,
+ /* success? */
+ TRUE);
}
static gboolean
@@ -311,8 +277,8 @@ main (int argc, char **argv)
{
GMainLoop *loop;
SoupServer *server;
- SoupURI *uri;
SoupAuthDomain *auth_domain;
+ int ret;
test_init (argc, argv, no_test_entry);
@@ -345,13 +311,45 @@ main (int argc, char **argv)
loop = g_main_loop_new (NULL, TRUE);
if (run_tests) {
- uri = soup_uri_new ("http://127.0.0.1");
- soup_uri_set_port (uri, soup_server_get_port (server));
- do_auth_tests (uri);
- soup_uri_free (uri);
+ int i;
+
+ base_uri = soup_uri_new ("http://127.0.0.1");
+ soup_uri_set_port (base_uri, soup_server_get_port (server));
+
+ for (i = 0; i < 16; i++) {
+ char *path;
+ const char *authtypes;
+
+ if (!TEST_GOOD_USER (i) && !TEST_GOOD_PASSWORD (i))
+ continue;
+ if (TEST_USES_BASIC (i)) {
+ if (TEST_USES_DIGEST (i))
+ authtypes = "basic+digest";
+ else
+ authtypes = "basic";
+ } else {
+ if (TEST_USES_DIGEST (i))
+ authtypes = "digest";
+ else
+ authtypes = "none";
+ }
+
+ path = g_strdup_printf ("/server-auth/%s/%s-user%c%s-password",
+ authtypes,
+ TEST_GOOD_USER (i) ? "good" : "bad",
+ TEST_GOOD_USER (i) ? '/' : '\0',
+ TEST_GOOD_PASSWORD (i) ? "good" : "bad");
+ g_test_add_data_func (path, GINT_TO_POINTER (i), do_server_auth_test);
+ g_free (path);
+ }
+
+ ret = g_test_run ();
+
+ soup_uri_free (base_uri);
} else {
g_print ("Listening on port %d\n", soup_server_get_port (server));
g_main_loop_run (loop);
+ ret = 0;
}
g_main_loop_unref (loop);
@@ -359,5 +357,5 @@ main (int argc, char **argv)
if (run_tests)
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/server-test.c b/tests/server-test.c
new file mode 100644
index 00000000..0c980908
--- /dev/null
+++ b/tests/server-test.c
@@ -0,0 +1,329 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright 2007-2012 Red Hat, Inc.
+ */
+
+#include "test-utils.h"
+
+SoupServer *server, *ssl_server;
+SoupURI *base_uri, *ssl_base_uri;
+
+static void
+server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ soup_message_headers_append (msg->response_headers,
+ "X-Handled-By", "server_callback");
+
+ if (!strcmp (path, "*")) {
+ soup_test_assert (FALSE, "default server_callback got request for '*'");
+ soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) {
+ soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ soup_message_set_response (msg, "text/plain",
+ SOUP_MEMORY_STATIC, "index", 5);
+}
+
+static void
+server_star_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ soup_message_headers_append (msg->response_headers,
+ "X-Handled-By", "star_callback");
+
+ if (strcmp (path, "*") != 0) {
+ soup_test_assert (FALSE, "server_star_callback got request for '%s'", path);
+ soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ if (msg->method != SOUP_METHOD_OPTIONS) {
+ soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED);
+ return;
+ }
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+}
+
+/* Server handlers for "*" work but are separate from handlers for
+ * all other URIs. #590751
+ */
+static void
+do_star_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ SoupURI *star_uri;
+ const char *handled_by;
+
+ g_test_bug ("590751");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+ star_uri = soup_uri_copy (base_uri);
+ soup_uri_set_path (star_uri, "*");
+
+ debug_printf (1, " Testing with no handler\n");
+ msg = soup_message_new_from_uri ("OPTIONS", star_uri);
+ soup_session_send_message (session, msg);
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_NOT_FOUND);
+ handled_by = soup_message_headers_get_one (msg->response_headers,
+ "X-Handled-By");
+ g_assert_cmpstr (handled_by, ==, NULL);
+ g_object_unref (msg);
+
+ soup_server_add_handler (server, "*", server_star_callback, NULL, NULL);
+
+ debug_printf (1, " Testing with handler\n");
+ msg = soup_message_new_from_uri ("OPTIONS", star_uri);
+ soup_session_send_message (session, msg);
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ handled_by = soup_message_headers_get_one (msg->response_headers,
+ "X-Handled-By");
+ g_assert_cmpstr (handled_by, ==, "star_callback");
+ g_object_unref (msg);
+
+ soup_test_session_abort_unref (session);
+ soup_uri_free (star_uri);
+}
+
+static void
+do_one_server_aliases_test (SoupURI *uri,
+ const char *alias,
+ gboolean succeed)
+{
+ GSocketClient *client;
+ GSocketConnectable *addr;
+ GSocketConnection *conn;
+ GInputStream *in;
+ GOutputStream *out;
+ GError *error = NULL;
+ GString *req;
+ static char buf[1024];
+
+ debug_printf (1, " %s via %s\n", alias, uri->scheme);
+
+ /* There's no way to make libsoup's client side send an absolute
+ * URI (to a non-proxy server), so we have to fake this.
+ */
+
+ client = g_socket_client_new ();
+ if (uri->scheme == SOUP_URI_SCHEME_HTTPS) {
+ g_socket_client_set_tls (client, TRUE);
+ g_socket_client_set_tls_validation_flags (client, 0);
+ }
+ addr = g_network_address_new (uri->host, uri->port);
+
+ conn = g_socket_client_connect (client, addr, NULL, &error);
+ g_object_unref (addr);
+ g_object_unref (client);
+ if (!conn) {
+ g_assert_no_error (error);
+ g_error_free (error);
+ return;
+ }
+
+ in = g_io_stream_get_input_stream (G_IO_STREAM (conn));
+ out = g_io_stream_get_output_stream (G_IO_STREAM (conn));
+
+ req = g_string_new (NULL);
+ g_string_append_printf (req, "GET %s://%s:%d HTTP/1.1\r\n",
+ alias, uri->host, uri->port);
+ g_string_append_printf (req, "Host: %s:%d\r\n",
+ uri->host, uri->port);
+ g_string_append (req, "Connection: close\r\n\r\n");
+
+ if (!g_output_stream_write_all (out, req->str, req->len, NULL, NULL, &error)) {
+ g_assert_no_error (error);
+ g_error_free (error);
+ g_object_unref (conn);
+ g_string_free (req, TRUE);
+ return;
+ }
+ g_string_free (req, TRUE);
+
+ if (!g_input_stream_read_all (in, buf, sizeof (buf), NULL, NULL, &error)) {
+ g_assert_no_error (error);
+ g_error_free (error);
+ g_object_unref (conn);
+ return;
+ }
+
+ if (succeed)
+ g_assert_true (g_str_has_prefix (buf, "HTTP/1.1 200 "));
+ else
+ g_assert_true (g_str_has_prefix (buf, "HTTP/1.1 400 "));
+
+ g_io_stream_close (G_IO_STREAM (conn), NULL, NULL);
+ g_object_unref (conn);
+}
+
+static void
+do_server_aliases_test (void)
+{
+ char *http_good[] = { "http", "dav", NULL };
+ char *http_bad[] = { "https", "davs", "fred", NULL };
+ char *https_good[] = { "https", "davs", NULL };
+ char *https_bad[] = { "http", "dav", "fred", NULL };
+ int i;
+
+ g_test_bug ("703694");
+
+ for (i = 0; http_good[i]; i++)
+ do_one_server_aliases_test (base_uri, http_good[i], TRUE);
+ for (i = 0; http_bad[i]; i++)
+ do_one_server_aliases_test (base_uri, http_bad[i], FALSE);
+
+ if (tls_available) {
+ for (i = 0; https_good[i]; i++)
+ do_one_server_aliases_test (ssl_base_uri, https_good[i], TRUE);
+ for (i = 0; https_bad[i]; i++)
+ do_one_server_aliases_test (ssl_base_uri, https_bad[i], FALSE);
+ }
+}
+
+static void
+do_dot_dot_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ SoupURI *uri;
+
+ g_test_bug ("667635");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+
+ uri = soup_uri_new_with_base (base_uri, "/..%2ftest");
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_uri_free (uri);
+
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_BAD_REQUEST);
+ g_object_unref (msg);
+
+ soup_test_session_abort_unref (session);
+}
+
+static void
+ipv6_server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ const char *host;
+ char expected_host[128];
+
+ g_snprintf (expected_host, sizeof (expected_host),
+ "[::1]:%d", soup_server_get_port (server));
+
+ host = soup_message_headers_get_one (msg->request_headers, "Host");
+ g_assert_cmpstr (host, ==, expected_host);
+
+ if (g_test_failed ())
+ soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
+ else
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+}
+
+static void
+do_ipv6_test (void)
+{
+ SoupServer *ipv6_server;
+ SoupURI *ipv6_uri;
+ SoupAddress *ipv6_addr;
+ SoupSession *session;
+ SoupMessage *msg;
+
+ g_test_bug ("666399");
+
+ ipv6_addr = soup_address_new ("::1", SOUP_ADDRESS_ANY_PORT);
+ soup_address_resolve_sync (ipv6_addr, NULL);
+ ipv6_server = soup_server_new (SOUP_SERVER_INTERFACE, ipv6_addr,
+ NULL);
+ g_object_unref (ipv6_addr);
+ if (!ipv6_server) {
+ debug_printf (1, " skipping due to lack of IPv6 support\n");
+ return;
+ }
+
+ soup_server_add_handler (ipv6_server, NULL, ipv6_server_callback, NULL, NULL);
+ soup_server_run_async (ipv6_server);
+
+ ipv6_uri = soup_uri_new ("http://[::1]/");
+ soup_uri_set_port (ipv6_uri, soup_server_get_port (ipv6_server));
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+
+ debug_printf (1, " HTTP/1.1\n");
+ msg = soup_message_new_from_uri ("GET", ipv6_uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_object_unref (msg);
+
+ debug_printf (1, " HTTP/1.0\n");
+ msg = soup_message_new_from_uri ("GET", ipv6_uri);
+ soup_message_set_http_version (msg, SOUP_HTTP_1_0);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_object_unref (msg);
+
+ soup_uri_free (ipv6_uri);
+ soup_test_session_abort_unref (session);
+ soup_test_server_quit_unref (ipv6_server);
+}
+
+int
+main (int argc, char **argv)
+{
+ char *http_aliases[] = { "dav", NULL };
+ char *https_aliases[] = { "davs", NULL };
+ int ret;
+
+ test_init (argc, argv, NULL);
+
+ server = soup_test_server_new (TRUE);
+ soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+ base_uri = soup_uri_new ("http://127.0.0.1/");
+ soup_uri_set_port (base_uri, soup_server_get_port (server));
+
+ g_object_set (G_OBJECT (server),
+ SOUP_SERVER_HTTP_ALIASES, http_aliases,
+ NULL);
+
+ if (tls_available) {
+ ssl_server = soup_test_server_new_ssl (TRUE);
+ soup_server_add_handler (ssl_server, NULL, server_callback, NULL, NULL);
+ ssl_base_uri = soup_uri_new ("https://127.0.0.1/");
+ soup_uri_set_port (ssl_base_uri, soup_server_get_port (ssl_server));
+ g_object_set (G_OBJECT (ssl_server),
+ SOUP_SERVER_HTTPS_ALIASES, https_aliases,
+ NULL);
+ }
+
+ g_test_add_func ("/server/OPTIONS *", do_star_test);
+ g_test_add_func ("/server/aliases", do_server_aliases_test);
+ g_test_add_func ("/server/..-in-path", do_dot_dot_test);
+ g_test_add_func ("/server/ipv6", do_ipv6_test);
+
+ ret = g_test_run ();
+
+ soup_uri_free (base_uri);
+ soup_test_server_quit_unref (server);
+
+ if (tls_available) {
+ soup_uri_free (ssl_base_uri);
+ soup_test_server_quit_unref (ssl_server);
+ }
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/session-test.c b/tests/session-test.c
new file mode 100644
index 00000000..15072058
--- /dev/null
+++ b/tests/session-test.c
@@ -0,0 +1,396 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include "test-utils.h"
+
+static gboolean server_processed_message;
+static gboolean timeout;
+static GMainLoop *loop;
+static SoupMessagePriority expected_priorities[3];
+
+static gboolean
+timeout_cb (gpointer user_data)
+{
+ gboolean *timeout = user_data;
+
+ *timeout = TRUE;
+ return FALSE;
+}
+
+static void
+server_handler (SoupServer *server,
+ SoupMessage *msg,
+ const char *path,
+ GHashTable *query,
+ SoupClientContext *client,
+ gpointer user_data)
+{
+ if (!strcmp (path, "/request-timeout")) {
+ GMainContext *context = soup_server_get_async_context (server);
+ GSource *timer;
+
+ timer = g_timeout_source_new (100);
+ g_source_set_callback (timer, timeout_cb, &timeout, NULL);
+ g_source_attach (timer, context);
+ g_source_unref (timer);
+ } else
+ server_processed_message = TRUE;
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ soup_message_set_response (msg, "text/plain",
+ SOUP_MEMORY_STATIC,
+ "ok\r\n", 4);
+}
+
+static void
+finished_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+ gboolean *finished = user_data;
+
+ *finished = TRUE;
+}
+
+static void
+cancel_message_cb (SoupMessage *msg, gpointer session)
+{
+ soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
+ g_main_loop_quit (loop);
+}
+
+static void
+do_test_for_session (SoupSession *session,
+ const char *uri,
+ gboolean queue_is_async,
+ gboolean send_is_blocking,
+ gboolean cancel_is_immediate)
+{
+ SoupMessage *msg;
+ gboolean finished, local_timeout;
+ guint timeout_id;
+ char *timeout_uri;
+
+ debug_printf (1, " queue_message\n");
+ debug_printf (2, " requesting timeout\n");
+ timeout_uri = g_strdup_printf ("%s/request-timeout", uri);
+ msg = soup_message_new ("GET", timeout_uri);
+ g_free (timeout_uri);
+ soup_session_send_message (session, msg);
+ g_object_unref (msg);
+
+ msg = soup_message_new ("GET", uri);
+ server_processed_message = timeout = finished = FALSE;
+ soup_session_queue_message (session, msg, finished_cb, &finished);
+ while (!timeout)
+ g_usleep (100);
+ debug_printf (2, " got timeout\n");
+
+ if (queue_is_async) {
+ g_assert_false (server_processed_message);
+ debug_printf (2, " waiting for finished\n");
+ while (!finished)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert_true (server_processed_message);
+ } else {
+ g_assert_true (server_processed_message);
+ g_assert_false (finished);
+ debug_printf (2, " waiting for finished\n");
+ while (!finished)
+ g_main_context_iteration (NULL, TRUE);
+ }
+
+ debug_printf (1, " send_message\n");
+ msg = soup_message_new ("GET", uri);
+ server_processed_message = local_timeout = FALSE;
+ timeout_id = g_idle_add_full (G_PRIORITY_HIGH, timeout_cb, &local_timeout, NULL);
+ soup_session_send_message (session, msg);
+
+ g_assert_true (server_processed_message);
+
+ if (send_is_blocking) {
+ soup_test_assert (!local_timeout,
+ "send_message ran main loop");
+ } else {
+ soup_test_assert (local_timeout,
+ "send_message didn't run main loop");
+ }
+
+ if (!local_timeout)
+ g_source_remove (timeout_id);
+
+ if (!queue_is_async)
+ return;
+
+ debug_printf (1, " cancel_message\n");
+ msg = soup_message_new ("GET", uri);
+ g_object_ref (msg);
+ finished = FALSE;
+ soup_session_queue_message (session, msg, finished_cb, &finished);
+ g_signal_connect (msg, "wrote-headers",
+ G_CALLBACK (cancel_message_cb), session);
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+
+ if (cancel_is_immediate)
+ g_assert_true (finished);
+ else
+ g_assert_false (finished);
+
+ if (!finished) {
+ debug_printf (2, " waiting for finished\n");
+ while (!finished)
+ g_main_context_iteration (NULL, TRUE);
+ }
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
+ g_object_unref (msg);
+}
+
+static void
+do_plain_tests (gconstpointer uri)
+{
+ SoupSession *session;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ do_test_for_session (session, uri, TRUE, TRUE, FALSE);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_async_tests (gconstpointer uri)
+{
+ SoupSession *session;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ do_test_for_session (session, uri, TRUE, FALSE, TRUE);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_sync_tests (gconstpointer uri)
+{
+ SoupSession *session;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+ do_test_for_session (session, uri, FALSE, TRUE, FALSE);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+priority_test_finished_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+ guint *finished_count = user_data;
+ SoupMessagePriority priority = soup_message_get_priority (msg);
+
+ debug_printf (1, " received message %d with priority %d\n",
+ *finished_count, priority);
+
+ soup_test_assert (priority == expected_priorities[*finished_count],
+ "message %d should have priority %d (%d found)",
+ *finished_count, expected_priorities[*finished_count], priority);
+
+ (*finished_count)++;
+}
+
+static void
+do_priority_tests (gconstpointer data)
+{
+ const char *uri = data;
+ SoupSession *session;
+ int i, finished_count = 0;
+ SoupMessagePriority priorities[] =
+ { SOUP_MESSAGE_PRIORITY_LOW,
+ SOUP_MESSAGE_PRIORITY_HIGH,
+ SOUP_MESSAGE_PRIORITY_NORMAL };
+
+ g_test_bug ("696277");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ g_object_set (session, "max-conns", 1, NULL);
+
+ expected_priorities[0] = SOUP_MESSAGE_PRIORITY_HIGH;
+ expected_priorities[1] = SOUP_MESSAGE_PRIORITY_NORMAL;
+ expected_priorities[2] = SOUP_MESSAGE_PRIORITY_LOW;
+
+ for (i = 0; i < 3; i++) {
+ char *msg_uri;
+ SoupMessage *msg;
+
+ msg_uri = g_strdup_printf ("%s/%d", uri, i);
+ msg = soup_message_new ("GET", uri);
+ g_free (msg_uri);
+
+ soup_message_set_priority (msg, priorities[i]);
+ soup_session_queue_message (session, msg, priority_test_finished_cb, &finished_count);
+ }
+
+ debug_printf (2, " waiting for finished\n");
+ while (finished_count != 3)
+ g_main_context_iteration (NULL, TRUE);
+
+ soup_test_session_abort_unref (session);
+}
+
+static void
+test_session_properties (const char *name,
+ SoupSession *session,
+ GProxyResolver *expected_proxy_resolver,
+ GTlsDatabase *expected_tls_database)
+{
+ GProxyResolver *proxy_resolver = NULL;
+ GTlsDatabase *tlsdb = NULL;
+
+ g_object_get (G_OBJECT (session),
+ SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver,
+ SOUP_SESSION_TLS_DATABASE, &tlsdb,
+ NULL);
+
+ soup_test_assert (proxy_resolver == expected_proxy_resolver,
+ "%s has %s proxy resolver",
+ name, proxy_resolver ? (expected_proxy_resolver ? "wrong" : "a") : "no");
+ soup_test_assert (tlsdb == expected_tls_database,
+ "%s has %s TLS database",
+ name, tlsdb ? (expected_tls_database ? "wrong" : "a") : "no");
+
+ g_clear_object (&proxy_resolver);
+ g_clear_object (&tlsdb);
+}
+
+static void
+do_property_tests (void)
+{
+ SoupSession *session;
+ GProxyResolver *proxy_resolver, *default_proxy_resolver;
+ GTlsDatabase *tlsdb, *default_tlsdb;
+ SoupURI *uri;
+
+ g_test_bug ("708696");
+
+ default_proxy_resolver = g_proxy_resolver_get_default ();
+ default_tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
+
+ /* NOTE: We intentionally do not use soup_test_session_new() here */
+
+ session = g_object_new (SOUP_TYPE_SESSION,
+ NULL);
+ test_session_properties ("Base plain session", session,
+ default_proxy_resolver, default_tlsdb);
+ g_object_unref (session);
+
+ session = g_object_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_PROXY_RESOLVER, NULL,
+ NULL);
+ test_session_properties ("Session with NULL :proxy-resolver", session,
+ NULL, default_tlsdb);
+ g_object_unref (session);
+
+ proxy_resolver = g_simple_proxy_resolver_new (NULL, NULL);
+ session = g_object_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_PROXY_RESOLVER, proxy_resolver,
+ NULL);
+ test_session_properties ("Session with non-NULL :proxy-resolver", session,
+ proxy_resolver, default_tlsdb);
+ g_object_unref (proxy_resolver);
+ g_object_unref (session);
+
+ session = g_object_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_PROXY_URI, NULL,
+ NULL);
+ test_session_properties ("Session with NULL :proxy-uri", session,
+ NULL, default_tlsdb);
+ g_object_unref (session);
+
+ uri = soup_uri_new ("http://example.com/");
+ session = g_object_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_PROXY_URI, uri,
+ NULL);
+ g_object_get (G_OBJECT (session),
+ SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver,
+ NULL);
+ test_session_properties ("Session with non-NULL :proxy-uri", session,
+ proxy_resolver, default_tlsdb);
+ g_assert_cmpstr (G_OBJECT_TYPE_NAME (proxy_resolver), ==, "GSimpleProxyResolver");
+ g_object_unref (proxy_resolver);
+ g_object_unref (session);
+ soup_uri_free (uri);
+
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+ session = g_object_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_REMOVE_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_URI_RESOLVER,
+ NULL);
+ test_session_properties ("Session with removed proxy resolver feature", session,
+ NULL, default_tlsdb);
+ g_object_unref (session);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
+
+ session = g_object_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_TLS_DATABASE, NULL,
+ NULL);
+ test_session_properties ("Session with NULL :tls-database", session,
+ default_proxy_resolver, NULL);
+ g_object_unref (session);
+
+ /* g_tls_file_database_new() will fail with the dummy backend,
+ * so we can only do this test if we have a real TLS backend.
+ */
+ if (tls_available) {
+ GError *error = NULL;
+
+ tlsdb = g_tls_file_database_new (g_test_get_filename (G_TEST_DIST,
+ "test-cert.pem",
+ NULL), &error);
+ g_assert_no_error (error);
+
+ session = g_object_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_TLS_DATABASE, tlsdb,
+ NULL);
+ test_session_properties ("Session with non-NULL :tls-database", session,
+ default_proxy_resolver, tlsdb);
+ g_object_unref (tlsdb);
+ g_object_unref (session);
+ }
+
+ session = g_object_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, FALSE,
+ NULL);
+ test_session_properties ("Session with :ssl-use-system-ca-file FALSE", session,
+ default_proxy_resolver, NULL);
+ g_object_unref (session);
+
+ session = g_object_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
+ NULL);
+ test_session_properties ("Session with :ssl-use-system-ca-file TRUE", session,
+ default_proxy_resolver, default_tlsdb);
+ g_object_unref (session);
+}
+
+int
+main (int argc, char **argv)
+{
+ SoupServer *server;
+ char *uri, *timeout_uri;
+ int ret;
+
+ test_init (argc, argv, NULL);
+
+ server = soup_test_server_new (TRUE);
+ soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
+ uri = g_strdup_printf ("http://127.0.0.1:%u",
+ soup_server_get_port (server));
+ timeout_uri = g_strdup_printf ("%s/request-timeout", uri);
+
+ g_test_add_data_func ("/session/SoupSession", uri, do_plain_tests);
+ g_test_add_data_func ("/session/SoupSessionAsync", uri, do_async_tests);
+ g_test_add_data_func ("/session/SoupSessionSync", uri, do_sync_tests);
+ g_test_add_data_func ("/session/priority", uri, do_priority_tests);
+ g_test_add_func ("/session/property", do_property_tests);
+
+ ret = g_test_run ();
+
+ g_free (uri);
+ g_free (timeout_uri);
+ soup_test_server_quit_unref (server);
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/simple-httpd.c b/tests/simple-httpd.c
deleted file mode 100644
index 46f0988d..00000000
--- a/tests/simple-httpd.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2001-2003, Ximian, Inc.
- */
-
-#include "test-utils.h"
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-
-#ifdef HAVE_MMAP
-struct mapping {
- void *start;
- size_t length;
-};
-
-static void
-free_mapping (gpointer data)
-{
- struct mapping *mapping = data;
- munmap (mapping->start, mapping->length);
- g_slice_free (struct mapping, mapping);
-}
-#endif
-
-static int
-compare_strings (gconstpointer a, gconstpointer b)
-{
- const char **sa = (const char **)a;
- const char **sb = (const char **)b;
-
- return strcmp (*sa, *sb);
-}
-
-static GString *
-get_directory_listing (const char *path)
-{
- GPtrArray *entries;
- GString *listing;
- char *escaped;
- DIR *dir;
- struct dirent *dent;
- int i;
-
- entries = g_ptr_array_new ();
- dir = opendir (path);
- if (dir) {
- while ((dent = readdir (dir))) {
- if (!strcmp (dent->d_name, ".") ||
- (!strcmp (dent->d_name, "..") &&
- !strcmp (path, "./")))
- continue;
- escaped = g_markup_escape_text (dent->d_name, -1);
- g_ptr_array_add (entries, escaped);
- }
- closedir (dir);
- }
-
- g_ptr_array_sort (entries, (GCompareFunc)compare_strings);
-
- listing = g_string_new ("<html>\r\n");
- escaped = g_markup_escape_text (strchr (path, '/'), -1);
- g_string_append_printf (listing, "<head><title>Index of %s</title></head>\r\n", escaped);
- g_string_append_printf (listing, "<body><h1>Index of %s</h1>\r\n<p>\r\n", escaped);
- g_free (escaped);
- for (i = 0; i < entries->len; i++) {
- g_string_append_printf (listing, "<a href=\"%s\">%s</a><br>\r\n",
- (char *)entries->pdata[i],
- (char *)entries->pdata[i]);
- g_free (entries->pdata[i]);
- }
- g_string_append (listing, "</body>\r\n</html>\r\n");
-
- g_ptr_array_free (entries, TRUE);
- return listing;
-}
-
-static void
-do_get (SoupServer *server, SoupMessage *msg, const char *path)
-{
- char *slash;
- struct stat st;
- int fd;
-
- if (stat (path, &st) == -1) {
- if (errno == EPERM)
- soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
- else if (errno == ENOENT)
- soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
- else
- soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
- return;
- }
-
- if (S_ISDIR (st.st_mode)) {
- GString *listing;
- char *index_path;
-
- slash = strrchr (path, '/');
- if (!slash || slash[1]) {
- char *redir_uri;
-
- redir_uri = g_strdup_printf ("%s/", soup_message_get_uri (msg)->path);
- soup_message_set_redirect (msg, SOUP_STATUS_MOVED_PERMANENTLY,
- redir_uri);
- g_free (redir_uri);
- return;
- }
-
- index_path = g_strdup_printf ("%s/index.html", path);
- if (stat (index_path, &st) != -1) {
- do_get (server, msg, index_path);
- g_free (index_path);
- return;
- }
- g_free (index_path);
-
- listing = get_directory_listing (path);
- soup_message_set_response (msg, "text/html",
- SOUP_MEMORY_TAKE,
- listing->str, listing->len);
- g_string_free (listing, FALSE);
- return;
- }
-
- fd = open (path, O_RDONLY);
- if (fd == -1) {
- soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
- return;
- }
-
- if (msg->method == SOUP_METHOD_GET) {
-#ifdef HAVE_MMAP
- struct mapping *mapping = g_slice_new (struct mapping);
- SoupBuffer *buffer;
-
- mapping->start = mmap (NULL, st.st_size, PROT_READ,
- MAP_PRIVATE, fd, 0);
- mapping->length = st.st_size;
- buffer = soup_buffer_new_with_owner (mapping->start,
- mapping->length,
- mapping, free_mapping);
- soup_message_body_append_buffer (msg->response_body, buffer);
- soup_buffer_free (buffer);
-#else
- char *buf;
-
- buf = g_malloc (st.st_size);
- read (fd, buf, st.st_size);
- close (fd);
- soup_message_body_append (msg->response_body, SOUP_MEMORY_TAKE,
- buf, st.st_size);
-#endif
- } else /* msg->method == SOUP_METHOD_HEAD */ {
- char *length;
-
- /* We could just use the same code for both GET and
- * HEAD. But we'll optimize and avoid the extra
- * malloc.
- */
- length = g_strdup_printf ("%lu", (gulong)st.st_size);
- soup_message_headers_append (msg->response_headers,
- "Content-Length", length);
- g_free (length);
- }
-
- soup_message_set_status (msg, SOUP_STATUS_OK);
-}
-
-static void
-do_put (SoupServer *server, SoupMessage *msg, const char *path)
-{
- struct stat st;
- FILE *f;
- gboolean created = TRUE;
-
- if (stat (path, &st) != -1) {
- const char *match = soup_message_headers_get_one (msg->request_headers, "If-None-Match");
- if (match && !strcmp (match, "*")) {
- soup_message_set_status (msg, SOUP_STATUS_CONFLICT);
- return;
- }
-
- if (!S_ISREG (st.st_mode)) {
- soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
- return;
- }
-
- created = FALSE;
- }
-
- f = fopen (path, "w");
- if (!f) {
- soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
- return;
- }
-
- fwrite (msg->request_body->data, 1, msg->request_body->length, f);
- fclose (f);
-
- soup_message_set_status (msg, created ? SOUP_STATUS_CREATED : SOUP_STATUS_OK);
-}
-
-static void
-server_callback (SoupServer *server, SoupMessage *msg,
- const char *path, GHashTable *query,
- SoupClientContext *context, gpointer data)
-{
- char *file_path;
- SoupMessageHeadersIter iter;
- const char *name, *value;
-
- g_print ("%s %s HTTP/1.%d\n", msg->method, path,
- soup_message_get_http_version (msg));
- soup_message_headers_iter_init (&iter, msg->request_headers);
- while (soup_message_headers_iter_next (&iter, &name, &value))
- g_print ("%s: %s\n", name, value);
- if (msg->request_body->length)
- g_print ("%s\n", msg->request_body->data);
-
- file_path = g_strdup_printf (".%s", path);
-
- if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD)
- do_get (server, msg, file_path);
- else if (msg->method == SOUP_METHOD_PUT)
- do_put (server, msg, file_path);
- else
- soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
-
- g_free (file_path);
- g_print (" -> %d %s\n\n", msg->status_code, msg->reason_phrase);
-}
-
-static void
-quit (int sig)
-{
- /* Exit cleanly on ^C in case we're valgrinding. */
- exit (0);
-}
-
-int
-main (int argc, char **argv)
-{
- GMainLoop *loop;
- SoupServer *server, *ssl_server;
- int opt;
- int port = SOUP_ADDRESS_ANY_PORT;
- int ssl_port = SOUP_ADDRESS_ANY_PORT;
- const char *ssl_cert_file = NULL, *ssl_key_file = NULL;
-
- g_type_init ();
- signal (SIGINT, quit);
-
- while ((opt = getopt (argc, argv, "p:k:c:s:")) != -1) {
- switch (opt) {
- case 'p':
- port = atoi (optarg);
- break;
- case 'k':
- ssl_key_file = optarg;
- break;
- case 'c':
- ssl_cert_file = optarg;
- break;
- case 's':
- ssl_port = atoi (optarg);
- break;
- default:
- g_printerr ("Usage: %s [-p port] [-c ssl-cert-file -k ssl-key-file [-s ssl-port]]\n",
- argv[0]);
- exit (1);
- }
- }
-
- server = soup_server_new (SOUP_SERVER_PORT, port,
- SOUP_SERVER_SERVER_HEADER, "simple-httpd ",
- NULL);
- if (!server) {
- g_printerr ("Unable to bind to server port %d\n", port);
- exit (1);
- }
- soup_server_add_handler (server, NULL,
- server_callback, NULL, NULL);
- g_print ("\nStarting Server on port %d\n",
- soup_server_get_port (server));
- soup_server_run_async (server);
-
- if (ssl_cert_file && ssl_key_file) {
- ssl_server = soup_server_new (
- SOUP_SERVER_PORT, ssl_port,
- SOUP_SERVER_SSL_CERT_FILE, ssl_cert_file,
- SOUP_SERVER_SSL_KEY_FILE, ssl_key_file,
- NULL);
-
- if (!ssl_server) {
- g_printerr ("Unable to bind to SSL server port %d\n", ssl_port);
- exit (1);
- }
- soup_server_add_handler (ssl_server, NULL,
- server_callback, NULL, NULL);
- g_print ("Starting SSL Server on port %d\n",
- soup_server_get_port (ssl_server));
- soup_server_run_async (ssl_server);
- }
-
- g_print ("\nWaiting for requests...\n");
-
- loop = g_main_loop_new (NULL, TRUE);
- g_main_loop_run (loop);
-
- return 0;
-}
diff --git a/tests/simple-proxy.c b/tests/simple-proxy.c
deleted file mode 100644
index f25f9a04..00000000
--- a/tests/simple-proxy.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2001-2003, Ximian, Inc.
- */
-
-#include "test-utils.h"
-
-/* WARNING: this is really really really not especially compliant with
- * RFC 2616. But it does work for basic stuff.
- */
-
-static SoupSession *session;
-static SoupServer *server;
-
-static void
-copy_header (const char *name, const char *value, gpointer dest_headers)
-{
- soup_message_headers_append (dest_headers, name, value);
-}
-
-static void
-send_headers (SoupMessage *from, SoupMessage *to)
-{
- g_print ("[%p] HTTP/1.%d %d %s\n", to,
- soup_message_get_http_version (from),
- from->status_code, from->reason_phrase);
-
- soup_message_set_status_full (to, from->status_code,
- from->reason_phrase);
- soup_message_headers_foreach (from->response_headers, copy_header,
- to->response_headers);
- soup_message_headers_remove (to->response_headers, "Content-Length");
- soup_server_unpause_message (server, to);
-}
-
-static void
-send_chunk (SoupMessage *from, SoupBuffer *chunk, SoupMessage *to)
-{
- g_print ("[%p] writing chunk of %lu bytes\n", to,
- (unsigned long)chunk->length);
-
- soup_message_body_append_buffer (to->response_body, chunk);
- soup_server_unpause_message (server, to);
-}
-
-static void
-client_msg_failed (SoupMessage *msg, gpointer msg2)
-{
- soup_session_cancel_message (session, msg2, SOUP_STATUS_IO_ERROR);
-}
-
-static void
-finish_msg (SoupSession *session, SoupMessage *msg2, gpointer data)
-{
- SoupMessage *msg = data;
-
- g_print ("[%p] done\n\n", msg);
- g_signal_handlers_disconnect_by_func (msg, client_msg_failed, msg2);
-
- soup_message_body_complete (msg->response_body);
- soup_server_unpause_message (server, msg);
- g_object_unref (msg);
-}
-
-static void
-server_callback (SoupServer *server, SoupMessage *msg,
- const char *path, GHashTable *query,
- SoupClientContext *context, gpointer data)
-{
- SoupMessage *msg2;
- char *uristr;
-
- uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
- g_print ("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uristr,
- soup_message_get_http_version (msg));
-
- if (msg->method == SOUP_METHOD_CONNECT) {
- soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- msg2 = soup_message_new (msg->method, uristr);
- soup_message_headers_foreach (msg->request_headers, copy_header,
- msg2->request_headers);
- soup_message_headers_remove (msg2->request_headers, "Host");
- soup_message_headers_remove (msg2->request_headers, "Connection");
-
- if (msg->request_body->length) {
- SoupBuffer *request = soup_message_body_flatten (msg->request_body);
- soup_message_body_append_buffer (msg2->request_body, request);
- soup_buffer_free (request);
- }
- soup_message_headers_set_encoding (msg->response_headers,
- SOUP_ENCODING_CHUNKED);
-
- g_signal_connect (msg2, "got_headers",
- G_CALLBACK (send_headers), msg);
- g_signal_connect (msg2, "got_chunk",
- G_CALLBACK (send_chunk), msg);
-
- g_signal_connect (msg, "finished", G_CALLBACK (client_msg_failed), msg2);
-
- soup_session_queue_message (session, msg2, finish_msg, msg);
-
- g_object_ref (msg);
- soup_server_pause_message (server, msg);
-}
-
-static gboolean
-auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg,
- const char *username, const char *password, gpointer data)
-{
- return !strcmp (username, "user") && !strcmp (password, "password");
-}
-
-static void
-quit (int sig)
-{
- /* Exit cleanly on ^C in case we're valgrinding. */
- exit (0);
-}
-
-int
-main (int argc, char **argv)
-{
- GMainLoop *loop;
- int opt;
- int port = SOUP_ADDRESS_ANY_PORT;
- SoupAuthDomain *auth_domain = NULL;
-
- g_type_init ();
- signal (SIGINT, quit);
-
- while ((opt = getopt (argc, argv, "ap:")) != -1) {
- switch (opt) {
- case 'a':
- auth_domain = soup_auth_domain_basic_new (
- SOUP_AUTH_DOMAIN_REALM, "simple-proxy",
- SOUP_AUTH_DOMAIN_PROXY, TRUE,
- SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback,
- NULL);
- break;
- case 'p':
- port = atoi (optarg);
- break;
- default:
- g_printerr ("Usage: %s [-p port] [-n]\n",
- argv[0]);
- exit (1);
- }
- }
-
- server = soup_server_new (SOUP_SERVER_PORT, port,
- NULL);
- if (!server) {
- g_printerr ("Unable to bind to server port %d\n", port);
- exit (1);
- }
- soup_server_add_handler (server, NULL,
- server_callback, NULL, NULL);
- if (auth_domain) {
- soup_server_add_auth_domain (server, auth_domain);
- g_object_unref (auth_domain);
- }
-
- g_print ("\nStarting proxy on port %d\n",
- soup_server_get_port (server));
- soup_server_run_async (server);
-
- session = soup_session_async_new ();
-
- g_print ("\nWaiting for requests...\n");
-
- loop = g_main_loop_new (NULL, TRUE);
- g_main_loop_run (loop);
- g_main_loop_unref (loop);
-
- return 0;
-}
diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c
index dd4eb4aa..32fad9fc 100644
--- a/tests/sniffing-test.c
+++ b/tests/sniffing-test.c
@@ -16,8 +16,8 @@ server_callback (SoupServer *server, SoupMessage *msg,
{
GError *error = NULL;
char *query_key;
- char *contents;
- gsize length = 0, offset;
+ SoupBuffer *response = NULL;
+ gsize offset;
gboolean empty_response = FALSE;
if (msg->method != SOUP_METHOD_GET) {
@@ -40,41 +40,35 @@ server_callback (SoupServer *server, SoupMessage *msg,
}
if (!strcmp (path, "/mbox")) {
- if (empty_response) {
- contents = g_strdup ("");
- length = 0;
- } else {
- g_file_get_contents (SRCDIR "/resources/mbox",
- &contents, &length,
- &error);
- }
-
- if (error) {
- g_error ("%s", error->message);
- g_error_free (error);
- exit (1);
+ if (!empty_response) {
+ response = soup_test_load_resource ("mbox", &error);
+ g_assert_no_error (error);
}
soup_message_headers_append (msg->response_headers,
"Content-Type", "text/plain");
}
- if (g_str_has_prefix (path, "/text_or_binary/")) {
+ if (g_str_has_prefix (path, "/nosniff/")) {
char *base_name = g_path_get_basename (path);
- char *file_name = g_strdup_printf (SRCDIR "/resources/%s", base_name);
-
- g_file_get_contents (file_name,
- &contents, &length,
- &error);
+ response = soup_test_load_resource (base_name, &error);
+ g_assert_no_error (error);
g_free (base_name);
- g_free (file_name);
- if (error) {
- g_error ("%s", error->message);
- g_error_free (error);
- exit (1);
- }
+ soup_message_headers_append (msg->response_headers,
+ "X-Content-Type-Options", "nosniff");
+
+ soup_message_headers_append (msg->response_headers,
+ "Content-Type", "no/sniffing-allowed");
+ }
+
+ if (g_str_has_prefix (path, "/text_or_binary/") || g_str_has_prefix (path, "/apache_bug/")) {
+ char *base_name = g_path_get_basename (path);
+
+ response = soup_test_load_resource (base_name, &error);
+ g_assert_no_error (error);
+ g_free (base_name);
soup_message_headers_append (msg->response_headers,
"Content-Type", "text/plain");
@@ -82,20 +76,10 @@ server_callback (SoupServer *server, SoupMessage *msg,
if (g_str_has_prefix (path, "/unknown/")) {
char *base_name = g_path_get_basename (path);
- char *file_name = g_strdup_printf (SRCDIR "/resources/%s", base_name);
-
- g_file_get_contents (file_name,
- &contents, &length,
- &error);
+ response = soup_test_load_resource (base_name, &error);
+ g_assert_no_error (error);
g_free (base_name);
- g_free (file_name);
-
- if (error) {
- g_error ("%s", error->message);
- g_error_free (error);
- exit (1);
- }
soup_message_headers_append (msg->response_headers,
"Content-Type", "UNKNOWN/unknown");
@@ -106,20 +90,10 @@ server_callback (SoupServer *server, SoupMessage *msg,
char *ptr;
char *base_name = g_path_get_basename (path);
- char *file_name = g_strdup_printf (SRCDIR "/resources/%s", base_name);
-
- g_file_get_contents (file_name,
- &contents, &length,
- &error);
+ response = soup_test_load_resource (base_name, &error);
+ g_assert_no_error (error);
g_free (base_name);
- g_free (file_name);
-
- if (error) {
- g_error ("%s", error->message);
- g_error_free (error);
- exit (1);
- }
/* Hack to allow passing type in the URI */
ptr = g_strrstr (components[2], "_");
@@ -132,20 +106,10 @@ server_callback (SoupServer *server, SoupMessage *msg,
if (g_str_has_prefix (path, "/multiple_headers/")) {
char *base_name = g_path_get_basename (path);
- char *file_name = g_strdup_printf (SRCDIR "/resources/%s", base_name);
-
- g_file_get_contents (file_name,
- &contents, &length,
- &error);
+ response = soup_test_load_resource (base_name, &error);
+ g_assert_no_error (error);
g_free (base_name);
- g_free (file_name);
-
- if (error) {
- g_error ("%s", error->message);
- g_error_free (error);
- exit (1);
- }
soup_message_headers_append (msg->response_headers,
"Content-Type", "text/xml");
@@ -153,15 +117,18 @@ server_callback (SoupServer *server, SoupMessage *msg,
"Content-Type", "text/plain");
}
- for (offset = 0; offset < length; offset += 500) {
- soup_message_body_append (msg->response_body,
- SOUP_MEMORY_COPY,
- contents + offset,
- MIN(500, length - offset));
+ if (response) {
+ for (offset = 0; offset < response->length; offset += 500) {
+ soup_message_body_append (msg->response_body,
+ SOUP_MEMORY_COPY,
+ response->data + offset,
+ MIN (500, response->length - offset));
+ }
+
+ soup_buffer_free (response);
}
- soup_message_body_complete (msg->response_body);
- g_free (contents);
+ soup_message_body_complete (msg->response_body);
}
static gboolean
@@ -181,10 +148,8 @@ content_sniffed (SoupMessage *msg, char *content_type, GHashTable *params, gpoin
debug_printf (2, " content-sniffed -> %s\n", content_type);
- if (g_object_get_data (G_OBJECT (msg), "got-chunk")) {
- debug_printf (1, " got-chunk got emitted before content-sniffed\n");
- errors++;
- }
+ soup_test_assert (g_object_get_data (G_OBJECT (msg), "got-chunk") == NULL,
+ "got-chunk got emitted before content-sniffed");
g_object_set_data (G_OBJECT (msg), "content-sniffed", GINT_TO_POINTER (TRUE));
@@ -202,10 +167,8 @@ got_headers (SoupMessage *msg, gpointer data)
debug_printf (2, " got-headers\n");
- if (g_object_get_data (G_OBJECT (msg), "content-sniffed")) {
- debug_printf (1, " content-sniffed got emitted before got-headers\n");
- errors++;
- }
+ soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") == NULL,
+ "content-sniffed got emitted before got-headers");
g_object_set_data (G_OBJECT (msg), "got-headers", GINT_TO_POINTER (TRUE));
@@ -233,13 +196,6 @@ got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer data)
}
static void
-finished (SoupSession *session, SoupMessage *msg, gpointer data)
-{
- GMainLoop *loop = (GMainLoop*)data;
- g_main_loop_quit (loop);
-}
-
-static void
do_signals_test (gboolean should_content_sniff,
gboolean should_pause,
gboolean should_accumulate,
@@ -248,9 +204,7 @@ do_signals_test (gboolean should_content_sniff,
{
SoupURI *uri = soup_uri_new_with_base (base_uri, "/mbox");
SoupMessage *msg = soup_message_new_from_uri ("GET", uri);
- GMainLoop *loop = g_main_loop_new (NULL, TRUE);
- char *contents;
- gsize length;
+ SoupBuffer *expected;
GError *error = NULL;
SoupBuffer *body = NULL;
@@ -283,34 +237,21 @@ do_signals_test (gboolean should_content_sniff,
"signal::content_sniffed", content_sniffed, GINT_TO_POINTER (should_pause),
NULL);
- g_object_ref (msg);
- soup_session_queue_message (session, msg, finished, loop);
-
- g_main_loop_run (loop);
-
- if (!should_content_sniff &&
- g_object_get_data (G_OBJECT (msg), "content-sniffed")) {
- debug_printf (1, " content-sniffed got emitted without a sniffer\n");
- errors++;
- } else if (should_content_sniff &&
- !g_object_get_data (G_OBJECT (msg), "content-sniffed")) {
- debug_printf (1, " content-sniffed did not get emitted\n");
- errors++;
- }
+ soup_session_send_message (session, msg);
- if (empty_response) {
- contents = g_strdup ("");
- length = 0;
+ if (should_content_sniff) {
+ soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") != NULL,
+ "content-sniffed did not get emitted");
} else {
- g_file_get_contents (SRCDIR "/resources/mbox",
- &contents, &length,
- &error);
+ soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") == NULL,
+ "content-sniffed got emitted without a sniffer");
}
- if (error) {
- g_error ("%s", error->message);
- g_error_free (error);
- exit (1);
+ if (empty_response)
+ expected = soup_buffer_new (SOUP_MEMORY_STATIC, "", 0);
+ else {
+ expected = soup_test_load_resource ("mbox", &error);
+ g_assert_no_error (error);
}
if (!should_accumulate && chunk_data)
@@ -318,17 +259,12 @@ do_signals_test (gboolean should_content_sniff,
else if (msg->response_body)
body = soup_message_body_flatten (msg->response_body);
- if (body && body->length != length) {
- debug_printf (1, " lengths do not match\n");
- errors++;
+ if (body) {
+ soup_assert_cmpmem (body->data, body->length,
+ expected->data, expected->length);
}
- if (body && memcmp (body->data, contents, length)) {
- debug_printf (1, " downloaded data does not match\n");
- errors++;
- }
-
- g_free (contents);
+ soup_buffer_free (expected);
if (body)
soup_buffer_free (body);
if (chunk_data) {
@@ -338,7 +274,42 @@ do_signals_test (gboolean should_content_sniff,
soup_uri_free (uri);
g_object_unref (msg);
- g_main_loop_unref (loop);
+}
+
+static void
+do_signals_tests (gconstpointer data)
+{
+ gboolean should_content_sniff = GPOINTER_TO_INT (data);
+
+ if (!should_content_sniff)
+ soup_session_remove_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
+
+ do_signals_test (should_content_sniff,
+ FALSE, FALSE, FALSE, FALSE);
+ do_signals_test (should_content_sniff,
+ FALSE, FALSE, TRUE, FALSE);
+ do_signals_test (should_content_sniff,
+ FALSE, TRUE, FALSE, FALSE);
+ do_signals_test (should_content_sniff,
+ FALSE, TRUE, TRUE, FALSE);
+
+ do_signals_test (should_content_sniff,
+ TRUE, TRUE, FALSE, FALSE);
+ do_signals_test (should_content_sniff,
+ TRUE, TRUE, TRUE, FALSE);
+ do_signals_test (should_content_sniff,
+ TRUE, FALSE, FALSE, FALSE);
+ do_signals_test (should_content_sniff,
+ TRUE, FALSE, TRUE, FALSE);
+
+ /* FIXME g_test_bug ("587907") */
+ do_signals_test (should_content_sniff,
+ TRUE, TRUE, FALSE, TRUE);
+ do_signals_test (should_content_sniff,
+ TRUE, TRUE, TRUE, TRUE);
+
+ if (!should_content_sniff)
+ soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
}
static void
@@ -347,102 +318,125 @@ sniffing_content_sniffed (SoupMessage *msg, const char *content_type,
{
char **sniffed_type = (char **)data;
GString *full_header;
- GList *keys;
- GList *iter;
-
- if (params == NULL) {
- *sniffed_type = g_strdup (content_type);
- return;
- }
+ GHashTableIter iter;
+ gpointer key, value;
full_header = g_string_new (content_type);
- g_string_append (full_header, "; ");
-
- keys = g_hash_table_get_keys (params);
- for (iter = keys; iter != NULL; iter = iter->next) {
- const gchar *value = (const gchar*) g_hash_table_lookup (params, iter->data);
+ g_hash_table_iter_init (&iter, params);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ if (full_header->len)
+ g_string_append (full_header, "; ");
soup_header_g_string_append_param (full_header,
- (const gchar*) iter->data,
- value);
+ (const char *) key,
+ (const char *) value);
}
- *sniffed_type = full_header->str;
-
- g_string_free (full_header, FALSE);
- g_list_free (keys);
+ *sniffed_type = g_string_free (full_header, FALSE);
}
static void
test_sniffing (const char *path, const char *expected_type)
{
- SoupURI *uri = soup_uri_new_with_base (base_uri, path);
- SoupMessage *msg = soup_message_new_from_uri ("GET", uri);
- GMainLoop *loop = g_main_loop_new (NULL, TRUE);
+ SoupURI *uri;
+ SoupMessage *msg;
+ SoupRequest *req;
+ GInputStream *stream;
char *sniffed_type = NULL;
+ const char *req_sniffed_type;
+ GError *error = NULL;
- debug_printf (1, "test_sniffing(\"%s\", \"%s\")\n", path, expected_type);
+ uri = soup_uri_new_with_base (base_uri, path);
+ msg = soup_message_new_from_uri ("GET", uri);
g_signal_connect (msg, "content-sniffed",
G_CALLBACK (sniffing_content_sniffed), &sniffed_type);
- g_object_ref (msg);
-
- soup_session_queue_message (session, msg, finished, loop);
-
- g_main_loop_run (loop);
+ soup_session_send_message (session, msg);
+ g_assert_cmpstr (sniffed_type, ==, expected_type);
+ g_free (sniffed_type);
+ g_object_unref (msg);
- if (!sniffed_type) {
- debug_printf (1, " message was not sniffed!\n");
- errors++;
- } else if (strcmp (sniffed_type, expected_type) != 0) {
- debug_printf (1, " sniffing failed! expected %s, got %s\n",
- expected_type, sniffed_type);
- errors++;
+ req = soup_session_request_uri (session, uri, NULL);
+ stream = soup_test_request_send (req, NULL, 0, &error);
+ if (stream) {
+ soup_test_request_close_stream (req, stream, NULL, &error);
+ g_object_unref (stream);
}
- g_free (sniffed_type);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+
+ req_sniffed_type = soup_request_get_content_type (req);
+ g_assert_cmpstr (req_sniffed_type, ==, expected_type);
+ g_object_unref (req);
soup_uri_free (uri);
- g_object_unref (msg);
- g_main_loop_unref (loop);
}
static void
-test_disabled (const char *path)
+do_sniffing_test (gconstpointer data)
{
- SoupURI *uri = soup_uri_new_with_base (base_uri, path);
- SoupMessage *msg = soup_message_new_from_uri ("GET", uri);
- GMainLoop *loop = g_main_loop_new (NULL, TRUE);
+ const char *path_and_result = data;
+ char **parts;
+
+ parts = g_strsplit (path_and_result, " => ", -1);
+ g_assert (parts && parts[0] && parts[1] && !parts[2]);
+
+ test_sniffing (parts[0], parts[1]);
+ g_strfreev (parts);
+}
+
+static void
+test_disabled (gconstpointer data)
+{
+ const char *path = data;
+ SoupURI *uri;
+ SoupMessage *msg;
+ SoupRequest *req;
+ GInputStream *stream;
char *sniffed_type = NULL;
+ const char *sniffed_content_type;
+ GError *error = NULL;
- soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER);
+ g_test_bug ("574773");
- debug_printf (1, "test_disabled(\"%s\")\n", path);
+ uri = soup_uri_new_with_base (base_uri, path);
+
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER);
g_signal_connect (msg, "content-sniffed",
G_CALLBACK (sniffing_content_sniffed), &sniffed_type);
- g_object_ref (msg);
-
- soup_session_queue_message (session, msg, finished, loop);
+ soup_session_send_message (session, msg);
- g_main_loop_run (loop);
+ g_assert_null (sniffed_type);
+ g_object_unref (msg);
- if (sniffed_type) {
- debug_printf (1, " message was sniffed!\n");
- errors++;
- g_free (sniffed_type);
+ req = soup_session_request_uri (session, uri, NULL);
+ msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+ soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER);
+ g_object_unref (msg);
+ stream = soup_test_request_send (req, NULL, 0, &error);
+ if (stream) {
+ soup_test_request_close_stream (req, stream, NULL, &error);
+ g_object_unref (stream);
}
+ g_assert_no_error (error);
+
+ sniffed_content_type = soup_request_get_content_type (req);
+ g_assert_cmpstr (sniffed_content_type, ==, NULL);
+
+ g_object_unref (req);
soup_uri_free (uri);
- g_object_unref (msg);
- g_main_loop_unref (loop);
}
int
main (int argc, char **argv)
{
SoupServer *server;
+ int ret;
test_init (argc, argv, NULL);
@@ -451,112 +445,171 @@ main (int argc, char **argv)
base_uri = soup_uri_new ("http://127.0.0.1/");
soup_uri_set_port (base_uri, soup_server_get_port (server));
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
-
- /* No sniffer, no content_sniffed should be emitted */
- do_signals_test (FALSE, FALSE, FALSE, FALSE, FALSE);
- do_signals_test (FALSE, FALSE, FALSE, TRUE, FALSE);
- do_signals_test (FALSE, FALSE, TRUE, FALSE, FALSE);
- do_signals_test (FALSE, FALSE, TRUE, TRUE, FALSE);
-
- do_signals_test (FALSE, TRUE, TRUE, FALSE, FALSE);
- do_signals_test (FALSE, TRUE, TRUE, TRUE, FALSE);
- do_signals_test (FALSE, TRUE, FALSE, FALSE, FALSE);
- do_signals_test (FALSE, TRUE, FALSE, TRUE, FALSE);
-
- /* Tests that the signals are correctly emitted for empty
- * responses; see
- * http://bugzilla.gnome.org/show_bug.cgi?id=587907 */
-
- do_signals_test (FALSE, TRUE, TRUE, FALSE, TRUE);
- do_signals_test (FALSE, TRUE, TRUE, TRUE, TRUE);
-
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
- /* Now, with a sniffer, content_sniffed must be emitted after
- * got-headers, and before got-chunk.
- */
- do_signals_test (TRUE, FALSE, FALSE, FALSE, FALSE);
- do_signals_test (TRUE, FALSE, FALSE, TRUE, FALSE);
- do_signals_test (TRUE, FALSE, TRUE, FALSE, FALSE);
- do_signals_test (TRUE, FALSE, TRUE, TRUE, FALSE);
-
- do_signals_test (TRUE, TRUE, TRUE, FALSE, FALSE);
- do_signals_test (TRUE, TRUE, TRUE, TRUE, FALSE);
- do_signals_test (TRUE, TRUE, FALSE, FALSE, FALSE);
- do_signals_test (TRUE, TRUE, FALSE, TRUE, FALSE);
-
- /* Empty response tests */
- do_signals_test (TRUE, TRUE, TRUE, FALSE, TRUE);
- do_signals_test (TRUE, TRUE, TRUE, TRUE, TRUE);
-
- /* Test the text_or_binary sniffing path */
+ g_test_add_data_func ("/sniffing/signals/no-sniffer",
+ GINT_TO_POINTER (FALSE),
+ do_signals_tests);
+ g_test_add_data_func ("/sniffing/signals/with-sniffer",
+ GINT_TO_POINTER (TRUE),
+ do_signals_tests);
+
+ /* Test the apache bug sniffing path */
+ g_test_add_data_func ("/sniffing/apache-bug/binary",
+ "/apache_bug/text_binary.txt => application/octet-stream",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/apache-bug/text",
+ "/apache_bug/text.txt => text/plain",
+ do_sniffing_test);
+
+ /* X-Content-Type-Options: nosniff */
+ g_test_add_data_func ("/sniffing/nosniff",
+ "nosniff/home.gif => no/sniffing-allowed",
+ do_sniffing_test);
/* GIF is a 'safe' type */
- test_sniffing ("/text_or_binary/home.gif", "image/gif");
+ g_test_add_data_func ("/sniffing/type/gif",
+ "text_or_binary/home.gif => image/gif",
+ do_sniffing_test);
/* With our current code, no sniffing is done using GIO, so
* the mbox will be identified as text/plain; should we change
* this?
*/
- test_sniffing ("/text_or_binary/mbox", "text/plain");
+ g_test_add_data_func ("/sniffing/type/mbox",
+ "text_or_binary/mbox => text/plain",
+ do_sniffing_test);
/* HTML is considered unsafe for this algorithm, since it is
* scriptable, so going from text/plain to text/html is
* considered 'privilege escalation'
*/
- test_sniffing ("/text_or_binary/test.html", "text/plain");
+ g_test_add_data_func ("/sniffing/type/html-in-text-context",
+ "text_or_binary/test.html => text/plain",
+ do_sniffing_test);
/* text/plain with binary content and unknown pattern should be
- * application/octet-stream */
- test_sniffing ("/text_or_binary/text_binary.txt", "application/octet-stream");
+ * application/octet-stream
+ */
+ g_test_add_data_func ("/sniffing/type/text-binary",
+ "text_or_binary/text_binary.txt => application/octet-stream",
+ do_sniffing_test);
- /* text/plain with binary content and scriptable pattern should be
- * application/octet-stream to avoid 'privilege escalation' */
- test_sniffing ("/text_or_binary/html_binary.html", "application/octet-stream");
+ /* text/html with binary content and scriptable pattern should be
+ * application/octet-stream to avoid 'privilege escalation'
+ */
+ g_test_add_data_func ("/sniffing/type/html-binary",
+ "text_or_binary/html_binary.html => application/octet-stream",
+ do_sniffing_test);
/* text/plain with binary content and non scriptable known pattern should
- * be the given type */
- test_sniffing ("/text_or_binary/ps_binary.ps", "application/postscript");
+ * be the given type
+ */
+ g_test_add_data_func ("/sniffing/type/ps",
+ "text_or_binary/ps_binary.ps => application/postscript",
+ do_sniffing_test);
/* Test the unknown sniffing path */
-
- test_sniffing ("/unknown/test.html", "text/html");
- test_sniffing ("/unknown/home.gif", "image/gif");
- test_sniffing ("/unknown/mbox", "text/plain");
- test_sniffing ("/unknown/text_binary.txt", "application/octet-stream");
+ g_test_add_data_func ("/sniffing/type/unknown-html",
+ "unknown/test.html => text/html",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/unknown-gif",
+ "unknown/home.gif => image/gif",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/unknown-mbox",
+ "unknown/mbox => text/plain",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/unknown-binary",
+ "unknown/text_binary.txt => application/octet-stream",
+ do_sniffing_test);
+ /* FIXME g_test_bug ("715126") */
+ g_test_add_data_func ("/sniffing/type/unknown-leading-space",
+ "unknown/leading_space.html => text/html",
+ do_sniffing_test);
/* Test the XML sniffing path */
-
- test_sniffing ("/type/text_xml/home.gif", "text/xml");
- test_sniffing ("/type/anice_type+xml/home.gif", "anice/type+xml");
- test_sniffing ("/type/application_xml/home.gif", "application/xml");
-
- /* Test the image sniffing path */
-
- test_sniffing ("/type/image_png/home.gif", "image/gif");
+ g_test_add_data_func ("/sniffing/type/xml",
+ "type/text_xml/home.gif => text/xml",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/xml+xml",
+ "type/anice_type+xml/home.gif => anice/type+xml",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/application-xml",
+ "type/application_xml/home.gif => application/xml",
+ do_sniffing_test);
/* Test the feed or html path */
+ g_test_add_data_func ("/sniffing/type/html/html",
+ "type/text_html/test.html => text/html",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/html/rss",
+ "type/text_html/rss20.xml => application/rss+xml",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/html/atom",
+ "type/text_html/atom.xml => application/atom+xml",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/html/rdf",
+ "type/text_html/feed.rdf => application/rss+xml",
+ do_sniffing_test);
- test_sniffing ("/type/text_html/test.html", "text/html");
- test_sniffing ("/type/text_html/rss20.xml", "application/rss+xml");
- test_sniffing ("/type/text_html/atom.xml", "application/atom+xml");
+ /* Test the image sniffing path */
+ g_test_add_data_func ("/sniffing/type/image/gif",
+ "type/image_png/home.gif => image/gif",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/image/png",
+ "type/image_gif/home.png => image/png",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/image/jpeg",
+ "type/image_png/home.jpg => image/jpeg",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/image/webp",
+ "type/image_png/tux.webp => image/webp",
+ do_sniffing_test);
+
+ /* Test audio and video sniffing path */
+ g_test_add_data_func ("/sniffing/type/audio/wav",
+ "type/audio_mpeg/test.wav => audio/wave",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/audio/aiff",
+ "type/audio_mpeg/test.aiff => audio/aiff",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/audio/ogg",
+ "type/audio_mpeg/test.ogg => application/ogg",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/video/webm",
+ "type/video_theora/test.webm => video/webm",
+ do_sniffing_test);
+
+ /* Test the MP4 sniffing path */
+ g_test_add_data_func ("/sniffing/type/video/mp4",
+ "unknown/test.mp4 => video/mp4",
+ do_sniffing_test);
/* The spec tells us to only use the last Content-Type header */
-
- test_sniffing ("/multiple_headers/home.gif", "image/gif");
+ g_test_add_data_func ("/sniffing/multiple-headers",
+ "multiple_headers/home.gif => image/gif",
+ do_sniffing_test);
/* Test that we keep the parameters when sniffing */
- test_sniffing ("/type/text_html; charset=UTF-8/test.html", "text/html; charset=UTF-8");
+ g_test_add_data_func ("/sniffing/parameters",
+ "type/text_html; charset=UTF-8/test.html => text/html; charset=UTF-8",
+ do_sniffing_test);
/* Test that disabling the sniffer works correctly */
+ g_test_add_data_func ("/sniffing/disabled",
+ "/text_or_binary/home.gif",
+ test_disabled);
- test_disabled ("/text_or_binary/home.gif");
+ ret = g_test_run ();
soup_uri_free (base_uri);
soup_test_session_abort_unref (session);
soup_test_server_quit_unref (server);
+
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/socket-test.c b/tests/socket-test.c
new file mode 100644
index 00000000..5bcc3b0c
--- /dev/null
+++ b/tests/socket-test.c
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright 2007-2012 Red Hat, Inc.
+ * Copyright 2012 Nokia Corporation
+ */
+
+#include "test-utils.h"
+
+#include <gio/gnetworking.h>
+
+static void
+do_unconnected_socket_test (void)
+{
+ SoupAddress *localhost;
+ SoupSocket *sock;
+ SoupSocket *client;
+ SoupAddress *addr;
+ guint res;
+ struct sockaddr_in in_localhost;
+
+ g_test_bug ("673083");
+
+ in_localhost.sin_family = AF_INET;
+ in_localhost.sin_port = 0;
+ in_localhost.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ localhost = soup_address_new_from_sockaddr (
+ (struct sockaddr *) &in_localhost, sizeof (in_localhost));
+ g_assert_true (localhost != NULL);
+ res = soup_address_resolve_sync (localhost, NULL);
+ g_assert_cmpuint (res, ==, SOUP_STATUS_OK);
+
+ sock = soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, localhost,
+ NULL);
+ g_assert_true (sock != NULL);
+
+ addr = soup_socket_get_local_address (sock);
+ g_assert_true (addr != NULL);
+ g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1");
+ g_assert_cmpuint (soup_address_get_port (addr), ==, 0);
+
+ /* fails with ENOTCONN */
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*socket not connected*");
+ addr = soup_socket_get_remote_address (sock);
+ g_test_assert_expected_messages ();
+ g_assert_null (addr);
+
+ res = soup_socket_listen (sock);
+ g_assert_true (res);
+
+ addr = soup_socket_get_local_address (sock);
+ g_assert_true (addr != NULL);
+ g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1");
+ g_assert_cmpuint (soup_address_get_port (addr), >, 0);
+
+ client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS,
+ soup_socket_get_local_address (sock),
+ NULL);
+ res = soup_socket_connect_sync (client, NULL);
+ g_assert_cmpuint (res, ==, SOUP_STATUS_OK);
+ addr = soup_socket_get_local_address (client);
+ g_assert_true (addr != NULL);
+ addr = soup_socket_get_remote_address (client);
+ g_assert_true (addr != NULL);
+ g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1");
+ g_assert_cmpuint (soup_address_get_port (addr), >, 0);
+ g_object_unref (client);
+
+ client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS,
+ soup_socket_get_local_address (sock),
+ NULL);
+ /* save it for later */
+
+ /* listening socket fails with ENOTCONN */
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*endpoint is not connected*");
+ addr = soup_socket_get_remote_address (sock);
+ g_test_assert_expected_messages ();
+ g_assert_null (addr);
+
+ soup_socket_disconnect (sock);
+
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*socket not connected*");
+ addr = soup_socket_get_remote_address (sock);
+ g_test_assert_expected_messages ();
+ g_assert_null (addr);
+
+ /* has never been connected */
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*socket not connected*");
+ addr = soup_socket_get_local_address (client);
+ g_test_assert_expected_messages ();
+ g_assert_null (addr);
+
+ res = soup_socket_connect_sync (client, NULL);
+ g_assert_cmpuint (res, ==, SOUP_STATUS_CANT_CONNECT);
+
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*socket not connected*");
+ addr = soup_socket_get_local_address (client);
+ g_test_assert_expected_messages ();
+ g_assert_null (addr);
+
+ g_object_unref (localhost);
+ g_object_unref (client);
+ g_object_unref (sock);
+}
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+
+ test_init (argc, argv, NULL);
+
+ g_test_add_func ("/sockets/unconnected", do_unconnected_socket_test);
+
+ ret = g_test_run ();
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml
new file mode 100644
index 00000000..b24a7297
--- /dev/null
+++ b/tests/soup-tests.gresource.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/libsoup/tests">
+ <file>index.txt</file>
+ <file>resources/atom.xml</file>
+ <file>resources/feed.rdf</file>
+ <file>resources/home.gif</file>
+ <file>resources/home.jpg</file>
+ <file>resources/home.png</file>
+ <file>resources/html_binary.html</file>
+ <file>resources/leading_space.html</file>
+ <file>resources/mbox</file>
+ <file>resources/mbox.gz</file>
+ <file>resources/mbox.raw</file>
+ <file>resources/mbox.zlib</file>
+ <file>resources/ps_binary.ps</file>
+ <file>resources/rss20.xml</file>
+ <file>resources/test.aiff</file>
+ <file>resources/test.html</file>
+ <file>resources/test.mp4</file>
+ <file>resources/test.ogg</file>
+ <file>resources/test.wav</file>
+ <file>resources/test.webm</file>
+ <file>resources/text.txt</file>
+ <file>resources/text_binary.txt</file>
+ <file>resources/tux.webp</file>
+ </gresource>
+</gresources>
diff --git a/tests/ssl-test.c b/tests/ssl-test.c
index 6d96bc79..e6bbb615 100644
--- a/tests/ssl-test.c
+++ b/tests/ssl-test.c
@@ -2,8 +2,10 @@
#include "test-utils.h"
+static char *uri;
+
static void
-do_properties_test_for_session (SoupSession *session, char *uri)
+do_properties_test_for_session (SoupSession *session, const char *uri)
{
SoupMessage *msg;
GTlsCertificate *cert;
@@ -11,42 +13,27 @@ do_properties_test_for_session (SoupSession *session, char *uri)
msg = soup_message_new ("GET", uri);
soup_session_send_message (session, msg);
- if (msg->status_code != SOUP_STATUS_OK) {
- debug_printf (1, " FAILED: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
if (soup_message_get_https_status (msg, &cert, &flags)) {
- if (!G_IS_TLS_CERTIFICATE (cert)) {
- debug_printf (1, " No certificate?\n");
- errors++;
- }
- if (flags != G_TLS_CERTIFICATE_UNKNOWN_CA) {
- debug_printf (1, " Wrong cert flags (got %x, wanted %x)\n",
- flags, G_TLS_CERTIFICATE_UNKNOWN_CA);
- errors++;
- }
- } else {
- debug_printf (1, " Response not https\n");
- errors++;
- }
- if (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) {
- debug_printf (1, " CERTIFICATE_TRUSTED set?\n");
- errors++;
- }
+ g_assert_true (G_IS_TLS_CERTIFICATE (cert));
+ g_assert_cmpuint (flags, ==, G_TLS_CERTIFICATE_UNKNOWN_CA);
+ } else
+ soup_test_assert (FALSE, "Response not https");
+
+ g_test_bug ("665182");
+ g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED);
g_object_unref (msg);
}
static void
-do_properties_tests (char *uri)
+do_async_properties_tests (void)
{
SoupSession *session;
- debug_printf (1, "\nSoupMessage properties\n");
+ SOUP_TEST_SKIP_IF_NO_TLS;
- debug_printf (1, " async\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
g_object_set (G_OBJECT (session),
SOUP_SESSION_SSL_CA_FILE, "/dev/null",
@@ -54,8 +41,15 @@ do_properties_tests (char *uri)
NULL);
do_properties_test_for_session (session, uri);
soup_test_session_abort_unref (session);
+}
+
+static void
+do_sync_properties_tests (void)
+{
+ SoupSession *session;
+
+ SOUP_TEST_SKIP_IF_NO_TLS;
- debug_printf (1, " sync\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
g_object_set (G_OBJECT (session),
SOUP_SESSION_SSL_CA_FILE, "/dev/null",
@@ -65,81 +59,74 @@ do_properties_tests (char *uri)
soup_test_session_abort_unref (session);
}
+typedef struct {
+ const char *name;
+ gboolean sync;
+ gboolean strict;
+ gboolean with_ca_list;
+ guint expected_status;
+} StrictnessTest;
+
+static const StrictnessTest strictness_tests[] = {
+ { "/ssl/strictness/async/strict/with-ca",
+ FALSE, TRUE, TRUE, SOUP_STATUS_OK },
+ { "/ssl/strictness/async/strict/without-ca",
+ FALSE, TRUE, FALSE, SOUP_STATUS_SSL_FAILED },
+ { "/ssl/strictness/async/non-strict/with-ca",
+ FALSE, FALSE, TRUE, SOUP_STATUS_OK },
+ { "/ssl/strictness/async/non-strict/without-ca",
+ FALSE, FALSE, FALSE, SOUP_STATUS_OK },
+ { "/ssl/strictness/sync/strict/with-ca",
+ TRUE, TRUE, TRUE, SOUP_STATUS_OK },
+ { "/ssl/strictness/sync/strict/without-ca",
+ TRUE, TRUE, FALSE, SOUP_STATUS_SSL_FAILED },
+ { "/ssl/strictness/sync/non-strict/with-ca",
+ TRUE, FALSE, TRUE, SOUP_STATUS_OK },
+ { "/ssl/strictness/sync/non-strict/without-ca",
+ TRUE, FALSE, FALSE, SOUP_STATUS_OK },
+};
+
static void
-do_one_strict_test (SoupSession *session, char *uri,
- gboolean strict, gboolean with_ca_list,
- guint expected_status)
+do_strictness_test (gconstpointer data)
{
+ const StrictnessTest *test = data;
+ SoupSession *session;
SoupMessage *msg;
+ GTlsCertificateFlags flags = 0;
- /* Note that soup_test_session_new() sets
- * SOUP_SESSION_SSL_CA_FILE by default, and turns off
- * SOUP_SESSION_SSL_STRICT.
- */
+ SOUP_TEST_SKIP_IF_NO_TLS;
- g_object_set (G_OBJECT (session),
- SOUP_SESSION_SSL_STRICT, strict,
- SOUP_SESSION_SSL_CA_FILE, with_ca_list ? SRCDIR "/test-cert.pem" : "/dev/null",
- NULL);
- /* Close existing connections with old params */
- soup_session_abort (session);
+ session = soup_test_session_new (test->sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC,
+ NULL);
+ if (!test->strict) {
+ g_object_set (G_OBJECT (session),
+ SOUP_SESSION_SSL_STRICT, FALSE,
+ NULL);
+ }
+ if (!test->with_ca_list) {
+ g_object_set (G_OBJECT (session),
+ SOUP_SESSION_SSL_CA_FILE, "/dev/null",
+ NULL);
+ }
msg = soup_message_new ("GET", uri);
soup_session_send_message (session, msg);
- if (msg->status_code != expected_status) {
- debug_printf (1, " FAILED: %d %s (expected %d %s)\n",
- msg->status_code, msg->reason_phrase,
- expected_status,
- soup_status_get_phrase (expected_status));
- if (msg->status_code == SOUP_STATUS_SSL_FAILED) {
- GTlsCertificateFlags flags = 0;
-
- soup_message_get_https_status (msg, NULL, &flags);
- debug_printf (1, " tls error flags: 0x%x\n", flags);
- }
- errors++;
- } else if (with_ca_list && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED)) {
- debug_printf (1, " CERTIFICATE_TRUSTED not set?\n");
- errors++;
- }
- } else {
- if (with_ca_list && soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) {
- debug_printf (1, " CERTIFICATE_TRUSTED set?\n");
- errors++;
- }
- }
-
- g_object_unref (msg);
-}
+ soup_test_assert_message_status (msg, test->expected_status);
-static void
-do_strict_tests (char *uri)
-{
- SoupSession *session;
+ g_test_bug ("690176");
+ g_assert_true (soup_message_get_https_status (msg, NULL, &flags));
- debug_printf (1, "\nstrict/nonstrict\n");
+ g_test_bug ("665182");
+ if (test->with_ca_list && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ g_assert_true (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED);
+ else
+ g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED);
- session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- debug_printf (1, " async with CA list\n");
- do_one_strict_test (session, uri, TRUE, TRUE, SOUP_STATUS_OK);
- debug_printf (1, " async without CA list\n");
- do_one_strict_test (session, uri, TRUE, FALSE, SOUP_STATUS_SSL_FAILED);
- debug_printf (1, " async non-strict with CA list\n");
- do_one_strict_test (session, uri, FALSE, TRUE, SOUP_STATUS_OK);
- debug_printf (1, " async non-strict without CA list\n");
- do_one_strict_test (session, uri, FALSE, FALSE, SOUP_STATUS_OK);
- soup_test_session_abort_unref (session);
+ if (msg->status_code == SOUP_STATUS_SSL_FAILED &&
+ test->expected_status != SOUP_STATUS_SSL_FAILED)
+ debug_printf (1, " tls error flags: 0x%x\n", flags);
- session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
- debug_printf (1, " sync with CA list\n");
- do_one_strict_test (session, uri, TRUE, TRUE, SOUP_STATUS_OK);
- debug_printf (1, " sync without CA list\n");
- do_one_strict_test (session, uri, TRUE, FALSE, SOUP_STATUS_SSL_FAILED);
- debug_printf (1, " sync non-strict with CA list\n");
- do_one_strict_test (session, uri, FALSE, TRUE, SOUP_STATUS_OK);
- debug_printf (1, " sync non-strict without CA list\n");
- do_one_strict_test (session, uri, FALSE, FALSE, SOUP_STATUS_OK);
+ g_object_unref (msg);
soup_test_session_abort_unref (session);
}
@@ -160,7 +147,9 @@ do_session_property_tests (void)
char *ca_file;
SoupSession *session;
- debug_printf (1, "session properties\n");
+ g_test_bug ("673678");
+
+ SOUP_TEST_SKIP_IF_NO_TLS;
session = soup_session_async_new ();
g_signal_connect (session, "notify::ssl-use-system-ca-file",
@@ -175,20 +164,12 @@ do_session_property_tests (void)
"tls-database", &tlsdb,
"ssl-ca-file", &ca_file,
NULL);
- if (use_system) {
- debug_printf (1, " ssl-use-system-ca-file defaults to TRUE?\n");
- errors++;
- }
- if (tlsdb) {
- debug_printf (1, " tls-database set by default?\n");
- errors++;
- g_object_unref (tlsdb);
- }
- if (ca_file) {
- debug_printf (1, " ca-file set by default?\n");
- errors++;
- g_free (ca_file);
- }
+ soup_test_assert (!use_system,
+ "ssl-use-system-ca-file defaults to TRUE");
+ soup_test_assert (tlsdb == NULL,
+ "tls-database set by default");
+ soup_test_assert (ca_file == NULL,
+ "ca-file set by default");
use_system_changed = tlsdb_changed = ca_file_changed = FALSE;
g_object_set (G_OBJECT (session),
@@ -199,68 +180,37 @@ do_session_property_tests (void)
"tls-database", &tlsdb,
"ssl-ca-file", &ca_file,
NULL);
- if (!use_system) {
- debug_printf (1, " setting ssl-use-system-ca-file failed\n");
- errors++;
- }
- if (!tlsdb) {
- debug_printf (1, " setting ssl-use-system-ca-file didn't set tls-database\n");
- errors++;
- } else
- g_object_unref (tlsdb);
- if (ca_file) {
- debug_printf (1, " setting ssl-use-system-ca-file set ssl-ca-file\n");
- errors++;
- g_free (ca_file);
- }
- if (!use_system_changed) {
- debug_printf (1, " setting ssl-use-system-ca-file didn't emit notify::ssl-use-system-ca-file\n");
- errors++;
- }
- if (!tlsdb_changed) {
- debug_printf (1, " setting ssl-use-system-ca-file didn't emit notify::tls-database\n");
- errors++;
- }
- if (ca_file_changed) {
- debug_printf (1, " setting ssl-use-system-ca-file emitted notify::ssl-ca-file\n");
- errors++;
- }
+ soup_test_assert (use_system,
+ "setting ssl-use-system-ca-file failed");
+ g_assert_true (use_system_changed);
+ soup_test_assert (tlsdb != NULL,
+ "setting ssl-use-system-ca-file didn't set tls-database");
+ g_assert_true (tlsdb_changed);
+ g_clear_object (&tlsdb);
+ soup_test_assert (ca_file == NULL,
+ "setting ssl-use-system-ca-file set ssl-ca-file");
+ g_assert_false (ca_file_changed);
use_system_changed = tlsdb_changed = ca_file_changed = FALSE;
g_object_set (G_OBJECT (session),
- "ssl-ca-file", SRCDIR "/test-cert.pem",
+ "ssl-ca-file", g_test_get_filename (G_TEST_DIST, "/test-cert.pem", NULL),
NULL);
g_object_get (G_OBJECT (session),
"ssl-use-system-ca-file", &use_system,
"tls-database", &tlsdb,
"ssl-ca-file", &ca_file,
NULL);
- if (use_system) {
- debug_printf (1, " setting ssl-ca-file left ssl-use-system-ca-file set\n");
- errors++;
- }
- if (!tlsdb) {
- debug_printf (1, " setting ssl-ca-file didn't set tls-database\n");
- errors++;
- } else
- g_object_unref (tlsdb);
- if (!ca_file) {
- debug_printf (1, " setting ssl-ca-file failed\n");
- errors++;
- } else
- g_free (ca_file);
- if (!use_system_changed) {
- debug_printf (1, " setting ssl-ca-file didn't emit notify::ssl-use-system-ca-file\n");
- errors++;
- }
- if (!tlsdb_changed) {
- debug_printf (1, " setting ssl-ca-file didn't emit notify::tls-database\n");
- errors++;
- }
- if (!ca_file_changed) {
- debug_printf (1, " setting ssl-ca-file didn't emit notify::ssl-ca-file\n");
- errors++;
- }
+ soup_test_assert (!use_system,
+ "setting ssl-ca-file left ssl-use-system-ca-file set");
+ g_assert_true (use_system_changed);
+ soup_test_assert (tlsdb != NULL,
+ "setting ssl-ca-file didn't set tls-database");
+ g_assert_true (tlsdb_changed);
+ g_clear_object (&tlsdb);
+ soup_test_assert (ca_file != NULL,
+ "setting ssl-ca-file failed");
+ g_assert_true (ca_file_changed);
+ g_free (ca_file);
use_system_changed = tlsdb_changed = ca_file_changed = FALSE;
g_object_set (G_OBJECT (session),
@@ -271,32 +221,15 @@ do_session_property_tests (void)
"tls-database", &tlsdb,
"ssl-ca-file", &ca_file,
NULL);
- if (use_system) {
- debug_printf (1, " setting tls-database NULL left ssl-use-system-ca-file set\n");
- errors++;
- }
- if (tlsdb) {
- debug_printf (1, " setting tls-database NULL failed\n");
- errors++;
- g_object_unref (tlsdb);
- }
- if (ca_file) {
- debug_printf (1, " setting tls-database didn't clear ssl-ca-file\n");
- errors++;
- g_free (ca_file);
- }
- if (use_system_changed) {
- debug_printf (1, " setting tls-database emitted notify::ssl-use-system-ca-file\n");
- errors++;
- }
- if (!tlsdb_changed) {
- debug_printf (1, " setting tls-database didn't emit notify::tls-database\n");
- errors++;
- }
- if (!ca_file_changed) {
- debug_printf (1, " setting tls-database didn't emit notify::ssl-ca-file\n");
- errors++;
- }
+ soup_test_assert (!use_system,
+ "setting tls-database NULL left ssl-use-system-ca-file set");
+ g_assert_false (use_system_changed);
+ soup_test_assert (tlsdb == NULL,
+ "setting tls-database NULL failed");
+ g_assert_true (tlsdb_changed);
+ soup_test_assert (ca_file == NULL,
+ "setting tls-database didn't clear ssl-ca-file");
+ g_assert_true (ca_file_changed);
soup_test_session_abort_unref (session);
}
@@ -319,7 +252,7 @@ int
main (int argc, char **argv)
{
SoupServer *server;
- char *uri;
+ int i, ret;
test_init (argc, argv, NULL);
@@ -328,15 +261,25 @@ main (int argc, char **argv)
soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
uri = g_strdup_printf ("https://127.0.0.1:%u/",
soup_server_get_port (server));
+ }
- do_session_property_tests ();
- do_strict_tests (uri);
- do_properties_tests (uri);
+ g_test_add_func ("/ssl/session-properties", do_session_property_tests);
+ g_test_add_func ("/ssl/message-properties/async", do_async_properties_tests);
+ g_test_add_func ("/ssl/message-properties/sync", do_sync_properties_tests);
+ for (i = 0; i < G_N_ELEMENTS (strictness_tests); i++) {
+ g_test_add_data_func (strictness_tests[i].name,
+ &strictness_tests[i],
+ do_strictness_test);
+ }
+
+ ret = g_test_run ();
+
+ if (tls_available) {
g_free (uri);
soup_test_server_quit_unref (server);
}
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/streaming-test.c b/tests/streaming-test.c
index 239e0ce8..8d8c02ef 100644
--- a/tests/streaming-test.c
+++ b/tests/streaming-test.c
@@ -7,28 +7,8 @@
#define RESPONSE_CHUNK_SIZE 1024
-char *full_response, *full_response_md5;
-gsize full_response_length;
-
-static void
-get_full_response (void)
-{
- GError *error = NULL;
-
- if (!g_file_get_contents (SRCDIR "/index.txt",
- &full_response,
- &full_response_length,
- &error)) {
- g_printerr ("Could not read index file %s: %s\n",
- SRCDIR "/index.txt", error->message);
- g_error_free (error);
- exit (1);
- }
-
- full_response_md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
- (guchar *)full_response,
- full_response_length);
-}
+SoupBuffer *full_response;
+char *full_response_md5;
static void
write_next_chunk (SoupMessage *msg, gpointer user_data)
@@ -36,12 +16,12 @@ write_next_chunk (SoupMessage *msg, gpointer user_data)
gsize *offset = user_data;
gsize chunk_length;
- chunk_length = MIN (RESPONSE_CHUNK_SIZE, full_response_length - *offset);
+ chunk_length = MIN (RESPONSE_CHUNK_SIZE, full_response->length - *offset);
if (chunk_length > 0) {
debug_printf (2, " writing chunk\n");
soup_message_body_append (msg->response_body,
SOUP_MEMORY_STATIC,
- full_response + *offset,
+ full_response->data + *offset,
chunk_length);
*offset += chunk_length;
} else {
@@ -74,7 +54,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
soup_message_headers_set_encoding (msg->response_headers,
SOUP_ENCODING_CONTENT_LENGTH);
soup_message_headers_set_content_length (msg->response_headers,
- full_response_length);
+ full_response->length);
} else if (!strcmp (path, "/eof")) {
soup_message_headers_set_encoding (msg->response_headers,
SOUP_ENCODING_EOF);
@@ -106,44 +86,49 @@ do_request (SoupSession *session, SoupURI *base_uri, char *path)
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, " message failed: %d %s\n",
- msg->status_code, msg->reason_phrase);
- errors++;
- }
-
- if (msg->response_body->length != full_response_length) {
- debug_printf (1, " received length mismatch: expected %d, got %d\n",
- (int)full_response_length, (int)msg->request_body->length);
- errors++;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_assert_cmpint (msg->response_body->length, ==, full_response->length);
md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
(guchar *)msg->response_body->data,
msg->response_body->length);
- if (strcmp (md5, full_response_md5) != 0) {
- debug_printf (1, " data mismatch: expected %s, got %s\n",
- full_response_md5, md5);
- errors++;
- }
+ g_assert_cmpstr (md5, ==, full_response_md5);
g_free (md5);
g_object_unref (msg);
}
static void
-do_tests (SoupURI *base_uri)
+do_chunked_test (gconstpointer data)
{
+ SoupURI *base_uri = (SoupURI *)data;
SoupSession *session;
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- debug_printf (1, "Chunked encoding\n");
do_request (session, base_uri, "chunked");
- debug_printf (1, "\n");
- debug_printf (1, "Content-Length encoding\n");
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_content_length_test (gconstpointer data)
+{
+ SoupURI *base_uri = (SoupURI *)data;
+ SoupSession *session;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
do_request (session, base_uri, "content-length");
- debug_printf (1, "\n");
- debug_printf (1, "EOF encoding\n");
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_eof_test (gconstpointer data)
+{
+ SoupURI *base_uri = (SoupURI *)data;
+ SoupSession *session;
+
+ g_test_bug ("572153");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
do_request (session, base_uri, "eof");
soup_test_session_abort_unref (session);
}
@@ -155,9 +140,14 @@ main (int argc, char **argv)
SoupServer *server;
guint port;
SoupURI *base_uri;
+ int ret;
test_init (argc, argv, NULL);
- get_full_response ();
+
+ full_response = soup_test_get_index ();
+ full_response_md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
+ (guchar *)full_response->data,
+ full_response->length);
server = soup_test_server_new (FALSE);
soup_server_add_handler (server, NULL,
@@ -168,14 +158,19 @@ main (int argc, char **argv)
base_uri = soup_uri_new ("http://127.0.0.1");
soup_uri_set_port (base_uri, port);
- do_tests (base_uri);
- soup_uri_free (base_uri);
+ g_test_add_data_func ("/streaming/chunked", base_uri, do_chunked_test);
+ g_test_add_data_func ("/streaming/content-length", base_uri, do_content_length_test);
+ g_test_add_data_func ("/streaming/eof", base_uri, do_eof_test);
+
+ ret = g_test_run ();
+
+ soup_uri_free (base_uri);
g_main_loop_unref (loop);
- g_free (full_response);
g_free (full_response_md5);
soup_test_server_quit_unref (server);
test_cleanup ();
- return errors != 0;
+
+ return ret;
}
diff --git a/tests/test-utils.c b/tests/test-utils.c
index f040b738..bc160aea 100644
--- a/tests/test-utils.c
+++ b/tests/test-utils.c
@@ -12,8 +12,9 @@ static gboolean apache_running;
#endif
static SoupLogger *logger;
+static SoupBuffer *index_buffer;
-int debug_level, errors;
+int debug_level;
gboolean expect_warning, tls_available;
static int http_debug_level;
@@ -37,7 +38,7 @@ static GOptionEntry debug_entry[] = {
{ "debug", 'd', G_OPTION_FLAG_NO_ARG,
G_OPTION_ARG_CALLBACK, increment_debug_level,
"Enable (or increase) test-specific debugging", NULL },
- { "http-debug", 'h', G_OPTION_FLAG_NO_ARG,
+ { "http-debug", 'H', G_OPTION_FLAG_NO_ARG,
G_OPTION_ARG_CALLBACK, increment_http_debug_level,
"Enable (or increase) HTTP-level debugging", NULL },
{ NULL }
@@ -54,21 +55,6 @@ quit (int sig)
exit (1);
}
-static void
-test_log_handler (const char *log_domain, GLogLevelFlags log_level,
- const char *message, gpointer user_data)
-{
- if (log_level & (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL)) {
- if (expect_warning) {
- expect_warning = FALSE;
- debug_printf (2, "Got expected warning: %s\n", message);
- return;
- } else
- errors++;
- }
- g_log_default_handler (log_domain, log_level, message, user_data);
-}
-
void
test_init (int argc, char **argv, GOptionEntry *entries)
{
@@ -78,7 +64,8 @@ test_init (int argc, char **argv, GOptionEntry *entries)
GTlsBackend *tls_backend;
setlocale (LC_ALL, "");
- g_type_init ();
+ g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
+ g_setenv ("GIO_USE_PROXY_RESOLVER", "dummy", TRUE);
name = strrchr (argv[0], '/');
if (!name++)
@@ -87,6 +74,10 @@ test_init (int argc, char **argv, GOptionEntry *entries)
name += 3;
g_set_prgname (name);
+ g_test_init (&argc, &argv, NULL);
+ g_test_set_nonfatal_assertions ();
+ g_test_bug_base ("https://bugzilla.gnome.org/");
+
opts = g_option_context_new (NULL);
g_option_context_add_main_entries (opts, debug_entry, NULL);
if (entries)
@@ -104,8 +95,6 @@ test_init (int argc, char **argv, GOptionEntry *entries)
/* Exit cleanly on ^C in case we're valgrinding. */
signal (SIGINT, quit);
- g_log_set_default_handler (test_log_handler, NULL);
-
tls_backend = g_tls_backend_get_default ();
tls_available = g_tls_backend_supports_tls (tls_backend);
}
@@ -120,16 +109,12 @@ test_cleanup (void)
if (logger)
g_object_unref (logger);
+ if (index_buffer)
+ soup_buffer_free (index_buffer);
g_main_context_unref (g_main_context_default ());
debug_printf (1, "\n");
- if (errors) {
- g_print ("%s: %d error(s).%s\n",
- g_get_prgname (), errors,
- debug_level == 0 ? " Run with '-d' for details" : "");
- } else
- g_print ("%s: OK\n", g_get_prgname ());
}
void
@@ -150,30 +135,52 @@ debug_printf (int level, const char *format, ...)
static gboolean
apache_cmd (const char *cmd)
{
- const char *argv[8];
- char *cwd, *conf;
+ GPtrArray *argv;
+ char *server_root, *cwd, *pid_file;
+#ifdef HAVE_APACHE_2_4
+ char *default_runtime_dir;
+#endif
int status;
gboolean ok;
+ server_root = g_test_build_filename (G_TEST_BUILT, "", NULL);
+
cwd = g_get_current_dir ();
- conf = g_build_filename (cwd, "httpd.conf", NULL);
-
- argv[0] = APACHE_HTTPD;
- argv[1] = "-d";
- argv[2] = cwd;
- argv[3] = "-f";
- argv[4] = conf;
- argv[5] = "-k";
- argv[6] = cmd;
- argv[7] = NULL;
-
- ok = g_spawn_sync (cwd, (char **)argv, NULL, 0, NULL, NULL,
+#ifdef HAVE_APACHE_2_4
+ default_runtime_dir = g_strdup_printf ("DefaultRuntimeDir %s", cwd);
+#endif
+ pid_file = g_strdup_printf ("PidFile %s/httpd.pid", cwd);
+
+ argv = g_ptr_array_new ();
+ g_ptr_array_add (argv, APACHE_HTTPD);
+ g_ptr_array_add (argv, "-d");
+ g_ptr_array_add (argv, server_root);
+ g_ptr_array_add (argv, "-f");
+ g_ptr_array_add (argv, "httpd.conf");
+
+#ifdef HAVE_APACHE_2_4
+ g_ptr_array_add (argv, "-c");
+ g_ptr_array_add (argv, default_runtime_dir);
+#endif
+ g_ptr_array_add (argv, "-c");
+ g_ptr_array_add (argv, pid_file);
+
+ g_ptr_array_add (argv, "-k");
+ g_ptr_array_add (argv, (char *)cmd);
+ g_ptr_array_add (argv, NULL);
+
+ ok = g_spawn_sync (cwd, (char **)argv->pdata, NULL, 0, NULL, NULL,
NULL, NULL, &status, NULL);
if (ok)
ok = (status == 0);
+ g_free (server_root);
g_free (cwd);
- g_free (conf);
+ g_free (pid_file);
+#ifdef HAVE_APACHE_2_4
+ g_free (default_runtime_dir);
+#endif
+ g_ptr_array_free (argv, TRUE);
return ok;
}
@@ -181,6 +188,9 @@ apache_cmd (const char *cmd)
void
apache_init (void)
{
+ if (g_getenv ("SOUP_TESTS_IN_MAKE_CHECK"))
+ return;
+
if (!apache_cmd ("start")) {
g_printerr ("Could not start apache\n");
exit (1);
@@ -218,15 +228,18 @@ soup_test_session_new (GType type, ...)
va_list args;
const char *propname;
SoupSession *session;
+ char *cafile;
va_start (args, type);
propname = va_arg (args, const char *);
session = (SoupSession *)g_object_new_valist (type, propname, args);
va_end (args);
+ cafile = g_test_build_filename (G_TEST_DIST, "test-cert.pem", NULL);
g_object_set (G_OBJECT (session),
- SOUP_SESSION_SSL_CA_FILE, SRCDIR "/test-cert.pem",
+ SOUP_SESSION_SSL_CA_FILE, cafile,
NULL);
+ g_free (cafile);
if (http_debug_level && !logger) {
SoupLoggerLogLevel level = MIN ((SoupLoggerLogLevel)http_debug_level, SOUP_LOGGER_LOG_BODY);
@@ -243,16 +256,10 @@ soup_test_session_new (GType type, ...)
void
soup_test_session_abort_unref (SoupSession *session)
{
- g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session);
-
soup_session_abort (session);
- g_object_unref (session);
- if (session) {
- errors++;
- debug_printf (1, "leaked SoupSession!\n");
- g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session);
- }
+ g_assert_cmpint (G_OBJECT (session)->ref_count, ==, 1);
+ g_object_unref (session);
}
static gpointer run_server_thread (gpointer user_data);
@@ -262,14 +269,14 @@ test_server_new (gboolean in_own_thread, gboolean ssl)
{
SoupServer *server;
GMainContext *async_context;
- const char *ssl_cert_file, *ssl_key_file;
+ char *ssl_cert_file, *ssl_key_file;
SoupAddress *addr;
async_context = in_own_thread ? g_main_context_new () : NULL;
if (ssl) {
- ssl_cert_file = SRCDIR "/test-cert.pem";
- ssl_key_file = SRCDIR "/test-key.pem";
+ ssl_cert_file = g_test_build_filename (G_TEST_DIST, "test-cert.pem", NULL);
+ ssl_key_file = g_test_build_filename (G_TEST_DIST, "test-key.pem", NULL);
} else
ssl_cert_file = ssl_key_file = NULL;
@@ -284,6 +291,8 @@ test_server_new (gboolean in_own_thread, gboolean ssl)
g_object_unref (addr);
if (async_context)
g_main_context_unref (async_context);
+ g_free (ssl_cert_file);
+ g_free (ssl_key_file);
if (!server) {
g_printerr ("Unable to create server\n");
@@ -334,9 +343,6 @@ soup_test_server_quit_unref (SoupServer *server)
{
GThread *thread;
- g_object_add_weak_pointer (G_OBJECT (server),
- (gpointer *)&server);
-
thread = g_object_get_data (G_OBJECT (server), "thread");
if (thread) {
soup_add_completion (soup_server_get_async_context (server),
@@ -344,19 +350,14 @@ soup_test_server_quit_unref (SoupServer *server)
g_thread_join (thread);
} else
soup_server_quit (server);
- g_object_unref (server);
- if (server) {
- errors++;
- debug_printf (1, "leaked SoupServer!\n");
- g_object_remove_weak_pointer (G_OBJECT (server),
- (gpointer *)&server);
- }
+ g_assert_cmpint (G_OBJECT (server)->ref_count, ==, 1);
+ g_object_unref (server);
}
typedef struct {
- GMainLoop *loop;
- GAsyncResult *result;
+ GMainLoop *loop;
+ GAsyncResult *result;
} AsyncAsSyncData;
static void
@@ -364,51 +365,269 @@ async_as_sync_callback (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- AsyncAsSyncData *data = user_data;
+ AsyncAsSyncData *data = user_data;
+ GMainContext *context;
+
+ data->result = g_object_ref (result);
+ context = g_main_loop_get_context (data->loop);
+ while (g_main_context_pending (context))
+ g_main_context_iteration (context, FALSE);
+ g_main_loop_quit (data->loop);
+}
+
+typedef struct {
+ SoupRequest *req;
+ GCancellable *cancellable;
+ SoupTestRequestFlags flags;
+} CancelData;
+
+static CancelData *
+create_cancel_data (SoupRequest *req,
+ GCancellable *cancellable,
+ SoupTestRequestFlags flags)
+{
+ CancelData *cancel_data;
+
+ if (!flags)
+ return NULL;
+
+ cancel_data = g_slice_new0 (CancelData);
+ cancel_data->flags = flags;
+ if (flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE && SOUP_IS_REQUEST_HTTP (req))
+ cancel_data->req = g_object_ref (req);
+ else if (flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE)
+ cancel_data->cancellable = g_object_ref (cancellable);
+ return cancel_data;
+}
- data->result = g_object_ref (result);
- g_main_loop_quit (data->loop);
+static void inline
+cancel_message_or_cancellable (CancelData *cancel_data)
+{
+ if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE) {
+ SoupRequest *req = cancel_data->req;
+ SoupMessage *msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+ soup_session_cancel_message (soup_request_get_session (req), msg,
+ SOUP_STATUS_CANCELLED);
+ g_object_unref (msg);
+ g_object_unref (req);
+ } else if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE) {
+ g_cancellable_cancel (cancel_data->cancellable);
+ g_object_unref (cancel_data->cancellable);
+ }
+ g_slice_free (CancelData, cancel_data);
+}
+
+static gboolean
+cancel_request_timeout (gpointer data)
+{
+ cancel_message_or_cancellable ((CancelData *) data);
+ return FALSE;
+}
+
+static gpointer
+cancel_request_thread (gpointer data)
+{
+ g_usleep (100000); /* .1s */
+ cancel_message_or_cancellable ((CancelData *) data);
+ return NULL;
}
GInputStream *
-soup_test_request_send_async_as_sync (SoupRequest *req,
- GCancellable *cancellable,
- GError **error)
+soup_test_request_send (SoupRequest *req,
+ GCancellable *cancellable,
+ guint flags,
+ GError **error)
{
- AsyncAsSyncData data;
- GInputStream *stream;
+ AsyncAsSyncData data;
+ GInputStream *stream;
+ CancelData *cancel_data = create_cancel_data (req, cancellable, flags);
- data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+ if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) {
+ GThread *thread;
- soup_request_send_async (req, cancellable, async_as_sync_callback, &data);
- g_main_loop_run (data.loop);
+ if (cancel_data)
+ thread = g_thread_new ("cancel_request_thread", cancel_request_thread,
+ cancel_data);
+ stream = soup_request_send (req, cancellable, error);
+ if (cancel_data)
+ g_thread_unref (thread);
+ return stream;
+ }
+
+ data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+ if (cancel_data &&
+ (flags & SOUP_TEST_REQUEST_CANCEL_SOON || flags & SOUP_TEST_REQUEST_CANCEL_IMMEDIATE)) {
+ guint interval = flags & SOUP_TEST_REQUEST_CANCEL_SOON ? 100 : 0;
+ g_timeout_add_full (G_PRIORITY_HIGH, interval, cancel_request_timeout, cancel_data, NULL);
+ }
+ if (cancel_data && (flags & SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE))
+ g_cancellable_cancel (cancellable);
+ soup_request_send_async (req, cancellable, async_as_sync_callback, &data);
+ g_main_loop_run (data.loop);
- stream = soup_request_send_finish (req, data.result, error);
+ stream = soup_request_send_finish (req, data.result, error);
- g_main_loop_unref (data.loop);
- g_object_unref (data.result);
+ if (cancel_data && (flags & SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH)) {
+ GMainContext *context;
- return stream;
+ cancel_message_or_cancellable (cancel_data);
+
+ context = g_main_loop_get_context (data.loop);
+ while (g_main_context_pending (context))
+ g_main_context_iteration (context, FALSE);
+ }
+
+ g_main_loop_unref (data.loop);
+ g_object_unref (data.result);
+
+ return stream;
+}
+
+gboolean
+soup_test_request_read_all (SoupRequest *req,
+ GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ char buf[8192];
+ AsyncAsSyncData data;
+ gsize nread;
+
+ if (!SOUP_IS_SESSION_SYNC (soup_request_get_session (req)))
+ data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+
+ do {
+ if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) {
+ nread = g_input_stream_read (stream, buf, sizeof (buf),
+ cancellable, error);
+ } else {
+ g_input_stream_read_async (stream, buf, sizeof (buf),
+ G_PRIORITY_DEFAULT, cancellable,
+ async_as_sync_callback, &data);
+ g_main_loop_run (data.loop);
+ nread = g_input_stream_read_finish (stream, data.result, error);
+ g_object_unref (data.result);
+ }
+ } while (nread > 0);
+
+ if (!SOUP_IS_SESSION_SYNC (soup_request_get_session (req)))
+ g_main_loop_unref (data.loop);
+
+ return nread == 0;
}
gboolean
-soup_test_stream_close_async_as_sync (GInputStream *stream,
- GCancellable *cancellable,
- GError **error)
+soup_test_request_close_stream (SoupRequest *req,
+ GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
{
- AsyncAsSyncData data;
- gboolean ok;
+ AsyncAsSyncData data;
+ gboolean ok;
- data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+ if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req)))
+ return g_input_stream_close (stream, cancellable, error);
- g_input_stream_close_async (stream, G_PRIORITY_DEFAULT, cancellable,
- async_as_sync_callback, &data);
- g_main_loop_run (data.loop);
+ data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
- ok = g_input_stream_close_finish (stream, data.result, error);
+ g_input_stream_close_async (stream, G_PRIORITY_DEFAULT, cancellable,
+ async_as_sync_callback, &data);
+ g_main_loop_run (data.loop);
- g_main_loop_unref (data.loop);
- g_object_unref (data.result);
+ ok = g_input_stream_close_finish (stream, data.result, error);
- return ok;
+ g_main_loop_unref (data.loop);
+ g_object_unref (data.result);
+
+ return ok;
}
+
+void
+soup_test_register_resources (void)
+{
+ static gboolean registered = FALSE;
+ GResource *resource;
+ char *path;
+ GError *error = NULL;
+
+ if (registered)
+ return;
+
+ path = g_test_build_filename (G_TEST_BUILT, "soup-tests.gresource", NULL);
+ resource = g_resource_load (path, &error);
+ if (!resource) {
+ g_printerr ("Could not load resource soup-tests.gresource: %s\n",
+ error->message);
+ exit (1);
+ }
+ g_free (path);
+
+ g_resources_register (resource);
+ g_resource_unref (resource);
+
+ registered = TRUE;
+}
+
+SoupBuffer *
+soup_test_load_resource (const char *name,
+ GError **error)
+{
+ GBytes *bytes;
+ char *path;
+
+ soup_test_register_resources ();
+
+ path = g_build_path ("/", "/org/gnome/libsoup/tests/resources", name, NULL);
+ bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, error);
+ g_free (path);
+
+ if (!bytes)
+ return NULL;
+
+ return soup_buffer_new_with_owner (g_bytes_get_data (bytes, NULL),
+ g_bytes_get_size (bytes),
+ bytes,
+ (GDestroyNotify) g_bytes_unref);
+}
+
+SoupBuffer *
+soup_test_get_index (void)
+{
+ if (!index_buffer) {
+ char *path, *contents;
+ gsize length;
+ GError *error = NULL;
+
+ path = g_test_build_filename (G_TEST_DIST, "index.txt", NULL);
+ if (!g_file_get_contents (path, &contents, &length, &error)) {
+ g_printerr ("Could not read index.txt: %s\n",
+ error->message);
+ exit (1);
+ }
+ g_free (path);
+
+ index_buffer = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length);
+ }
+
+ return index_buffer;
+}
+
+#ifndef G_HAVE_ISO_VARARGS
+void
+soup_test_assert (gboolean expr, const char *fmt, ...)
+{
+ char *message;
+ va_list args;
+
+ if (G_UNLIKELY (!expr)) {
+ va_start (args, fmt);
+ message = g_strdup_vprintf (fmt, args);
+ va_end (args);
+
+ g_assertion_message (G_LOG_DOMAIN,
+ "???", 0, "???"
+ message);
+ g_free (message);
+ }
+}
+#endif
diff --git a/tests/test-utils.h b/tests/test-utils.h
index 9e969038..03637dcf 100644
--- a/tests/test-utils.h
+++ b/tests/test-utils.h
@@ -1,3 +1,5 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -9,22 +11,47 @@
#include "libsoup/soup.h"
#include "libsoup/soup-requester.h"
-#include "libsoup/soup-request-data.h"
-#include "libsoup/soup-request-file.h"
-#include "libsoup/soup-request-http.h"
void test_init (int argc, char **argv, GOptionEntry *entries);
void test_cleanup (void);
-extern int debug_level, errors;
-extern gboolean expect_warning, tls_available;
+extern int debug_level;
+extern gboolean tls_available;
+extern gboolean apache_available;
void debug_printf (int level, const char *format, ...) G_GNUC_PRINTF (2, 3);
+#define SOUP_TEST_SKIP_IF_NO_TLS \
+ G_STMT_START { \
+ if (!tls_available) { \
+ g_test_skip ("TLS is not available"); \
+ return; \
+ } \
+ } G_STMT_END
+
#ifdef HAVE_APACHE
void apache_init (void);
void apache_cleanup (void);
+#define SOUP_TEST_SKIP_IF_NO_APACHE
+#else
+#define apache_init()
+#define apache_cleanup()
+#define SOUP_TEST_SKIP_IF_NO_APACHE \
+ G_STMT_START { \
+ g_test_skip ("apache is not available"); \
+ return; \
+ } G_STMT_END
#endif
+typedef enum {
+ SOUP_TEST_REQUEST_NONE = 0,
+ SOUP_TEST_REQUEST_CANCEL_MESSAGE = (1 << 0),
+ SOUP_TEST_REQUEST_CANCEL_CANCELLABLE = (1 << 1),
+ SOUP_TEST_REQUEST_CANCEL_SOON = (1 << 2),
+ SOUP_TEST_REQUEST_CANCEL_IMMEDIATE = (1 << 3),
+ SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE = (1 << 4),
+ SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH = (1 << 5),
+} SoupTestRequestFlags;
+
SoupSession *soup_test_session_new (GType type, ...);
void soup_test_session_abort_unref (SoupSession *session);
@@ -32,9 +59,68 @@ SoupServer *soup_test_server_new (gboolean in_own_thread);
SoupServer *soup_test_server_new_ssl (gboolean in_own_thread);
void soup_test_server_quit_unref (SoupServer *server);
-GInputStream *soup_test_request_send_async_as_sync (SoupRequest *req,
- GCancellable *cancellable,
- GError **error);
-gboolean soup_test_stream_close_async_as_sync (GInputStream *stream,
- GCancellable *cancellable,
- GError **error);
+GInputStream *soup_test_request_send (SoupRequest *req,
+ GCancellable *cancellable,
+ guint flags,
+ GError **error);
+gboolean soup_test_request_read_all (SoupRequest *req,
+ GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+gboolean soup_test_request_close_stream (SoupRequest *req,
+ GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+
+void soup_test_register_resources (void);
+SoupBuffer *soup_test_load_resource (const char *name,
+ GError **error);
+
+SoupBuffer *soup_test_get_index (void);
+
+#ifdef G_HAVE_ISO_VARARGS
+#define soup_test_assert(expr, ...) \
+G_STMT_START { \
+ char *_message; \
+ if (G_UNLIKELY (!(expr))) { \
+ _message = g_strdup_printf (__VA_ARGS__); \
+ g_assertion_message (G_LOG_DOMAIN, \
+ __FILE__, __LINE__, G_STRFUNC, \
+ _message); \
+ g_free (_message); \
+ } \
+} G_STMT_END
+#else
+void soup_test_assert (gboolean expr, const char *fmt, ...);
+#endif
+
+#define soup_test_assert_message_status(msg, status) \
+G_STMT_START { \
+ SoupMessage *_msg = (msg); \
+ guint _status = (status); \
+ char *_message; \
+ \
+ if (G_UNLIKELY (_msg->status_code != _status)) { \
+ _message = g_strdup_printf ("Unexpected status %d %s (expected %d %s)", \
+ _msg->status_code, _msg->reason_phrase, \
+ _status, soup_status_get_phrase (_status)); \
+ g_assertion_message (G_LOG_DOMAIN, \
+ __FILE__, __LINE__, G_STRFUNC, \
+ _message); \
+ g_free (_message); \
+ } \
+} G_STMT_END
+
+#define soup_assert_cmpmem(s1, l1, s2, l2) \
+G_STMT_START { \
+ int __l1 = l1, __l2 = l2; \
+ gconstpointer __s1 = s1, __s2 = s2; \
+ if (G_UNLIKELY ((__l1) != (__l2))) { \
+ g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
+ "len(" #s1 ") == len(" #s2 ")", __l1, "==", __l2, \
+ 'i'); \
+ } else if (G_UNLIKELY (memcmp (__s1, __s2, __l1) != 0)) { \
+ g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
+ "assertion failed (" #s1 " == " #s2 ")"); \
+ } \
+} G_STMT_END
diff --git a/tests/timeout-test.c b/tests/timeout-test.c
index 2bb91d8a..81fb4331 100644
--- a/tests/timeout-test.c
+++ b/tests/timeout-test.c
@@ -2,31 +2,14 @@
#include "test-utils.h"
+static gboolean slow_https;
+
static void
-do_message_to_session (SoupSession *session, const char *uri,
- const char *comment, guint expected_status)
+message_finished (SoupMessage *msg, gpointer user_data)
{
- SoupMessage *msg;
-
- debug_printf (1, " %s\n", comment);
- msg = soup_message_new ("GET", uri);
- soup_session_send_message (session, msg);
-
- if (msg->status_code != expected_status) {
- debug_printf (1, " FAILED: %d %s (expected %d %s)\n",
- msg->status_code, msg->reason_phrase,
- expected_status,
- soup_status_get_phrase (expected_status));
- errors++;
- }
+ gboolean *finished = user_data;
- if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code) &&
- !soup_message_is_keepalive (msg)) {
- debug_printf (1, " ERROR: message is not keepalive!");
- errors++;
- }
-
- g_object_unref (msg);
+ *finished = TRUE;
}
static void
@@ -39,10 +22,37 @@ request_started_cb (SoupSession *session, SoupMessage *msg,
}
static void
-do_tests_for_session (SoupSession *timeout_session,
- SoupSession *idle_session,
- SoupSession *plain_session,
- char *fast_uri, char *slow_uri)
+do_message_to_session (SoupSession *session, const char *uri,
+ const char *comment, guint expected_status)
+{
+ SoupMessage *msg;
+ gboolean finished = FALSE;
+
+ if (comment)
+ debug_printf (1, " msg %s\n", comment);
+ msg = soup_message_new ("GET", uri);
+
+ g_signal_connect (msg, "finished",
+ G_CALLBACK (message_finished), &finished);
+ soup_session_send_message (session, msg);
+
+ soup_test_assert_message_status (msg, expected_status);
+ if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ g_assert_true (soup_message_is_keepalive (msg));
+ g_assert_true (finished);
+
+ g_signal_handlers_disconnect_by_func (msg,
+ G_CALLBACK (message_finished),
+ &finished);
+ g_object_unref (msg);
+}
+
+static void
+do_msg_tests_for_session (SoupSession *timeout_session,
+ SoupSession *idle_session,
+ SoupSession *plain_session,
+ const char *fast_uri,
+ const char *slow_uri)
{
SoupSocket *ret, *idle_first, *idle_second;
SoupSocket *plain_first, *plain_second;
@@ -51,14 +61,14 @@ do_tests_for_session (SoupSession *timeout_session,
g_signal_connect (idle_session, "request-started",
G_CALLBACK (request_started_cb), &ret);
do_message_to_session (idle_session, fast_uri, "fast to idle", SOUP_STATUS_OK);
- idle_first = ret;
+ idle_first = g_object_ref (ret);
}
if (plain_session) {
g_signal_connect (plain_session, "request-started",
G_CALLBACK (request_started_cb), &ret);
do_message_to_session (plain_session, fast_uri, "fast to plain", SOUP_STATUS_OK);
- plain_first = ret;
+ plain_first = g_object_ref (ret);
}
do_message_to_session (timeout_session, fast_uri, "fast to timeout", SOUP_STATUS_OK);
@@ -71,10 +81,9 @@ do_tests_for_session (SoupSession *timeout_session,
(gpointer)request_started_cb,
&ret);
- if (idle_first == idle_second) {
- debug_printf (1, " ERROR: idle_session did not close first connection\n");
- errors++;
- }
+ soup_test_assert (idle_first != idle_second,
+ "idle_session did not close first connection");
+ g_object_unref (idle_first);
}
if (plain_session) {
@@ -84,46 +93,174 @@ do_tests_for_session (SoupSession *timeout_session,
(gpointer)request_started_cb,
&ret);
- if (plain_first != plain_second) {
- debug_printf (1, " ERROR: plain_session closed connection\n");
- errors++;
- }
+ soup_test_assert (plain_first == plain_second,
+ "plain_session closed connection");
+ g_object_unref (plain_first);
+ }
+}
+
+static void
+do_request_to_session (SoupSession *session, const char *uri,
+ const char *comment, gboolean expect_timeout)
+{
+ SoupRequest *req;
+ SoupMessage *msg;
+ GInputStream *stream;
+ GError *error = NULL;
+ gboolean finished = FALSE;
+
+ debug_printf (1, " req %s\n", comment);
+ req = soup_session_request (session, uri, NULL);
+ msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+
+ g_signal_connect (msg, "finished",
+ G_CALLBACK (message_finished), &finished);
+ stream = soup_test_request_send (req, NULL, 0, &error);
+
+ if (expect_timeout)
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT);
+ else
+ g_assert_no_error (error);
+ g_clear_error (&error);
+
+ if (stream) {
+ soup_test_request_read_all (req, stream, NULL, &error);
+ g_assert_no_error (error);
+ }
+
+ if (stream) {
+ soup_test_request_close_stream (req, stream, NULL, &error);
+ g_assert_no_error (error);
+ g_object_unref (stream);
}
+
+ if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ g_assert_true (soup_message_is_keepalive (msg));
+ g_assert_true (finished);
+
+ g_signal_handlers_disconnect_by_func (msg,
+ G_CALLBACK (message_finished),
+ &finished);
+ g_object_unref (msg);
+ g_object_unref (req);
}
static void
-do_timeout_tests (char *fast_uri, char *slow_uri)
+do_req_tests_for_session (SoupSession *timeout_session,
+ SoupSession *idle_session,
+ SoupSession *plain_session,
+ const char *fast_uri,
+ const char *slow_uri)
+{
+ SoupSocket *ret, *idle_first, *idle_second;
+ SoupSocket *plain_first, *plain_second;
+
+ if (idle_session) {
+ g_signal_connect (idle_session, "request-started",
+ G_CALLBACK (request_started_cb), &ret);
+ do_request_to_session (idle_session, fast_uri, "fast to idle", FALSE);
+ idle_first = g_object_ref (ret);
+ }
+
+ if (plain_session) {
+ g_signal_connect (plain_session, "request-started",
+ G_CALLBACK (request_started_cb), &ret);
+ do_request_to_session (plain_session, fast_uri, "fast to plain", FALSE);
+ plain_first = g_object_ref (ret);
+ }
+
+ do_request_to_session (timeout_session, fast_uri, "fast to timeout", FALSE);
+ do_request_to_session (timeout_session, slow_uri, "slow to timeout", TRUE);
+
+ if (idle_session) {
+ do_request_to_session (idle_session, fast_uri, "fast to idle", FALSE);
+ idle_second = ret;
+ g_signal_handlers_disconnect_by_func (idle_session,
+ (gpointer)request_started_cb,
+ &ret);
+
+ soup_test_assert (idle_first != idle_second,
+ "idle_session did not close first connection");
+ g_object_unref (idle_first);
+ }
+
+ if (plain_session) {
+ do_request_to_session (plain_session, fast_uri, "fast to plain", FALSE);
+ plain_second = ret;
+ g_signal_handlers_disconnect_by_func (plain_session,
+ (gpointer)request_started_cb,
+ &ret);
+
+ soup_test_assert (plain_first == plain_second,
+ "plain_session closed connection");
+ g_object_unref (plain_first);
+ }
+}
+
+static void
+do_async_timeout_tests (gconstpointer data)
{
SoupSession *timeout_session, *idle_session, *plain_session;
+ const char *fast_uri = data;
+ const char *slow_uri = g_build_path ("/", fast_uri, "slow", NULL);
+ gboolean extra_slow;
+
+ if (g_str_has_prefix (fast_uri, "https")) {
+ SOUP_TEST_SKIP_IF_NO_TLS;
+
+ extra_slow = slow_https;
+ } else
+ extra_slow = FALSE;
- debug_printf (1, " async\n");
timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_TIMEOUT, 1,
- NULL);
+ SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
idle_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_IDLE_TIMEOUT, 1,
+ SOUP_SESSION_IDLE_TIMEOUT, extra_slow ? 2 : 1,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
/* The "plain" session also has an idle timeout, but it's longer
* than the test takes, so for our purposes it should behave like
* it has no timeout.
*/
plain_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
- SOUP_SESSION_IDLE_TIMEOUT, 2,
+ SOUP_SESSION_IDLE_TIMEOUT, 20,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
- do_tests_for_session (timeout_session, idle_session, plain_session,
- fast_uri, slow_uri);
+
+ do_msg_tests_for_session (timeout_session, idle_session, plain_session,
+ fast_uri, slow_uri);
+ do_req_tests_for_session (timeout_session, idle_session, plain_session,
+ fast_uri, slow_uri);
soup_test_session_abort_unref (timeout_session);
soup_test_session_abort_unref (idle_session);
soup_test_session_abort_unref (plain_session);
+}
+
+static void
+do_sync_timeout_tests (gconstpointer data)
+{
+ SoupSession *timeout_session, *plain_session;
+ const char *fast_uri = data;
+ const char *slow_uri = g_build_path ("/", fast_uri, "slow", NULL);
+ gboolean extra_slow;
+
+ if (g_str_has_prefix (fast_uri, "https")) {
+ SOUP_TEST_SKIP_IF_NO_TLS;
+
+ extra_slow = slow_https;
+ } else
+ extra_slow = FALSE;
- debug_printf (1, " sync\n");
timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
- SOUP_SESSION_TIMEOUT, 1,
+ SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1,
NULL);
/* SOUP_SESSION_TIMEOUT doesn't work with sync sessions */
plain_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
NULL);
- do_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri);
+ do_msg_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri);
+ do_req_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri);
soup_test_session_abort_unref (timeout_session);
soup_test_session_abort_unref (plain_session);
}
@@ -154,44 +291,63 @@ server_handler (SoupServer *server,
soup_server_pause_message (server, msg);
g_object_set_data (G_OBJECT (msg), "server", server);
soup_add_timeout (soup_server_get_async_context (server),
- 1100, timeout_finish_message, msg);
+ 4000, timeout_finish_message, msg);
}
}
int
main (int argc, char **argv)
{
- SoupServer *server;
- char *fast_uri, *slow_uri;
+ SoupServer *server, *https_server = NULL;
+ char *uri, *https_uri = NULL;
+ int ret;
test_init (argc, argv, NULL);
- debug_printf (1, "http\n");
server = soup_test_server_new (TRUE);
soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
- fast_uri = g_strdup_printf ("http://127.0.0.1:%u/",
- soup_server_get_port (server));
- slow_uri = g_strdup_printf ("http://127.0.0.1:%u/slow",
- soup_server_get_port (server));
- do_timeout_tests (fast_uri, slow_uri);
- g_free (fast_uri);
- g_free (slow_uri);
- soup_test_server_quit_unref (server);
+ uri = g_strdup_printf ("http://127.0.0.1:%u/",
+ soup_server_get_port (server));
if (tls_available) {
- debug_printf (1, "\nhttps\n");
- server = soup_test_server_new_ssl (TRUE);
- soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
- fast_uri = g_strdup_printf ("https://127.0.0.1:%u/",
- soup_server_get_port (server));
- slow_uri = g_strdup_printf ("https://127.0.0.1:%u/slow",
- soup_server_get_port (server));
- do_timeout_tests (fast_uri, slow_uri);
- g_free (fast_uri);
- g_free (slow_uri);
- soup_test_server_quit_unref (server);
- }
+ SoupSession *test_session;
+ gint64 start, end;
+
+ https_server = soup_test_server_new_ssl (TRUE);
+ soup_server_add_handler (https_server, NULL, server_handler, NULL, NULL);
+ https_uri = g_strdup_printf ("https://127.0.0.1:%u/",
+ soup_server_get_port (https_server));
+
+ /* The 1-second timeouts are too fast for some machines... */
+ test_session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ start = g_get_monotonic_time ();
+ do_message_to_session (test_session, uri, NULL, SOUP_STATUS_OK);
+ end = g_get_monotonic_time ();
+ soup_test_session_abort_unref (test_session);
+ debug_printf (2, " (https request took %0.3fs)\n", (end - start) / 1000000.0);
+ if (end - start > 750000) {
+ debug_printf (1, " (using extra-slow mode)\n\n");
+ slow_https = TRUE;
+ } else {
+ debug_printf (2, "\n");
+ slow_https = FALSE;
+ }
+ } else
+ https_uri = g_strdup ("https://fail.");
+
+ g_test_add_data_func ("/timeout/http/async", uri, do_async_timeout_tests);
+ g_test_add_data_func ("/timeout/http/sync", uri, do_sync_timeout_tests);
+ g_test_add_data_func ("/timeout/https/async", https_uri, do_async_timeout_tests);
+ g_test_add_data_func ("/timeout/https/sync", https_uri, do_sync_timeout_tests);
+
+ ret = g_test_run ();
+
+ g_free (uri);
+ g_free (https_uri);
+ soup_test_server_quit_unref (server);
+ if (https_server)
+ soup_test_server_quit_unref (https_server);
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/tld-test.c b/tests/tld-test.c
index 5f66c686..4fad8625 100644
--- a/tests/tld-test.c
+++ b/tests/tld-test.c
@@ -7,124 +7,186 @@
/* From http://publicsuffix.org/list/test.txt */
static struct {
- const char *hostname;
- const char *result;
+ const char *hostname;
+ const char *result;
+ SoupTLDError error;
} tld_tests[] = {
- /* NULL input. Not checked here because the API requires a valid hostname. */
- /* { NULL, NULL }, */
- /* Mixed case. Not checked because the API requires a valid hostname. */
- /* { "COM", NULL }, */
- /* { "example.COM", "example.com" }, */
- /* { "WwW.example.COM", "example.com" }, */
- /* Leading dot. */
- { ".com", NULL },
- { ".example", NULL },
- { ".example.com", NULL },
- { ".example.example", NULL },
- /* Unlisted TLD.*/
- { "example", NULL },
- { "example.example", NULL },
- { "b.example.example", NULL },
- { "a.b.example.example", NULL },
- /* Listed, but non-Internet, TLD. */
- { "local", NULL },
- { "example.local", NULL },
- { "b.example.local", NULL },
- { "a.b.example.local", NULL },
- /* TLD with only 1 rule. */
- { "biz", NULL },
- { "domain.biz", "domain.biz" },
- { "b.domain.biz", "domain.biz" },
- { "a.b.domain.biz", "domain.biz" },
- /* TLD with some 2-level rules. */
- { "com", NULL },
- { "example.com", "example.com" },
- { "b.example.com", "example.com" },
- { "a.b.example.com", "example.com" },
- { "uk.com", NULL },
- { "example.uk.com", "example.uk.com" },
- { "b.example.uk.com", "example.uk.com" },
- { "a.b.example.uk.com", "example.uk.com" },
- { "test.ac", "test.ac" },
- /* TLD with only 1 (wildcard) rule. */
- { "cy", NULL },
- { "c.cy", NULL },
- { "b.c.cy", "b.c.cy" },
- { "a.b.c.cy", "b.c.cy" },
- /* More complex TLD. */
- { "jp", NULL },
- { "test.jp", "test.jp" },
- { "www.test.jp", "test.jp" },
- { "ac.jp", NULL },
- { "test.ac.jp", "test.ac.jp" },
- { "www.test.ac.jp", "test.ac.jp" },
- { "kyoto.jp", NULL },
- { "c.kyoto.jp", NULL },
- { "b.c.kyoto.jp", "b.c.kyoto.jp" },
- { "a.b.c.kyoto.jp", "b.c.kyoto.jp" },
- { "pref.kyoto.jp", "pref.kyoto.jp" }, /* Exception rule. */
- { "www.pref.kyoto.jp", "pref.kyoto.jp" }, /* Exception rule. */
- { "city.kyoto.jp", "city.kyoto.jp" }, /* Exception rule. */
- { "www.city.kyoto.jp", "city.kyoto.jp" }, /* Exception rule. */
- /* TLD with a wildcard rule and exceptions. */
- { "om", NULL },
- { "test.om", NULL },
- { "b.test.om", "b.test.om" },
- { "a.b.test.om", "b.test.om" },
- { "songfest.om", "songfest.om" },
- { "www.songfest.om", "songfest.om" },
- /* US K12. */
- { "us", NULL },
- { "test.us", "test.us" },
- { "www.test.us", "test.us" },
- { "ak.us", NULL },
- { "test.ak.us", "test.ak.us" },
- { "www.test.ak.us", "test.ak.us" },
- { "k12.ak.us", NULL },
- { "test.k12.ak.us", "test.k12.ak.us" },
- { "www.test.k12.ak.us", "test.k12.ak.us" },
- /* This is not in http://publicsuffix.org/list/test.txt but we want to check it anyway. */
- { "co.uk", NULL },
- /* The original list does not include non-ASCII tests. Let's add a couple. */
- { "公司.cn", NULL },
- { "a.b.åfjord.no", "b.åfjord.no" }
+ /* NULL input. Not checked here because the API requires a valid hostname. */
+ /* { NULL, NULL, -1 }, */
+ /* Mixed case. Not checked because the API requires a valid hostname. */
+ /* { "COM", NULL, -1 }, */
+ /* { "example.COM", "example.com", -1 }, */
+ /* { "WwW.example.COM", "example.com", -1 }, */
+ /* Leading dot. */
+ { ".com", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME },
+ { ".example", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME },
+ { ".example.com", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME },
+ { ".example.example", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME },
+ /* TLD with only 1 rule. */
+ { "biz", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "domain.biz", "domain.biz", -1 },
+ { "b.domain.biz", "domain.biz", -1 },
+ { "a.b.domain.biz", "domain.biz", -1 },
+ /* TLD with some 2-level rules. */
+ { "com", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "example.com", "example.com", -1 },
+ { "b.example.com", "example.com", -1 },
+ { "a.b.example.com", "example.com", -1 },
+ { "uk.com", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "example.uk.com", "example.uk.com", -1 },
+ { "b.example.uk.com", "example.uk.com", -1 },
+ { "a.b.example.uk.com", "example.uk.com", -1 },
+ { "test.ac", "test.ac", -1 },
+ /* TLD with only 1 (wildcard) rule. */
+ { "cy", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "c.cy", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "b.c.cy", "b.c.cy", -1 },
+ { "a.b.c.cy", "b.c.cy", -1 },
+ /* More complex TLD. */
+ { "jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "test.jp", "test.jp", -1 },
+ { "www.test.jp", "test.jp", -1 },
+ { "ac.jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "test.ac.jp", "test.ac.jp", -1 },
+ { "www.test.ac.jp", "test.ac.jp", -1 },
+ { "kyoto.jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "minami.kyoto.jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "b.minami.kyoto.jp", "b.minami.kyoto.jp", -1 },
+ { "a.b.minami.kyoto.jp", "b.minami.kyoto.jp", -1 },
+ { "pref.kyoto.jp", "pref.kyoto.jp", -1 },
+ { "www.pref.kyoto.jp", "pref.kyoto.jp", -1 },
+ { "city.kyoto.jp", "city.kyoto.jp", -1 },
+ { "www.city.kyoto.jp", "city.kyoto.jp", -1 },
+ /* TLD with a wildcard rule and exceptions. */
+ { "ck", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "test.ck", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "b.test.ck", "b.test.ck", -1 },
+ { "a.b.test.ck", "b.test.ck", -1 },
+ { "www.ck", "www.ck", -1 },
+ { "www.www.ck", "www.ck", -1 },
+ /* US K12. */
+ { "us", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "test.us", "test.us", -1 },
+ { "www.test.us", "test.us", -1 },
+ { "ak.us", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "test.ak.us", "test.ak.us", -1 },
+ { "www.test.ak.us", "test.ak.us", -1 },
+ { "k12.ak.us", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "test.k12.ak.us", "test.k12.ak.us", -1 },
+ { "www.test.k12.ak.us", "test.k12.ak.us", -1 },
+ /* IDN labels. */
+ { "食狮.com.cn", "食狮.com.cn", -1 },
+ { "食狮.公司.cn", "食狮.公司.cn", -1 },
+ { "www.食狮.公司.cn", "食狮.公司.cn", -1 },
+ { "shishi.公司.cn", "shishi.公司.cn", -1 },
+ { "公司.cn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "食狮.中国", "食狮.中国", -1 },
+ { "www.食狮.中国", "食狮.中国", -1 },
+ { "shishi.中国", "shishi.中国", -1 },
+ { "中国", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ /* Same as above, but punycoded. */
+ { "xn--85x722f.com.cn", "xn--85x722f.com.cn", -1 },
+ { "xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn", -1 },
+ { "www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn", -1 },
+ { "shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn", -1 },
+ { "xn--55qx5d.cn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s", -1 },
+ { "www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s", -1 },
+ { "shishi.xn--fiqs8s", "shishi.xn--fiqs8s", -1 },
+ { "xn--fiqs8s", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ /* End of publicsuffix.org tests */
+
+ /* Let's just double-check this one... */
+ { "co.uk", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "test.co.uk", "test.co.uk", -1 },
+ { "www.test.co.uk", "test.co.uk", -1 },
+
+ /* Two levels of non-ASCII */
+ { "våler.østfold.no", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "test.våler.østfold.no", "test.våler.østfold.no", -1 },
+ { "www.test.våler.østfold.no", "test.våler.østfold.no", -1 },
+ { "xn--vler-qoa.xn--stfold-9xa.no", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no", -1 },
+ { "www.test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no", -1 },
+},
+
+/* Non Internet TLDs have NULL as expected result
+ */
+non_inet_tld_tests[] = {
+ /* Unlisted TLD.*/
+ { "example", NULL },
+ { "example.example", NULL },
+ { "b.example.example", NULL },
+ { "a.b.example.example", NULL },
+ /* Listed, but non-Internet, TLD. */
+ { "local", NULL },
+ { "example.local", NULL },
+ { "b.example.local", NULL },
+ { "a.b.example.local", NULL }
};
+static void
+do_inet_tests (void)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (tld_tests); i++) {
+ GError *error = NULL;
+ gboolean is_public;
+ const char *base_domain;
+
+ debug_printf (1, "Testing %s\n", tld_tests[i].hostname);
+
+ is_public = soup_tld_domain_is_public_suffix (tld_tests[i].hostname);
+ base_domain = soup_tld_get_base_domain (tld_tests[i].hostname, &error);
+
+ if (base_domain) {
+ g_assert_no_error (error);
+ g_assert_false (is_public);
+ g_assert_cmpstr (base_domain, ==, tld_tests[i].result);
+ } else {
+ g_assert_null (tld_tests[i].result);
+ g_assert_error (error, SOUP_TLD_ERROR, tld_tests[i].error);
+ g_clear_error (&error);
+ }
+ }
+}
+
+static void
+do_non_inet_tests (void)
+{
+ int i;
+
+ g_test_bug ("679230");
+ g_test_bug ("681085");
+
+ for (i = 0; i < G_N_ELEMENTS (non_inet_tld_tests); i++) {
+ gboolean is_public;
+ const char *base_domain;
+
+ debug_printf (1, "Testing %s\n", non_inet_tld_tests[i].hostname);
+
+ is_public = soup_tld_domain_is_public_suffix (non_inet_tld_tests[i].hostname);
+ base_domain = soup_tld_get_base_domain (non_inet_tld_tests[i].hostname, NULL);
+
+ g_assert_false (is_public);
+ g_assert_null (base_domain);
+ }
+}
+
int
main (int argc, char **argv)
{
- int i;
+ int ret;
test_init (argc, argv, NULL);
- errors = 0;
- for (i = 0; i < G_N_ELEMENTS (tld_tests); ++i) {
- gboolean is_public = soup_tld_domain_is_public_suffix (tld_tests[i].hostname);
- const char *base_domain = soup_tld_get_base_domain (tld_tests[i].hostname, NULL);
-
- debug_printf (1, "Testing %s: ", tld_tests[i].hostname);
- if (tld_tests[i].result) {
- /* Public domains have NULL expected results. */
- if (is_public || g_strcmp0 (tld_tests[i].result, base_domain)) {
- debug_printf (1, "ERROR: %s got %s (%s expected)\n",
- tld_tests[i].hostname, base_domain, tld_tests[i].result);
- ++errors;
- } else
- debug_printf (1, "OK\n");
- } else {
- /* If there is no expected result then either the domain is public or
- * the hostname invalid (for example starts with a leading dot).
- */
- if (!is_public && base_domain) {
- debug_printf (1, "ERROR: public domain %s got %s (none expected)\n",
- tld_tests[i].hostname, base_domain);
- ++errors;
- } else
- debug_printf (1, "OK\n");
- }
- }
+ g_test_add_func ("/tld/inet", do_inet_tests);
+ g_test_add_func ("/tld/non-inet", do_non_inet_tests);
+
+ ret = g_test_run ();
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c
index 08274a28..d56b655f 100644
--- a/tests/uri-parsing.c
+++ b/tests/uri-parsing.c
@@ -3,123 +3,155 @@
#include "test-utils.h"
static struct {
- const char *uri_string, *result;
+ const char *uri_string, *result, *bugref;
const SoupURI bits;
} abs_tests[] = {
- { "foo:", "foo:",
+ { "foo:", "foo:", NULL,
{ "foo", NULL, NULL, NULL, 0, "", NULL, NULL } },
- { "file:/dev/null", "file:/dev/null",
+ { "file:/dev/null", "file:/dev/null", NULL,
{ "file", NULL, NULL, NULL, 0, "/dev/null", NULL, NULL } },
- { "file:///dev/null", "file:///dev/null",
+ { "file:///dev/null", "file:///dev/null", NULL,
{ "file", NULL, NULL, "", 0, "/dev/null", NULL, NULL } },
- { "ftp://user@host/path", "ftp://user@host/path",
+ { "ftp://user@host/path", "ftp://user@host/path", NULL,
{ "ftp", "user", NULL, "host", 21, "/path", NULL, NULL } },
- { "ftp://user@host:9999/path", "ftp://user@host:9999/path",
+ { "ftp://user@host:9999/path", "ftp://user@host:9999/path", NULL,
{ "ftp", "user", NULL, "host", 9999, "/path", NULL, NULL } },
- { "ftp://user:password@host/path", "ftp://user@host/path",
+ { "ftp://user:password@host/path", "ftp://user@host/path", NULL,
{ "ftp", "user", "password", "host", 21, "/path", NULL, NULL } },
- { "ftp://user:password@host:9999/path", "ftp://user@host:9999/path",
+ { "ftp://user:password@host:9999/path", "ftp://user@host:9999/path", NULL,
{ "ftp", "user", "password", "host", 9999, "/path", NULL, NULL } },
- { "ftp://user:password@host", "ftp://user@host",
+ { "ftp://user:password@host", "ftp://user@host", NULL,
{ "ftp", "user", "password", "host", 21, "", NULL, NULL } },
- { "http://us%65r@host", "http://user@host/",
+ { "http://us%65r@host", "http://user@host/", NULL,
{ "http", "user", NULL, "host", 80, "/", NULL, NULL } },
- { "http://us%40r@host", "http://us%40r@host/",
+ { "http://us%40r@host", "http://us%40r@host/", NULL,
{ "http", "us\x40r", NULL, "host", 80, "/", NULL, NULL } },
- { "http://us%3ar@host", "http://us%3Ar@host/",
+ { "http://us%3ar@host", "http://us%3Ar@host/", NULL,
{ "http", "us\x3ar", NULL, "host", 80, "/", NULL, NULL } },
- { "http://us%2fr@host", "http://us%2Fr@host/",
+ { "http://us%2fr@host", "http://us%2Fr@host/", NULL,
{ "http", "us\x2fr", NULL, "host", 80, "/", NULL, NULL } },
- { "http://us%3fr@host", "http://us%3Fr@host/",
+ { "http://us%3fr@host", "http://us%3Fr@host/", NULL,
{ "http", "us\x3fr", NULL, "host", 80, "/", NULL, NULL } },
- { "http://host?query", "http://host/?query",
+ { "http://host?query", "http://host/?query", NULL,
{ "http", NULL, NULL, "host", 80, "/", "query", NULL } },
{ "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=value",
- "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=value",
+ "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=value", NULL,
{ "http", NULL, NULL, "host", 80, "/path", "query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=value", NULL } },
{ "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F",
- "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F",
+ "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", NULL,
{ "http", NULL, NULL, "control-chars", 80, "/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", NULL, NULL } },
{ "http://space/%20",
- "http://space/%20",
+ "http://space/%20", NULL,
{ "http", NULL, NULL, "space", 80, "/%20", NULL, NULL } },
{ "http://delims/%3C%3E%23%25%22",
- "http://delims/%3C%3E%23%25%22",
+ "http://delims/%3C%3E%23%25%22", NULL,
{ "http", NULL, NULL, "delims", 80, "/%3C%3E%23%25%22", NULL, NULL } },
{ "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60",
- "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60",
+ "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", NULL,
{ "http", NULL, NULL, "unwise-chars", 80, "/%7B%7D%7C%5C%5E%5B%5D%60", NULL, NULL } },
/* From RFC 2732 */
{ "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html",
- "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html",
+ "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html", NULL,
{ "http", NULL, NULL, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80, "/index.html", NULL, NULL } },
{ "http://[1080:0:0:0:8:800:200C:417A]/index.html",
- "http://[1080:0:0:0:8:800:200C:417A]/index.html",
+ "http://[1080:0:0:0:8:800:200C:417A]/index.html", NULL,
{ "http", NULL, NULL, "1080:0:0:0:8:800:200C:417A", 80, "/index.html", NULL, NULL } },
{ "http://[3ffe:2a00:100:7031::1]",
- "http://[3ffe:2a00:100:7031::1]/",
+ "http://[3ffe:2a00:100:7031::1]/", NULL,
{ "http", NULL, NULL, "3ffe:2a00:100:7031::1", 80, "/", NULL, NULL } },
{ "http://[1080::8:800:200C:417A]/foo",
- "http://[1080::8:800:200C:417A]/foo",
+ "http://[1080::8:800:200C:417A]/foo", NULL,
{ "http", NULL, NULL, "1080::8:800:200C:417A", 80, "/foo", NULL, NULL } },
{ "http://[::192.9.5.5]/ipng",
- "http://[::192.9.5.5]/ipng",
+ "http://[::192.9.5.5]/ipng", NULL,
{ "http", NULL, NULL, "::192.9.5.5", 80, "/ipng", NULL, NULL } },
{ "http://[::FFFF:129.144.52.38]:80/index.html",
- "http://[::FFFF:129.144.52.38]/index.html",
+ "http://[::FFFF:129.144.52.38]/index.html", NULL,
{ "http", NULL, NULL, "::FFFF:129.144.52.38", 80, "/index.html", NULL, NULL } },
{ "http://[2010:836B:4179::836B:4179]",
- "http://[2010:836B:4179::836B:4179]/",
+ "http://[2010:836B:4179::836B:4179]/", NULL,
{ "http", NULL, NULL, "2010:836B:4179::836B:4179", 80, "/", NULL, NULL } },
/* Try to recover certain kinds of invalid URIs */
{ "http://host/path with spaces",
- "http://host/path%20with%20spaces",
+ "http://host/path%20with%20spaces", "566530",
{ "http", NULL, NULL, "host", 80, "/path%20with%20spaces", NULL, NULL } },
- { " http://host/path", "http://host/path",
+ { " http://host/path", "http://host/path", "594405",
{ "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
- { "http://host/path ", "http://host/path",
+ { "http://host/path ", "http://host/path", "594405",
{ "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
- { "http://host ", "http://host/",
+ { "http://host ", "http://host/", "594405",
{ "http", NULL, NULL, "host", 80, "/", NULL, NULL } },
- { "http://host:999 ", "http://host:999/",
+ { "http://host:999 ", "http://host:999/", "594405",
{ "http", NULL, NULL, "host", 999, "/", NULL, NULL } },
- { "http://host/pa\nth", "http://host/path",
+ { "http://host/pa\nth", "http://host/path", "594405",
{ "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
- { "http:\r\n//host/path", "http://host/path",
+ { "http:\r\n//host/path", "http://host/path", "594405",
{ "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
- { "http://\thost/path", "http://host/path",
+ { "http://\thost/path", "http://host/path", "594405",
{ "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
- /* Bug 594405; 0-length is different from not-present */
- { "http://host/path?", "http://host/path?",
+ /* 0-length is different from not-present */
+ { "http://host/path?", "http://host/path?", "594405",
{ "http", NULL, NULL, "host", 80, "/path", "", NULL } },
- { "http://host/path#", "http://host/path#",
+ { "http://host/path#", "http://host/path#", "594405",
{ "http", NULL, NULL, "host", 80, "/path", NULL, "" } },
- /* Bug 590524; ignore badly-%-encoding */
- { "http://host/path%", "http://host/path%",
+ /* ignore bad %-encoding */
+ { "http://host/path%", "http://host/path%", "590524",
{ "http", NULL, NULL, "host", 80, "/path%", NULL, NULL } },
- { "http://h%ost/path", "http://h%25ost/path",
+ { "http://h%ost/path", "http://h%25ost/path", "590524",
{ "http", NULL, NULL, "h%ost", 80, "/path", NULL, NULL } },
- { "http://host/path%%", "http://host/path%%",
+ { "http://host/path%%", "http://host/path%%", "590524",
{ "http", NULL, NULL, "host", 80, "/path%%", NULL, NULL } },
- { "http://host/path%%%", "http://host/path%%%",
+ { "http://host/path%%%", "http://host/path%%%", "590524",
{ "http", NULL, NULL, "host", 80, "/path%%%", NULL, NULL } },
- { "http://host/path%/x/", "http://host/path%/x/",
+ { "http://host/path%/x/", "http://host/path%/x/", "590524",
{ "http", NULL, NULL, "host", 80, "/path%/x/", NULL, NULL } },
- { "http://host/path%0x/", "http://host/path%0x/",
+ { "http://host/path%0x/", "http://host/path%0x/", "590524",
{ "http", NULL, NULL, "host", 80, "/path%0x/", NULL, NULL } },
- { "http://host/path%ax", "http://host/path%ax",
+ { "http://host/path%ax", "http://host/path%ax", "590524",
{ "http", NULL, NULL, "host", 80, "/path%ax", NULL, NULL } },
- /* Bug 662806; %-encode non-ASCII characters */
- { "http://host/p\xc3\xa4th/", "http://host/p%C3%A4th/",
+ /* %-encode non-ASCII characters */
+ { "http://host/p\xc3\xa4th/", "http://host/p%C3%A4th/", "662806",
{ "http", NULL, NULL, "host", 80, "/p%C3%A4th/", NULL, NULL } },
- { "HTTP:////////////////", "http:////////////////",
+ { "HTTP:////////////////", "http:////////////////", "667637",
{ "http", NULL, NULL, "", 80, "//////////////", NULL, NULL } },
+
+ { "http://@host", "http://@host/", NULL,
+ { "http", "", NULL, "host", 80, "/", NULL, NULL } },
+ { "http://:@host", "http://@host/", NULL,
+ { "http", "", "", "host", 80, "/", NULL, NULL } },
+
+ { "http://host/keep%00nuls", "http://host/keep%00nuls", NULL,
+ { "http", NULL, NULL, "host", 80, "/keep%00nuls", NULL, NULL } },
+
+ /* scheme parsing */
+ { "foo0://host/path", "foo0://host/path", "703776",
+ { "foo0", NULL, NULL, "host", 0, "/path", NULL, NULL } },
+ { "f0.o://host/path", "f0.o://host/path", "703776",
+ { "f0.o", NULL, NULL, "host", 0, "/path", NULL, NULL } },
+ { "http++://host/path", "http++://host/path", "703776",
+ { "http++", NULL, NULL, "host", 0, "/path", NULL, NULL } },
+ { "http-ish://host/path", "http-ish://host/path", "703776",
+ { "http-ish", NULL, NULL, "host", 0, "/path", NULL, NULL } },
+ { "99http://host/path", NULL, "703776",
+ { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } },
+ { ".http://host/path", NULL, "703776",
+ { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } },
+ { "+http://host/path", NULL, "703776",
+ { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } },
+
+ /* IPv6 scope ID parsing (both correct and incorrect) */
+ { "http://[fe80::dead:beef%em1]/", "http://[fe80::dead:beef%25em1]/", NULL,
+ { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } },
+ { "http://[fe80::dead:beef%25em1]/", "http://[fe80::dead:beef%25em1]/", NULL,
+ { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } },
+ { "http://[fe80::dead:beef%10]/", "http://[fe80::dead:beef%2510]/", NULL,
+ { "http", NULL, NULL, "fe80::dead:beef%10", 80, "/", NULL, NULL } }
};
static int num_abs_tests = G_N_ELEMENTS(abs_tests);
@@ -223,50 +255,18 @@ static struct {
static int num_rel_tests = G_N_ELEMENTS(rel_tests);
static struct {
- const char *one, *two;
+ const char *one, *two, *bugref;
} eq_tests[] = {
- { "example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7Bfoo%7D" },
- { "http://example.com", "http://example.com/" },
+ { "example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7Bfoo%7D", "628728" },
+ { "http://example.com", "http://example.com/", NULL },
/* From RFC 2616 */
- { "http://abc.com:80/~smith/home.html", "http://abc.com:80/~smith/home.html" },
- { "http://abc.com:80/~smith/home.html", "http://ABC.com/%7Esmith/home.html" },
- { "http://abc.com:80/~smith/home.html", "http://ABC.com:/%7esmith/home.html" },
+ { "http://abc.com:80/~smith/home.html", "http://abc.com:80/~smith/home.html", NULL },
+ { "http://abc.com:80/~smith/home.html", "http://ABC.com/%7Esmith/home.html", NULL },
+ { "http://abc.com:80/~smith/home.html", "http://ABC.com:/%7esmith/home.html", NULL },
};
static int num_eq_tests = G_N_ELEMENTS(eq_tests);
-#define test_cmpstr(a, b) _test_cmpstr (#a, #b, a, b)
-
-static gboolean
-_test_cmpstr (const char *got_desc,
- const char *exp_desc,
- const char *got,
- const char *expected)
-{
- if (got == expected)
- return TRUE;
-
- if (got == NULL) {
- debug_printf (1, "ERR\n %s = NULL, expected %s = \"%s\"\n",
- got_desc, exp_desc, expected);
- return FALSE;
- }
-
- if (expected == NULL) {
- debug_printf (1, "ERR\n %s = \"%s\", expected %s = NULL\n",
- got_desc, got, exp_desc);
- return FALSE;
- }
-
- if (strcmp (got, expected) != 0) {
- debug_printf (1, "ERR\n %s = \"%s\", expected %s = \"%s\"\n",
- got_desc, got, exp_desc, expected);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
+static void
do_uri (SoupURI *base_uri, const char *base_str,
const char *in_uri, const char *out_uri,
const SoupURI *bits)
@@ -275,76 +275,94 @@ do_uri (SoupURI *base_uri, const char *base_str,
char *uri_string;
if (base_uri) {
- debug_printf (1, "<%s> + <%s> = <%s>? ", base_str, in_uri,
+ debug_printf (1, "<%s> + <%s> = <%s>\n", base_str, in_uri,
out_uri ? out_uri : "ERR");
uri = soup_uri_new_with_base (base_uri, in_uri);
} else {
- debug_printf (1, "<%s> => <%s>? ", in_uri,
+ debug_printf (1, "<%s> => <%s>\n", in_uri,
out_uri ? out_uri : "ERR");
uri = soup_uri_new (in_uri);
}
if (!uri) {
- if (out_uri) {
- debug_printf (1, "ERR\n Could not parse %s\n", in_uri);
- return FALSE;
- } else {
- debug_printf (1, "OK\n");
- return TRUE;
- }
+ g_assert_null (out_uri);
+ return;
}
if (bits != NULL) {
- gboolean failed = FALSE;
-
- if (!test_cmpstr (uri->scheme, bits->scheme))
- failed = TRUE;
+ g_assert_cmpstr (uri->scheme, ==, bits->scheme);
+ g_assert_cmpstr (uri->user, ==, bits->user);
+ g_assert_cmpstr (uri->password, ==, bits->password);
+ g_assert_cmpstr (uri->host, ==, bits->host);
+ g_assert_cmpuint (uri->port, ==, bits->port);
+ g_assert_cmpstr (uri->path, ==, bits->path);
+ g_assert_cmpstr (uri->query, ==, bits->query);
+ g_assert_cmpstr (uri->fragment, ==, bits->fragment);
+ }
- if (!test_cmpstr (uri->user, bits->user))
- failed = TRUE;
+ uri_string = soup_uri_to_string (uri, FALSE);
+ soup_uri_free (uri);
- if (!test_cmpstr (uri->password, bits->password))
- failed = TRUE;
+ g_assert_cmpstr (uri_string, ==, out_uri);
+ g_free (uri_string);
+}
- if (!test_cmpstr (uri->host, bits->host))
- failed = TRUE;
+static void
+do_absolute_uri_tests (void)
+{
+ int i;
- if (uri->port != bits->port) {
- debug_printf (1, "ERR\n port was %u, expected %u\n",
- uri->port, bits->port);
- failed = TRUE;
- }
+ for (i = 0; i < num_abs_tests; i++) {
+ if (abs_tests[i].bugref)
+ g_test_bug (abs_tests[i].bugref);
+ do_uri (NULL, NULL, abs_tests[i].uri_string,
+ abs_tests[i].result, &abs_tests[i].bits);
+ }
+}
- if (!test_cmpstr (uri->path, bits->path))
- failed = TRUE;
+static void
+do_relative_uri_tests (void)
+{
+ SoupURI *base_uri;
+ char *uri_string;
+ int i;
- if (!test_cmpstr (uri->query, bits->query))
- failed = TRUE;
+ base_uri = soup_uri_new (base);
+ if (!base_uri) {
+ g_printerr ("Could not parse %s!\n", base);
+ exit (1);
+ }
- if (!test_cmpstr (uri->fragment, bits->fragment))
- failed = TRUE;
+ uri_string = soup_uri_to_string (base_uri, FALSE);
+ g_assert_cmpstr (uri_string, ==, base);
+ g_free (uri_string);
- if (failed)
- return FALSE;
+ for (i = 0; i < num_rel_tests; i++) {
+ do_uri (base_uri, base, rel_tests[i].uri_string,
+ rel_tests[i].result, &rel_tests[i].bits);
}
+ soup_uri_free (base_uri);
+}
- uri_string = soup_uri_to_string (uri, FALSE);
- soup_uri_free (uri);
+static void
+do_equality_tests (void)
+{
+ SoupURI *uri1, *uri2;
+ int i;
- if (!out_uri) {
- debug_printf (1, "ERR\n Got %s\n", uri_string);
- return FALSE;
- }
+ for (i = 0; i < num_eq_tests; i++) {
+ if (eq_tests[i].bugref)
+ g_test_bug (eq_tests[i].bugref);
- if (strcmp (uri_string, out_uri) != 0) {
- debug_printf (1, "NO\n Unparses to <%s>\n", uri_string);
- g_free (uri_string);
- return FALSE;
- }
- g_free (uri_string);
+ uri1 = soup_uri_new (eq_tests[i].one);
+ uri2 = soup_uri_new (eq_tests[i].two);
- debug_printf (1, "OK\n");
- return TRUE;
+ debug_printf (1, "<%s> == <%s>\n", eq_tests[i].one, eq_tests[i].two);
+ g_assert_true (soup_uri_equal (uri1, uri2));
+
+ soup_uri_free (uri1);
+ soup_uri_free (uri2);
+ }
}
static void
@@ -353,146 +371,83 @@ do_soup_uri_null_tests (void)
SoupURI *uri, *uri2;
char *uri_string;
- debug_printf (1, "\nsoup_uri_new (NULL)\n");
+ g_test_bug ("667637");
+ g_test_bug ("670431");
+
uri = soup_uri_new (NULL);
- if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) {
- debug_printf (1, " ERROR: soup_uri_new(NULL) returns valid URI?\n");
- errors++;
- }
+ g_assert_false (SOUP_URI_IS_VALID (uri));
+ g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri));
/* This implicitly also verifies that none of these methods g_warn */
- if (soup_uri_get_scheme (uri) ||
- soup_uri_get_user (uri) ||
- soup_uri_get_password (uri) ||
- soup_uri_get_host (uri) ||
- soup_uri_get_port (uri) ||
- soup_uri_get_path (uri) ||
- soup_uri_get_query (uri) ||
- soup_uri_get_fragment (uri)) {
- debug_printf (1, " ERROR: soup_uri_new(NULL) returns non-empty URI?\n");
- errors++;
- }
-
- expect_warning = TRUE;
+ g_assert_null (soup_uri_get_scheme (uri));
+ g_assert_null (soup_uri_get_user (uri));
+ g_assert_null (soup_uri_get_password (uri));
+ g_assert_null (soup_uri_get_host (uri));
+ g_assert_cmpint (soup_uri_get_port (uri), ==, 0);
+ g_assert_null (soup_uri_get_path (uri));
+ g_assert_null (soup_uri_get_query (uri));
+ g_assert_null (soup_uri_get_fragment (uri));
+
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_CRITICAL,
+ "*base == NULL*");
uri2 = soup_uri_new_with_base (uri, "/path");
- if (uri2 || expect_warning) {
- debug_printf (1, " ERROR: soup_uri_new_with_base didn't fail on NULL URI?\n");
- errors++;
- expect_warning = FALSE;
- }
+ g_test_assert_expected_messages ();
+ g_assert_null (uri2);
- expect_warning = TRUE;
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*SOUP_URI_IS_VALID*");
uri_string = soup_uri_to_string (uri, FALSE);
- if (expect_warning) {
- debug_printf (1, " ERROR: soup_uri_to_string didn't fail on NULL URI?\n");
- errors++;
- expect_warning = FALSE;
- } else if (*uri_string) {
- debug_printf (1, " ERROR: soup_uri_to_string on NULL URI returned '%s'\n",
- uri_string);
- errors++;
- }
+ g_test_assert_expected_messages ();
+ g_assert_cmpstr (uri_string, ==, "");
g_free (uri_string);
soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
- if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) {
- debug_printf (1, " ERROR: setting scheme on NULL URI makes it valid?\n");
- errors++;
- }
+ g_assert_false (SOUP_URI_IS_VALID (uri));
+ g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri));
- expect_warning = TRUE;
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*SOUP_URI_IS_VALID*");
uri_string = soup_uri_to_string (uri, FALSE);
- if (expect_warning) {
- debug_printf (1, " ERROR: soup_uri_to_string didn't fail on scheme-only URI?\n");
- errors++;
- expect_warning = FALSE;
- } else if (strcmp (uri_string, "http:") != 0) {
- debug_printf (1, " ERROR: soup_uri_to_string returned '%s' instead of 'http:'\n",
- uri_string);
- errors++;
- }
+ g_test_assert_expected_messages ();
+ g_assert_cmpstr (uri_string, ==, "http:");
g_free (uri_string);
soup_uri_set_host (uri, "localhost");
- if (SOUP_URI_IS_VALID (uri)) {
- debug_printf (1, " ERROR: setting scheme+host on NULL URI makes it valid?\n");
- errors++;
- }
- if (SOUP_URI_VALID_FOR_HTTP (uri)) {
- debug_printf (1, " ERROR: setting scheme+host on NULL URI makes it valid for http?\n");
- errors++;
- }
+ g_assert_false (SOUP_URI_IS_VALID (uri));
+ g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri));
- expect_warning = TRUE;
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*SOUP_URI_IS_VALID*");
uri_string = soup_uri_to_string (uri, FALSE);
- if (expect_warning) {
- debug_printf (1, " ERROR: soup_uri_to_string didn't fail on scheme+host URI?\n");
- errors++;
- expect_warning = FALSE;
- } else if (strcmp (uri_string, "http://localhost/") != 0) {
- debug_printf (1, " ERROR: soup_uri_to_string with NULL path returned '%s' instead of 'http://localhost/'\n",
- uri_string);
- errors++;
- }
+ g_test_assert_expected_messages ();
+ g_assert_cmpstr (uri_string, ==, "http://localhost/");
g_free (uri_string);
- expect_warning = TRUE;
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*SOUP_URI_IS_VALID*");
uri2 = soup_uri_new_with_base (uri, "/path");
- if (expect_warning) {
- debug_printf (1, " ERROR: soup_uri_new_with_base didn't warn on NULL+scheme URI?\n");
- errors++;
- expect_warning = FALSE;
- } else if (!uri2) {
- debug_printf (1, " ERROR: soup_uri_new_with_base didn't fix path on NULL+scheme URI\n");
- errors++;
- }
+ g_test_assert_expected_messages ();
+ g_assert_true (uri2 != NULL);
if (uri2) {
uri_string = soup_uri_to_string (uri2, FALSE);
- if (!uri_string) {
- debug_printf (1, " ERROR: soup_uri_to_string failed on uri2?\n");
- errors++;
- } else if (strcmp (uri_string, "http://localhost/path") != 0) {
- debug_printf (1, " ERROR: soup_uri_to_string returned '%s' instead of 'http://localhost/path'\n",
- uri_string);
- errors++;
- }
+ g_assert_cmpstr (uri_string, ==, "http://localhost/path");
g_free (uri_string);
soup_uri_free (uri2);
}
- expect_warning = TRUE;
+ g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ "*path != NULL*");
soup_uri_set_path (uri, NULL);
- if (expect_warning) {
- debug_printf (1, " ERROR: setting path to NULL doesn't warn\n");
- errors++;
- expect_warning = FALSE;
- }
- if (!uri->path || *uri->path) {
- debug_printf (1, " ERROR: setting path to NULL != \"\"\n");
- errors++;
- soup_uri_set_path (uri, "");
- }
+ g_test_assert_expected_messages ();
+ g_assert_cmpstr (uri->path, ==, "");
uri_string = soup_uri_to_string (uri, FALSE);
- if (!uri_string) {
- debug_printf (1, " ERROR: soup_uri_to_string failed on complete URI?\n");
- errors++;
- } else if (strcmp (uri_string, "http://localhost/") != 0) {
- debug_printf (1, " ERROR: soup_uri_to_string with empty path returned '%s' instead of 'http://localhost/'\n",
- uri_string);
- errors++;
- }
+ g_assert_cmpstr (uri_string, ==, "http://localhost/");
g_free (uri_string);
- if (!SOUP_URI_IS_VALID (uri)) {
- debug_printf (1, " ERROR: setting scheme+path on NULL URI doesn't make it valid?\n");
- errors++;
- }
- if (!SOUP_URI_VALID_FOR_HTTP (uri)) {
- debug_printf (1, " ERROR: setting scheme+host+path on NULL URI doesn't make it valid for http?\n");
- errors++;
- }
+ g_assert_true (SOUP_URI_IS_VALID (uri));
+ g_assert_true (SOUP_URI_VALID_FOR_HTTP (uri));
soup_uri_free (uri);
}
@@ -517,29 +472,23 @@ do_normalization_tests (void)
char *normalized;
int i;
- debug_printf (1, "\nsoup_uri_normalize\n");
+ g_test_bug ("680018");
for (i = 0; i < num_normalization_tests; i++) {
if (normalization_tests[i].unescape_extra) {
- debug_printf (1, "<%s> unescaping <%s> => <%s>: ",
+ debug_printf (1, "<%s> unescaping <%s> => <%s>\n",
normalization_tests[i].uri_string,
normalization_tests[i].unescape_extra,
normalization_tests[i].result);
} else {
- debug_printf (1, "<%s> => <%s>: ",
+ debug_printf (1, "<%s> => <%s>\n",
normalization_tests[i].uri_string,
normalization_tests[i].result);
}
normalized = soup_uri_normalize (normalization_tests[i].uri_string,
normalization_tests[i].unescape_extra);
-
- if (!strcmp (normalized, normalization_tests[i].result))
- debug_printf (1, "OK\n");
- else {
- debug_printf (1, "NO, got <%s>\n", normalized);
- errors++;
- }
+ g_assert_cmpstr (normalized, ==, normalization_tests[i].result);
g_free (normalized);
}
}
@@ -547,62 +496,18 @@ do_normalization_tests (void)
int
main (int argc, char **argv)
{
- SoupURI *base_uri, *uri1, *uri2;
- char *uri_string;
- int i;
+ int ret;
test_init (argc, argv, NULL);
- debug_printf (1, "Absolute URI parsing\n");
- for (i = 0; i < num_abs_tests; i++) {
- if (!do_uri (NULL, NULL, abs_tests[i].uri_string,
- abs_tests[i].result, &abs_tests[i].bits))
- errors++;
- }
-
- debug_printf (1, "\nRelative URI parsing\n");
- base_uri = soup_uri_new (base);
- if (!base_uri) {
- g_printerr ("Could not parse %s!\n", base);
- exit (1);
- }
-
- uri_string = soup_uri_to_string (base_uri, FALSE);
- if (strcmp (uri_string, base) != 0) {
- g_printerr ("URI <%s> unparses to <%s>\n",
- base, uri_string);
- errors++;
- }
- g_free (uri_string);
-
- for (i = 0; i < num_rel_tests; i++) {
- if (!do_uri (base_uri, base, rel_tests[i].uri_string,
- rel_tests[i].result, &rel_tests[i].bits))
- errors++;
- }
- soup_uri_free (base_uri);
-
- debug_printf (1, "\nURI equality testing\n");
- for (i = 0; i < num_eq_tests; i++) {
- uri1 = soup_uri_new (eq_tests[i].one);
- uri2 = soup_uri_new (eq_tests[i].two);
- debug_printf (1, "<%s> == <%s>? ", eq_tests[i].one, eq_tests[i].two);
- if (soup_uri_equal (uri1, uri2))
- debug_printf (1, "OK\n");
- else {
- debug_printf (1, "NO\n");
- debug_printf (1, "%s : %s : %s\n%s : %s : %s\n",
- uri1->scheme, uri1->host, uri1->path,
- uri2->scheme, uri2->host, uri2->path);
- errors++;
- }
- soup_uri_free (uri1);
- soup_uri_free (uri2);
- }
+ g_test_add_func ("/uri/absolute", do_absolute_uri_tests);
+ g_test_add_func ("/uri/relative", do_relative_uri_tests);
+ g_test_add_func ("/uri/equality", do_equality_tests);
+ g_test_add_func ("/uri/null", do_soup_uri_null_tests);
+ g_test_add_func ("/uri/normalization", do_normalization_tests);
- do_soup_uri_null_tests ();
- do_normalization_tests ();
+ ret = g_test_run ();
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c
index 8ad2187b..bfeb200a 100644
--- a/tests/xmlrpc-server-test.c
+++ b/tests/xmlrpc-server-test.c
@@ -5,12 +5,12 @@
#include "test-utils.h"
+static char *uri;
+
#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
#endif
-GMainLoop *loop;
-
static void
type_error (SoupMessage *msg, GType expected, GValueArray *params, int bad_value)
{
@@ -180,7 +180,17 @@ do_echo (SoupMessage *msg, GValueArray *params)
soup_xmlrpc_set_response (msg, G_TYPE_VALUE_ARRAY, out);
g_value_array_free (out);
+}
+
+static void
+do_ping (SoupMessage *msg, GValueArray *params)
+{
+ if (params->n_values) {
+ args_error (msg, params, 0);
+ return;
+ }
+ soup_xmlrpc_set_response (msg, G_TYPE_STRING, "pong");
}
static void
@@ -216,6 +226,8 @@ server_callback (SoupServer *server, SoupMessage *msg,
do_dateChange (msg, params);
else if (!strcmp (method_name, "echo"))
do_echo (msg, params);
+ else if (!strcmp (method_name, "ping"))
+ do_ping (msg, params);
else {
soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND,
"Unknown method %s", method_name);
@@ -225,73 +237,64 @@ server_callback (SoupServer *server, SoupMessage *msg,
g_value_array_free (params);
}
-static void
-xmlrpc_test_exited (GPid pid, int status, gpointer data)
-{
- errors = WIFEXITED (status) ? WEXITSTATUS (status) : 1;
- g_main_loop_quit (loop);
-}
-
static gboolean
-xmlrpc_test_print (GIOChannel *io, GIOCondition cond, gpointer data)
+run_xmlrpc_test (char **argv,
+ char **stdout_out,
+ char **stderr_out,
+ GError **error)
{
- char *line;
- gsize len;
- GIOStatus status;
+ gboolean ok;
+ int status;
- if (!(cond & G_IO_IN))
- return FALSE;
+ argv[0] = g_test_build_filename (G_TEST_BUILT, "xmlrpc-test", NULL);
+ ok = g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL,
+ stdout_out, stderr_out, &status,
+ error);
+ g_free (argv[0]);
- status = g_io_channel_read_line (io, &line, &len, NULL, NULL);
- if (status == G_IO_STATUS_NORMAL) {
- /* Don't print the exit status, just the debug stuff */
- if (strncmp (line, "xmlrpc-test:", strlen ("xmlrpc-test:")) != 0)
- g_print ("%s", line);
- g_free (line);
- return TRUE;
- } else if (status == G_IO_STATUS_AGAIN)
- return TRUE;
- else
+ if (!ok)
return FALSE;
+
+ return g_spawn_check_exit_status (status, error);
}
static void
-do_xmlrpc_tests (SoupURI *uri)
+do_one_xmlrpc_test (gconstpointer data)
{
- char *argv[8];
- int arg, out;
- gboolean ok;
- GPid pid;
+ const char *path = data;
+ char *argv[12];
+ char *stdout_out, *stderr_out;
GError *error = NULL;
- GIOChannel *child_out;
+ int arg;
- argv[0] = "./xmlrpc-test";
- argv[1] = "-s";
- argv[2] = "-u";
- argv[3] = soup_uri_to_string (uri, FALSE);
+ argv[0] = NULL;
+ argv[1] = "-S";
+ argv[2] = "-U";
+ argv[3] = uri;
+ argv[4] = "-q";
+ argv[5] = "-p";
+ argv[6] = (char *) path;
for (arg = 0; arg < debug_level && arg < 3; arg++)
- argv[arg + 4] = "-d";
- argv[arg + 4] = NULL;
-
- ok = g_spawn_async_with_pipes (NULL, argv, NULL,
- G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL, &pid,
- NULL, &out, NULL,
- &error);
- g_free (argv[3]);
-
- if (!ok) {
- g_print ("Could not run xmlrpc-test: %s\n", error->message);
- errors++;
- return;
+ argv[arg + 7] = "-d";
+ argv[arg + 7] = NULL;
+
+ run_xmlrpc_test (argv, &stdout_out, &stderr_out, &error);
+ if (stdout_out) {
+ g_print ("%s", stdout_out);
+ g_free (stdout_out);
+ }
+ if (stderr_out) {
+ g_printerr ("%s", stderr_out);
+ g_free (stderr_out);
}
- g_child_watch_add (pid, xmlrpc_test_exited, NULL);
- child_out = g_io_channel_unix_new (out);
- g_io_add_watch (child_out, G_IO_IN | G_IO_ERR | G_IO_HUP,
- xmlrpc_test_print, NULL);
- g_io_channel_unref (child_out);
+ if ( g_error_matches (error, G_SPAWN_EXIT_ERROR, 1)
+ || g_error_matches (error, G_SPAWN_EXIT_ERROR, 77))
+ g_test_fail ();
+ else
+ g_assert_no_error (error);
+ g_clear_error (&error);
}
gboolean run_tests = TRUE;
@@ -307,29 +310,61 @@ int
main (int argc, char **argv)
{
SoupServer *server;
- SoupURI *uri;
+ int ret;
test_init (argc, argv, no_test_entry);
- server = soup_test_server_new (FALSE);
+ server = soup_test_server_new (run_tests);
soup_server_add_handler (server, "/xmlrpc-server.php",
server_callback, NULL, NULL);
-
- loop = g_main_loop_new (NULL, TRUE);
+ uri = g_strdup_printf ("http://127.0.0.1:%u/xmlrpc-server.php",
+ soup_server_get_port (server));
if (run_tests) {
- uri = soup_uri_new ("http://127.0.0.1/xmlrpc-server.php");
- soup_uri_set_port (uri, soup_server_get_port (server));
- do_xmlrpc_tests (uri);
- soup_uri_free (uri);
- } else
+ char *out, **tests, *path;
+ char *list_argv[4];
+ GError *error = NULL;
+ int i;
+
+ list_argv[0] = NULL;
+ list_argv[1] = "-S";
+ list_argv[2] = "-l";
+ list_argv[3] = NULL;
+
+ if (!run_xmlrpc_test (list_argv, &out, NULL, &error)) {
+ g_printerr ("'xmlrpc-test -l' failed: %s\n", error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ tests = g_strsplit (out, "\n", -1);
+ g_free (out);
+
+ for (i = 0; tests[i] && *tests[i]; i++) {
+ g_assert_true (g_str_has_prefix (tests[i], "/xmlrpc/"));
+ path = g_strdup_printf ("/xmlrpc-server/%s", tests[i] + strlen ("/xmlrpc/"));
+ g_test_add_data_func (path, tests[i], do_one_xmlrpc_test);
+ g_free (path);
+ }
+
+ ret = g_test_run ();
+
+ g_strfreev (tests);
+ } else {
+ GMainLoop *loop;
+
g_print ("Listening on port %d\n", soup_server_get_port (server));
- g_main_loop_run (loop);
- g_main_loop_unref (loop);
+ loop = g_main_loop_new (NULL, TRUE);
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ ret = 0;
+ }
soup_test_server_quit_unref (server);
+ g_free (uri);
if (run_tests)
test_cleanup ();
- return errors != 0;
+ return ret;
}
diff --git a/tests/xmlrpc-server.php b/tests/xmlrpc-server.php
index 2e3dd381..66cb2be7 100644
--- a/tests/xmlrpc-server.php
+++ b/tests/xmlrpc-server.php
@@ -2,13 +2,13 @@
function paramfault ()
{
- # xmlrpc-epi-php translates this into a real <fault>
+ # xmlrpc-php translates this into a real <fault>
$fault["faultCode"] = -32602;
$fault["faultString"] = "bad parameter";
return $fault;
}
-# We only check the params in sum(), because that's the one that
+# We only check the params in sum(), because that is the one that
# xmlrpc-test tests will fail if given bad args
function sum ($method_name, $params, $app_data)
@@ -69,8 +69,16 @@ function echo_ ($method_name, $params, $app_data)
return $params[0];
}
-# Work around xmlrpc-epi-php lossage; otherwise the datetime values
-# we return will sometimes get a DST adjustment we don't want.
+function ping ($method_name, $params, $app_data)
+{
+ if (count ($params) == 0)
+ return "pong";
+ else
+ return paramfault ();
+}
+
+# Work around xmlrpc-php lossage; otherwise the datetime values
+# we return will sometimes get a DST adjustment we do not want.
putenv ("TZ=");
$xmlrpc_server = xmlrpc_server_create ();
@@ -79,6 +87,7 @@ xmlrpc_server_register_method($xmlrpc_server, "countBools", "countBools");
xmlrpc_server_register_method($xmlrpc_server, "md5sum", "md5sum");
xmlrpc_server_register_method($xmlrpc_server, "dateChange", "dateChange");
xmlrpc_server_register_method($xmlrpc_server, "echo", "echo_");
+xmlrpc_server_register_method($xmlrpc_server, "ping", "ping");
$response = xmlrpc_server_call_method ($xmlrpc_server,
implode("\r\n", file('php://input')),
diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c
index ec67e4d1..f6b20b8f 100644
--- a/tests/xmlrpc-test.c
+++ b/tests/xmlrpc-test.c
@@ -14,6 +14,18 @@ static const char *default_uri = "http://127.0.0.1:47524/xmlrpc-server.php";
static const char *uri = NULL;
static gboolean server_test = FALSE;
+#ifdef HAVE_PHP_XMLRPC
+#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER
+#else
+#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER \
+ G_STMT_START { \
+ if (!server_test) { \
+ g_test_skip ("php-xmlrpc is not available"); \
+ return; \
+ } \
+ } G_STMT_END
+#endif
+
static const char *const value_type[] = {
"BAD",
"int",
@@ -27,44 +39,26 @@ static const char *const value_type[] = {
};
static gboolean
-do_xmlrpc (const char *method, GValue *retval, ...)
+send_xmlrpc (const char *body, GValue *retval)
{
SoupMessage *msg;
- va_list args;
- GValueArray *params;
GError *err = NULL;
- char *body;
-
- va_start (args, retval);
- params = soup_value_array_from_args (args);
- va_end (args);
-
- body = soup_xmlrpc_build_method_call (method, params->values,
- params->n_values);
- g_value_array_free (params);
- if (!body)
- return FALSE;
msg = soup_message_new ("POST", uri);
- soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE,
+ soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
body, strlen (body));
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, "ERROR: %d %s\n", msg->status_code,
- msg->reason_phrase);
- g_object_unref (msg);
- return FALSE;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
msg->response_body->length,
retval, &err)) {
if (err) {
- debug_printf (1, "FAULT: %d %s\n", err->code, err->message);
+ soup_test_assert (FALSE, "FAULT: %d %s\n", err->code, err->message);
g_error_free (err);
} else
- debug_printf (1, "ERROR: could not parse response\n");
+ soup_test_assert (FALSE, "ERROR: could not parse response\n");
g_object_unref (msg);
return FALSE;
}
@@ -74,13 +68,36 @@ do_xmlrpc (const char *method, GValue *retval, ...)
}
static gboolean
+do_xmlrpc (const char *method, GValue *retval, ...)
+{
+ va_list args;
+ GValueArray *params;
+ char *body;
+ gboolean ret;
+
+ va_start (args, retval);
+ params = soup_value_array_from_args (args);
+ va_end (args);
+
+ body = soup_xmlrpc_build_method_call (method, params->values,
+ params->n_values);
+ g_value_array_free (params);
+ if (!body)
+ return FALSE;
+
+ ret = send_xmlrpc (body, retval);
+ g_free (body);
+
+ return ret;
+}
+
+static gboolean
check_xmlrpc (GValue *value, GType type, ...)
{
va_list args;
if (!G_VALUE_HOLDS (value, type)) {
- debug_printf (1, "ERROR: could not parse response\n");
- g_value_unset (value);
+ g_assert_true (G_VALUE_HOLDS (value, type));
return FALSE;
}
@@ -90,7 +107,7 @@ check_xmlrpc (GValue *value, GType type, ...)
return TRUE;
}
-static gboolean
+static void
test_sum (void)
{
GValueArray *ints;
@@ -98,7 +115,9 @@ test_sum (void)
GValue retval;
gboolean ok;
- debug_printf (1, "sum (array of int -> int): ");
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ debug_printf (2, "sum (array of int -> int): ");
ints = g_value_array_new (10);
for (i = sum = 0; i < 10; i++) {
@@ -116,14 +135,13 @@ test_sum (void)
g_value_array_free (ints);
if (!ok)
- return FALSE;
+ return;
- debug_printf (2, "%d: ", result);
- debug_printf (1, "%s\n", result == sum ? "OK!" : "WRONG!");
- return result == sum;
+ debug_printf (2, "%d\n", result);
+ g_assert_cmpint (result, ==, sum);
}
-static gboolean
+static void
test_countBools (void)
{
GValueArray *bools;
@@ -133,7 +151,9 @@ test_countBools (void)
gboolean val, ok;
GHashTable *result;
- debug_printf (1, "countBools (array of boolean -> struct of ints): ");
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ debug_printf (2, "countBools (array of boolean -> struct of ints): ");
bools = g_value_array_new (10);
for (i = trues = falses = 0; i < 10; i++) {
@@ -153,25 +173,19 @@ test_countBools (void)
check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result));
g_value_array_free (bools);
if (!ok)
- return FALSE;
+ return;
+
+ g_assert_true (soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues));
+ g_assert_true (soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses));
- if (!soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues)) {
- debug_printf (1, "NO 'true' value in response\n");
- return FALSE;
- }
- if (!soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses)) {
- debug_printf (1, "NO 'false' value in response\n");
- return FALSE;
- }
g_hash_table_destroy (result);
- debug_printf (2, "{ true: %d, false: %d } ", ret_trues, ret_falses);
- ok = (trues == ret_trues) && (falses == ret_falses);
- debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
- return ok;
+ debug_printf (2, "{ true: %d, false: %d }\n", ret_trues, ret_falses);
+ g_assert_cmpint (trues, ==, ret_trues);
+ g_assert_cmpint (falses, ==, ret_falses);
}
-static gboolean
+static void
test_md5sum (void)
{
GByteArray *data, *result;
@@ -182,7 +196,9 @@ test_md5sum (void)
GValue retval;
gboolean ok;
- debug_printf (1, "md5sum (base64 -> base64): ");
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ debug_printf (2, "md5sum (base64 -> base64)\n");
data = g_byte_array_new ();
g_byte_array_set_size (data, 256);
@@ -200,21 +216,14 @@ test_md5sum (void)
check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result));
g_byte_array_free (data, TRUE);
if (!ok)
- return FALSE;
+ return;
- if (result->len != digest_len) {
- debug_printf (1, "result has WRONG length (%d)\n", result->len);
- g_byte_array_free (result, TRUE);
- return FALSE;
- }
-
- ok = (memcmp (digest, result->data, digest_len) == 0);
- debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
+ soup_assert_cmpmem (result->data, result->len,
+ digest, digest_len);
g_byte_array_free (result, TRUE);
- return ok;
}
-static gboolean
+static void
test_dateChange (void)
{
GHashTable *structval;
@@ -223,7 +232,9 @@ test_dateChange (void)
GValue retval;
gboolean ok;
- debug_printf (1, "dateChange (date, struct of ints -> time): ");
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ debug_printf (2, "dateChange (date, struct of ints -> time)\n");
date = soup_date_new (1970 + (g_random_int_range (0, 50)),
1 + g_random_int_range (0, 12),
@@ -288,26 +299,24 @@ test_dateChange (void)
g_hash_table_destroy (structval);
if (!ok) {
soup_date_free (date);
- return FALSE;
+ return;
}
if (debug_level >= 2) {
timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC);
- debug_printf (2, "%s: ", timestamp);
+ debug_printf (2, "%s\n", timestamp);
g_free (timestamp);
}
- ok = ((date->year == result->year) &&
- (date->month == result->month) &&
- (date->day == result->day) &&
- (date->hour == result->hour) &&
- (date->minute == result->minute) &&
- (date->second == result->second));
+ g_assert_cmpint (date->year, ==, result->year);
+ g_assert_cmpint (date->month, ==, result->month);
+ g_assert_cmpint (date->day, ==, result->day);
+ g_assert_cmpint (date->hour, ==, result->hour);
+ g_assert_cmpint (date->minute, ==, result->minute);
+ g_assert_cmpint (date->second, ==, result->second);
+
soup_date_free (date);
soup_date_free (result);
-
- debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!");
- return ok;
}
static const char *const echo_strings[] = {
@@ -325,15 +334,16 @@ static const char *const echo_strings_broken[] = {
"amp; so is lt;thisgt;"
};
-static gboolean
+static void
test_echo (void)
{
GValueArray *originals, *echoes;
GValue retval;
int i;
- gboolean php_bug = FALSE;
- debug_printf (1, "echo (array of string -> array of string): ");
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ debug_printf (2, "echo (array of string -> array of string):\n");
originals = g_value_array_new (N_ECHO_STRINGS);
for (i = 0; i < N_ECHO_STRINGS; i++) {
@@ -347,7 +357,7 @@ test_echo (void)
G_TYPE_INVALID) &&
check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) {
g_value_array_free (originals);
- return FALSE;
+ return;
}
g_value_array_free (originals);
@@ -356,36 +366,71 @@ test_echo (void)
debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ",
g_value_get_string (&echoes->values[i]));
}
- debug_printf (2, "] -> ");
+ debug_printf (2, "]\n");
}
- if (echoes->n_values != N_ECHO_STRINGS) {
- debug_printf (1, " WRONG! Wrong number of return strings");
- g_value_array_free (echoes);
- return FALSE;
- }
+ g_assert_cmpint (echoes->n_values, ==, N_ECHO_STRINGS);
for (i = 0; i < echoes->n_values; i++) {
- if (strcmp (echo_strings[i], g_value_get_string (&echoes->values[i])) != 0) {
- if (!server_test && strcmp (echo_strings_broken[i], g_value_get_string (&echoes->values[i])) == 0)
- php_bug = TRUE;
- else {
- debug_printf (1, " WRONG! Mismatch at %d\n", i + 1);
- g_value_array_free (echoes);
- return FALSE;
- }
+ if (!server_test && strcmp (echo_strings_broken[i], g_value_get_string (&echoes->values[i])) == 0) {
+ g_test_skip ("PHP bug");
+ g_value_array_free (echoes);
+ return;
}
+
+ g_assert_cmpstr (echo_strings[i], ==, g_value_get_string (&echoes->values[i]));
}
- if (php_bug)
- debug_printf (1, "WRONG, but it's php's fault\n");
- else
- debug_printf (1, "OK!\n");
g_value_array_free (echoes);
- return TRUE;
}
-static gboolean
+static void
+test_ping (gconstpointer include_params)
+{
+ GValueArray *params;
+ GValue retval;
+ char *request;
+ char *out;
+ gboolean ret;
+
+ g_test_bug ("671661");
+
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ debug_printf (2, "ping (void (%s) -> string)\n",
+ include_params ? "empty <params>" : "no <params>");
+
+ params = soup_value_array_new ();
+ request = soup_xmlrpc_build_method_call ("ping", params->values,
+ params->n_values);
+ g_value_array_free (params);
+ if (!request)
+ return;
+
+ if (!include_params) {
+ char *params, *end;
+
+ params = strstr (request, "<params/>");
+ if (!params) {
+ soup_test_assert (FALSE, "ERROR: XML did not contain <params/>!");
+ return;
+ }
+ end = params + strlen ("<params/>");
+ memmove (params, end, strlen (end) + 1);
+ }
+
+ ret = send_xmlrpc (request, &retval);
+ g_free (request);
+
+ if (!ret || !check_xmlrpc (&retval, G_TYPE_STRING, &out))
+ return;
+
+ g_assert_cmpstr (out, ==, "pong");
+
+ g_free (out);
+}
+
+static void
do_bad_xmlrpc (const char *body)
{
SoupMessage *msg;
@@ -397,12 +442,7 @@ do_bad_xmlrpc (const char *body)
body, strlen (body));
soup_session_send_message (session, msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- debug_printf (1, "ERROR: %d %s\n", msg->status_code,
- msg->reason_phrase);
- g_object_unref (msg);
- return FALSE;
- }
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
msg->response_body->length,
@@ -412,44 +452,43 @@ do_bad_xmlrpc (const char *body)
err->code, err->message);
g_error_free (err);
g_object_unref (msg);
- return TRUE;
+ return;
} else
- debug_printf (1, "ERROR: could not parse response\n");
+ soup_test_assert (FALSE, "ERROR: could not parse response\n");
} else
- debug_printf (1, "Unexpectedly got successful response!\n");
+ soup_test_assert (FALSE, "Unexpectedly got successful response!\n");
g_object_unref (msg);
- return FALSE;
}
-static gboolean
+static void
test_fault_malformed (void)
{
- debug_printf (1, "malformed request: ");
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
- return do_bad_xmlrpc ("<methodCall/>");
+ do_bad_xmlrpc ("<methodCall/>");
}
-static gboolean
+static void
test_fault_method (void)
{
- debug_printf (1, "request to non-existent method: ");
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
- return do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
+ do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
}
-static gboolean
+static void
test_fault_args (void)
{
- debug_printf (1, "request with invalid args: ");
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
- return do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
+ do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
}
static GOptionEntry xmlrpc_entries[] = {
- { "uri", 'u', 0, G_OPTION_ARG_STRING, &uri,
+ { "uri", 'U', 0, G_OPTION_ARG_STRING, &uri,
"Alternate URI for server", NULL },
- { "server-test", 's', 0, G_OPTION_ARG_NONE, &server_test,
+ { "server-test", 'S', 0, G_OPTION_ARG_NONE, &server_test,
"If this is being run from xmlrpc-server-test", NULL },
{ NULL }
};
@@ -457,34 +496,32 @@ static GOptionEntry xmlrpc_entries[] = {
int
main (int argc, char **argv)
{
+ int ret;
+
test_init (argc, argv, xmlrpc_entries);
- if (!uri) {
+ if (!uri && !server_test) {
apache_init ();
uri = default_uri;
}
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
- if (!test_sum ())
- errors++;
- if (!test_countBools ())
- errors++;
- if (!test_md5sum ())
- errors++;
- if (!test_dateChange ())
- errors++;
- if (!test_echo ())
- errors++;
- if (!test_fault_malformed ())
- errors++;
- if (!test_fault_method ())
- errors++;
- if (!test_fault_args ())
- errors++;
+ g_test_add_func ("/xmlrpc/sum", test_sum);
+ g_test_add_func ("/xmlrpc/countBools", test_countBools);
+ g_test_add_func ("/xmlrpc/md5sum", test_md5sum);
+ g_test_add_func ("/xmlrpc/dateChange", test_dateChange);
+ g_test_add_func ("/xmlrpc/echo", test_echo);
+ g_test_add_data_func ("/xmlrpc/ping/empty-params", GINT_TO_POINTER (TRUE), test_ping);
+ g_test_add_data_func ("/xmlrpc/ping/no-params", GINT_TO_POINTER (FALSE), test_ping);
+ g_test_add_func ("/xmlrpc/fault/malformed", test_fault_malformed);
+ g_test_add_func ("/xmlrpc/fault/method", test_fault_method);
+ g_test_add_func ("/xmlrpc/fault/args", test_fault_args);
+
+ ret = g_test_run ();
soup_test_session_abort_unref (session);
test_cleanup ();
- return errors != 0;
+ return ret;
}