summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorSeonah Moon <seonah1.moon@samsung.com>2019-12-10 13:58:05 +0900
committerSeonah Moon <seonah1.moon@samsung.com>2019-12-10 13:58:46 +0900
commita4c63790246af7f0e0715ec58045ee0d7d0bd4bd (patch)
tree5d14b6de79b14cfe9d0aa2c13a3c0c9433c9af42 /tests
parent7e83c2dd89bc4fcbbc823eaa53a335013dbd4343 (diff)
parent58894334cd3f0b89c865304e8e9d6eea3cd20a55 (diff)
downloadlibsoup-a4c63790246af7f0e0715ec58045ee0d7d0bd4bd.tar.gz
libsoup-a4c63790246af7f0e0715ec58045ee0d7d0bd4bd.tar.bz2
libsoup-a4c63790246af7f0e0715ec58045ee0d7d0bd4bd.zip
Change-Id: I8b24412aceb62f5217597e6ddf4106bac947c809
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.am34
-rw-r--r--tests/Makefile.in163
-rw-r--r--tests/auth-test.c270
-rw-r--r--tests/cache-test.c156
-rw-r--r--tests/chunk-io-test.c6
-rw-r--r--tests/chunk-test.c11
-rw-r--r--tests/coding-test.c5
-rw-r--r--tests/connection-test.c289
-rw-r--r--tests/context-test.c19
-rw-r--r--tests/continue-test.c47
-rw-r--r--tests/cookies-test.c66
-rw-r--r--tests/date.c15
-rw-r--r--tests/forms-test.c24
-rw-r--r--tests/header-parsing.c130
-rw-r--r--tests/httpd.conf.22.in292
-rw-r--r--tests/httpd.conf.in (renamed from tests/httpd.conf.24.in)12
-rw-r--r--tests/libsoup.supp88
-rw-r--r--tests/misc-test.c361
-rw-r--r--tests/multipart-test.c5
-rw-r--r--tests/no-ssl-test.c29
-rw-r--r--tests/ntlm-test.c125
-rw-r--r--tests/proxy-test.c86
-rw-r--r--tests/range-test.c18
-rw-r--r--tests/redirect-test.c21
-rw-r--r--tests/requester-test.c152
-rw-r--r--tests/resources/misc.xml11
-rw-r--r--tests/server-auth-test.c60
-rw-r--r--tests/server-test.c1150
-rw-r--r--tests/session-test.c51
-rw-r--r--tests/sniffing-test.c9
-rw-r--r--tests/socket-test.c235
-rw-r--r--tests/soup-tests.gresource.xml1
-rw-r--r--tests/ssl-test.c216
-rw-r--r--tests/streaming-test.c7
-rw-r--r--tests/test-cert.pem31
-rw-r--r--tests/test-utils.c287
-rw-r--r--tests/test-utils.h19
-rw-r--r--tests/timeout-test.c58
-rw-r--r--tests/tld-test.c8
-rw-r--r--tests/uri-parsing.c73
-rw-r--r--tests/websocket-test.c971
-rw-r--r--tests/xmlrpc-old-server-test.c374
-rw-r--r--tests/xmlrpc-old-test.c502
-rw-r--r--tests/xmlrpc-server-test.c248
-rw-r--r--tests/xmlrpc-server.php4
-rw-r--r--tests/xmlrpc-test.c583
46 files changed, 6111 insertions, 1211 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a8b9d019..81a72cbc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -41,6 +41,9 @@ test_programs = \
timeout-test \
tld-test \
uri-parsing \
+ websocket-test \
+ xmlrpc-old-server-test \
+ xmlrpc-old-test \
xmlrpc-server-test \
xmlrpc-test
@@ -64,22 +67,6 @@ libtest_la_SOURCES = \
LDADD = libtest.la
if HAVE_APACHE
-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 $@
-
-BUILT_SOURCES += httpd.conf
test_data += \
htdigest \
htpasswd \
@@ -94,8 +81,7 @@ soup-tests.gresource: soup-tests.gresource.xml $(RESOURCES)
EXTRA_DIST += \
htdigest \
htpasswd \
- httpd.conf.22.in \
- httpd.conf.24.in \
+ httpd.conf.in \
index.txt \
libsoup.supp \
soup-tests.gresource.xml \
@@ -116,21 +102,9 @@ check-local: check-TESTS
.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:
-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/Makefile.in b/tests/Makefile.in
index 5e432785..91f53720 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -20,7 +20,17 @@
VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@@ -83,9 +93,6 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-DIST_COMMON = $(top_srcdir)/glib-tap.mk $(srcdir)/Makefile.in \
- $(srcdir)/Makefile.am $(top_srcdir)/build-aux/depcomp \
- $(top_srcdir)/build-aux/test-driver
TESTS = $(am__EXEEXT_1)
installed_test_PROGRAMS = $(am__EXEEXT_6)
noinst_PROGRAMS = $(am__EXEEXT_7)
@@ -115,25 +122,26 @@ check_PROGRAMS = $(am__EXEEXT_5)
@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_installed_test_data)
@ENABLE_INSTALLED_TESTS_TRUE@am__append_12 = $(test_ltlibraries) $(installed_test_ltlibraries)
@ENABLE_INSTALLED_TESTS_TRUE@am__append_13 = $(installed_test_meta_DATA)
-@HAVE_APACHE_TRUE@am__append_14 = httpd.conf
-@HAVE_APACHE_TRUE@am__append_15 = \
+@HAVE_APACHE_TRUE@am__append_14 = \
@HAVE_APACHE_TRUE@ htdigest \
@HAVE_APACHE_TRUE@ htpasswd \
@HAVE_APACHE_TRUE@ httpd.conf
subdir = tests
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glibtests.m4 \
- $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
- $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \
+ $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/gtk-doc.m4 \
+ $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/vapigen.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_FILES = httpd.conf
CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
@@ -189,7 +197,9 @@ am__EXEEXT_1 = auth-test$(EXEEXT) cache-test$(EXEEXT) \
server-test$(EXEEXT) sniffing-test$(EXEEXT) \
socket-test$(EXEEXT) ssl-test$(EXEEXT) streaming-test$(EXEEXT) \
timeout-test$(EXEEXT) tld-test$(EXEEXT) uri-parsing$(EXEEXT) \
- xmlrpc-server-test$(EXEEXT) xmlrpc-test$(EXEEXT)
+ websocket-test$(EXEEXT) xmlrpc-old-server-test$(EXEEXT) \
+ xmlrpc-old-test$(EXEEXT) xmlrpc-server-test$(EXEEXT) \
+ xmlrpc-test$(EXEEXT)
am__EXEEXT_2 = $(am__EXEEXT_1)
am__EXEEXT_3 = ntlm-test-helper$(EXEEXT) $(am__EXEEXT_2)
am__EXEEXT_4 = $(am__EXEEXT_1) $(am__EXEEXT_3)
@@ -330,6 +340,18 @@ uri_parsing_SOURCES = uri-parsing.c
uri_parsing_OBJECTS = uri-parsing.$(OBJEXT)
uri_parsing_LDADD = $(LDADD)
uri_parsing_DEPENDENCIES = libtest.la
+websocket_test_SOURCES = websocket-test.c
+websocket_test_OBJECTS = websocket-test.$(OBJEXT)
+websocket_test_LDADD = $(LDADD)
+websocket_test_DEPENDENCIES = libtest.la
+xmlrpc_old_server_test_SOURCES = xmlrpc-old-server-test.c
+xmlrpc_old_server_test_OBJECTS = xmlrpc-old-server-test.$(OBJEXT)
+xmlrpc_old_server_test_LDADD = $(LDADD)
+xmlrpc_old_server_test_DEPENDENCIES = libtest.la
+xmlrpc_old_test_SOURCES = xmlrpc-old-test.c
+xmlrpc_old_test_OBJECTS = xmlrpc-old-test.$(OBJEXT)
+xmlrpc_old_test_LDADD = $(LDADD)
+xmlrpc_old_test_DEPENDENCIES = libtest.la
xmlrpc_server_test_SOURCES = xmlrpc-server-test.c
xmlrpc_server_test_OBJECTS = xmlrpc-server-test.$(OBJEXT)
xmlrpc_server_test_LDADD = $(LDADD)
@@ -382,6 +404,7 @@ SOURCES = $(libtest_la_SOURCES) auth-test.c cache-test.c \
resource-test.c server-auth-test.c server-test.c \
session-test.c sniffing-test.c socket-test.c ssl-test.c \
streaming-test.c timeout-test.c tld-test.c uri-parsing.c \
+ websocket-test.c xmlrpc-old-server-test.c xmlrpc-old-test.c \
xmlrpc-server-test.c xmlrpc-test.c
DIST_SOURCES = $(libtest_la_SOURCES) auth-test.c cache-test.c \
chunk-io-test.c chunk-test.c coding-test.c connection-test.c \
@@ -392,6 +415,7 @@ DIST_SOURCES = $(libtest_la_SOURCES) auth-test.c cache-test.c \
resource-test.c server-auth-test.c server-test.c \
session-test.c sniffing-test.c socket-test.c ssl-test.c \
streaming-test.c timeout-test.c tld-test.c uri-parsing.c \
+ websocket-test.c xmlrpc-old-server-test.c xmlrpc-old-test.c \
xmlrpc-server-test.c xmlrpc-test.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
@@ -595,6 +619,9 @@ TEST_LOGS = $(am__test_logs2:.test.log=.log)
TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
$(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/httpd.conf.in \
+ $(top_srcdir)/build-aux/depcomp \
+ $(top_srcdir)/build-aux/test-driver $(top_srcdir)/glib-tap.mk
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALL_LINGUAS = @ALL_LINGUAS@
@@ -602,7 +629,6 @@ AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
APACHE_HTTPD = @APACHE_HTTPD@
APACHE_MODULE_DIR = @APACHE_MODULE_DIR@
-APACHE_PHP_MODULE = @APACHE_PHP_MODULE@
APACHE_PHP_MODULE_DIR = @APACHE_PHP_MODULE_DIR@
APACHE_SSL_MODULE_DIR = @APACHE_SSL_MODULE_DIR@
AR = @AR@
@@ -614,6 +640,11 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
+CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@
+CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@
+CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
+CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CURL = @CURL@
@@ -629,6 +660,8 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GCOV = @GCOV@
+GENHTML = @GENHTML@
GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
@@ -647,6 +680,7 @@ GTKDOC_MKPDF = @GTKDOC_MKPDF@
GTKDOC_REBASE = @GTKDOC_REBASE@
HAVE_GNOME = @HAVE_GNOME@
HTML_DIR = @HTML_DIR@
+IF_HAVE_MOD_UNIXD = @IF_HAVE_MOD_UNIXD@
IF_HAVE_PHP = @IF_HAVE_PHP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -669,6 +703,10 @@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+KRB5_CFLAGS = @KRB5_CFLAGS@
+KRB5_CONFIG = @KRB5_CONFIG@
+KRB5_LIBS = @KRB5_LIBS@
+LCOV = @LCOV@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
@@ -680,6 +718,7 @@ LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
@@ -711,6 +750,7 @@ SOUP_AGE = @SOUP_AGE@
SOUP_API_VERSION = @SOUP_API_VERSION@
SOUP_CURRENT = @SOUP_CURRENT@
SOUP_DEBUG_FLAGS = @SOUP_DEBUG_FLAGS@
+SOUP_HIDDEN_VISIBILITY_CFLAGS = @SOUP_HIDDEN_VISIBILITY_CFLAGS@
SOUP_MAJOR_VERSION = @SOUP_MAJOR_VERSION@
SOUP_MICRO_VERSION = @SOUP_MICRO_VERSION@
SOUP_MINOR_VERSION = @SOUP_MINOR_VERSION@
@@ -719,6 +759,11 @@ SQLITE_CFLAGS = @SQLITE_CFLAGS@
SQLITE_LIBS = @SQLITE_LIBS@
STRIP = @STRIP@
USE_NLS = @USE_NLS@
+VALAC = @VALAC@
+VAPIDIR = @VAPIDIR@
+VAPIGEN = @VAPIGEN@
+VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
+VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
XML_CFLAGS = @XML_CFLAGS@
@@ -772,6 +817,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@@ -789,15 +835,15 @@ LOG_COMPILER = $(top_srcdir)/tap-test
NULL =
# initialize variables for unconditional += appending
-BUILT_SOURCES = $(am__append_14)
+BUILT_SOURCES =
BUILT_EXTRA_DIST =
CLEANFILES = *.log *.trs $(am__append_13)
DISTCLEANFILES = soup-tests.gresource httpd.conf
MAINTAINERCLEANFILES =
EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) 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)
+ htpasswd httpd.conf.in index.txt libsoup.supp \
+ soup-tests.gresource.xml test-cert.pem test-key.pem \
+ xmlrpc-server.php $(RESOURCES)
installed_test_LTLIBRARIES = $(am__append_12)
installed_test_SCRIPTS = $(am__append_10)
nobase_installed_test_DATA = $(am__append_11)
@@ -868,6 +914,9 @@ test_programs = \
timeout-test \
tld-test \
uri-parsing \
+ websocket-test \
+ xmlrpc-old-server-test \
+ xmlrpc-old-test \
xmlrpc-server-test \
xmlrpc-test
@@ -876,14 +925,12 @@ test_extra_programs = \
$(TESTS)
test_data = index.txt soup-tests.gresource test-cert.pem test-key.pem \
- xmlrpc-server.php $(am__append_15)
+ xmlrpc-server.php $(am__append_14)
libtest_la_SOURCES = \
test-utils.c \
test-utils.h
LDADD = libtest.la
-@HAVE_APACHE_2_2_FALSE@@HAVE_APACHE_TRUE@httpd_conf_in = httpd.conf.24.in
-@HAVE_APACHE_2_2_TRUE@@HAVE_APACHE_TRUE@httpd_conf_in = httpd.conf.22.in
RESOURCES = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -902,7 +949,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/glib-tap.mk $(am__co
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign tests/Makefile
-.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -911,7 +957,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
-$(top_srcdir)/glib-tap.mk:
+$(top_srcdir)/glib-tap.mk $(am__empty):
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
@@ -921,6 +967,8 @@ $(top_srcdir)/configure: $(am__configure_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
+httpd.conf: $(top_builddir)/config.status $(srcdir)/httpd.conf.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
clean-checkLTLIBRARIES:
-test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES)
@@ -1181,6 +1229,18 @@ uri-parsing$(EXEEXT): $(uri_parsing_OBJECTS) $(uri_parsing_DEPENDENCIES) $(EXTRA
@rm -f uri-parsing$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(uri_parsing_OBJECTS) $(uri_parsing_LDADD) $(LIBS)
+websocket-test$(EXEEXT): $(websocket_test_OBJECTS) $(websocket_test_DEPENDENCIES) $(EXTRA_websocket_test_DEPENDENCIES)
+ @rm -f websocket-test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(websocket_test_OBJECTS) $(websocket_test_LDADD) $(LIBS)
+
+xmlrpc-old-server-test$(EXEEXT): $(xmlrpc_old_server_test_OBJECTS) $(xmlrpc_old_server_test_DEPENDENCIES) $(EXTRA_xmlrpc_old_server_test_DEPENDENCIES)
+ @rm -f xmlrpc-old-server-test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(xmlrpc_old_server_test_OBJECTS) $(xmlrpc_old_server_test_LDADD) $(LIBS)
+
+xmlrpc-old-test$(EXEEXT): $(xmlrpc_old_test_OBJECTS) $(xmlrpc_old_test_DEPENDENCIES) $(EXTRA_xmlrpc_old_test_DEPENDENCIES)
+ @rm -f xmlrpc-old-test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(xmlrpc_old_test_OBJECTS) $(xmlrpc_old_test_LDADD) $(LIBS)
+
xmlrpc-server-test$(EXEEXT): $(xmlrpc_server_test_OBJECTS) $(xmlrpc_server_test_DEPENDENCIES) $(EXTRA_xmlrpc_server_test_DEPENDENCIES)
@rm -f xmlrpc-server-test$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(xmlrpc_server_test_OBJECTS) $(xmlrpc_server_test_LDADD) $(LIBS)
@@ -1264,6 +1324,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timeout-test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tld-test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri-parsing.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/websocket-test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-old-server-test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-old-test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-server-test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrpc-test.Po@am__quote@
@@ -1272,14 +1335,14 @@ distclean-compile:
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -1421,7 +1484,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS)
if test -n "$$am__remaking_logs"; then \
echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
"recursion detected" >&2; \
- else \
+ elif test -n "$$redo_logs"; then \
am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
fi; \
if $(am__make_dryrun); then :; else \
@@ -1756,6 +1819,27 @@ uri-parsing.log: uri-parsing$(EXEEXT)
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
+websocket-test.log: websocket-test$(EXEEXT)
+ @p='websocket-test$(EXEEXT)'; \
+ b='websocket-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+xmlrpc-old-server-test.log: xmlrpc-old-server-test$(EXEEXT)
+ @p='xmlrpc-old-server-test$(EXEEXT)'; \
+ b='xmlrpc-old-server-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+xmlrpc-old-test.log: xmlrpc-old-test$(EXEEXT)
+ @p='xmlrpc-old-test$(EXEEXT)'; \
+ b='xmlrpc-old-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
xmlrpc-server-test.log: xmlrpc-server-test$(EXEEXT)
@p='xmlrpc-server-test$(EXEEXT)'; \
b='xmlrpc-server-test'; \
@@ -1971,21 +2055,14 @@ uninstall-am: uninstall-installed_testLTLIBRARIES \
uninstall-installed_test_metaDATA \
uninstall-nobase_installed_testDATA
+.PRECIOUS: Makefile
+
@ENABLE_INSTALLED_TESTS_TRUE@%.test: %$(EXEEXT) Makefile
@ENABLE_INSTALLED_TESTS_TRUE@ $(AM_V_GEN) (echo '[Test]' > $@.tmp; \
@ENABLE_INSTALLED_TESTS_TRUE@ echo 'Type=session' >> $@.tmp; \
@ENABLE_INSTALLED_TESTS_TRUE@ echo 'Exec=$(installed_testdir)/$<' >> $@.tmp; \
@ENABLE_INSTALLED_TESTS_TRUE@ mv $@.tmp $@)
-@HAVE_APACHE_TRUE@httpd.conf: $(httpd_conf_in)
-@HAVE_APACHE_TRUE@ $(AM_V_GEN) sed -e 's,[@]srcdir@,$(srcdir),' \
-@HAVE_APACHE_TRUE@ -e 's,[@]builddir@,$(builddir),' \
-@HAVE_APACHE_TRUE@ -e 's,[@]APACHE_MODULE_DIR@,$(APACHE_MODULE_DIR),' \
-@HAVE_APACHE_TRUE@ -e 's,[@]APACHE_PHP_MODULE_DIR@,$(APACHE_PHP_MODULE_DIR),' \
-@HAVE_APACHE_TRUE@ -e 's,[@]APACHE_PHP_MODULE@,$(APACHE_PHP_MODULE),' \
-@HAVE_APACHE_TRUE@ -e 's,[@]IF_HAVE_PHP@,$(IF_HAVE_PHP),' \
-@HAVE_APACHE_TRUE@ -e 's,[@]APACHE_SSL_MODULE_DIR@,$(APACHE_SSL_MODULE_DIR),' \
-@HAVE_APACHE_TRUE@ $< > $@ || rm -f $@
soup-tests.gresource: soup-tests.gresource.xml $(RESOURCES)
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $<
@@ -1998,16 +2075,12 @@ check-local: check-TESTS
.PHONY: start-httpd kill-httpd
start-httpd:
-@HAVE_APACHE_2_2_TRUE@ @$(APACHE_HTTPD) -d $(abs_srcdir) -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k start;
-@HAVE_APACHE_2_4_TRUE@ @$(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k start;
+ @$(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k start;
kill-httpd:
-@HAVE_APACHE_2_2_TRUE@ @if [ -f httpd.pid ]; then \
-@HAVE_APACHE_2_2_TRUE@ $(APACHE_HTTPD) -d $(abs_srcdir) -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k stop; \
-@HAVE_APACHE_2_2_TRUE@ fi
-@HAVE_APACHE_2_4_TRUE@ @if [ -f httpd.pid ]; then \
-@HAVE_APACHE_2_4_TRUE@ $(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k stop; \
-@HAVE_APACHE_2_4_TRUE@ fi
+ @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
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/tests/auth-test.c b/tests/auth-test.c
index 8ed5cead..1144decf 100644
--- a/tests/auth-test.c
+++ b/tests/auth-test.c
@@ -414,13 +414,18 @@ digest_nonce_unauthorized (SoupMessage *msg, gpointer data)
static void
do_digest_nonce_test (SoupSession *session,
- const char *nth, const char *uri,
+ const char *nth, const char *uri, gboolean use_auth_cache,
gboolean expect_401, gboolean expect_signal)
{
SoupMessage *msg;
gboolean got_401;
msg = soup_message_new (SOUP_METHOD_GET, uri);
+ if (!use_auth_cache) {
+ SoupMessageFlags flags = soup_message_get_flags (msg);
+
+ soup_message_set_flags (msg, flags | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE);
+ }
if (expect_signal) {
g_signal_connect (session, "authenticate",
G_CALLBACK (digest_nonce_authenticate),
@@ -437,6 +442,12 @@ do_digest_nonce_test (SoupSession *session,
got_401 ? "got" : "did not get");
soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ if (expect_signal) {
+ g_signal_handlers_disconnect_by_func (session,
+ G_CALLBACK (digest_nonce_authenticate),
+ NULL);
+ }
+
g_object_unref (msg);
}
@@ -451,15 +462,15 @@ do_digest_expiration_test (void)
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
uri = g_strconcat (base_uri, "Digest/realm1/", NULL);
- do_digest_nonce_test (session, "First", uri, TRUE, TRUE);
+ do_digest_nonce_test (session, "First", uri, TRUE, TRUE, TRUE);
g_free (uri);
sleep (2);
uri = g_strconcat (base_uri, "Digest/realm1/expire/", NULL);
- do_digest_nonce_test (session, "Second", uri, TRUE, FALSE);
+ do_digest_nonce_test (session, "Second", uri, TRUE, TRUE, FALSE);
sleep (1);
- do_digest_nonce_test (session, "Third", uri, FALSE, FALSE);
+ do_digest_nonce_test (session, "Third", uri, TRUE, FALSE, FALSE);
sleep (1);
- do_digest_nonce_test (session, "Fourth", uri, FALSE, FALSE);
+ do_digest_nonce_test (session, "Fourth", uri, TRUE, FALSE, FALSE);
g_free (uri);
soup_test_session_abort_unref (session);
@@ -864,12 +875,10 @@ do_select_auth_test (void)
* side of this scenario correctly, because we test it against
* curl in server-auth-test.
*/
- server = soup_test_server_new (FALSE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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));
+ uri = soup_test_server_get_uri (server, "http", NULL);
basic_auth_domain = soup_auth_domain_basic_new (
SOUP_AUTH_DOMAIN_REALM, "auth-test",
@@ -1012,12 +1021,12 @@ do_auth_close_test (void)
SoupURI *uri;
AuthCloseData acd;
- server = soup_test_server_new (FALSE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
soup_server_add_handler (server, NULL,
server_callback, NULL, NULL);
- uri = soup_uri_new ("http://127.0.0.1/close");
- soup_uri_set_port (uri, soup_server_get_port (server));
+ uri = soup_test_server_get_uri (server, "http", NULL);
+ soup_uri_set_path (uri, "/close");
basic_auth_domain = soup_auth_domain_basic_new (
SOUP_AUTH_DOMAIN_REALM, "auth-test",
@@ -1123,14 +1132,13 @@ do_disappearing_auth_test (void)
SoupSession *session;
int counter;
- g_test_bug ("https://bugzilla.redhat.com/show_bug.cgi?id=916224");
+ g_test_bug_base ("https://bugzilla.redhat.com/");
+ g_test_bug ("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));
+ uri = soup_test_server_get_uri (server, "http", NULL);
auth_domain = soup_auth_domain_basic_new (
SOUP_AUTH_DOMAIN_REALM, "auth-test",
@@ -1187,6 +1195,17 @@ static SoupAuthTest relogin_tests[] = {
{ NULL }
};
+/* https://bugzilla.gnome.org/show_bug.cgi?id=755617 */
+static SoupAuthTest basic_root_pspace_test[] = {
+ { "Auth provided via URL, should succeed",
+ "BasicRoot", "1", TRUE, "01", SOUP_STATUS_OK },
+
+ { "Parent dir should automatically reuse auth",
+ "/", "1", FALSE, "1", SOUP_STATUS_OK },
+
+ { NULL }
+};
+
static void
do_batch_tests (gconstpointer data)
{
@@ -1257,6 +1276,220 @@ do_batch_tests (gconstpointer data)
soup_test_session_abort_unref (session);
}
+static void
+do_clear_credentials_test (void)
+{
+ SoupSession *session;
+ SoupAuthManager *manager;
+ char *uri;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+
+ uri = g_strconcat (base_uri, "Digest/realm1/", NULL);
+ do_digest_nonce_test (session, "First", uri, TRUE, TRUE, TRUE);
+
+ manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER));
+ soup_auth_manager_clear_cached_credentials (manager);
+
+ do_digest_nonce_test (session, "Second", uri, TRUE, TRUE, TRUE);
+ g_free (uri);
+
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_message_do_not_use_auth_cache_test (void)
+{
+ SoupSession *session;
+ SoupAuthManager *manager;
+ SoupMessage *msg;
+ SoupMessageFlags flags;
+ SoupURI *soup_uri;
+ char *uri;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+
+ uri = g_strconcat (base_uri, "Digest/realm1/", NULL);
+
+ /* First check that cached credentials are not used */
+ do_digest_nonce_test (session, "First", uri, TRUE, TRUE, TRUE);
+ do_digest_nonce_test (session, "Second", uri, TRUE, FALSE, FALSE);
+ do_digest_nonce_test (session, "Third", uri, FALSE, TRUE, TRUE);
+
+ /* Passing credentials in the URI should always authenticate
+ * no matter whether the cache is used or not
+ */
+ soup_uri = soup_uri_new (uri);
+ soup_uri_set_user (soup_uri, "user1");
+ soup_uri_set_password (soup_uri, "realm1");
+ msg = soup_message_new_from_uri (SOUP_METHOD_GET, soup_uri);
+ flags = soup_message_get_flags (msg);
+ soup_message_set_flags (msg, flags | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_object_unref (msg);
+ soup_uri_free (soup_uri);
+
+ manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER));
+
+ soup_auth_manager_clear_cached_credentials (manager);
+
+ /* Now check that credentials are not stored */
+ do_digest_nonce_test (session, "First", uri, FALSE, TRUE, TRUE);
+ do_digest_nonce_test (session, "Second", uri, TRUE, TRUE, TRUE);
+ do_digest_nonce_test (session, "Third", uri, TRUE, FALSE, FALSE);
+
+ /* Credentials were stored for uri, but if we set SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE flag,
+ * and we don't have the authenticate signal, it should respond with 401
+ */
+ msg = soup_message_new (SOUP_METHOD_GET, uri);
+ flags = soup_message_get_flags (msg);
+ soup_message_set_flags (msg, flags | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED);
+ g_object_unref (msg);
+ g_free (uri);
+
+ soup_test_session_abort_unref (session);
+}
+
+static void
+async_no_auth_cache_authenticate (SoupSession *session, SoupMessage *msg,
+ SoupAuth *auth, gboolean retrying, SoupAuth **auth_out)
+{
+ debug_printf (1, " async_no_auth_cache_authenticate\n");
+
+ soup_session_pause_message (session, msg);
+ *auth_out = g_object_ref (auth);
+ g_main_loop_quit (loop);
+}
+
+static void
+async_no_auth_cache_finished (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+ debug_printf (1, " async_no_auth_cache_finished\n");
+
+ g_main_loop_quit (loop);
+}
+
+static void
+do_async_message_do_not_use_auth_cache_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ char *uri;
+ SoupAuth *auth = NULL;
+ SoupMessageFlags flags;
+
+ 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);
+
+ msg = soup_message_new ("GET", uri);
+ g_free (uri);
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (async_no_auth_cache_authenticate), &auth);
+ flags = soup_message_get_flags (msg);
+ soup_message_set_flags (msg, flags | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE);
+ g_object_ref (msg);
+ soup_session_queue_message (session, msg, async_no_auth_cache_finished, NULL);
+ g_main_loop_run (loop);
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED);
+
+ soup_test_assert (auth, "msg didn't get authenticate signal");
+ soup_auth_authenticate (auth, "user1", "realm1");
+ g_object_unref (auth);
+
+ soup_session_unpause_message (session, msg);
+ g_main_loop_run (loop);
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
+ soup_test_session_abort_unref (session);
+ g_object_unref (msg);
+ g_main_loop_unref (loop);
+}
+
+static void
+has_authorization_header_authenticate (SoupSession *session, SoupMessage *msg,
+ SoupAuth *auth, gboolean retrying, gpointer data)
+{
+ SoupAuth **saved_auth = data;
+
+ soup_auth_authenticate (auth, "user1", "realm1");
+ *saved_auth = g_object_ref (auth);
+}
+
+static void
+has_authorization_header_authenticate_assert (SoupSession *session, SoupMessage *msg,
+ SoupAuth *auth, gboolean retrying, gpointer data)
+{
+ soup_test_assert (FALSE, "authenticate emitted unexpectedly");
+}
+
+static void
+do_message_has_authorization_header_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ SoupAuthManager *manager;
+ SoupAuth *auth = NULL;
+ char *token;
+ guint auth_id;
+ char *uri;
+
+ g_test_bug ("775882");
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ uri = g_strconcat (base_uri, "Digest/realm1/", NULL);
+
+ msg = soup_message_new ("GET", uri);
+ auth_id = g_signal_connect (session, "authenticate",
+ G_CALLBACK (has_authorization_header_authenticate), &auth);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ soup_test_assert (SOUP_IS_AUTH (auth), "Expected a SoupAuth");
+ token = soup_auth_get_authorization (auth, msg);
+ g_object_unref (auth);
+ g_object_unref (msg);
+ g_signal_handler_disconnect (session, auth_id);
+
+ manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER));
+ soup_auth_manager_clear_cached_credentials (manager);
+
+ msg = soup_message_new ("GET", uri);
+ soup_message_headers_replace (msg->request_headers, "Authorization", token);
+ auth_id = g_signal_connect (session, "authenticate",
+ G_CALLBACK (has_authorization_header_authenticate_assert),
+ NULL);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_object_unref (msg);
+
+ /* Check that we can also provide our own Authorization header when not using credentials cache. */
+ soup_auth_manager_clear_cached_credentials (manager);
+ msg = soup_message_new ("GET", uri);
+ soup_message_headers_replace (msg->request_headers, "Authorization", token);
+ soup_message_set_flags (msg, soup_message_get_flags (msg) | SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_object_unref (msg);
+ g_free (token);
+ g_signal_handler_disconnect (session, auth_id);
+
+ g_free (uri);
+ soup_test_session_abort_unref (session);
+}
+
int
main (int argc, char **argv)
{
@@ -1269,6 +1502,7 @@ main (int argc, char **argv)
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_data_func ("/auth/basic-root-pspec-test", basic_root_pspace_test, 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);
@@ -1278,6 +1512,10 @@ main (int argc, char **argv)
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);
+ g_test_add_func ("/auth/clear-credentials", do_clear_credentials_test);
+ g_test_add_func ("/auth/message-do-not-use-auth-cache", do_message_do_not_use_auth_cache_test);
+ g_test_add_func ("/auth/async-message-do-not-use-auth-cache", do_async_message_do_not_use_auth_cache_test);
+ g_test_add_func ("/auth/authorization-header-request", do_message_has_authorization_header_test);
ret = g_test_run ();
diff --git a/tests/cache-test.c b/tests/cache-test.c
index 3478f377..7d5897c0 100644
--- a/tests/cache-test.c
+++ b/tests/cache-test.c
@@ -122,6 +122,7 @@ static char *do_request (SoupSession *session,
static gboolean last_request_hit_network;
static gboolean last_request_validated;
+static gboolean last_request_unqueued;
static guint cancelled_requests;
static void
@@ -152,6 +153,7 @@ do_request (SoupSession *session,
GError *error = NULL;
last_request_validated = last_request_hit_network = FALSE;
+ last_request_unqueued = FALSE;
uri = soup_uri_new_with_base (base_uri, path);
req = soup_session_request_http_uri (session, method, uri, NULL);
@@ -181,6 +183,12 @@ do_request (SoupSession *session,
g_object_unref (msg);
+ if (last_request_validated)
+ last_request_unqueued = FALSE;
+ else
+ soup_test_assert (!last_request_unqueued,
+ "Request unqueued before finishing");
+
last_request_hit_network = is_network_stream (stream);
g_input_stream_read_all (stream, buf, sizeof (buf), &nread,
@@ -219,7 +227,7 @@ do_request_with_cancel (SoupSession *session,
GError *error = NULL;
GCancellable *cancellable;
- last_request_validated = last_request_hit_network = FALSE;
+ last_request_validated = last_request_hit_network = last_request_unqueued = FALSE;
cancelled_requests = 0;
uri = soup_uri_new_with_base (base_uri, path);
@@ -232,7 +240,8 @@ do_request_with_cancel (SoupSession *session,
g_object_unref (stream);
g_object_unref (req);
return;
- }
+ } else
+ g_clear_error (&error);
g_clear_object (&cancellable);
g_clear_object (&stream);
@@ -242,8 +251,7 @@ do_request_with_cancel (SoupSession *session,
}
static void
-request_started (SoupSession *session, SoupMessage *msg,
- SoupSocket *socket)
+message_starting (SoupMessage *msg, gpointer data)
{
if (soup_message_headers_get_one (msg->request_headers,
"If-Modified-Since") ||
@@ -256,11 +264,21 @@ request_started (SoupSession *session, SoupMessage *msg,
}
static void
+request_queued (SoupSession *session, SoupMessage *msg,
+ gpointer data)
+{
+ g_signal_connect (msg, "starting",
+ G_CALLBACK (message_starting),
+ data);
+}
+
+static void
request_unqueued (SoupSession *session, SoupMessage *msg,
gpointer data)
{
if (msg->status_code == SOUP_STATUS_CANCELLED)
cancelled_requests++;
+ last_request_unqueued = TRUE;
}
static void
@@ -279,8 +297,11 @@ do_basics_test (gconstpointer data)
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
SOUP_SESSION_ADD_FEATURE, cache,
NULL);
- g_signal_connect (session, "request-started",
- G_CALLBACK (request_started), NULL);
+
+ g_signal_connect (session, "request-queued",
+ G_CALLBACK (request_queued), 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,
@@ -288,9 +309,11 @@ do_basics_test (gconstpointer data)
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);
body3 = do_request (session, base_uri, "GET", "/3", NULL,
"Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT",
+ "Test-Set-Expires", "Sat, 02 Jan 2011 00:00:00 GMT",
"Test-Set-Cache-Control", "must-revalidate",
NULL);
body4 = do_request (session, base_uri, "GET", "/4", NULL,
@@ -308,6 +331,8 @@ do_basics_test (gconstpointer data)
NULL);
soup_test_assert (!last_request_hit_network,
"Request for /1 not filled from cache");
+ soup_test_assert (last_request_unqueued,
+ "Cached resource /1 not unqueued");
g_assert_cmpstr (body1, ==, cmp);
g_free (cmp);
@@ -316,8 +341,13 @@ do_basics_test (gconstpointer data)
debug_printf (1, " Heuristically-fresh cached resource\n");
cmp = do_request (session, base_uri, "GET", "/2", NULL,
NULL);
+ /* Not validated even if it has must-revalidate, because it hasn't expired */
+ soup_test_assert (!last_request_validated,
+ "Request for /2 was validated");
soup_test_assert (!last_request_hit_network,
"Request for /2 not filled from cache");
+ soup_test_assert (last_request_unqueued,
+ "Cached resource /2 not unqueued");
g_assert_cmpstr (body2, ==, cmp);
g_free (cmp);
@@ -328,26 +358,33 @@ do_basics_test (gconstpointer data)
NULL);
soup_test_assert (last_request_hit_network,
"Request for /1?attr=value filled from cache");
+ soup_test_assert (last_request_unqueued,
+ "Cached resource /1?attr=value not unqueued");
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");
+ soup_test_assert (last_request_unqueued,
+ "Request for /1 not unqueued");
g_assert_cmpstr (body1, ==, cmp);
g_free (cmp);
- /* Last-Modified + must-revalidate causes a conditional request */
+ /* Expired + 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-Expires", "Sat, 02 Jan 2011 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");
+ soup_test_assert (last_request_unqueued,
+ "Cached resource /3 not unqueued");
g_assert_cmpstr (body3, ==, cmp);
g_free (cmp);
@@ -356,12 +393,15 @@ do_basics_test (gconstpointer data)
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-Expires", "Sat, 02 Jan 2011 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");
+ soup_test_assert (last_request_unqueued,
+ "Request for /3 not unqueued");
g_assert_cmpstr (body3, !=, cmp);
g_free (cmp);
@@ -374,6 +414,8 @@ do_basics_test (gconstpointer data)
"Second request for /3 not validated");
soup_test_assert (!last_request_hit_network,
"Second request for /3 not filled from cache");
+ soup_test_assert (last_request_unqueued,
+ "Cached resource /3 not unqueued");
g_assert_cmpstr (body3, !=, cmp);
g_free (cmp);
@@ -386,6 +428,8 @@ do_basics_test (gconstpointer data)
"Request for /4 not validated");
soup_test_assert (!last_request_hit_network,
"Request for /4 not filled from cache");
+ soup_test_assert (last_request_unqueued,
+ "Cached resource /4 not unqueued");
g_assert_cmpstr (body4, ==, cmp);
g_free (cmp);
@@ -397,6 +441,8 @@ do_basics_test (gconstpointer data)
NULL);
soup_test_assert (last_request_hit_network,
"Request for /5 filled from cache");
+ soup_test_assert (last_request_unqueued,
+ "Request for /5 not unqueued");
g_assert_cmpstr (body5, ==, cmp);
g_free (cmp);
@@ -455,6 +501,7 @@ do_cancel_test (gconstpointer data)
NULL);
body2 = do_request (session, base_uri, "GET", "/2", NULL,
"Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT",
+ "Test-Set-Expires", "Fri, 01 Jan 2011 00:00:00 GMT",
"Test-Set-Cache-Control", "must-revalidate",
NULL);
@@ -463,11 +510,15 @@ do_cancel_test (gconstpointer data)
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);
+ soup_test_assert (last_request_unqueued,
+ "Cancelled request /1 not unqueued");
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_assert (last_request_unqueued,
+ "Cancelled request /1 not unqueued");
soup_test_session_abort_unref (session);
@@ -483,11 +534,15 @@ do_cancel_test (gconstpointer data)
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);
+ soup_test_assert (last_request_unqueued,
+ "Cancelled request /2 not unqueued");
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_assert (last_request_unqueued,
+ "Cancelled request /2 not unqueued");
soup_test_session_abort_unref (session);
@@ -588,8 +643,8 @@ do_headers_test (gconstpointer data)
SOUP_SESSION_ADD_FEATURE, cache,
NULL);
- g_signal_connect (session, "request-started",
- G_CALLBACK (request_started), NULL);
+ g_signal_connect (session, "request-queued",
+ G_CALLBACK (request_queued), NULL);
debug_printf (2, " Initial requests\n");
body1 = do_request (session, base_uri, "GET", "/1", NULL,
@@ -630,6 +685,85 @@ do_headers_test (gconstpointer data)
g_free (body1);
}
+static guint
+count_cached_resources_in_dir (const char *cache_dir)
+{
+ GDir *dir;
+ const char *name;
+ guint retval = 0;
+
+ dir = g_dir_open (cache_dir, 0, NULL);
+ while ((name = g_dir_read_name (dir))) {
+ if (g_str_has_prefix (name, "soup."))
+ continue;
+
+ retval++;
+ }
+ g_dir_close (dir);
+
+ return retval;
+}
+
+static void
+do_leaks_test (gconstpointer data)
+{
+ SoupURI *base_uri = (SoupURI *)data;
+ SoupSession *session;
+ SoupCache *cache;
+ char *cache_dir;
+ char *body;
+
+ 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);
+
+ debug_printf (2, " Initial requests\n");
+ body = do_request (session, base_uri, "GET", "/1", NULL,
+ "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT",
+ NULL);
+ g_free (body);
+ body = do_request (session, base_uri, "GET", "/2", NULL,
+ "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT",
+ NULL);
+ g_free (body);
+ body = do_request (session, base_uri, "GET", "/3", NULL,
+ "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT",
+ NULL);
+ g_free (body);
+
+ debug_printf (2, " Dumping the cache\n");
+ soup_cache_dump (cache);
+
+ g_assert_cmpuint (count_cached_resources_in_dir (cache_dir), ==, 3);
+
+ body = do_request (session, base_uri, "GET", "/4", NULL,
+ "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT",
+ NULL);
+ g_free (body);
+ body = do_request (session, base_uri, "GET", "/5", NULL,
+ "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT",
+ NULL);
+ g_free (body);
+
+ /* Destroy the cache without dumping the last two resources */
+ soup_test_session_abort_unref (session);
+ g_object_unref (cache);
+
+ cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER);
+
+ debug_printf (2, " Loading the cache\n");
+ g_assert_cmpuint (count_cached_resources_in_dir (cache_dir), ==, 5);
+ soup_cache_load (cache);
+ g_assert_cmpuint (count_cached_resources_in_dir (cache_dir), ==, 3);
+
+ g_object_unref (cache);
+ g_free (cache_dir);
+}
+
int
main (int argc, char **argv)
{
@@ -641,13 +775,13 @@ main (int argc, char **argv)
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));
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
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);
+ g_test_add_data_func ("/cache/leaks", base_uri, do_leaks_test);
ret = g_test_run ();
diff --git a/tests/chunk-io-test.c b/tests/chunk-io-test.c
index 1e53eef1..4746ea6c 100644
--- a/tests/chunk-io-test.c
+++ b/tests/chunk-io-test.c
@@ -10,7 +10,6 @@ force_io_streams_init (void)
{
SoupServer *server;
SoupSession *session;
- guint port;
SoupURI *base_uri;
SoupMessage *msg;
@@ -20,10 +19,7 @@ force_io_streams_init (void)
*/
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);
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
msg = soup_message_new_from_uri ("POST", base_uri);
diff --git a/tests/chunk-test.c b/tests/chunk-test.c
index 864f8620..c658cbd4 100644
--- a/tests/chunk-test.c
+++ b/tests/chunk-test.c
@@ -314,7 +314,8 @@ do_temporary_test (void)
char *client_md5;
const char *server_md5;
- g_test_bug ("https://bugs.webkit.org/show_bug.cgi?id=18343");
+ g_test_bug_base ("https://bugs.webkit.org/");
+ g_test_bug ("18343");
msg = soup_message_new_from_uri ("PUT", base_uri);
soup_message_body_append (msg->request_body, SOUP_MEMORY_TEMPORARY,
@@ -427,21 +428,17 @@ main (int argc, char **argv)
{
GMainLoop *loop;
SoupServer *server;
- guint port;
int ret;
test_init (argc, argv, NULL);
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
soup_server_add_handler (server, NULL,
server_callback, NULL, NULL);
- port = soup_server_get_port (server);
loop = g_main_loop_new (NULL, TRUE);
- base_uri = soup_uri_new ("http://127.0.0.1");
- soup_uri_set_port (base_uri, port);
-
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
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);
diff --git a/tests/coding-test.c b/tests/coding-test.c
index 0445f632..de2949be 100644
--- a/tests/coding-test.c
+++ b/tests/coding-test.c
@@ -486,10 +486,9 @@ main (int argc, char **argv)
test_init (argc, argv, NULL);
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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 = soup_test_server_get_uri (server, "http", NULL);
g_test_add ("/coding/message/plain", CodingTestData,
GINT_TO_POINTER (CODING_TEST_NO_DECODER),
diff --git a/tests/connection-test.c b/tests/connection-test.c
index 8f8c74be..ec54daea 100644
--- a/tests/connection-test.c
+++ b/tests/connection-test.c
@@ -51,16 +51,21 @@ timeout_request_started (SoupServer *server, SoupMessage *msg,
SoupClientContext *client, gpointer user_data)
{
SoupSocket *sock;
- GMainContext *context = soup_server_get_async_context (server);
+ GMainContext *context = g_main_context_get_thread_default ();
guint readable;
+ g_signal_handlers_disconnect_by_func (server, timeout_request_started, NULL);
+
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
sock = soup_client_context_get_socket (client);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
readable = g_signal_connect (sock, "readable",
G_CALLBACK (timeout_socket), NULL);
+
+ g_mutex_unlock (&server_mutex);
while (soup_socket_is_connected (sock))
g_main_context_iteration (context, TRUE);
g_signal_handler_disconnect (sock, readable);
- g_signal_handlers_disconnect_by_func (server, timeout_request_started, NULL);
}
static void
@@ -78,17 +83,18 @@ setup_timeout_persistent (SoupServer *server, SoupSocket *sock)
* fail (since the client is waiting for us to
* return a response). This will cause it to
* emit "readable" later.
- * 2. Connect to the server's request-started signal.
- * 3. Run an inner main loop from that signal handler
- * until the socket emits "readable". (If we don't
- * do this then it's possible the client's next
- * request would be ready before we returned to
- * the main loop, and so the signal would never be
- * emitted.)
+ * 2. Wait for the server to finish this request and
+ * start reading the next one (and lock server_mutex
+ * to interlock with the client and ensure that it
+ * doesn't start writing its next request until
+ * that point).
+ * 3. Block until "readable" is emitted, meaning the
+ * client has written its request.
* 4. Close the socket.
*/
soup_socket_read (sock, buf, 1, &nread, NULL, NULL);
+ g_mutex_lock (&server_mutex);
g_signal_connect (server, "request-started",
G_CALLBACK (timeout_request_started), NULL);
}
@@ -130,7 +136,9 @@ server_callback (SoupServer *server, SoupMessage *msg,
* the declared Content-Length. Instead, we
* forcibly close the socket at that point.
*/
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
sock = soup_client_context_get_socket (context);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
g_signal_connect (msg, "wrote-chunk",
G_CALLBACK (close_socket), sock);
} else if (no_close) {
@@ -148,7 +156,9 @@ server_callback (SoupServer *server, SoupMessage *msg,
if (!strcmp (path, "/timeout-persistent")) {
SoupSocket *sock;
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
sock = soup_client_context_get_socket (context);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
setup_timeout_persistent (server, sock);
}
@@ -250,6 +260,12 @@ do_timeout_test_for_session (SoupSession *session)
}
g_object_unref (msg);
+ /* The server will grab server_mutex before returning the response,
+ * and release it when it's ready for us to send the second request.
+ */
+ g_mutex_lock (&server_mutex);
+ g_mutex_unlock (&server_mutex);
+
debug_printf (1, " Second message\n");
msg = soup_message_new_from_uri ("GET", base_uri);
soup_session_send_message (session, msg);
@@ -314,6 +330,12 @@ do_timeout_req_test_for_session (SoupSession *session)
}
g_object_unref (req);
+ /* The server will grab server_mutex before returning the response,
+ * and release it when it's ready for us to send the second request.
+ */
+ g_mutex_lock (&server_mutex);
+ g_mutex_unlock (&server_mutex);
+
debug_printf (1, " Second request\n");
req = soup_session_request_uri (session, base_uri, NULL);
@@ -382,7 +404,7 @@ static GMainLoop *max_conns_loop;
static int msgs_done;
static guint quit_loop_timeout;
#define MAX_CONNS 2
-#define TEST_CONNS (MAX_CONNS * 2)
+#define TEST_CONNS (MAX_CONNS * 2) + 1
static gboolean
idle_start_server (gpointer data)
@@ -403,7 +425,7 @@ static void
max_conns_request_started (SoupSession *session, SoupMessage *msg,
SoupSocket *socket, gpointer user_data)
{
- if (++msgs_done == MAX_CONNS) {
+ if (++msgs_done >= MAX_CONNS) {
if (quit_loop_timeout)
g_source_remove (quit_loop_timeout);
quit_loop_timeout = g_timeout_add (100, quit_loop, NULL);
@@ -420,7 +442,8 @@ max_conns_message_complete (SoupSession *session, SoupMessage *msg, gpointer use
static void
do_max_conns_test_for_session (SoupSession *session)
{
- SoupMessage *msgs[TEST_CONNS];
+ SoupMessage *msgs[TEST_CONNS + 1];
+ SoupMessageFlags flags;
int i;
max_conns_loop = g_main_loop_new (NULL, TRUE);
@@ -430,7 +453,7 @@ do_max_conns_test_for_session (SoupSession *session)
g_signal_connect (session, "request-started",
G_CALLBACK (max_conns_request_started), NULL);
msgs_done = 0;
- for (i = 0; i < TEST_CONNS; i++) {
+ for (i = 0; i < TEST_CONNS - 1; i++) {
msgs[i] = soup_message_new_from_uri ("GET", base_uri);
g_object_ref (msgs[i]);
soup_session_queue_message (session, msgs[i],
@@ -439,6 +462,21 @@ do_max_conns_test_for_session (SoupSession *session)
g_main_loop_run (max_conns_loop);
g_assert_cmpint (msgs_done, ==, MAX_CONNS);
+
+ if (quit_loop_timeout)
+ g_source_remove (quit_loop_timeout);
+ quit_loop_timeout = g_timeout_add (1000, quit_loop, NULL);
+
+ /* Message with SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS should start */
+ msgs[i] = soup_message_new_from_uri ("GET", base_uri);
+ flags = soup_message_get_flags (msgs[i]);
+ soup_message_set_flags (msgs[i], flags | SOUP_MESSAGE_IGNORE_CONNECTION_LIMITS);
+ g_object_ref (msgs[i]);
+ soup_session_queue_message (session, msgs[i],
+ max_conns_message_complete, NULL);
+
+ g_main_loop_run (max_conns_loop);
+ g_assert_cmpint (msgs_done, ==, MAX_CONNS + 1);
g_signal_handlers_disconnect_by_func (session, max_conns_request_started, NULL);
msgs_done = 0;
@@ -762,11 +800,46 @@ network_event (SoupMessage *msg, GSocketClientEvent event,
{
const char **events = user_data;
- debug_printf (2, " %s\n", event_name_from_abbrev (**events));
+ debug_printf (2, " %s\n", event_names[event]);
soup_test_assert (**events == event_abbrevs[event],
- "Unexpected event: %s (expected %s)\n",
+ "Unexpected event: %s (expected %s)",
event_names[event],
event_name_from_abbrev (**events));
+
+ if (**events == event_abbrevs[event]) {
+ if (event == G_SOCKET_CLIENT_RESOLVING ||
+ event == G_SOCKET_CLIENT_RESOLVED) {
+ soup_test_assert (connection == NULL,
+ "Unexpectedly got connection (%s) with '%s' event",
+ G_OBJECT_TYPE_NAME (connection),
+ event_names[event]);
+ } else if (event < G_SOCKET_CLIENT_TLS_HANDSHAKING) {
+ soup_test_assert (G_IS_SOCKET_CONNECTION (connection),
+ "Unexpectedly got %s with '%s' event",
+ G_OBJECT_TYPE_NAME (connection),
+ event_names[event]);
+ } else if (event == G_SOCKET_CLIENT_TLS_HANDSHAKING ||
+ event == G_SOCKET_CLIENT_TLS_HANDSHAKED) {
+ soup_test_assert (G_IS_TLS_CLIENT_CONNECTION (connection),
+ "Unexpectedly got %s with '%s' event",
+ G_OBJECT_TYPE_NAME (connection),
+ event_names[event]);
+ } else if (event == G_SOCKET_CLIENT_COMPLETE) {
+ /* See if the previous expected event was TLS_HANDSHAKED */
+ if ((*events)[-1] == 'T') {
+ soup_test_assert (G_IS_TLS_CLIENT_CONNECTION (connection),
+ "Unexpectedly got %s with '%s' event",
+ G_OBJECT_TYPE_NAME (connection),
+ event_names[event]);
+ } else {
+ soup_test_assert (G_IS_SOCKET_CONNECTION (connection),
+ "Unexpectedly got %s with '%s' event",
+ G_OBJECT_TYPE_NAME (connection),
+ event_names[event]);
+ }
+ }
+ }
+
*events = *events + 1;
}
@@ -841,6 +914,186 @@ do_connection_event_test (void)
soup_test_session_abort_unref (session);
}
+typedef struct {
+ GMainLoop *loop;
+ GIOStream *stream;
+ GError *error;
+ const char *events;
+} ConnectTestData;
+
+static void
+connect_progress (SoupSession *session, GSocketClientEvent event, GIOStream *connection, ConnectTestData *data)
+{
+ soup_test_assert (*data->events == event_abbrevs[event],
+ "Unexpected event: %s (expected %s)",
+ event_names[event],
+ event_name_from_abbrev (*data->events));
+ data->events = data->events + 1;
+}
+
+static void
+connect_finished (SoupSession *session, GAsyncResult *result, ConnectTestData *data)
+{
+ data->stream = soup_session_connect_finish (session, result, &data->error);
+ g_main_loop_quit (data->loop);
+}
+
+static void
+do_one_connection_connect_test (SoupSession *session, SoupURI *uri, const char *response, const char *events)
+{
+ ConnectTestData data = { NULL, NULL, NULL, events };
+ static const char *request = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n";
+ gsize bytes = 0;
+ char buffer[128];
+
+ data.loop = g_main_loop_new (NULL, FALSE);
+ soup_session_connect_async (session, uri, NULL,
+ (SoupSessionConnectProgressCallback)connect_progress,
+ (GAsyncReadyCallback)connect_finished,
+ &data);
+ g_main_loop_run (data.loop);
+
+ g_assert (G_IS_IO_STREAM (data.stream));
+ g_assert_no_error (data.error);
+ g_assert (g_output_stream_write_all (g_io_stream_get_output_stream (data.stream),
+ request, strlen (request), &bytes, NULL, NULL));
+ g_assert (g_input_stream_read_all (g_io_stream_get_input_stream (data.stream),
+ buffer, sizeof (buffer), &bytes, NULL, NULL));
+ buffer[strlen (response)] = '\0';
+ g_assert_cmpstr (buffer, ==, response);
+
+ while (*data.events) {
+ soup_test_assert (!*data.events,
+ "Expected %s",
+ event_name_from_abbrev (*data.events));
+ data.events++;
+ }
+
+ g_object_unref (data.stream);
+ g_main_loop_unref (data.loop);
+}
+
+static void
+do_one_connection_connect_fail_test (SoupSession *session, SoupURI *uri, GQuark domain, gint code, const char *events)
+{
+ ConnectTestData data = { NULL, NULL, NULL, events };
+
+ data.loop = g_main_loop_new (NULL, FALSE);
+ soup_session_connect_async (session, uri, NULL,
+ (SoupSessionConnectProgressCallback)connect_progress,
+ (GAsyncReadyCallback)connect_finished,
+ &data);
+ g_main_loop_run (data.loop);
+
+ g_assert (!data.stream);
+ g_assert_error (data.error, domain, code);
+
+ while (*data.events) {
+ soup_test_assert (!*data.events,
+ "Expected %s",
+ event_name_from_abbrev (*data.events));
+ data.events++;
+ }
+}
+
+static void
+do_connection_connect_test (void)
+{
+ SoupSession *session;
+ SoupURI *http_uri;
+ SoupURI *https_uri = NULL;
+ SoupURI *ws_uri;
+ SoupURI *wss_uri = NULL;
+ SoupURI *file_uri;
+ SoupURI *wrong_http_uri;
+ SoupURI *proxy_uri;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ NULL);
+
+ debug_printf (1, " http\n");
+ http_uri = soup_uri_new (HTTP_SERVER);
+ do_one_connection_connect_test (session, http_uri,
+ "HTTP/1.1 200 OK", "rRcCx");
+
+ if (tls_available) {
+ debug_printf (1, " https\n");
+ https_uri = soup_uri_new (HTTPS_SERVER);
+ do_one_connection_connect_test (session, https_uri,
+ "HTTP/1.1 200 OK", "rRcCtTx");
+ } else
+ debug_printf (1, " https -- SKIPPING\n");
+
+ debug_printf (1, " ws\n");
+ ws_uri = soup_uri_new (HTTP_SERVER);
+ ws_uri->scheme = SOUP_URI_SCHEME_WS;
+ do_one_connection_connect_test (session, ws_uri,
+ "HTTP/1.1 200 OK", "rRcCx");
+
+ if (tls_available) {
+ debug_printf (1, " wss\n");
+ wss_uri = soup_uri_new (HTTPS_SERVER);
+ do_one_connection_connect_test (session, wss_uri,
+ "HTTP/1.1 200 OK", "rRcCtTx");
+ } else
+ debug_printf (1, " wss -- SKIPPING\n");
+
+ debug_printf (1, " file\n");
+ file_uri = soup_uri_new ("file:///foo/bar");
+ do_one_connection_connect_fail_test (session, file_uri,
+ G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
+ "r");
+
+ debug_printf (1, " wrong http (invalid port)\n");
+ wrong_http_uri = soup_uri_new (HTTP_SERVER);
+ wrong_http_uri->port = 1234;
+ do_one_connection_connect_fail_test (session, wrong_http_uri,
+ G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED,
+ "rRcr"); /* FIXME: why r again? GLib bug? */
+
+ proxy_uri = soup_uri_new (HTTP_PROXY);
+ g_object_set (G_OBJECT (session),
+ SOUP_SESSION_PROXY_URI, proxy_uri,
+ NULL);
+
+ debug_printf (1, " http with proxy\n");
+ do_one_connection_connect_test (session, http_uri,
+ "HTTP/1.1 403 Forbidden", "rRcCx");
+
+ if (tls_available) {
+ debug_printf (1, " https with proxy\n");
+ do_one_connection_connect_test (session, https_uri,
+ "HTTP/1.1 200 OK", "rRcCpPtTx");
+ } else
+ debug_printf (1, " https with proxy -- SKIPPING\n");
+
+ debug_printf (1, " ws with proxy\n");
+ do_one_connection_connect_test (session, ws_uri,
+ "HTTP/1.1 403 Forbidden", "rRcCx");
+
+ if (tls_available) {
+ debug_printf (1, " wss with proxy\n");
+ do_one_connection_connect_test (session, wss_uri,
+ "HTTP/1.1 200 OK", "rRcCpPtTx");
+ } else
+ debug_printf (1, " wss with proxy -- SKIPPING\n");
+
+ soup_uri_free (http_uri);
+ if (https_uri)
+ soup_uri_free (https_uri);
+ soup_uri_free (ws_uri);
+ if (wss_uri)
+ soup_uri_free (wss_uri);
+ soup_uri_free (file_uri);
+ soup_uri_free (wrong_http_uri);
+ soup_uri_free (proxy_uri);
+
+ soup_test_session_abort_unref (session);
+}
+
int
main (int argc, char **argv)
{
@@ -849,10 +1102,9 @@ main (int argc, char **argv)
test_init (argc, argv, NULL);
apache_init ();
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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));
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
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);
@@ -861,6 +1113,7 @@ main (int argc, char **argv)
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);
+ g_test_add_func ("/connection/connect", do_connection_connect_test);
ret = g_test_run ();
diff --git a/tests/context-test.c b/tests/context-test.c
index 727c63ba..567512fe 100644
--- a/tests/context-test.c
+++ b/tests/context-test.c
@@ -14,12 +14,12 @@ typedef struct {
} SlowData;
static void
-request_failed (SoupMessage *msg, gpointer data)
+request_finished (SoupMessage *msg, gpointer data)
{
SlowData *sd = data;
- if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
- g_source_destroy (sd->timeout);
+ g_source_destroy (sd->timeout);
+ g_source_unref (sd->timeout);
g_free (sd);
}
@@ -65,10 +65,11 @@ server_callback (SoupServer *server, SoupMessage *msg,
sd->server = server;
sd->msg = msg;
sd->timeout = soup_add_timeout (
- soup_server_get_async_context (server),
+ g_main_context_get_thread_default (),
200, add_body_chunk, sd);
+ g_source_ref (sd->timeout);
g_signal_connect (msg, "finished",
- G_CALLBACK (request_failed), sd);
+ G_CALLBACK (request_finished), sd);
}
/* Test 1: An async session in another thread with its own
@@ -329,14 +330,16 @@ int
main (int argc, char **argv)
{
SoupServer *server;
+ SoupURI *uri;
int ret;
test_init (argc, argv, NULL);
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
- base_uri = g_strdup_printf ("http://127.0.0.1:%u/",
- soup_server_get_port (server));
+ uri = soup_test_server_get_uri (server, "http", NULL);
+ base_uri = soup_uri_to_string (uri, FALSE);
+ soup_uri_free (uri);
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);
diff --git a/tests/continue-test.c b/tests/continue-test.c
index b6a5805f..5e0c6603 100644
--- a/tests/continue-test.c
+++ b/tests/continue-test.c
@@ -10,7 +10,7 @@
#define MAX_POST_LENGTH (sizeof (SHORT_BODY))
-static int port;
+static SoupURI *base_uri;
static GSList *events;
static void
@@ -54,17 +54,20 @@ do_message (const char *path, gboolean long_body,
SoupSession *session;
SoupMessage *msg;
const char *body;
- char *uri;
+ SoupURI *uri;
va_list ap;
const char *expected_event;
char *actual_event;
int expected_status, actual_status;
- uri = g_strdup_printf ("http://%s127.0.0.1:%d/%s",
- auth ? "user:pass@" : "",
- port, path);
- msg = soup_message_new ("POST", uri);
- g_free (uri);
+ uri = soup_uri_copy (base_uri);
+ if (auth) {
+ soup_uri_set_user (uri, "user");
+ soup_uri_set_password (uri, "pass");
+ }
+ soup_uri_set_path (uri, path);
+ msg = soup_message_new_from_uri ("POST", uri);
+ soup_uri_free (uri);
body = long_body ? LONG_BODY : SHORT_BODY;
soup_message_set_request (msg, "text/plain", SOUP_MEMORY_STATIC,
@@ -148,7 +151,7 @@ do_message (const char *path, gboolean long_body,
static void
do_test_unauth_short_noexpect_nopass (void)
{
- do_message ("unauth", FALSE, FALSE, FALSE,
+ do_message ("/unauth", FALSE, FALSE, FALSE,
"client-wrote_headers",
"client-wrote_body",
"server-got_headers",
@@ -165,7 +168,7 @@ do_test_unauth_short_noexpect_nopass (void)
static void
do_test_unauth_long_noexpect_nopass (void)
{
- do_message ("unauth", TRUE, FALSE, FALSE,
+ do_message ("/unauth", TRUE, FALSE, FALSE,
"client-wrote_headers",
"client-wrote_body",
"server-got_headers",
@@ -182,7 +185,7 @@ do_test_unauth_long_noexpect_nopass (void)
static void
do_test_unauth_short_expect_nopass (void)
{
- do_message ("unauth", FALSE, TRUE, FALSE,
+ do_message ("/unauth", FALSE, TRUE, FALSE,
"client-wrote_headers",
"server-got_headers",
"server-wrote_informational", SOUP_STATUS_CONTINUE,
@@ -201,7 +204,7 @@ do_test_unauth_short_expect_nopass (void)
static void
do_test_unauth_long_expect_nopass (void)
{
- do_message ("unauth", TRUE, TRUE, FALSE,
+ do_message ("/unauth", TRUE, TRUE, FALSE,
"client-wrote_headers",
"server-got_headers",
"server-wrote_headers", SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE,
@@ -216,7 +219,7 @@ do_test_unauth_long_expect_nopass (void)
static void
do_test_auth_short_noexpect_nopass (void)
{
- do_message ("auth", FALSE, FALSE, FALSE,
+ do_message ("/auth", FALSE, FALSE, FALSE,
"client-wrote_headers",
"client-wrote_body",
"server-got_headers",
@@ -233,7 +236,7 @@ do_test_auth_short_noexpect_nopass (void)
static void
do_test_auth_long_noexpect_nopass (void)
{
- do_message ("auth", TRUE, FALSE, FALSE,
+ do_message ("/auth", TRUE, FALSE, FALSE,
"client-wrote_headers",
"client-wrote_body",
"server-got_headers",
@@ -250,7 +253,7 @@ do_test_auth_long_noexpect_nopass (void)
static void
do_test_auth_short_expect_nopass (void)
{
- do_message ("auth", FALSE, TRUE, FALSE,
+ do_message ("/auth", FALSE, TRUE, FALSE,
"client-wrote_headers",
"server-got_headers",
"server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
@@ -265,7 +268,7 @@ do_test_auth_short_expect_nopass (void)
static void
do_test_auth_long_expect_nopass (void)
{
- do_message ("auth", TRUE, TRUE, FALSE,
+ do_message ("/auth", TRUE, TRUE, FALSE,
"client-wrote_headers",
"server-got_headers",
"server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
@@ -280,7 +283,7 @@ do_test_auth_long_expect_nopass (void)
static void
do_test_auth_short_noexpect_pass (void)
{
- do_message ("auth", FALSE, FALSE, TRUE,
+ do_message ("/auth", FALSE, FALSE, TRUE,
"client-wrote_headers",
"client-wrote_body",
"server-got_headers",
@@ -306,7 +309,7 @@ do_test_auth_short_noexpect_pass (void)
static void
do_test_auth_long_noexpect_pass (void)
{
- do_message ("auth", TRUE, FALSE, TRUE,
+ do_message ("/auth", TRUE, FALSE, TRUE,
"client-wrote_headers",
"client-wrote_body",
"server-got_headers",
@@ -332,7 +335,7 @@ do_test_auth_long_noexpect_pass (void)
static void
do_test_auth_short_expect_pass (void)
{
- do_message ("auth", FALSE, TRUE, TRUE,
+ do_message ("/auth", FALSE, TRUE, TRUE,
"client-wrote_headers",
"server-got_headers",
"server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
@@ -358,7 +361,7 @@ do_test_auth_short_expect_pass (void)
static void
do_test_auth_long_expect_pass (void)
{
- do_message ("auth", TRUE, TRUE, TRUE,
+ do_message ("/auth", TRUE, TRUE, TRUE,
"client-wrote_headers",
"server-got_headers",
"server-wrote_headers", SOUP_STATUS_UNAUTHORIZED,
@@ -452,7 +455,7 @@ setup_server (void)
SoupServer *server;
SoupAuthDomain *auth_domain;
- server = soup_test_server_new (FALSE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
g_signal_connect (server, "request-started",
G_CALLBACK (request_started), NULL);
@@ -481,7 +484,7 @@ main (int argc, char **argv)
test_init (argc, argv, NULL);
server = setup_server ();
- port = soup_server_get_port (server);
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
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);
@@ -499,6 +502,8 @@ main (int argc, char **argv)
ret = g_test_run ();
soup_test_server_quit_unref (server);
+ soup_uri_free (base_uri);
+
test_cleanup ();
return ret;
diff --git a/tests/cookies-test.c b/tests/cookies-test.c
index 12529d81..8735964c 100644
--- a/tests/cookies-test.c
+++ b/tests/cookies-test.c
@@ -94,6 +94,61 @@ do_cookies_accept_policy_test (void)
soup_test_session_abort_unref (session);
}
+static void
+do_cookies_subdomain_policy_test (void)
+{
+ SoupCookieJar *jar;
+ GSList *cookies;
+ SoupURI *uri1;
+ SoupURI *uri2;
+
+ g_test_bug ("792130");
+
+ /* Only the base domain should be considered when deciding
+ * whether a cookie is a third-party cookie.
+ */
+ uri1 = soup_uri_new ("https://www.gnome.org");
+ uri2 = soup_uri_new ("https://foundation.gnome.org");
+
+ /* We can't check subdomains with a test server running on
+ * localhost, so we'll just check the cookie jar API itself.
+ */
+
+ /* Cookie should be accepted. One cookie in the jar. */
+ jar = soup_cookie_jar_new ();
+ soup_cookie_jar_set_accept_policy (jar, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY);
+ soup_cookie_jar_set_cookie_with_first_party (jar, uri1, uri2, "1=foo");
+ cookies = soup_cookie_jar_all_cookies (jar);
+ g_assert_cmpint (g_slist_length (cookies), ==, 1);
+ g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free);
+
+ /* Cookie should be accepted. Two cookies in the jar. */
+ soup_cookie_jar_set_cookie_with_first_party (jar, uri2, uri1, "2=foo");
+ cookies = soup_cookie_jar_all_cookies (jar);
+ g_assert_cmpint (g_slist_length (cookies), ==, 2);
+ g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free);
+
+ /* Third-party cookie should be rejected, so there are still
+ * only two cookies in the jar.
+ */
+ soup_cookie_jar_set_cookie_with_first_party (jar, third_party_uri, uri1, "3=foo");
+ cookies = soup_cookie_jar_all_cookies (jar);
+ g_assert_cmpint (g_slist_length (cookies), ==, 2);
+ g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free);
+
+ /* A leading dot in the domain property should not affect things.
+ * This cookie should be accepted. Three cookies in the jar.
+ */
+ soup_cookie_jar_set_cookie_with_first_party (jar, uri1, uri1, "4=foo; Domain=.www.gnome.org");
+ cookies = soup_cookie_jar_all_cookies (jar);
+ g_assert_cmpint (g_slist_length (cookies), ==, 3);
+ g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free);
+
+ soup_uri_free (uri1);
+ soup_uri_free (uri2);
+ g_object_unref (jar);
+}
+
/* FIXME: moar tests! */
static void
do_cookies_parsing_test (void)
@@ -167,24 +222,29 @@ do_cookies_parsing_test (void)
int
main (int argc, char **argv)
{
+ SoupURI *server_uri;
int ret;
test_init (argc, argv, NULL);
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+ server_uri = soup_test_server_get_uri (server, "http", NULL);
+
first_party_uri = soup_uri_new (first_party);
third_party_uri = soup_uri_new (third_party);
- soup_uri_set_port (first_party_uri, soup_server_get_port (server));
- soup_uri_set_port (third_party_uri, soup_server_get_port (server));
+ soup_uri_set_port (first_party_uri, server_uri->port);
+ soup_uri_set_port (third_party_uri, server_uri->port);
g_test_add_func ("/cookies/accept-policy", do_cookies_accept_policy_test);
+ g_test_add_func ("/cookies/accept-policy-subdomains", do_cookies_subdomain_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_uri_free (server_uri);
soup_test_server_quit_unref (server);
test_cleanup ();
diff --git a/tests/date.c b/tests/date.c
index e51fa57f..f623061b 100644
--- a/tests/date.c
+++ b/tests/date.c
@@ -102,6 +102,9 @@ static const OkDate ok_dates[] = {
{ "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 },
{ "06-Nov-04 08:09:07 GMT", NULL },
@@ -130,16 +133,6 @@ static const OkDate ok_dates[] = {
{ "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", 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", NULL },
{ "Saturday, 06-Nov-04 8:9:07 GMT", NULL },
@@ -177,6 +170,8 @@ check_ok_time_t (void)
g_assert_cmpint (date->hour, ==, 8);
g_assert_cmpint (date->minute, ==, 9);
g_assert_cmpint (date->second, ==, 7);
+
+ soup_date_free (date);
}
typedef struct {
diff --git a/tests/forms-test.c b/tests/forms-test.c
index 3915b019..349932bf 100644
--- a/tests/forms-test.c
+++ b/tests/forms-test.c
@@ -420,41 +420,43 @@ main (int argc, char **argv)
{
GMainLoop *loop;
SoupServer *server;
- guint port;
- char *uri_str;
+ SoupURI *base_uri, *uri;
int ret = 0;
test_init (argc, argv, no_test_entry);
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
soup_server_add_handler (server, "/hello",
hello_callback, NULL, NULL);
soup_server_add_handler (server, "/md5",
md5_callback, NULL, NULL);
- port = soup_server_get_port (server);
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
loop = g_main_loop_new (NULL, TRUE);
if (run_tests) {
- uri_str = g_strdup_printf ("http://127.0.0.1:%u/hello", port);
- g_test_add_data_func_full ("/forms/hello", uri_str, do_hello_tests, g_free);
+ uri = soup_uri_new_with_base (base_uri, "/hello");
+ g_test_add_data_func_full ("/forms/hello", soup_uri_to_string (uri, FALSE), do_hello_tests, g_free);
+ soup_uri_free (uri);
- uri_str = g_strdup_printf ("http://127.0.0.1:%u/md5", port);
- 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);
+ uri = soup_uri_new_with_base (base_uri, "/md5");
+ g_test_add_data_func_full ("/forms/md5/curl", soup_uri_to_string (uri, FALSE), do_md5_test_curl, g_free);
+ g_test_add_data_func_full ("/forms/md5/libsoup", soup_uri_to_string (uri, FALSE), do_md5_test_libsoup, g_free);
+ soup_uri_free (uri);
g_test_add_func ("/forms/decode", do_form_decode_test);
ret = g_test_run ();
} else {
- g_print ("Listening on port %d\n", port);
+ g_print ("Listening on port %d\n", base_uri->port);
g_main_loop_run (loop);
}
g_main_loop_unref (loop);
soup_test_server_quit_unref (server);
+ soup_uri_free (base_uri);
+
if (run_tests)
test_cleanup ();
return ret;
diff --git a/tests/header-parsing.c b/tests/header-parsing.c
index fdc7885d..9cf06cee 100644
--- a/tests/header-parsing.c
+++ b/tests/header-parsing.c
@@ -358,6 +358,24 @@ static struct RequestTest {
}
},
+ { "NUL in header name", "760832",
+ "GET / HTTP/1.1\r\nHost\x00: example.com\r\n", 36,
+ SOUP_STATUS_OK,
+ "GET", "/", SOUP_HTTP_1_1,
+ { { "Host", "example.com" },
+ { NULL }
+ }
+ },
+
+ { "NUL in header value", "760832",
+ "GET / HTTP/1.1\r\nHost: example\x00" "com\r\n", 35,
+ SOUP_STATUS_OK,
+ "GET", "/", SOUP_HTTP_1_1,
+ { { "Host", "examplecom" },
+ { NULL }
+ }
+ },
+
/************************/
/*** INVALID REQUESTS ***/
/************************/
@@ -418,20 +436,6 @@ static struct RequestTest {
{ { NULL } }
},
- { "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", NULL,
- "GET / HTTP/1.1\r\nHost: example\x00com\r\n", 37,
- SOUP_STATUS_BAD_REQUEST,
- NULL, NULL, -1,
- { { NULL } }
- },
-
{ "No terminating CRLF", NULL,
"GET / HTTP/1.1\r\nHost: example.com", -1,
SOUP_STATUS_BAD_REQUEST,
@@ -513,6 +517,14 @@ static struct ResponseTest {
}
},
+ { "Response w/ unknown status code", NULL,
+ "HTTP/1.1 999 Request denied\r\nFoo: bar\r\n", -1,
+ SOUP_HTTP_1_1, 999, "Request denied",
+ { { "Foo", "bar" },
+ { NULL }
+ }
+ },
+
{ "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",
@@ -608,6 +620,46 @@ static struct ResponseTest {
{ NULL } }
},
+ { "NUL in header name", "760832",
+ "HTTP/1.1 200 OK\r\nF\x00oo: bar\r\n", 28,
+ SOUP_HTTP_1_1, SOUP_STATUS_OK, "OK",
+ { { "Foo", "bar" },
+ { NULL }
+ }
+ },
+
+ { "NUL in header value", "760832",
+ "HTTP/1.1 200 OK\r\nFoo: b\x00" "ar\r\n", 28,
+ SOUP_HTTP_1_1, SOUP_STATUS_OK, "OK",
+ { { "Foo", "bar" },
+ { NULL }
+ }
+ },
+
+ /********************************/
+ /*** VALID CONTINUE RESPONSES ***/
+ /********************************/
+
+ /* Tests from Cockpit project */
+
+ { "Response w/ 101 Switching Protocols + spaces after new line", NULL,
+ "HTTP/1.0 101 Switching Protocols\r\n \r\n", 38,
+ SOUP_HTTP_1_0, SOUP_STATUS_SWITCHING_PROTOCOLS, "Switching Protocols",
+ { { NULL } }
+ },
+
+ { "Response w/ 101 Switching Protocols missing \\r + spaces", NULL,
+ "HTTP/1.0 101 Switching Protocols\r\n \r\n", 40,
+ SOUP_HTTP_1_0, SOUP_STATUS_SWITCHING_PROTOCOLS, "Switching Protocols",
+ { { NULL } }
+ },
+
+ { "Response w/ 101 Switching Protocols + spaces after & before new line", NULL,
+ "HTTP/1.1 101 Switching Protocols \r\n \r\n", 42,
+ SOUP_HTTP_1_1, SOUP_STATUS_SWITCHING_PROTOCOLS, "Switching Protocols",
+ { { NULL } }
+ },
+
/*************************/
/*** INVALID RESPONSES ***/
/*************************/
@@ -660,8 +712,8 @@ static struct ResponseTest {
{ { NULL } }
},
- { "Status code > 599", NULL,
- "HTTP/1.1 600 OK\r\nFoo: bar\r\n", -1,
+ { "Status code > 999", NULL,
+ "HTTP/1.1 1000 OK\r\nFoo: bar\r\n", -1,
-1, 0, NULL,
{ { NULL } }
},
@@ -678,17 +730,44 @@ static struct ResponseTest {
{ { NULL } }
},
- { "NUL in header name", NULL,
- "HTTP/1.1 200 OK\r\nF\x00oo: bar\r\n", 28,
+ /* Failing test from Cockpit */
+
+ { "Partial response stops after HTTP/", NULL,
+ "HTTP/", -1,
-1, 0, NULL,
{ { NULL } }
},
- { "NUL in header value", NULL,
- "HTTP/1.1 200 OK\r\nFoo: b\x00ar\r\n", 28,
+ { "Space before HTTP/", NULL,
+ " HTTP/1.0 101 Switching Protocols\r\n ", -1,
-1, 0, NULL,
{ { NULL } }
},
+
+ { "Missing reason", NULL,
+ "HTTP/1.0 101\r\n ", -1,
+ -1, 0, NULL,
+ { { NULL } }
+ },
+
+ { "Response code containing alphabetic character", NULL,
+ "HTTP/1.1 1A01 Switching Protocols \r\n ", -1,
+ -1, 0, NULL,
+ { { NULL } }
+ },
+
+ { "TESTONE\\r\\n", NULL,
+ "TESTONE\r\n ", -1,
+ -1, 0, NULL,
+ { { NULL } }
+ },
+
+ { "Response w/ 3 headers truncated", NULL,
+ "HTTP/1.0 200 ok\r\nHeader1: value3\r\nHeader2: field\r\nHead3: Anothe", -1,
+ -1, 0, NULL,
+ { { NULL }
+ }
+ },
};
static const int num_resptests = G_N_ELEMENTS (resptests);
@@ -837,6 +916,17 @@ do_qvalue_tests (void)
debug_printf (1, " acceptable: ");
if (acceptable) {
+ /* Kludge to deal with the fact that the sort order of the first
+ * test is not fully specified.
+ */
+ if (i == 0 && acceptable->next &&
+ !g_str_equal (acceptable->data, qvaluetests[i].acceptable[0]) &&
+ g_str_equal (acceptable->data, qvaluetests[i].acceptable[1])) {
+ gpointer tmp = acceptable->data;
+ acceptable->data = acceptable->next->data;
+ acceptable->next->data = tmp;
+ }
+
for (iter = acceptable, j = 0; iter; iter = iter->next, j++) {
debug_printf (1, "%s ", (char *)iter->data);
g_assert_cmpstr (iter->data, ==, qvaluetests[i].acceptable[j]);
diff --git a/tests/httpd.conf.22.in b/tests/httpd.conf.22.in
deleted file mode 100644
index b912ca36..00000000
--- a/tests/httpd.conf.22.in
+++ /dev/null
@@ -1,292 +0,0 @@
-# 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 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_file_module @APACHE_MODULE_DIR@/mod_authn_file.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
-
-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 *>
- Order Deny,Allow
- Deny from all
- </Proxy>
-
- # Allow local http connections
- <Proxy http://127.0.0.1*>
- Order Allow,Deny
- Allow from all
- </Proxy>
-
- # Allow CONNECT to local https port
- <Proxy 127.0.0.1:47525>
- Order Allow,Deny
- Allow from all
- </Proxy>
-
- # Deny non-proxy requests
- <Directory />
- Order Deny,Allow
- Deny from all
- </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 *>
- Order Deny,Allow
- Deny from all
- </Proxy>
-
- # Allow local http connections with authentication
- <Proxy http://127.0.0.1:47524*>
- Order Allow,Deny
- Allow from all
-
- AuthType Basic
- AuthName realm1
- AuthUserFile ./htpasswd
- Require valid-user
- </Proxy>
-
- # Allow CONNECT to local https port with authentication
- <Proxy 127.0.0.1:47525>
- Order Allow,Deny
- Allow from all
-
- AuthType Basic
- AuthName realm1
- AuthUserFile ./htpasswd
- Require valid-user
- </Proxy>
-
- # Fail non-proxy requests
- <Directory />
- Order Deny,Allow
- Deny from all
- </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 *>
- Order Deny,Allow
- Deny from all
- </Proxy>
-
- # Allow local http connections with authentication
- <Proxy http://127.0.0.1:47524*>
- Order Allow,Deny
- Allow from all
-
- 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>
- Order Allow,Deny
- Allow from all
-
- AuthType Basic
- AuthName realm1
- AuthUserFile ./htpasswd
- Require user no-such-user
- </Proxy>
-
- # Fail non-proxy requests
- <Directory />
- Order Deny,Allow
- Deny from all
- </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/httpd.conf.24.in b/tests/httpd.conf.in
index 850b8393..b818c12d 100644
--- a/tests/httpd.conf.24.in
+++ b/tests/httpd.conf.in
@@ -24,12 +24,12 @@ 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@
+@IF_HAVE_PHP@LoadModule php7_module @APACHE_PHP_MODULE_DIR@/libphp7.so
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
+@IF_HAVE_MOD_UNIXD@LoadModule unixd_module @APACHE_SSL_MODULE_DIR@/mod_unixd.so
DirectoryIndex index.txt
TypesConfig /dev/null
@@ -155,6 +155,7 @@ Alias /Basic/realm12 .
Alias /Basic/realm2 .
Alias /Basic/realm3 .
Alias /Basic .
+Alias /BasicRoot .
<Location /Basic/realm1>
AuthType Basic
@@ -205,6 +206,13 @@ Alias /Basic .
Require user user3
</Location>
+<Location /BasicRoot>
+ AuthType Basic
+ AuthName realm1
+ AuthUserFile ./htpasswd
+ Require user user1
+</Location>
+
# Digest auth tests
Alias /Digest/realm1/realm2/realm1 .
Alias /Digest/realm1/realm2 .
diff --git a/tests/libsoup.supp b/tests/libsoup.supp
index ae8bda38..2c7ba9b5 100644
--- a/tests/libsoup.supp
+++ b/tests/libsoup.supp
@@ -208,13 +208,20 @@
glib/tlsdb
Memcheck:Leak
...
- fun:g_tls_backend_get_default_database
+ fun:g_tls_backend_gnutls_get_default_database
+}
+{
+ glib/tlsdb_dummy
+ Memcheck:Leak
+ ...
+ fun:g_dummy_tls_backend_get_default_database
}
{
glib/tlscache
Memcheck:Leak
...
- fun:g_tls_backend_gnutls_cache_session_data
+ fun:g_bytes_new_with_free_func
+ fun:g_tls_client_connection_gnutls_constructed
}
{
glib/tlspriority
@@ -230,6 +237,12 @@
fun:lookup_attribute
}
{
+ glib/gfileinfo2
+ Memcheck:Leak
+ ...
+ fun:_lookup_namespace
+}
+{
glib/unixsignalthread
Memcheck:Leak
...
@@ -312,7 +325,7 @@
glib/unused_thread_queue
Memcheck:Leak
...
- fun:g_async_queue_new
+ fun:g_async_queue_new_full
fun:g_thread_pool_new
}
{
@@ -336,6 +349,18 @@
fun:g_get_charset
}
{
+ glib/tmpdir
+ Memcheck:Leak
+ ...
+ fun:g_get_tmp_dir
+}
+{
+ glib/g_get_user_name
+ Memcheck:Leak
+ ...
+ fun:g_get_user_name
+}
+{
glib/gtlssessioncache
Memcheck:Leak
...
@@ -414,6 +439,30 @@
fun:g_thread_pool_new
fun:g_task_thread_pool_init
}
+{
+ glib/resources
+ Memcheck:Leak
+ ...
+ fun:g_resource_load
+}
+{
+ glib/resources2
+ Memcheck:Leak
+ ...
+ fun:g_resources_register
+}
+{
+ glib/worker
+ Memcheck:Leak
+ ...
+ fun:g_get_worker_context
+}
+{
+ glib/worker2
+ Memcheck:Leak
+ ...
+ fun:glib_worker_main
+}
# probably inlines the aggressive memcpy/memcmp
{
@@ -444,10 +493,16 @@
}
{
- libxml2/xmlInitParser
+ libxml2/xmlInitGlobals
+ Memcheck:Leak
+ ...
+ fun:xmlInitGlobals
+}
+{
+ libxml2/xmlInitMemory
Memcheck:Leak
...
- fun:xmlInitParser
+ fun:xmlInitMemory
}
{
libxml2/xmlInitParserCtxt
@@ -459,7 +514,7 @@
libxml2/xmlInitializeDict
Memcheck:Leak
...
- fun:xmlInitializeDict
+ fun:__xmlInitializeDict
}
{
libxml2/xmlInitCharEncodingHandlers
@@ -504,6 +559,20 @@
fun:g_mutex_get_impl
}
{
+ glib/grecmuteximpl
+ Memcheck:Leak
+ ...
+ fun:g_rec_mutex_impl_new
+ fun:g_rec_mutex_get_impl
+}
+{
+ glib/grwlockimpl
+ Memcheck:Leak
+ ...
+ fun:g_rw_lock_impl_new
+ fun:g_rw_lock_get_impl
+}
+{
glib/gcondimpl
Memcheck:Leak
...
@@ -517,3 +586,10 @@
fun:g_private_impl_new
fun:g_private_get_impl
}
+{
+ glib/test_uri_base
+ Memcheck:Leak
+ ...
+ fun:g_strdup
+ fun:test_case_run
+} \ No newline at end of file
diff --git a/tests/misc-test.c b/tests/misc-test.c
index 00559a03..8cbda80a 100644
--- a/tests/misc-test.c
+++ b/tests/misc-test.c
@@ -73,7 +73,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
if (!strcmp (path, "/slow")) {
soup_server_pause_message (server, msg);
g_object_set_data (G_OBJECT (msg), "server", server);
- soup_add_timeout (soup_server_get_async_context (server),
+ soup_add_timeout (g_main_context_get_thread_default (),
1000, timeout_finish_message, msg);
}
@@ -120,6 +120,38 @@ do_host_test (void)
g_object_unref (two);
}
+/* request with too big header should be discarded with a IO error to
+ * prevent DOS attacks.
+ */
+static void
+do_host_big_header (void)
+{
+ SoupMessage *msg;
+ SoupSession *session;
+ int i;
+
+ g_test_bug ("792173");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+
+ msg = soup_message_new_from_uri ("GET", base_uri);
+ for (i = 0; i < 2048; i++) {
+ char *key = g_strdup_printf ("test-long-header-key%d", i);
+ char *value = g_strdup_printf ("test-long-header-key%d", i);
+ soup_message_headers_append (msg->request_headers, key, value);
+ g_free (value);
+ g_free (key);
+ }
+
+ soup_session_send_message (session, msg);
+
+ soup_test_session_abort_unref (session);
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_IO_ERROR);
+
+ g_object_unref (msg);
+}
+
/* 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.)
@@ -151,35 +183,28 @@ static void
do_callback_unref_test (void)
{
SoupServer *bad_server;
- SoupAddress *addr;
SoupSession *session;
SoupMessage *one, *two;
GMainLoop *loop;
- char *bad_uri;
+ SoupURI *bad_uri;
g_test_bug ("533473");
/* Get a guaranteed-bad URI */
- addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT);
- soup_address_resolve_sync (addr, NULL);
- bad_server = soup_server_new (SOUP_SERVER_INTERFACE, addr,
- NULL);
- g_object_unref (addr);
-
- bad_uri = g_strdup_printf ("http://127.0.0.1:%u/",
- soup_server_get_port (bad_server));
- g_object_unref (bad_server);
+ bad_server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
+ bad_uri = soup_test_server_get_uri (bad_server, "http", NULL);
+ soup_test_server_quit_unref (bad_server);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session);
loop = g_main_loop_new (NULL, TRUE);
- one = soup_message_new ("GET", bad_uri);
+ one = soup_message_new_from_uri ("GET", bad_uri);
g_object_add_weak_pointer (G_OBJECT (one), (gpointer *)&one);
- two = soup_message_new ("GET", bad_uri);
+ two = soup_message_new_from_uri ("GET", bad_uri);
g_object_add_weak_pointer (G_OBJECT (two), (gpointer *)&two);
- g_free (bad_uri);
+ soup_uri_free (bad_uri);
soup_session_queue_message (session, one, cu_one_completed, loop);
soup_session_queue_message (session, two, cu_two_completed, loop);
@@ -245,22 +270,15 @@ static void
do_callback_unref_req_test (void)
{
SoupServer *bad_server;
- SoupAddress *addr;
SoupSession *session;
SoupRequest *one, *two;
GMainLoop *loop;
- char *bad_uri;
+ SoupURI *bad_uri;
/* Get a guaranteed-bad URI */
- addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT);
- soup_address_resolve_sync (addr, NULL);
- bad_server = soup_server_new (SOUP_SERVER_INTERFACE, addr,
- NULL);
- g_object_unref (addr);
-
- bad_uri = g_strdup_printf ("http://127.0.0.1:%u/",
- soup_server_get_port (bad_server));
- g_object_unref (bad_server);
+ bad_server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
+ bad_uri = soup_test_server_get_uri (bad_server, "http", NULL);
+ soup_test_server_quit_unref (bad_server);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
@@ -269,11 +287,11 @@ do_callback_unref_req_test (void)
loop = g_main_loop_new (NULL, TRUE);
- one = soup_session_request (session, bad_uri, NULL);
+ one = soup_session_request_uri (session, bad_uri, NULL);
g_object_add_weak_pointer (G_OBJECT (one), (gpointer *)&one);
- two = soup_session_request (session, bad_uri, NULL);
+ two = soup_session_request_uri (session, bad_uri, NULL);
g_object_add_weak_pointer (G_OBJECT (two), (gpointer *)&two);
- g_free (bad_uri);
+ soup_uri_free (bad_uri);
soup_request_send_async (one, NULL, cur_one_completed, session);
g_object_unref (one);
@@ -418,7 +436,7 @@ ea_connection_created (SoupSession *session, GObject *conn, gpointer user_data)
}
static void
-ea_request_started (SoupSession *session, SoupMessage *msg, SoupSocket *socket, gpointer user_data)
+ea_message_starting (SoupMessage *msg, SoupSession *session)
{
soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
}
@@ -469,8 +487,8 @@ do_early_abort_test (void)
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
msg = soup_message_new_from_uri ("GET", base_uri);
- g_signal_connect (session, "request-started",
- G_CALLBACK (ea_request_started), NULL);
+ g_signal_connect (msg, "starting",
+ G_CALLBACK (ea_message_starting), session);
soup_session_send_message (session, msg);
debug_printf (2, " Message 3 completed\n");
@@ -521,13 +539,21 @@ ear_three_completed (GObject *source, GAsyncResult *result, gpointer loop)
}
static void
-ear_request_started (SoupSession *session, SoupMessage *msg,
- SoupSocket *socket, gpointer cancellable)
+ear_message_starting (SoupMessage *msg, gpointer cancellable)
{
g_cancellable_cancel (cancellable);
}
static void
+ear_request_queued (SoupSession *session, SoupMessage *msg,
+ gpointer cancellable)
+{
+ g_signal_connect (msg, "starting",
+ G_CALLBACK (ear_message_starting),
+ cancellable);
+}
+
+static void
do_early_abort_req_test (void)
{
SoupSession *session;
@@ -574,8 +600,8 @@ do_early_abort_req_test (void)
req = soup_session_request_uri (session, base_uri, NULL);
cancellable = g_cancellable_new ();
- g_signal_connect (session, "request-started",
- G_CALLBACK (ear_request_started), cancellable);
+ g_signal_connect (session, "request-queued",
+ G_CALLBACK (ear_request_queued), cancellable);
soup_request_send_async (req, cancellable, ear_three_completed, loop);
g_main_loop_run (loop);
g_object_unref (req);
@@ -914,6 +940,254 @@ do_pause_abort_test (void)
g_assert_null (ptr);
}
+static GMainLoop *pause_cancel_loop;
+
+static void
+pause_cancel_got_headers (SoupMessage *msg, gpointer user_data)
+{
+ SoupSession *session = user_data;
+
+ soup_session_pause_message (session, msg);
+ g_main_loop_quit (pause_cancel_loop);
+}
+
+static void
+pause_cancel_finished (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+ gboolean *finished = user_data;
+
+ *finished = TRUE;
+ g_main_loop_quit (pause_cancel_loop);
+}
+
+static gboolean
+pause_cancel_timeout (gpointer user_data)
+{
+ gboolean *timed_out = user_data;
+
+ *timed_out = TRUE;
+ g_main_loop_quit (pause_cancel_loop);
+ return FALSE;
+}
+
+static void
+do_pause_cancel_test (void)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ gboolean finished = FALSE, timed_out = FALSE;
+ guint timeout_id;
+
+ g_test_bug ("745094");
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ pause_cancel_loop = g_main_loop_new (NULL, FALSE);
+
+ timeout_id = g_timeout_add_seconds (5, pause_cancel_timeout, &timed_out);
+
+ msg = soup_message_new_from_uri ("GET", base_uri);
+ g_object_ref (msg);
+ g_signal_connect (msg, "got-headers",
+ G_CALLBACK (pause_cancel_got_headers), session);
+
+ soup_session_queue_message (session, msg, pause_cancel_finished, &finished);
+ g_main_loop_run (pause_cancel_loop);
+ g_assert_false (finished);
+
+ soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
+ g_main_loop_run (pause_cancel_loop);
+ g_assert_true (finished);
+ g_assert_false (timed_out);
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
+ g_object_unref (msg);
+
+ soup_test_session_abort_unref (session);
+ g_main_loop_unref (pause_cancel_loop);
+ if (!timed_out)
+ g_source_remove (timeout_id);
+}
+
+static gboolean
+run_echo_server (gpointer user_data)
+{
+ GIOStream *stream = user_data;
+ GInputStream *istream;
+ GDataInputStream *distream;
+ GOutputStream *ostream;
+ char *str, *caps;
+ gssize n;
+ GError *error = NULL;
+
+ istream = g_io_stream_get_input_stream (stream);
+ distream = G_DATA_INPUT_STREAM (g_data_input_stream_new (istream));
+ ostream = g_io_stream_get_output_stream (stream);
+
+ /* Echo until the client disconnects */
+ while (TRUE) {
+ str = g_data_input_stream_read_line (distream, NULL, NULL, &error);
+ g_assert_no_error (error);
+ if (!str)
+ break;
+
+ caps = g_ascii_strup (str, -1);
+ n = g_output_stream_write (ostream, caps, strlen (caps), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (n, ==, strlen (caps));
+ n = g_output_stream_write (ostream, "\n", 1, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (n, ==, 1);
+ g_free (caps);
+ g_free (str);
+ }
+
+ g_object_unref (distream);
+
+ g_io_stream_close (stream, NULL, &error);
+ g_assert_no_error (error);
+ g_object_unref (stream);
+
+ return FALSE;
+}
+
+static void
+steal_after_upgrade (SoupMessage *msg, gpointer user_data)
+{
+ SoupClientContext *context = user_data;
+ GIOStream *stream;
+ GSource *source;
+
+ /* This should not ever be seen. */
+ soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
+
+ stream = soup_client_context_steal_connection (context);
+
+ source = g_idle_source_new ();
+ g_source_set_callback (source, run_echo_server, stream, NULL);
+ g_source_attach (source, g_main_context_get_thread_default ());
+ g_source_unref (source);
+}
+
+static void
+upgrade_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_SWITCHING_PROTOCOLS);
+ soup_message_headers_append (msg->request_headers, "Upgrade", "ECHO");
+ soup_message_headers_append (msg->request_headers, "Connection", "upgrade");
+
+ g_signal_connect (msg, "wrote-informational",
+ G_CALLBACK (steal_after_upgrade), context);
+}
+
+static void
+callback_not_reached (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+ g_assert_not_reached ();
+}
+
+static void
+switching_protocols (SoupMessage *msg, gpointer user_data)
+{
+ GIOStream **out_iostream = user_data;
+ SoupSession *session = g_object_get_data (G_OBJECT (msg), "SoupSession");
+
+ *out_iostream = soup_session_steal_connection (session, msg);
+}
+
+static void
+do_stealing_test (gconstpointer data)
+{
+ gboolean sync = GPOINTER_TO_INT (data);
+ SoupServer *server;
+ SoupURI *uri;
+ SoupSession *session;
+ SoupMessage *msg;
+ GIOStream *iostream;
+ GInputStream *istream;
+ GDataInputStream *distream;
+ GOutputStream *ostream;
+ int i;
+ gssize n;
+ char *str, *caps;
+ GError *error = NULL;
+ static const char *strings[] = { "one", "two", "three", "four", "five" };
+
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
+ uri = soup_test_server_get_uri (server, SOUP_URI_SCHEME_HTTP, "127.0.0.1");
+ soup_server_add_handler (server, NULL, upgrade_server_callback, NULL, NULL);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_message_headers_append (msg->request_headers, "Upgrade", "echo");
+ soup_message_headers_append (msg->request_headers, "Connection", "upgrade");
+ g_object_set_data (G_OBJECT (msg), "SoupSession", session);
+
+ soup_message_add_status_code_handler (msg, "got-informational",
+ SOUP_STATUS_SWITCHING_PROTOCOLS,
+ G_CALLBACK (switching_protocols), &iostream);
+
+ iostream = NULL;
+
+ if (sync) {
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_SWITCHING_PROTOCOLS);
+ } else {
+ g_object_ref (msg);
+ soup_session_queue_message (session, msg, callback_not_reached, NULL);
+ while (iostream == NULL)
+ g_main_context_iteration (NULL, TRUE);
+ }
+
+ g_assert (iostream != NULL);
+
+ g_object_unref (msg);
+ soup_test_session_abort_unref (session);
+ soup_uri_free (uri);
+
+ /* Now iostream connects to a (capitalizing) echo server */
+
+ istream = g_io_stream_get_input_stream (iostream);
+ distream = G_DATA_INPUT_STREAM (g_data_input_stream_new (istream));
+ ostream = g_io_stream_get_output_stream (iostream);
+
+ for (i = 0; i < G_N_ELEMENTS (strings); i++) {
+ n = g_output_stream_write (ostream, strings[i], strlen (strings[i]),
+ NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (n, ==, strlen (strings[i]));
+ n = g_output_stream_write (ostream, "\n", 1, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (n, ==, 1);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (strings); i++) {
+ str = g_data_input_stream_read_line (distream, NULL, NULL, &error);
+ g_assert_no_error (error);
+ caps = g_ascii_strup (strings[i], -1);
+ g_assert_cmpstr (caps, ==, str);
+ g_free (caps);
+ g_free (str);
+ }
+
+ g_object_unref (distream);
+
+ g_io_stream_close (iostream, NULL, &error);
+ g_assert_no_error (error);
+ g_object_unref (iostream);
+
+ /* We can't do this until the end because it's in another thread, and
+ * soup_test_server_quit_unref() will wait for that thread to exit.
+ */
+ soup_test_server_quit_unref (server);
+}
+
int
main (int argc, char **argv)
{
@@ -922,10 +1196,9 @@ main (int argc, char **argv)
test_init (argc, argv, NULL);
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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));
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
auth_domain = soup_auth_domain_basic_new (
SOUP_AUTH_DOMAIN_REALM, "misc-test",
@@ -936,12 +1209,12 @@ main (int argc, char **argv)
g_object_unref (auth_domain);
if (tls_available) {
- ssl_server = soup_test_server_new_ssl (TRUE);
+ ssl_server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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));
+ ssl_base_uri = soup_test_server_get_uri (ssl_server, "https", "127.0.0.1");
}
+ g_test_add_func ("/misc/bigheader", do_host_big_header);
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);
@@ -956,6 +1229,9 @@ main (int argc, char **argv)
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);
+ g_test_add_func ("/misc/pause-cancel", do_pause_cancel_test);
+ g_test_add_data_func ("/misc/stealing/async", GINT_TO_POINTER (FALSE), do_stealing_test);
+ g_test_add_data_func ("/misc/stealing/sync", GINT_TO_POINTER (TRUE), do_stealing_test);
ret = g_test_run ();
@@ -967,5 +1243,6 @@ main (int argc, char **argv)
soup_test_server_quit_unref (ssl_server);
}
+ test_cleanup ();
return ret;
}
diff --git a/tests/multipart-test.c b/tests/multipart-test.c
index e057412e..488865ae 100644
--- a/tests/multipart-test.c
+++ b/tests/multipart-test.c
@@ -486,10 +486,9 @@ main (int argc, char **argv)
buffer = g_malloc (READ_BUFFER_SIZE);
- server = soup_test_server_new (FALSE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
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 = soup_test_server_get_uri (server, "http", NULL);
base_uri_string = soup_uri_to_string (base_uri, FALSE);
/* FIXME: I had to raise the number of connections allowed here, otherwise I
diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c
index 82532c74..c9d9bcad 100644
--- a/tests/no-ssl-test.c
+++ b/tests/no-ssl-test.c
@@ -3,14 +3,14 @@
#include "test-utils.h"
static void
-do_ssl_test_for_session (SoupSession *session, const char *uri)
+do_ssl_test_for_session (SoupSession *session, SoupURI *uri)
{
SoupMessage *msg;
GTlsCertificate *cert = NULL;
GTlsCertificateFlags flags;
gboolean is_https;
- msg = soup_message_new ("GET", uri);
+ msg = soup_message_new_from_uri ("GET", uri);
soup_session_send_message (session, msg);
soup_test_assert_message_status (msg, SOUP_STATUS_SSL_FAILED);
@@ -24,8 +24,9 @@ do_ssl_test_for_session (SoupSession *session, const char *uri)
}
static void
-do_ssl_tests (gconstpointer uri)
+do_ssl_tests (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
SoupSession *session;
g_test_bug ("700518");
@@ -53,10 +54,18 @@ do_session_property_tests (void)
GTlsDatabase *tlsdb;
char *ca_file;
SoupSession *session;
+ GParamSpec *pspec;
g_test_bug ("700518");
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
session = soup_session_async_new ();
+ G_GNUC_END_IGNORE_DEPRECATIONS;
+
+ /* Temporarily undeprecate SOUP_SESSION_SSL_CA_FILE to avoid warnings. */
+ pspec = g_object_class_find_property (g_type_class_peek (SOUP_TYPE_SESSION),
+ SOUP_SESSION_SSL_CA_FILE);
+ pspec->flags &= ~G_PARAM_DEPRECATED;
g_object_get (G_OBJECT (session),
"ssl-use-system-ca-file", &use_system,
@@ -101,6 +110,9 @@ do_session_property_tests (void)
soup_test_assert (ca_file == NULL, "setting tls-database NULL set ssl-ca-file");
soup_test_session_abort_unref (session);
+
+ /* Re-deprecate SOUP_SESSION_SSL_CA_FILE */
+ pspec->flags |= G_PARAM_DEPRECATED;
}
static void
@@ -121,7 +133,8 @@ int
main (int argc, char **argv)
{
SoupServer *server;
- char *uri;
+ SoupURI *uri;
+ guint port;
int ret;
/* Force this test to use the dummy TLS backend */
@@ -135,15 +148,17 @@ main (int argc, char **argv)
*/
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));
+ uri = soup_test_server_get_uri (server, "http", NULL);
+ port = uri->port;
+ soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS);
+ soup_uri_set_port (uri, port);
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_uri_free (uri);
soup_test_server_quit_unref (server);
test_cleanup ();
diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c
index 24a0f2e4..0cc41a7b 100644
--- a/tests/ntlm-test.c
+++ b/tests/ntlm-test.c
@@ -11,8 +11,6 @@
#include "test-utils.h"
-static SoupURI *uri;
-
typedef enum {
NTLM_UNAUTHENTICATED,
NTLM_RECEIVED_REQUEST,
@@ -29,9 +27,17 @@ static const char *state_name[] = {
#define NTLM_RESPONSE_START "TlRMTVNTUAADAAAA"
#define NTLM_CHALLENGE "TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA="
+#define NTLMSSP_CHALLENGE "TlRMTVNTUAACAAAADAAMADAAAAABAokAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA="
#define NTLM_RESPONSE_USER(response) ((response)[86] == 'E' ? NTLM_AUTHENTICATED_ALICE : ((response)[86] == 'I' ? NTLM_AUTHENTICATED_BOB : NTLM_UNAUTHENTICATED))
+typedef struct {
+ SoupServer *server;
+ GHashTable *connections;
+ SoupURI *uri;
+ gboolean ntlmssp;
+} TestServer;
+
static void
clear_state (gpointer connections, GObject *ex_connection)
{
@@ -43,8 +49,8 @@ server_callback (SoupServer *server, SoupMessage *msg,
const char *path, GHashTable *query,
SoupClientContext *client, gpointer data)
{
- GHashTable *connections = data;
- SoupSocket *socket;
+ TestServer *ts = data;
+ GSocket *socket;
const char *auth;
NTLMServerState state, required_user = 0;
gboolean auth_required, not_found = FALSE;
@@ -70,8 +76,8 @@ server_callback (SoupServer *server, SoupMessage *msg,
if (strstr (path, "/404"))
not_found = TRUE;
- socket = soup_client_context_get_socket (client);
- state = GPOINTER_TO_INT (g_hash_table_lookup (connections, socket));
+ socket = soup_client_context_get_gsocket (client);
+ state = GPOINTER_TO_INT (g_hash_table_lookup (ts->connections, socket));
auth = soup_message_headers_get_one (msg->request_headers,
"Authorization");
@@ -121,7 +127,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
if (ntlm_allowed && state == NTLM_RECEIVED_REQUEST) {
soup_message_headers_append (msg->response_headers,
"WWW-Authenticate",
- "NTLM " NTLM_CHALLENGE);
+ ts->ntlmssp ? ("NTLM " NTLMSSP_CHALLENGE) : ("NTLM " NTLM_CHALLENGE));
state = NTLM_SENT_CHALLENGE;
} else if (ntlm_allowed) {
soup_message_headers_append (msg->response_headers,
@@ -141,8 +147,37 @@ 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);
+ g_hash_table_insert (ts->connections, socket, GINT_TO_POINTER (state));
+ g_object_weak_ref (G_OBJECT (socket), clear_state, ts->connections);
+}
+
+static void
+setup_server (TestServer *ts,
+ gconstpointer test_data)
+{
+ ts->server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
+ ts->connections = g_hash_table_new (NULL, NULL);
+ ts->ntlmssp = FALSE;
+ soup_server_add_handler (ts->server, NULL, server_callback, ts, NULL);
+
+ ts->uri = soup_test_server_get_uri (ts->server, "http", NULL);
+}
+
+static void
+setup_ntlmssp_server (TestServer *ts,
+ gconstpointer test_data)
+{
+ setup_server (ts, test_data);
+ ts->ntlmssp = TRUE;
+}
+
+static void
+teardown_server (TestServer *ts,
+ gconstpointer test_data)
+{
+ soup_uri_free (ts->uri);
+ soup_test_server_quit_unref (ts->server);
+ g_hash_table_destroy (ts->connections);
}
static gboolean authenticated_ntlm = FALSE;
@@ -178,8 +213,10 @@ prompt_check (SoupMessage *msg, gpointer user_data)
if (header && strstr (header, "Basic "))
state->got_basic_prompt = TRUE;
if (header && strstr (header, "NTLM") &&
- !strstr (header, NTLM_CHALLENGE))
+ (!strstr (header, NTLM_CHALLENGE) &&
+ !strstr (header, NTLMSSP_CHALLENGE))) {
state->got_ntlm_prompt = TRUE;
+ }
}
static void
@@ -342,7 +379,7 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm,
* asking.
*/
authenticated_ntlm = FALSE;
- do_message (session, base_uri, "/noauth",
+ do_message (session, base_uri, "/noauth/",
FALSE, use_ntlm,
FALSE, FALSE,
SOUP_STATUS_OK);
@@ -358,7 +395,7 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm,
* previous step, then we'll just immediately get a 401 here.
* So in no case will we see the client try to do_ntlm.
*/
- do_message (session, base_uri, "/alice",
+ do_message (session, base_uri, "/alice/",
!alice_via_ntlm, FALSE,
!alice_via_ntlm, alice_via_basic,
alice ? SOUP_STATUS_OK :
@@ -378,7 +415,7 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm,
SOUP_STATUS_UNAUTHORIZED);
/* 4. Should be exactly the same as #3, except the status code */
- do_message (session, base_uri, "/alice",
+ do_message (session, base_uri, "/alice/",
!alice, bob_via_ntlm,
!alice, alice_via_basic,
alice ? SOUP_STATUS_OK :
@@ -390,7 +427,7 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm,
* (and fail). Bob-via-NTLM will try to do NTLM right away and
* succeed.
*/
- do_message (session, base_uri, "/bob",
+ do_message (session, base_uri, "/bob/",
!bob_via_ntlm, bob_via_ntlm,
!bob_via_ntlm, alice_via_basic,
bob ? SOUP_STATUS_OK :
@@ -402,7 +439,7 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm,
* still knows about this path, so will try Basic right away
* and succeed.
*/
- do_message (session, base_uri, "/alice",
+ do_message (session, base_uri, "/alice/",
!alice_via_ntlm, alice_via_ntlm,
!alice_via_ntlm, alice_via_basic,
alice ? SOUP_STATUS_OK :
@@ -412,19 +449,19 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm,
* Since Bob-via-NTLM is unauthenticated at this point, he'll try
* NTLM before realizing that the server doesn't support it.
*/
- do_message (session, base_uri, "/basic",
+ do_message (session, base_uri, "/basic/",
FALSE, bob_via_ntlm,
TRUE, user != NULL,
user != NULL ? SOUP_STATUS_OK :
SOUP_STATUS_UNAUTHORIZED);
/* 8. Server accepts Basic or NTLM from either user.
- * Alice-via-NTLM is still authenticated at this point from #6,
- * and Bob-via-NTLM is authenticated from #7, so neither
- * of them will do anything.
+ * NTLM users will try NTLM without getting a prompt (their
+ * previous NTLM connections will have been closed by the 401
+ * from /basic). Non-NTLM users will be prompted for either.
*/
- do_message (session, base_uri, "/either",
- !use_ntlm, FALSE,
+ do_message (session, base_uri, "/either/",
+ !use_ntlm, use_ntlm,
!use_ntlm, !use_ntlm && user != NULL,
user != NULL ? SOUP_STATUS_OK :
SOUP_STATUS_UNAUTHORIZED);
@@ -461,8 +498,16 @@ static const NtlmTest ntlm_tests[] = {
{ "/ntlm/fallback/basic", "alice", FALSE, FALLBACK }
};
+static const NtlmTest ntlmssp_tests[] = {
+ { "/ntlm/ssp/none", NULL, FALSE, BUILTIN },
+ { "/ntlm/ssp/alice", "alice", TRUE, BUILTIN },
+ { "/ntlm/ssp/bob", "bob", TRUE, BUILTIN },
+ { "/ntlm/ssp/basic", "alice", FALSE, BUILTIN }
+};
+
static void
-do_ntlm_test (gconstpointer data)
+do_ntlm_test (TestServer *ts,
+ gconstpointer data)
{
const NtlmTest *test = data;
gboolean use_builtin_ntlm = TRUE;
@@ -509,7 +554,7 @@ do_ntlm_test (gconstpointer data)
break;
}
- do_ntlm_round (uri, test->conn_uses_ntlm, test->user, use_builtin_ntlm);
+ do_ntlm_round (ts->uri, test->conn_uses_ntlm, test->user, use_builtin_ntlm);
}
static void
@@ -532,9 +577,9 @@ retry_test_authenticate (SoupSession *session, SoupMessage *msg,
}
static void
-do_retrying_test (gconstpointer data)
+do_retrying_test (TestServer *ts,
+ gconstpointer data)
{
- SoupURI *base_uri = (SoupURI *)data;
SoupSession *session;
SoupMessage *msg;
SoupURI *uri;
@@ -552,7 +597,7 @@ do_retrying_test (gconstpointer data)
g_signal_connect (session, "authenticate",
G_CALLBACK (retry_test_authenticate), &retried);
- uri = soup_uri_new_with_base (base_uri, "/alice");
+ uri = soup_uri_new_with_base (ts->uri, "/alice");
msg = soup_message_new_from_uri ("GET", uri);
soup_uri_free (uri);
@@ -574,7 +619,7 @@ do_retrying_test (gconstpointer data)
G_CALLBACK (retry_test_authenticate), &retried);
retried = FALSE;
- uri = soup_uri_new_with_base (base_uri, "/bob");
+ uri = soup_uri_new_with_base (ts->uri, "/bob");
msg = soup_message_new_from_uri ("GET", uri);
soup_uri_free (uri);
@@ -591,31 +636,25 @@ do_retrying_test (gconstpointer data)
int
main (int argc, char **argv)
{
- SoupServer *server;
- GHashTable *connections;
int i, ret;
test_init (argc, argv, NULL);
- server = soup_test_server_new (TRUE);
- connections = g_hash_table_new (NULL, NULL);
- soup_server_add_handler (server, NULL,
- server_callback, connections, NULL);
-
- uri = soup_uri_new ("http://127.0.0.1/");
- soup_uri_set_port (uri, soup_server_get_port (server));
+ for (i = 0; i < G_N_ELEMENTS (ntlm_tests); i++) {
+ g_test_add (ntlm_tests[i].name, TestServer, &ntlm_tests[i],
+ setup_server, do_ntlm_test, teardown_server);
+ }
+ for (i = 0; i < G_N_ELEMENTS (ntlmssp_tests); i++) {
+ g_test_add (ntlmssp_tests[i].name, TestServer, &ntlmssp_tests[i],
+ setup_ntlmssp_server, do_ntlm_test, teardown_server);
+ }
- 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);
+ g_test_add ("/ntlm/retry", TestServer, NULL,
+ setup_server, do_retrying_test, teardown_server);
ret = g_test_run ();
- soup_uri_free (uri);
-
- soup_test_server_quit_unref (server);
test_cleanup ();
- g_hash_table_destroy (connections);
return ret;
}
diff --git a/tests/proxy-test.c b/tests/proxy-test.c
index 4b6679b3..1d68aa05 100644
--- a/tests/proxy-test.c
+++ b/tests/proxy-test.c
@@ -322,6 +322,84 @@ do_proxy_redirect_test (void)
soup_test_session_abort_unref (session);
}
+static void
+do_proxy_auth_request (const char *url, SoupSession *session, gboolean do_read)
+{
+ SoupRequest *request;
+ SoupMessage *msg;
+ GInputStream *stream;
+ GError *error = NULL;
+
+ request = soup_session_request (session, url, NULL);
+ msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
+
+ stream = soup_test_request_send (request, NULL, 0, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+
+ if (do_read) {
+ char buffer[256];
+ gsize nread;
+
+ do {
+ g_input_stream_read_all (stream, buffer, sizeof (buffer), &nread,
+ NULL, &error);
+ g_assert_no_error (error);
+ g_clear_error (&error);
+ } while (nread > 0);
+ }
+
+ 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);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
+ g_object_unref (msg);
+ g_object_unref (request);
+}
+
+static void
+do_proxy_auth_cache_test (void)
+{
+ SoupSession *session;
+ char *cache_dir;
+ SoupCache *cache;
+ char *url;
+
+ g_test_bug ("756076");
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ 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);
+ g_free (cache_dir);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+ SOUP_SESSION_PROXY_RESOLVER, proxy_resolvers[AUTH_PROXY],
+ SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+ SOUP_SESSION_ADD_FEATURE, cache,
+ NULL);
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (authenticate), NULL);
+
+ url = g_strconcat (HTTP_SERVER, "/Basic/realm1/", NULL);
+
+ debug_printf (1, " GET %s via %s (from network)\n", url, proxy_names[AUTH_PROXY]);
+ do_proxy_auth_request (url, session, TRUE);
+ soup_cache_flush (cache);
+
+ debug_printf (1, " GET %s via %s (from cache)\n", url, proxy_names[AUTH_PROXY]);
+ do_proxy_auth_request (url, session, FALSE);
+
+ g_free (url);
+ soup_test_session_abort_unref (session);
+ g_object_unref (cache);
+}
+
int
main (int argc, char **argv)
{
@@ -338,10 +416,9 @@ main (int argc, char **argv)
g_simple_proxy_resolver_new (proxies[i], (char **) ignore_hosts);
}
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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 = soup_test_server_get_uri (server, "http", NULL);
for (i = 0; i < ntests; i++) {
path = g_strdup_printf ("/proxy/async/%s", tests[i].explanation);
@@ -356,11 +433,14 @@ main (int argc, char **argv)
g_test_add_data_func ("/proxy/fragment", base_uri, do_proxy_fragment_test);
g_test_add_func ("/proxy/redirect", do_proxy_redirect_test);
+ g_test_add_func ("/proxy/auth-cache", do_proxy_auth_cache_test);
ret = g_test_run ();
soup_uri_free (base_uri);
soup_test_server_quit_unref (server);
+ for (i = 0; i < 3; i++)
+ g_object_unref (proxy_resolvers[i]);
test_cleanup ();
return ret;
diff --git a/tests/range-test.c b/tests/range-test.c
index c23ba462..d3c49963 100644
--- a/tests/range-test.c
+++ b/tests/range-test.c
@@ -334,11 +334,7 @@ do_apache_range_test (void)
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);
}
@@ -361,16 +357,18 @@ do_libsoup_range_test (void)
{
SoupSession *session;
SoupServer *server;
- char *base_uri;
+ SoupURI *base_uri;
+ char *base_uri_str;
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
- server = soup_test_server_new (FALSE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
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, TRUE);
- g_free (base_uri);
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
+ base_uri_str = soup_uri_to_string (base_uri, FALSE);
+ do_range_test (session, base_uri_str, TRUE, TRUE);
+ soup_uri_free (base_uri);
+ g_free (base_uri_str);
soup_test_server_quit_unref (server);
soup_test_session_abort_unref (session);
diff --git a/tests/redirect-test.c b/tests/redirect-test.c
index ad8dabaa..ccdd4c29 100644
--- a/tests/redirect-test.c
+++ b/tests/redirect-test.c
@@ -395,24 +395,24 @@ main (int argc, char **argv)
{
GMainLoop *loop;
SoupServer *server, *server2;
- guint port;
+ SoupURI *uri2;
char *path;
int n, ret;
test_init (argc, argv, NULL);
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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);
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
- server2 = soup_test_server_new (TRUE);
+ server2 = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
soup_server_add_handler (server2, NULL,
server2_callback, NULL, NULL);
- server2_uri = g_strdup_printf ("http://127.0.0.1:%d/on-server2",
- soup_server_get_port (server2));
+ uri2 = soup_test_server_get_uri (server2, "http", NULL);
+ soup_uri_set_path (uri2, "/on-server2");
+ server2_uri = soup_uri_to_string (uri2, FALSE);
+ soup_uri_free (uri2);
loop = g_main_loop_new (NULL, TRUE);
@@ -422,8 +422,8 @@ main (int argc, char **argv)
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,
+ 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);
@@ -458,5 +458,6 @@ main (int argc, char **argv)
soup_test_session_abort_unref (async_session);
soup_test_session_abort_unref (sync_session);
+ test_cleanup ();
return ret;
}
diff --git a/tests/requester-test.c b/tests/requester-test.c
index 39b30bd5..6d6d5728 100644
--- a/tests/requester-test.c
+++ b/tests/requester-test.c
@@ -17,6 +17,12 @@ 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"
+typedef enum {
+ NO_CANCEL,
+ SYNC_CANCEL,
+ PAUSE_AND_CANCEL_ON_IDLE
+} CancelPolicy;
+
static gboolean
slow_finish_message (gpointer msg)
{
@@ -205,6 +211,32 @@ cancel_message (SoupMessage *msg, gpointer session)
soup_session_cancel_message (session, msg, SOUP_STATUS_FORBIDDEN);
}
+typedef struct {
+ SoupMessage *msg;
+ SoupSession *session;
+} CancelData;
+
+static gboolean
+cancel_message_idle (CancelData *data)
+{
+ cancel_message (data->msg, data->session);
+ return FALSE;
+}
+
+static void
+pause_and_cancel_message (SoupMessage *msg, gpointer session)
+{
+ CancelData *data = g_new (CancelData, 1);
+ GSource *source = g_idle_source_new ();
+
+ soup_session_pause_message (session, msg);
+ data->msg = msg;
+ data->session = session;
+ g_source_set_callback (source, (GSourceFunc)cancel_message_idle, data, g_free);
+ g_source_attach (source, soup_session_get_async_context (session));
+ g_source_unref (source);
+}
+
static void
request_started (SoupSession *session, SoupMessage *msg,
SoupSocket *socket, gpointer user_data)
@@ -219,7 +251,7 @@ static void
do_async_test (SoupSession *session, SoupURI *uri,
GAsyncReadyCallback callback, guint expected_status,
SoupBuffer *expected_response,
- gboolean persistent, gboolean cancel)
+ gboolean persistent, CancelPolicy cancel_policy)
{
SoupRequester *requester;
SoupRequest *request;
@@ -234,16 +266,24 @@ do_async_test (SoupSession *session, SoupURI *uri,
requester = NULL;
data.body = g_string_new (NULL);
- data.cancel = cancel;
+ data.cancel = cancel_policy != NO_CANCEL;
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) {
+ switch (cancel_policy) {
+ case SYNC_CANCEL:
g_signal_connect (msg, "got-headers",
G_CALLBACK (cancel_message), session);
+ break;
+ case PAUSE_AND_CANCEL_ON_IDLE:
+ g_signal_connect (msg, "got-headers",
+ G_CALLBACK (pause_and_cancel_message), session);
+ break;
+ case NO_CANCEL:
+ break;
}
started_id = g_signal_connect (session, "request-started",
@@ -279,7 +319,7 @@ do_async_test (SoupSession *session, SoupURI *uri,
}
static void
-do_test_for_thread_and_context (SoupSession *session, const char *base_uri)
+do_test_for_thread_and_context (SoupSession *session, SoupURI *base_uri)
{
SoupRequester *requester;
SoupURI *uri;
@@ -292,48 +332,50 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri)
soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
debug_printf (1, " basic test\n");
- uri = soup_uri_new (base_uri);
- do_async_test (session, uri, test_sent,
+ do_async_test (session, base_uri, test_sent,
SOUP_STATUS_OK, response,
- TRUE, FALSE);
- soup_uri_free (uri);
+ TRUE, NO_CANCEL);
debug_printf (1, " chunked test\n");
- uri = soup_uri_new (base_uri);
- soup_uri_set_path (uri, "/chunked");
+ uri = soup_uri_new_with_base (base_uri, "/chunked");
do_async_test (session, uri, test_sent,
SOUP_STATUS_OK, response,
- TRUE, FALSE);
+ TRUE, NO_CANCEL);
soup_uri_free (uri);
debug_printf (1, " auth test\n");
- uri = soup_uri_new (base_uri);
- soup_uri_set_path (uri, "/auth");
+ uri = soup_uri_new_with_base (base_uri, "/auth");
do_async_test (session, uri, auth_test_sent,
SOUP_STATUS_UNAUTHORIZED, auth_response,
- TRUE, FALSE);
+ TRUE, NO_CANCEL);
soup_uri_free (uri);
debug_printf (1, " non-persistent test\n");
- uri = soup_uri_new (base_uri);
- soup_uri_set_path (uri, "/non-persistent");
+ uri = soup_uri_new_with_base (base_uri, "/non-persistent");
do_async_test (session, uri, test_sent,
SOUP_STATUS_OK, response,
- FALSE, FALSE);
+ FALSE, NO_CANCEL);
soup_uri_free (uri);
debug_printf (1, " cancellation test\n");
- uri = soup_uri_new (base_uri);
- soup_uri_set_path (uri, "/");
+ uri = soup_uri_new_with_base (base_uri, "/");
do_async_test (session, uri, test_sent,
SOUP_STATUS_FORBIDDEN, NULL,
- FALSE, TRUE);
+ FALSE, SYNC_CANCEL);
+ soup_uri_free (uri);
+
+ debug_printf (1, " cancellation after paused test\n");
+ uri = soup_uri_new_with_base (base_uri, "/");
+ do_async_test (session, uri, test_sent,
+ SOUP_STATUS_FORBIDDEN, NULL,
+ FALSE, PAUSE_AND_CANCEL_ON_IDLE);
soup_uri_free (uri);
}
static void
-do_simple_plain_test (gconstpointer uri)
+do_simple_plain_test (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
SoupSession *session;
g_test_bug ("653707");
@@ -344,8 +386,9 @@ do_simple_plain_test (gconstpointer uri)
}
static void
-do_simple_async_test (gconstpointer uri)
+do_simple_async_test (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
SoupSession *session;
g_test_bug ("653707");
@@ -358,7 +401,7 @@ do_simple_async_test (gconstpointer uri)
}
static void
-do_test_with_context_and_type (const char *uri, gboolean plain_session)
+do_test_with_context_and_type (SoupURI *uri, gboolean plain_session)
{
GMainContext *async_context;
SoupSession *session;
@@ -381,14 +424,18 @@ do_test_with_context_and_type (const char *uri, gboolean plain_session)
}
static void
-do_async_test_with_context (gconstpointer uri)
+do_async_test_with_context (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
+
do_test_with_context_and_type (uri, FALSE);
}
static void
-do_plain_test_with_context (gconstpointer uri)
+do_plain_test_with_context (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
+
do_test_with_context_and_type (uri, TRUE);
}
@@ -407,8 +454,9 @@ plain_test_thread (gpointer uri)
}
static void
-do_async_test_in_thread (gconstpointer uri)
+do_async_test_in_thread (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
GThread *thread;
thread = g_thread_new ("do_async_test_in_thread",
@@ -418,8 +466,9 @@ do_async_test_in_thread (gconstpointer uri)
}
static void
-do_plain_test_in_thread (gconstpointer uri)
+do_plain_test_in_thread (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
GThread *thread;
thread = g_thread_new ("do_plain_test_in_thread",
@@ -431,7 +480,7 @@ do_plain_test_in_thread (gconstpointer uri)
static void
do_sync_request (SoupSession *session, SoupRequest *request,
guint expected_status, SoupBuffer *expected_response,
- gboolean persistent, gboolean cancel)
+ gboolean persistent, CancelPolicy cancel_policy)
{
GInputStream *in;
SoupMessage *msg;
@@ -443,7 +492,7 @@ do_sync_request (SoupSession *session, SoupRequest *request,
SoupSocket *socket = NULL;
msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
- if (cancel) {
+ if (cancel_policy == SYNC_CANCEL) {
g_signal_connect (msg, "got-headers",
G_CALLBACK (cancel_message), session);
}
@@ -454,7 +503,7 @@ do_sync_request (SoupSession *session, SoupRequest *request,
in = soup_request_send (request, NULL, &error);
g_signal_handler_disconnect (session, started_id);
- if (cancel) {
+ if (cancel_policy == SYNC_CANCEL) {
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
g_clear_error (&error);
g_object_unref (msg);
@@ -504,7 +553,7 @@ do_sync_request (SoupSession *session, SoupRequest *request,
}
static void
-do_sync_tests_for_session (SoupSession *session, const char *uri_string)
+do_sync_tests_for_session (SoupSession *session, SoupURI *base_uri)
{
SoupRequester *requester;
SoupRequest *request;
@@ -512,7 +561,7 @@ do_sync_tests_for_session (SoupSession *session, const char *uri_string)
requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER));
- uri = soup_uri_new (uri_string);
+ uri = soup_uri_copy (base_uri);
debug_printf (1, " basic test\n");
if (requester)
@@ -521,7 +570,7 @@ do_sync_tests_for_session (SoupSession *session, const char *uri_string)
request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_OK, response,
- TRUE, FALSE);
+ TRUE, NO_CANCEL);
g_object_unref (request);
debug_printf (1, " chunked test\n");
@@ -532,7 +581,7 @@ do_sync_tests_for_session (SoupSession *session, const char *uri_string)
request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_OK, response,
- TRUE, FALSE);
+ TRUE, NO_CANCEL);
g_object_unref (request);
debug_printf (1, " auth test\n");
@@ -543,7 +592,7 @@ do_sync_tests_for_session (SoupSession *session, const char *uri_string)
request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_UNAUTHORIZED, auth_response,
- TRUE, FALSE);
+ TRUE, NO_CANCEL);
g_object_unref (request);
debug_printf (1, " non-persistent test\n");
@@ -554,7 +603,7 @@ do_sync_tests_for_session (SoupSession *session, const char *uri_string)
request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_OK, response,
- FALSE, FALSE);
+ FALSE, NO_CANCEL);
g_object_unref (request);
debug_printf (1, " cancel test\n");
@@ -565,15 +614,16 @@ do_sync_tests_for_session (SoupSession *session, const char *uri_string)
request = soup_session_request_uri (session, uri, NULL);
do_sync_request (session, request,
SOUP_STATUS_FORBIDDEN, NULL,
- TRUE, TRUE);
+ TRUE, SYNC_CANCEL);
g_object_unref (request);
soup_uri_free (uri);
}
static void
-do_plain_sync_test (gconstpointer uri)
+do_plain_sync_test (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
SoupSession *session;
session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
@@ -582,8 +632,9 @@ do_plain_sync_test (gconstpointer uri)
}
static void
-do_sync_sync_test (gconstpointer uri)
+do_sync_sync_test (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
SoupSession *session;
SoupRequester *requester;
@@ -743,6 +794,7 @@ do_close_test_for_session (SoupSession *session,
if (error)
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
g_clear_error (&error);
+ g_object_unref (cancellable);
g_assert_true (finished);
@@ -751,16 +803,16 @@ do_close_test_for_session (SoupSession *session,
}
static void
-do_async_close_test (gconstpointer uri)
+do_async_close_test (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
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");
+ slow_uri = soup_uri_new_with_base ((SoupURI *)uri, "/slow");
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
@@ -772,18 +824,17 @@ do_async_close_test (gconstpointer uri)
}
static void
-do_sync_close_test (gconstpointer uri)
+do_sync_close_test (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
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");
+ slow_uri = soup_uri_new_with_base ((SoupURI *)uri, "/slow");
- debug_printf (1, " SoupSessionSync\n");
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
NULL);
@@ -796,7 +847,7 @@ do_sync_close_test (gconstpointer uri)
int
main (int argc, char **argv)
{
- char *uri;
+ SoupURI *uri;
int ret;
test_init (argc, argv, NULL);
@@ -806,10 +857,11 @@ main (int argc, char **argv)
AUTH_HTML_BODY,
strlen (AUTH_HTML_BODY));
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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));
+ uri = soup_test_server_get_uri (server, "http", NULL);
+ soup_uri_set_path (uri, "/foo");
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);
@@ -826,7 +878,7 @@ main (int argc, char **argv)
ret = g_test_run ();
- g_free (uri);
+ soup_uri_free (uri);
soup_buffer_free (auth_response);
soup_test_server_quit_unref (server);
diff --git a/tests/resources/misc.xml b/tests/resources/misc.xml
new file mode 100644
index 00000000..15361e62
--- /dev/null
+++ b/tests/resources/misc.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource>
+ <file compressed="true">test1.txt</file>
+ <file preprocess="xml-stripblanks">test.gresource.xml</file>
+ </gresource>
+ <gresource prefix="/a_prefix">
+ <file alias="test2-alias.txt">test2.txt</file>
+ <file>test2.txt</file>
+ </gresource>
+</gresources>
diff --git a/tests/server-auth-test.c b/tests/server-auth-test.c
index f386f526..34c297bc 100644
--- a/tests/server-auth-test.c
+++ b/tests/server-auth-test.c
@@ -36,7 +36,11 @@ do_test (SoupURI *base_uri, const char *path,
GPid pid;
gboolean done;
- uri = soup_uri_new_with_base (base_uri, path);
+ /* We build the URI this way to avoid having soup_uri_new()
+ normalize the path, hence losing the encoded characters in
+ tests 4. and 5. below. */
+ uri = soup_uri_copy (base_uri);
+ soup_uri_set_path (uri, path);
uri_str = soup_uri_to_string (uri, FALSE);
soup_uri_free (uri);
@@ -156,7 +160,46 @@ do_server_auth_test (gconstpointer data)
/* success? */
TEST_USES_DIGEST (i) && TEST_GOOD_AUTH (i));
- /* 4. Any auth required. */
+ /* 4. Digest auth with encoded URI. See #794208.
+ */
+ do_test (base_uri, "/Digest/A%20B",
+ 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));
+
+ /* 5. Digest auth with a mixture of encoded and decoded chars in the URI. See #794208.
+ */
+ do_test (base_uri, "/Digest/A%20|%20B",
+ 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));
+
+ /* 6. Digest auth with UTF-8 chars in the URI. See #794208.
+ */
+ do_test (base_uri, "/Digest/A௹B",
+ 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));
+
+ /* 7. Any auth required. */
do_test (base_uri, "/Any/foo",
TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i),
/* request */
@@ -168,7 +211,7 @@ do_server_auth_test (gconstpointer data)
/* success? */
(TEST_USES_BASIC (i) || TEST_USES_DIGEST (i)) && TEST_GOOD_AUTH (i));
- /* 5. No auth required again. (Makes sure that
+ /* 8. No auth required again. (Makes sure that
* SOUP_AUTH_DOMAIN_REMOVE_PATH works.)
*/
do_test (base_uri, "/Any/Not/foo",
@@ -282,7 +325,7 @@ main (int argc, char **argv)
test_init (argc, argv, no_test_entry);
- server = soup_test_server_new (FALSE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
g_signal_connect (server, "request_started",
G_CALLBACK (request_started_callback), NULL);
soup_server_add_handler (server, NULL,
@@ -310,12 +353,10 @@ main (int argc, char **argv)
loop = g_main_loop_new (NULL, TRUE);
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
if (run_tests) {
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;
@@ -344,13 +385,12 @@ main (int argc, char **argv)
}
ret = g_test_run ();
-
- soup_uri_free (base_uri);
} else {
- g_print ("Listening on port %d\n", soup_server_get_port (server));
+ g_print ("Listening on port %d\n", base_uri->port);
g_main_loop_run (loop);
ret = 0;
}
+ soup_uri_free (base_uri);
g_main_loop_unref (loop);
soup_test_server_quit_unref (server);
diff --git a/tests/server-test.c b/tests/server-test.c
index 0c980908..cf132b33 100644
--- a/tests/server-test.c
+++ b/tests/server-test.c
@@ -5,8 +5,13 @@
#include "test-utils.h"
-SoupServer *server, *ssl_server;
-SoupURI *base_uri, *ssl_base_uri;
+#include <gio/gnetworking.h>
+
+typedef struct {
+ SoupServer *server;
+ SoupURI *base_uri, *ssl_base_uri;
+ GSList *handlers;
+} ServerData;
static void
server_callback (SoupServer *server, SoupMessage *msg,
@@ -33,6 +38,58 @@ server_callback (SoupServer *server, SoupMessage *msg,
}
static void
+server_setup_nohandler (ServerData *sd, gconstpointer test_data)
+{
+ sd->server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
+ sd->base_uri = soup_test_server_get_uri (sd->server, "http", NULL);
+ if (tls_available)
+ sd->ssl_base_uri = soup_test_server_get_uri (sd->server, "https", NULL);
+}
+
+static void
+server_add_handler (ServerData *sd,
+ const char *path,
+ SoupServerCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ soup_server_add_handler (sd->server, path, callback, user_data, destroy);
+ sd->handlers = g_slist_prepend (sd->handlers, g_strdup (path));
+}
+
+static void
+server_add_early_handler (ServerData *sd,
+ const char *path,
+ SoupServerCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ soup_server_add_early_handler (sd->server, path, callback, user_data, destroy);
+ sd->handlers = g_slist_prepend (sd->handlers, g_strdup (path));
+}
+
+static void
+server_setup (ServerData *sd, gconstpointer test_data)
+{
+ server_setup_nohandler (sd, test_data);
+ server_add_handler (sd, NULL, server_callback, NULL, NULL);
+}
+
+static void
+server_teardown (ServerData *sd, gconstpointer test_data)
+{
+ GSList *iter;
+
+ for (iter = sd->handlers; iter; iter = iter->next)
+ soup_server_remove_handler (sd->server, iter->data);
+ g_slist_free_full (sd->handlers, g_free);
+
+ g_clear_pointer (&sd->server, soup_test_server_quit_unref);
+ g_clear_pointer (&sd->base_uri, soup_uri_free);
+ g_clear_pointer (&sd->ssl_base_uri, soup_uri_free);
+}
+
+static void
server_star_callback (SoupServer *server, SoupMessage *msg,
const char *path, GHashTable *query,
SoupClientContext *context, gpointer data)
@@ -58,7 +115,7 @@ server_star_callback (SoupServer *server, SoupMessage *msg,
* all other URIs. #590751
*/
static void
-do_star_test (void)
+do_star_test (ServerData *sd, gconstpointer test_data)
{
SoupSession *session;
SoupMessage *msg;
@@ -68,7 +125,7 @@ do_star_test (void)
g_test_bug ("590751");
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
- star_uri = soup_uri_copy (base_uri);
+ star_uri = soup_uri_copy (sd->base_uri);
soup_uri_set_path (star_uri, "*");
debug_printf (1, " Testing with no handler\n");
@@ -81,7 +138,7 @@ do_star_test (void)
g_assert_cmpstr (handled_by, ==, NULL);
g_object_unref (msg);
- soup_server_add_handler (server, "*", server_star_callback, NULL, NULL);
+ server_add_handler (sd, "*", server_star_callback, NULL, NULL);
debug_printf (1, " Testing with handler\n");
msg = soup_message_new_from_uri ("OPTIONS", star_uri);
@@ -169,8 +226,10 @@ do_one_server_aliases_test (SoupURI *uri,
}
static void
-do_server_aliases_test (void)
+do_server_aliases_test (ServerData *sd, gconstpointer test_data)
{
+ char *http_aliases[] = { "dav", NULL };
+ char *https_aliases[] = { "davs", NULL };
char *http_good[] = { "http", "dav", NULL };
char *http_bad[] = { "https", "davs", "fred", NULL };
char *https_good[] = { "https", "davs", NULL };
@@ -179,21 +238,26 @@ do_server_aliases_test (void)
g_test_bug ("703694");
+ g_object_set (G_OBJECT (sd->server),
+ SOUP_SERVER_HTTP_ALIASES, http_aliases,
+ SOUP_SERVER_HTTPS_ALIASES, https_aliases,
+ NULL);
+
for (i = 0; http_good[i]; i++)
- do_one_server_aliases_test (base_uri, http_good[i], TRUE);
+ do_one_server_aliases_test (sd->base_uri, http_good[i], TRUE);
for (i = 0; http_bad[i]; i++)
- do_one_server_aliases_test (base_uri, http_bad[i], FALSE);
+ do_one_server_aliases_test (sd->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);
+ do_one_server_aliases_test (sd->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);
+ do_one_server_aliases_test (sd->ssl_base_uri, https_bad[i], FALSE);
}
}
static void
-do_dot_dot_test (void)
+do_dot_dot_test (ServerData *sd, gconstpointer test_data)
{
SoupSession *session;
SoupMessage *msg;
@@ -203,7 +267,7 @@ do_dot_dot_test (void)
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 (sd->base_uri, "/..%2ftest");
msg = soup_message_new_from_uri ("GET", uri);
soup_uri_free (uri);
@@ -220,10 +284,13 @@ ipv6_server_callback (SoupServer *server, SoupMessage *msg,
SoupClientContext *context, gpointer data)
{
const char *host;
+ GSocketAddress *addr;
char expected_host[128];
+ addr = soup_client_context_get_local_address (context);
g_snprintf (expected_host, sizeof (expected_host),
- "[::1]:%d", soup_server_get_port (server));
+ "[::1]:%d",
+ g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)));
host = soup_message_headers_get_one (msg->request_headers, "Host");
g_assert_cmpstr (host, ==, expected_host);
@@ -235,95 +302,1052 @@ ipv6_server_callback (SoupServer *server, SoupMessage *msg,
}
static void
-do_ipv6_test (void)
+do_ipv6_test (ServerData *sd, gconstpointer test_data)
{
- SoupServer *ipv6_server;
- SoupURI *ipv6_uri;
- SoupAddress *ipv6_addr;
SoupSession *session;
SoupMessage *msg;
+ GError *error = NULL;
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");
+ sd->server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER);
+ server_add_handler (sd, NULL, ipv6_server_callback, NULL, NULL);
+
+ if (!soup_server_listen_local (sd->server, 0,
+ SOUP_SERVER_LISTEN_IPV6_ONLY,
+ &error)) {
+#if GLIB_CHECK_VERSION (2, 41, 0)
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
+#endif
+ g_test_skip ("no IPv6 support");
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));
+ sd->base_uri = soup_test_server_get_uri (sd->server, "http", "::1");
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);
+ msg = soup_message_new_from_uri ("GET", sd->base_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);
+ msg = soup_message_new_from_uri ("GET", sd->base_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)
+static void
+multi_server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
{
- char *http_aliases[] = { "dav", NULL };
- char *https_aliases[] = { "davs", NULL };
- int ret;
+ GSocketAddress *addr;
+ GInetSocketAddress *iaddr;
+ SoupURI *uri;
+ char *uristr, *addrstr;
- test_init (argc, argv, NULL);
+ addr = soup_client_context_get_local_address (context);
+ iaddr = G_INET_SOCKET_ADDRESS (addr);
- 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));
+ uri = soup_message_get_uri (msg);
+ uristr = soup_uri_to_string (uri, FALSE);
- g_object_set (G_OBJECT (server),
- SOUP_SERVER_HTTP_ALIASES, http_aliases,
- NULL);
+ addrstr = g_inet_address_to_string (g_inet_socket_address_get_address (iaddr));
+ g_assert_cmpstr (addrstr, ==, uri->host);
+ g_free (addrstr);
- 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_assert_cmpint (g_inet_socket_address_get_port (iaddr), ==, uri->port);
+
+ /* FIXME ssl */
+
+ soup_message_set_response (msg, "text/plain",
+ SOUP_MEMORY_TAKE, uristr, strlen (uristr));
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+}
+
+static void
+do_multi_test (ServerData *sd, SoupURI *uri1, SoupURI *uri2)
+{
+ char *uristr;
+ SoupSession *session;
+ SoupMessage *msg;
+
+ server_add_handler (sd, NULL, multi_server_callback, NULL, NULL);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+
+ uristr = soup_uri_to_string (uri1, FALSE);
+ msg = soup_message_new ("GET", uristr);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_assert_cmpstr (msg->response_body->data, ==, uristr);
+ g_object_unref (msg);
+ g_free (uristr);
+
+ uristr = soup_uri_to_string (uri2, FALSE);
+ msg = soup_message_new ("GET", uristr);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_assert_cmpstr (msg->response_body->data, ==, uristr);
+ g_object_unref (msg);
+ g_free (uristr);
+
+ soup_test_session_abort_unref (session);
+
+ soup_uri_free (uri1);
+ soup_uri_free (uri2);
+}
+
+static void
+do_multi_port_test (ServerData *sd, gconstpointer test_data)
+{
+ GSList *uris;
+ SoupURI *uri1, *uri2;
+ GError *error = NULL;
+
+ sd->server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER);
+
+ if (!soup_server_listen_local (sd->server, 0, SOUP_SERVER_LISTEN_IPV4_ONLY, &error)) {
+ g_assert_no_error (error);
+ g_error_free (error);
+ return;
+ }
+ if (!soup_server_listen_local (sd->server, 0, SOUP_SERVER_LISTEN_IPV4_ONLY, &error)) {
+ g_assert_no_error (error);
+ g_error_free (error);
+ return;
}
- 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);
+ uris = soup_server_get_uris (sd->server);
+ g_assert_cmpint (g_slist_length (uris), ==, 2);
+ uri1 = uris->data;
+ uri2 = uris->next->data;
+ g_slist_free (uris);
- ret = g_test_run ();
+ g_assert_cmpint (uri1->port, !=, uri2->port);
+
+ do_multi_test (sd, uri1, uri2);
+}
+
+static void
+do_multi_scheme_test (ServerData *sd, gconstpointer test_data)
+{
+ GSList *uris;
+ SoupURI *uri1, *uri2;
+ GError *error = NULL;
+
+ SOUP_TEST_SKIP_IF_NO_TLS;
+
+ sd->server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER);
+
+ if (!soup_server_listen_local (sd->server, 0, SOUP_SERVER_LISTEN_IPV4_ONLY, &error)) {
+ g_assert_no_error (error);
+ g_error_free (error);
+ return;
+ }
+ if (!soup_server_listen_local (sd->server, 0,
+ SOUP_SERVER_LISTEN_IPV4_ONLY | SOUP_SERVER_LISTEN_HTTPS,
+ &error)) {
+ g_assert_no_error (error);
+ g_error_free (error);
+ return;
+ }
+
+ uris = soup_server_get_uris (sd->server);
+ g_assert_cmpint (g_slist_length (uris), ==, 2);
+ uri1 = uris->data;
+ uri2 = uris->next->data;
+ g_slist_free (uris);
+
+ g_assert_cmpstr (uri1->scheme, !=, uri2->scheme);
+
+ do_multi_test (sd, uri1, uri2);
+}
+
+static void
+do_multi_family_test (ServerData *sd, gconstpointer test_data)
+{
+ GSList *uris;
+ SoupURI *uri1, *uri2;
+ GError *error = NULL;
+
+ sd->server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER);
+
+ if (!soup_server_listen_local (sd->server, 0, 0, &error)) {
+ g_assert_no_error (error);
+ g_error_free (error);
+ return;
+ }
+
+ uris = soup_server_get_uris (sd->server);
+ if (g_slist_length (uris) == 1) {
+ gboolean ipv6_works;
+
+ /* No IPv6? Double-check */
+ ipv6_works = soup_server_listen_local (sd->server, 0,
+ SOUP_SERVER_LISTEN_IPV6_ONLY,
+ NULL);
+ if (ipv6_works)
+ g_assert_false (ipv6_works);
+ else
+ g_test_skip ("no IPv6 support");
+ return;
+ }
+
+ g_assert_cmpint (g_slist_length (uris), ==, 2);
+ uri1 = uris->data;
+ uri2 = uris->next->data;
+ g_slist_free (uris);
+
+ g_assert_cmpstr (uri1->host, !=, uri2->host);
+ g_assert_cmpint (uri1->port, ==, uri2->port);
+
+ do_multi_test (sd, uri1, uri2);
+}
+
+static void
+do_gsocket_import_test (void)
+{
+ GSocket *gsock;
+ GSocketAddress *gaddr;
+ SoupServer *server;
+ GSList *listeners;
+ SoupURI *uri;
+ SoupSession *session;
+ SoupMessage *msg;
+ GError *error = NULL;
+
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &error);
+ g_assert_no_error (error);
+
+ gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
+ g_socket_bind (gsock, gaddr, TRUE, &error);
+ g_object_unref (gaddr);
+ g_assert_no_error (error);
+ g_socket_listen (gsock, &error);
+ g_assert_no_error (error);
+
+ gaddr = g_socket_get_local_address (gsock, &error);
+ g_assert_no_error (error);
+ g_object_unref (gaddr);
+
+ server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER);
+ soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+
+ listeners = soup_server_get_listeners (server);
+ g_assert_cmpint (g_slist_length (listeners), ==, 0);
+ g_slist_free (listeners);
+
+ soup_server_listen_socket (server, gsock, 0, &error);
+ g_assert_no_error (error);
+ listeners = soup_server_get_listeners (server);
+ g_assert_cmpint (g_slist_length (listeners), ==, 1);
+ g_slist_free (listeners);
+
+ uri = soup_test_server_get_uri (server, "http", "127.0.0.1");
+ g_assert_nonnull (uri);
+ listeners = soup_server_get_listeners (server);
+ g_assert_cmpint (g_slist_length (listeners), ==, 1);
+ g_slist_free (listeners);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_object_unref (msg);
+
+ soup_test_session_abort_unref (session);
+
+ soup_uri_free (uri);
+ soup_test_server_quit_unref (server);
+
+ g_assert_false (g_socket_is_connected (gsock));
+ g_object_unref (gsock);
+}
- soup_uri_free (base_uri);
+static void
+do_fd_import_test (void)
+{
+ GSocket *gsock;
+ GSocketAddress *gaddr;
+ SoupServer *server;
+ GSList *listeners;
+ SoupURI *uri;
+ SoupSession *session;
+ SoupMessage *msg;
+ int type;
+ GError *error = NULL;
+
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &error);
+ g_assert_no_error (error);
+
+ gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
+ g_socket_bind (gsock, gaddr, TRUE, &error);
+ g_object_unref (gaddr);
+ g_assert_no_error (error);
+ g_socket_listen (gsock, &error);
+ g_assert_no_error (error);
+
+ gaddr = g_socket_get_local_address (gsock, &error);
+ g_assert_no_error (error);
+ g_object_unref (gaddr);
+
+ server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER);
+ soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+
+ listeners = soup_server_get_listeners (server);
+ g_assert_cmpint (g_slist_length (listeners), ==, 0);
+ g_slist_free (listeners);
+
+ soup_server_listen_fd (server, g_socket_get_fd (gsock), 0, &error);
+ g_assert_no_error (error);
+ listeners = soup_server_get_listeners (server);
+ g_assert_cmpint (g_slist_length (listeners), ==, 1);
+ g_slist_free (listeners);
+
+ uri = soup_test_server_get_uri (server, "http", "127.0.0.1");
+ g_assert_nonnull (uri);
+ listeners = soup_server_get_listeners (server);
+ g_assert_cmpint (g_slist_length (listeners), ==, 1);
+ g_slist_free (listeners);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_object_unref (msg);
+
+ soup_test_session_abort_unref (session);
+
+ soup_uri_free (uri);
soup_test_server_quit_unref (server);
- if (tls_available) {
- soup_uri_free (ssl_base_uri);
- soup_test_server_quit_unref (ssl_server);
+ /* @server should have closed our socket, although @gsock doesn't
+ * know this.
+ */
+ g_socket_get_option (gsock, SOL_SOCKET, SO_TYPE, &type, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
+ g_clear_error (&error);
+ g_object_unref (gsock);
+}
+
+typedef struct
+{
+ GIOStream parent;
+ GInputStream *input_stream;
+ GOutputStream *output_stream;
+} GTestIOStream;
+
+typedef struct
+{
+ GIOStreamClass parent_class;
+} GTestIOStreamClass;
+
+static GType g_test_io_stream_get_type (void);
+G_DEFINE_TYPE (GTestIOStream, g_test_io_stream, G_TYPE_IO_STREAM);
+
+
+static GInputStream *
+get_input_stream (GIOStream *io_stream)
+{
+ GTestIOStream *self = (GTestIOStream *) io_stream;
+
+ return self->input_stream;
+}
+
+static GOutputStream *
+get_output_stream (GIOStream *io_stream)
+{
+ GTestIOStream *self = (GTestIOStream *) io_stream;
+
+ return self->output_stream;
+}
+
+static void
+finalize (GObject *object)
+{
+ GTestIOStream *self = (GTestIOStream *) object;
+
+ if (self->input_stream != NULL)
+ g_object_unref (self->input_stream);
+
+ if (self->output_stream != NULL)
+ g_object_unref (self->output_stream);
+
+ G_OBJECT_CLASS (g_test_io_stream_parent_class)->finalize (object);
+}
+
+static void
+g_test_io_stream_class_init (GTestIOStreamClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GIOStreamClass *io_class = G_IO_STREAM_CLASS (klass);
+
+ object_class->finalize = finalize;
+
+ io_class->get_input_stream = get_input_stream;
+ io_class->get_output_stream = get_output_stream;
+}
+
+static void
+g_test_io_stream_init (GTestIOStream *self)
+{
+}
+
+static GIOStream *
+g_test_io_stream_new (GInputStream *input, GOutputStream *output)
+{
+ GTestIOStream *self;
+
+ self = g_object_new (g_test_io_stream_get_type (), NULL);
+ self->input_stream = g_object_ref (input);
+ self->output_stream = g_object_ref (output);
+
+ return G_IO_STREAM (self);
+}
+
+static void
+mem_server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ GSocketAddress *addr;
+ GSocket *sock;
+ const char *host;
+
+ addr = soup_client_context_get_local_address (context);
+ g_assert_nonnull (addr);
+
+ addr = soup_client_context_get_remote_address (context);
+ g_assert_nonnull (addr);
+
+ sock = soup_client_context_get_gsocket (context);
+ g_assert_null (sock);
+
+ host = soup_client_context_get_host (context);
+ g_assert_cmpstr (host, ==, "127.0.0.1");
+
+ server_callback (server, msg, path, query, context, data);
+}
+
+static void
+do_iostream_accept_test (void)
+{
+ GError *error = NULL;
+ SoupServer *server;
+ GInputStream *input;
+ GOutputStream *output;
+ GIOStream *stream;
+ GSocketAddress *addr;
+ const char req[] = "GET / HTTP/1.0\r\n\r\n";
+ gchar *reply;
+ gsize reply_size;
+
+ server = soup_test_server_new (SOUP_TEST_SERVER_NO_DEFAULT_LISTENER);
+ soup_server_add_handler (server, NULL, mem_server_callback, NULL, NULL);
+
+ input = g_memory_input_stream_new_from_data (req, sizeof(req), NULL);
+ output = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
+ stream = g_test_io_stream_new (input, output);
+
+ addr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
+
+ soup_server_accept_iostream (server, stream, addr, addr, &error);
+ g_assert_no_error (error);
+
+ soup_test_server_quit_unref (server);
+
+ reply = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (output));
+ reply_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (output));
+ g_assert_true (reply_size > 0);
+ g_assert_true (g_str_has_prefix (reply, "HTTP/1.0 200 OK"));
+
+ g_clear_object (&addr);
+ g_clear_object (&stream);
+ g_clear_object (&input);
+ g_clear_object (&output);
+ g_clear_error (&error);
+}
+
+typedef struct {
+ SoupServer *server;
+ SoupMessage *smsg;
+ gboolean handler_called;
+ gboolean paused;
+} UnhandledServerData;
+
+static gboolean
+idle_unpause_message (gpointer user_data)
+{
+ UnhandledServerData *usd = user_data;
+
+ soup_server_unpause_message (usd->server, usd->smsg);
+ return FALSE;
+}
+
+static void
+unhandled_server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ UnhandledServerData *usd = data;
+
+ usd->handler_called = TRUE;
+
+ if (soup_message_headers_get_one (msg->request_headers, "X-Test-Server-Pause")) {
+ usd->paused = TRUE;
+ usd->server = server;
+ usd->smsg = msg;
+ soup_server_pause_message (server, msg);
+ g_idle_add (idle_unpause_message, usd);
+ }
+}
+
+static void
+do_fail_404_test (ServerData *sd, gconstpointer test_data)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ UnhandledServerData usd;
+
+ usd.handler_called = usd.paused = FALSE;
+
+ server_add_handler (sd, "/not-a-match", unhandled_server_callback, &usd, NULL);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ msg = soup_message_new_from_uri ("GET", sd->base_uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_NOT_FOUND);
+ g_object_unref (msg);
+
+ g_assert_false (usd.handler_called);
+ g_assert_false (usd.paused);
+
+ soup_test_session_abort_unref (session);
+}
+
+static void
+do_fail_500_test (ServerData *sd, gconstpointer pause)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ UnhandledServerData usd;
+
+ usd.handler_called = usd.paused = FALSE;
+
+ server_add_handler (sd, NULL, unhandled_server_callback, &usd, NULL);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+ msg = soup_message_new_from_uri ("GET", sd->base_uri);
+ if (pause)
+ soup_message_headers_append (msg->request_headers, "X-Test-Server-Pause", "true");
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
+ g_object_unref (msg);
+
+ g_assert_true (usd.handler_called);
+ if (pause)
+ g_assert_true (usd.paused);
+ else
+ g_assert_false (usd.paused);
+
+ soup_test_session_abort_unref (session);
+}
+
+static void
+stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data)
+{
+ GChecksum *checksum = user_data;
+
+ g_checksum_update (checksum, (const guchar *)chunk->data, chunk->length);
+}
+
+static void
+stream_got_body (SoupMessage *msg, gpointer user_data)
+{
+ GChecksum *checksum = user_data;
+ const char *md5 = g_checksum_get_string (checksum);
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ soup_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY,
+ md5, strlen (md5));
+ g_checksum_free (checksum);
+}
+
+static void
+early_stream_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ GChecksum *checksum;
+
+ if (msg->method != SOUP_METHOD_POST) {
+ soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED);
+ return;
}
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+ g_signal_connect (msg, "got-chunk",
+ G_CALLBACK (stream_got_chunk), checksum);
+ g_signal_connect (msg, "got-body",
+ G_CALLBACK (stream_got_body), checksum);
+
+ soup_message_body_set_accumulate (msg->request_body, TRUE);
+}
+
+static void
+do_early_stream_test (ServerData *sd, gconstpointer test_data)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ SoupBuffer *index;
+ char *md5;
+
+ server_add_early_handler (sd, NULL, early_stream_callback, NULL, NULL);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+
+ msg = soup_message_new_from_uri ("POST", sd->base_uri);
+
+ index = soup_test_get_index ();
+ soup_message_body_append (msg->request_body, SOUP_MEMORY_COPY,
+ index->data, index->length);
+ soup_session_send_message (session, msg);
+
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+
+ md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5,
+ (guchar *) index->data, index->length);
+ g_assert_cmpstr (md5, ==, msg->response_body->data);
+ g_free (md5);
+
+ g_object_unref (msg);
+ soup_test_session_abort_unref (session);
+}
+
+static void
+early_respond_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ if (!strcmp (path, "/"))
+ soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
+}
+
+static void
+do_early_respond_test (ServerData *sd, gconstpointer test_data)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ SoupURI *uri2;
+
+ server_add_early_handler (sd, NULL, early_respond_callback, NULL, NULL);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+
+ /* The early handler will intercept, and the normal handler will be skipped */
+ msg = soup_message_new_from_uri ("GET", sd->base_uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_FORBIDDEN);
+ g_assert_cmpint (msg->response_body->length, ==, 0);
+ g_object_unref (msg);
+
+ /* The early handler will ignore this one */
+ uri2 = soup_uri_new_with_base (sd->base_uri, "/subdir");
+ msg = soup_message_new_from_uri ("GET", uri2);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_assert_cmpstr (msg->response_body->data, ==, "index");
+ g_object_unref (msg);
+ soup_uri_free (uri2);
+
+ soup_test_session_abort_unref (session);
+}
+
+static void
+early_multi_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ soup_message_headers_append (msg->response_headers, "X-Early", "yes");
+}
+
+static void
+do_early_multi_test (ServerData *sd, gconstpointer test_data)
+{
+ SoupSession *session;
+ SoupMessage *msg;
+ SoupURI *uri;
+ struct {
+ const char *path;
+ gboolean expect_normal, expect_early;
+ } multi_tests[] = {
+ { "/", FALSE, FALSE },
+ { "/normal", TRUE, FALSE },
+ { "/normal/subdir", TRUE, FALSE },
+ { "/normal/early", FALSE, TRUE },
+ { "/normal/early/subdir", FALSE, TRUE },
+ { "/early", FALSE, TRUE },
+ { "/early/subdir", FALSE, TRUE },
+ { "/early/normal", TRUE, FALSE },
+ { "/early/normal/subdir", TRUE, FALSE },
+ { "/both", TRUE, TRUE },
+ { "/both/subdir", TRUE, TRUE }
+ };
+ int i;
+ const char *header;
+
+ server_add_handler (sd, "/normal", server_callback, NULL, NULL);
+ server_add_early_handler (sd, "/normal/early", early_multi_callback, NULL, NULL);
+ server_add_early_handler (sd, "/early", early_multi_callback, NULL, NULL);
+ server_add_handler (sd, "/early/normal", server_callback, NULL, NULL);
+ server_add_handler (sd, "/both", server_callback, NULL, NULL);
+ server_add_early_handler (sd, "/both", early_multi_callback, NULL, NULL);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (multi_tests); i++) {
+ uri = soup_uri_new_with_base (sd->base_uri, multi_tests[i].path);
+ msg = soup_message_new_from_uri ("GET", uri);
+ soup_uri_free (uri);
+
+ soup_session_send_message (session, msg);
+
+ /* The normal handler sets status to OK. The early handler doesn't
+ * touch status, meaning that if it runs and the normal handler doesn't,
+ * then SoupServer will set the status to INTERNAL_SERVER_ERROR
+ * (since a handler ran, but didn't set the status). If neither handler
+ * runs then SoupServer will set the status to NOT_FOUND.
+ */
+ if (multi_tests[i].expect_normal)
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ else if (multi_tests[i].expect_early)
+ soup_test_assert_message_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
+ else
+ soup_test_assert_message_status (msg, SOUP_STATUS_NOT_FOUND);
+
+ header = soup_message_headers_get_one (msg->response_headers, "X-Early");
+ if (multi_tests[i].expect_early)
+ g_assert_cmpstr (header, ==, "yes");
+ else
+ g_assert_cmpstr (header, ==, NULL);
+ if (multi_tests[i].expect_normal)
+ g_assert_cmpstr (msg->response_body->data, ==, "index");
+ else
+ g_assert_cmpint (msg->response_body->length, ==, 0);
+
+ g_object_unref (msg);
+ }
+
+ soup_test_session_abort_unref (session);
+}
+
+typedef struct {
+ GIOStream *iostream;
+ GInputStream *istream;
+ GOutputStream *ostream;
+
+ gssize nread, nwrote;
+ guchar *buffer;
+} TunnelEnd;
+
+typedef struct {
+ SoupServer *self;
+ SoupMessage *msg;
+ SoupClientContext *context;
+ GCancellable *cancellable;
+
+ TunnelEnd client, server;
+} Tunnel;
+
+#define BUFSIZE 8192
+
+static void tunnel_read_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data);
+
+static void
+tunnel_close (Tunnel *tunnel)
+{
+ if (tunnel->cancellable) {
+ g_cancellable_cancel (tunnel->cancellable);
+ g_object_unref (tunnel->cancellable);
+ }
+
+ if (tunnel->client.iostream) {
+ g_io_stream_close (tunnel->client.iostream, NULL, NULL);
+ g_object_unref (tunnel->client.iostream);
+ }
+ if (tunnel->server.iostream) {
+ g_io_stream_close (tunnel->server.iostream, NULL, NULL);
+ g_object_unref (tunnel->server.iostream);
+ }
+
+ g_free (tunnel->client.buffer);
+ g_free (tunnel->server.buffer);
+
+ g_clear_object (&tunnel->self);
+ g_clear_object (&tunnel->msg);
+
+ g_free (tunnel);
+}
+
+static void
+tunnel_wrote_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ Tunnel *tunnel = user_data;
+ TunnelEnd *write_end, *read_end;
+ GError *error = NULL;
+ gssize nwrote;
+
+ nwrote = g_output_stream_write_finish (G_OUTPUT_STREAM (object), result, &error);
+ if (nwrote <= 0) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_error_free (error);
+ return;
+ } else if (error) {
+ g_print ("Tunnel write failed: %s\n", error->message);
+ g_error_free (error);
+ }
+ tunnel_close (tunnel);
+ return;
+ }
+
+ if (object == (GObject *)tunnel->client.ostream) {
+ write_end = &tunnel->client;
+ read_end = &tunnel->server;
+ } else {
+ write_end = &tunnel->server;
+ read_end = &tunnel->client;
+ }
+
+ write_end->nwrote += nwrote;
+ if (write_end->nwrote < read_end->nread) {
+ g_output_stream_write_async (write_end->ostream,
+ read_end->buffer + write_end->nwrote,
+ read_end->nread - write_end->nwrote,
+ G_PRIORITY_DEFAULT, tunnel->cancellable,
+ tunnel_wrote_cb, tunnel);
+ } else {
+ g_input_stream_read_async (read_end->istream,
+ read_end->buffer, BUFSIZE,
+ G_PRIORITY_DEFAULT, tunnel->cancellable,
+ tunnel_read_cb, tunnel);
+ }
+}
+
+static void
+tunnel_read_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ Tunnel *tunnel = user_data;
+ TunnelEnd *read_end, *write_end;
+ GError *error = NULL;
+ gssize nread;
+
+ nread = g_input_stream_read_finish (G_INPUT_STREAM (object), result, &error);
+ if (nread <= 0) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_error_free (error);
+ return;
+ } else if (error) {
+ g_print ("Tunnel read failed: %s\n", error->message);
+ g_error_free (error);
+ }
+ tunnel_close (tunnel);
+ return;
+ }
+
+ if (object == (GObject *)tunnel->client.istream) {
+ read_end = &tunnel->client;
+ write_end = &tunnel->server;
+ } else {
+ read_end = &tunnel->server;
+ write_end = &tunnel->client;
+ }
+
+ read_end->nread = nread;
+ write_end->nwrote = 0;
+ g_output_stream_write_async (write_end->ostream,
+ read_end->buffer, read_end->nread,
+ G_PRIORITY_DEFAULT, tunnel->cancellable,
+ tunnel_wrote_cb, tunnel);
+}
+
+static void
+start_tunnel (SoupMessage *msg, gpointer user_data)
+{
+ Tunnel *tunnel = user_data;
+
+ tunnel->client.iostream = soup_client_context_steal_connection (tunnel->context);
+ tunnel->client.istream = g_io_stream_get_input_stream (tunnel->client.iostream);
+ tunnel->client.ostream = g_io_stream_get_output_stream (tunnel->client.iostream);
+ g_clear_object (&tunnel->self);
+ g_clear_object (&tunnel->msg);
+
+ tunnel->client.buffer = g_malloc (BUFSIZE);
+ tunnel->server.buffer = g_malloc (BUFSIZE);
+
+ tunnel->cancellable = g_cancellable_new ();
+
+ g_input_stream_read_async (tunnel->client.istream,
+ tunnel->client.buffer, BUFSIZE,
+ G_PRIORITY_DEFAULT, tunnel->cancellable,
+ tunnel_read_cb, tunnel);
+ g_input_stream_read_async (tunnel->server.istream,
+ tunnel->server.buffer, BUFSIZE,
+ G_PRIORITY_DEFAULT, tunnel->cancellable,
+ tunnel_read_cb, tunnel);
+}
+
+
+static void
+tunnel_connected_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ Tunnel *tunnel = user_data;
+ GError *error = NULL;
+
+ tunnel->server.iostream = (GIOStream *)
+ g_socket_client_connect_to_host_finish (G_SOCKET_CLIENT (object), result, &error);
+ if (!tunnel->server.iostream) {
+ soup_message_set_status (tunnel->msg, SOUP_STATUS_BAD_GATEWAY);
+ soup_message_set_response (tunnel->msg, "text/plain",
+ SOUP_MEMORY_COPY,
+ error->message, strlen (error->message));
+ g_error_free (error);
+ soup_server_unpause_message (tunnel->self, tunnel->msg);
+ tunnel_close (tunnel);
+ return;
+ }
+
+ tunnel->server.istream = g_io_stream_get_input_stream (tunnel->server.iostream);
+ tunnel->server.ostream = g_io_stream_get_output_stream (tunnel->server.iostream);
+
+ soup_message_set_status (tunnel->msg, SOUP_STATUS_OK);
+ soup_server_unpause_message (tunnel->self, tunnel->msg);
+ g_signal_connect (tunnel->msg, "wrote-body",
+ G_CALLBACK (start_tunnel), tunnel);
+}
+
+static void
+proxy_server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ GSocketClient *sclient;
+ SoupURI *dest_uri;
+ Tunnel *tunnel;
+
+ if (msg->method != SOUP_METHOD_CONNECT) {
+ soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ soup_server_pause_message (server, msg);
+
+ tunnel = g_new0 (Tunnel, 1);
+ tunnel->self = g_object_ref (server);
+ tunnel->msg = g_object_ref (msg);
+ tunnel->context = context;
+
+ dest_uri = soup_message_get_uri (msg);
+ sclient = g_socket_client_new ();
+ g_socket_client_connect_to_host_async (sclient, dest_uri->host, dest_uri->port,
+ NULL, tunnel_connected_cb, tunnel);
+ g_object_unref (sclient);
+}
+
+static void
+do_steal_connect_test (ServerData *sd, gconstpointer test_data)
+{
+ SoupServer *proxy;
+ SoupURI *proxy_uri;
+ SoupSession *session;
+ SoupMessage *msg;
+ const char *handled_by;
+
+ SOUP_TEST_SKIP_IF_NO_TLS;
+
+ proxy = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
+ proxy_uri = soup_test_server_get_uri (proxy, SOUP_URI_SCHEME_HTTP, "127.0.0.1");
+ soup_server_add_handler (proxy, NULL, proxy_server_callback, NULL, NULL);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION,
+ SOUP_SESSION_PROXY_URI, proxy_uri,
+ NULL);
+ msg = soup_message_new_from_uri ("GET", sd->ssl_base_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, ==, "server_callback");
+
+ g_object_unref (msg);
+ soup_test_session_abort_unref (session);
+
+ soup_test_server_quit_unref (proxy);
+ soup_uri_free (proxy_uri);
+}
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+
+ test_init (argc, argv, NULL);
+
+ g_test_add ("/server/OPTIONS *", ServerData, NULL,
+ server_setup, do_star_test, server_teardown);
+ g_test_add ("/server/aliases", ServerData, NULL,
+ server_setup, do_server_aliases_test, server_teardown);
+ g_test_add ("/server/..-in-path", ServerData, NULL,
+ server_setup, do_dot_dot_test, server_teardown);
+ g_test_add ("/server/ipv6", ServerData, NULL,
+ NULL, do_ipv6_test, server_teardown);
+ g_test_add ("/server/multi/port", ServerData, NULL,
+ NULL, do_multi_port_test, server_teardown);
+ g_test_add ("/server/multi/scheme", ServerData, NULL,
+ NULL, do_multi_scheme_test, server_teardown);
+ g_test_add ("/server/multi/family", ServerData, NULL,
+ NULL, do_multi_family_test, server_teardown);
+ g_test_add_func ("/server/import/gsocket", do_gsocket_import_test);
+ g_test_add_func ("/server/import/fd", do_fd_import_test);
+ g_test_add_func ("/server/accept/iostream", do_iostream_accept_test);
+ g_test_add ("/server/fail/404", ServerData, NULL,
+ server_setup_nohandler, do_fail_404_test, server_teardown);
+ g_test_add ("/server/fail/500", ServerData, GINT_TO_POINTER (FALSE),
+ server_setup_nohandler, do_fail_500_test, server_teardown);
+ g_test_add ("/server/fail/500-pause", ServerData, GINT_TO_POINTER (TRUE),
+ server_setup_nohandler, do_fail_500_test, server_teardown);
+ g_test_add ("/server/early/stream", ServerData, NULL,
+ server_setup_nohandler, do_early_stream_test, server_teardown);
+ g_test_add ("/server/early/respond", ServerData, NULL,
+ server_setup, do_early_respond_test, server_teardown);
+ g_test_add ("/server/early/multi", ServerData, NULL,
+ server_setup_nohandler, do_early_multi_test, server_teardown);
+ g_test_add ("/server/steal/CONNECT", ServerData, NULL,
+ server_setup, do_steal_connect_test, server_teardown);
+
+ ret = g_test_run ();
+
test_cleanup ();
return ret;
}
diff --git a/tests/session-test.c b/tests/session-test.c
index 15072058..8957a258 100644
--- a/tests/session-test.c
+++ b/tests/session-test.c
@@ -25,7 +25,7 @@ server_handler (SoupServer *server,
gpointer user_data)
{
if (!strcmp (path, "/request-timeout")) {
- GMainContext *context = soup_server_get_async_context (server);
+ GMainContext *context = g_main_context_get_thread_default ();
GSource *timer;
timer = g_timeout_source_new (100);
@@ -57,8 +57,7 @@ cancel_message_cb (SoupMessage *msg, gpointer session)
}
static void
-do_test_for_session (SoupSession *session,
- const char *uri,
+do_test_for_session (SoupSession *session, SoupURI *uri,
gboolean queue_is_async,
gboolean send_is_blocking,
gboolean cancel_is_immediate)
@@ -66,17 +65,17 @@ do_test_for_session (SoupSession *session,
SoupMessage *msg;
gboolean finished, local_timeout;
guint timeout_id;
- char *timeout_uri;
+ SoupURI *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);
+ timeout_uri = soup_uri_new_with_base (uri, "/request-timeout");
+ msg = soup_message_new_from_uri ("GET", timeout_uri);
+ soup_uri_free (timeout_uri);
soup_session_send_message (session, msg);
g_object_unref (msg);
- msg = soup_message_new ("GET", uri);
+ msg = soup_message_new_from_uri ("GET", uri);
server_processed_message = timeout = finished = FALSE;
soup_session_queue_message (session, msg, finished_cb, &finished);
while (!timeout)
@@ -98,10 +97,11 @@ do_test_for_session (SoupSession *session,
}
debug_printf (1, " send_message\n");
- msg = soup_message_new ("GET", uri);
+ msg = soup_message_new_from_uri ("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_object_unref (msg);
g_assert_true (server_processed_message);
@@ -120,7 +120,7 @@ do_test_for_session (SoupSession *session,
return;
debug_printf (1, " cancel_message\n");
- msg = soup_message_new ("GET", uri);
+ msg = soup_message_new_from_uri ("GET", uri);
g_object_ref (msg);
finished = FALSE;
soup_session_queue_message (session, msg, finished_cb, &finished);
@@ -140,14 +140,16 @@ do_test_for_session (SoupSession *session,
while (!finished)
g_main_context_iteration (NULL, TRUE);
}
+ g_main_loop_unref (loop);
soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
g_object_unref (msg);
}
static void
-do_plain_tests (gconstpointer uri)
+do_plain_tests (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
SoupSession *session;
session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
@@ -156,8 +158,9 @@ do_plain_tests (gconstpointer uri)
}
static void
-do_async_tests (gconstpointer uri)
+do_async_tests (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
SoupSession *session;
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
@@ -166,8 +169,9 @@ do_async_tests (gconstpointer uri)
}
static void
-do_sync_tests (gconstpointer uri)
+do_sync_tests (gconstpointer data)
{
+ SoupURI *uri = (SoupURI *)data;
SoupSession *session;
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
@@ -194,7 +198,7 @@ priority_test_finished_cb (SoupSession *session, SoupMessage *msg, gpointer user
static void
do_priority_tests (gconstpointer data)
{
- const char *uri = data;
+ SoupURI *uri = (SoupURI *)data;
SoupSession *session;
int i, finished_count = 0;
SoupMessagePriority priorities[] =
@@ -212,12 +216,14 @@ do_priority_tests (gconstpointer data)
expected_priorities[2] = SOUP_MESSAGE_PRIORITY_LOW;
for (i = 0; i < 3; i++) {
- char *msg_uri;
+ SoupURI *msg_uri;
SoupMessage *msg;
+ char buf[5];
- msg_uri = g_strdup_printf ("%s/%d", uri, i);
- msg = soup_message_new ("GET", uri);
- g_free (msg_uri);
+ g_snprintf (buf, sizeof (buf), "%d", i);
+ msg_uri = soup_uri_new_with_base (uri, buf);
+ msg = soup_message_new_from_uri ("GET", msg_uri);
+ soup_uri_free (msg_uri);
soup_message_set_priority (msg, priorities[i]);
soup_session_queue_message (session, msg, priority_test_finished_cb, &finished_count);
@@ -368,16 +374,14 @@ int
main (int argc, char **argv)
{
SoupServer *server;
- char *uri, *timeout_uri;
+ SoupURI *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);
+ uri = soup_test_server_get_uri (server, "http", NULL);
g_test_add_data_func ("/session/SoupSession", uri, do_plain_tests);
g_test_add_data_func ("/session/SoupSessionAsync", uri, do_async_tests);
@@ -387,8 +391,7 @@ main (int argc, char **argv)
ret = g_test_run ();
- g_free (uri);
- g_free (timeout_uri);
+ soup_uri_free (uri);
soup_test_server_quit_unref (server);
test_cleanup ();
diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c
index 32fad9fc..7b391178 100644
--- a/tests/sniffing-test.c
+++ b/tests/sniffing-test.c
@@ -440,10 +440,9 @@ main (int argc, char **argv)
test_init (argc, argv, NULL);
- server = soup_test_server_new (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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 = soup_test_server_get_uri (server, "http", NULL);
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
@@ -529,6 +528,10 @@ main (int argc, char **argv)
g_test_add_data_func ("/sniffing/type/unknown-leading-space",
"unknown/leading_space.html => text/html",
do_sniffing_test);
+ /* https://bugs.webkit.org/show_bug.cgi?id=173923 */
+ g_test_add_data_func ("/sniffing/type/unknown-xml",
+ "unknown/misc.xml => text/xml",
+ do_sniffing_test);
/* Test the XML sniffing path */
g_test_add_data_func ("/sniffing/type/xml",
diff --git a/tests/socket-test.c b/tests/socket-test.c
index 5bcc3b0c..5b2b390e 100644
--- a/tests/socket-test.c
+++ b/tests/socket-test.c
@@ -5,7 +5,9 @@
*/
#include "test-utils.h"
+#include "libsoup/soup-socket-private.h"
+#include <fcntl.h>
#include <gio/gnetworking.h>
static void
@@ -74,7 +76,10 @@ do_unconnected_socket_test (void)
/* listening socket fails with ENOTCONN */
g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
- "*endpoint is not connected*");
+ /* We can't check the error message since it comes from
+ * libc and is locale-dependent.
+ */
+ "*");
addr = soup_socket_get_remote_address (sock);
g_test_assert_expected_messages ();
g_assert_null (addr);
@@ -82,6 +87,7 @@ do_unconnected_socket_test (void)
soup_socket_disconnect (sock);
g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
+ /* This error message comes from soup-socket.c though */
"*socket not connected*");
addr = soup_socket_get_remote_address (sock);
g_test_assert_expected_messages ();
@@ -108,6 +114,230 @@ do_unconnected_socket_test (void)
g_object_unref (sock);
}
+static void
+do_socket_from_fd_client_test (void)
+{
+ SoupServer *server;
+ SoupURI *uri;
+ GSocket *gsock;
+ SoupSocket *sock;
+ SoupAddress *local, *remote;
+ GSocketAddress *gaddr;
+ gboolean is_server;
+ GError *error = NULL;
+
+ server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
+ uri = soup_test_server_get_uri (server, "http", "127.0.0.1");
+
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &error);
+ g_assert_no_error (error);
+
+ gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", uri->port);
+ g_socket_connect (gsock, gaddr, NULL, &error);
+ g_object_unref (gaddr);
+ g_assert_no_error (error);
+ g_assert_true (g_socket_is_connected (gsock));
+
+ gaddr = g_socket_get_local_address (gsock, &error);
+ g_assert_no_error (error);
+
+ sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
+ SOUP_SOCKET_FD, g_socket_get_fd (gsock),
+ NULL);
+ g_assert_no_error (error);
+ g_assert_nonnull (sock);
+
+ g_object_get (G_OBJECT (sock),
+ SOUP_SOCKET_LOCAL_ADDRESS, &local,
+ SOUP_SOCKET_REMOTE_ADDRESS, &remote,
+ SOUP_SOCKET_IS_SERVER, &is_server,
+ NULL);
+ g_assert_cmpint (soup_socket_get_fd (sock), ==, g_socket_get_fd (gsock));
+ g_assert_false (is_server);
+ g_assert_true (soup_socket_is_connected (sock));
+
+ g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1");
+ g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr)));
+ g_assert_cmpstr (soup_address_get_physical (remote), ==, "127.0.0.1");
+ g_assert_cmpint (soup_address_get_port (remote), ==, uri->port);
+
+ g_object_unref (local);
+ g_object_unref (remote);
+ g_object_unref (gaddr);
+
+ g_object_unref (sock);
+ g_object_unref (gsock);
+
+ soup_test_server_quit_unref (server);
+ soup_uri_free (uri);
+}
+
+static void
+do_socket_from_fd_server_test (void)
+{
+ GSocket *gsock;
+ SoupSocket *sock;
+ SoupAddress *local;
+ GSocketAddress *gaddr;
+ gboolean is_server;
+ GError *error = NULL;
+
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &error);
+ g_assert_no_error (error);
+
+ gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
+ g_socket_bind (gsock, gaddr, TRUE, &error);
+ g_object_unref (gaddr);
+ g_assert_no_error (error);
+ g_socket_listen (gsock, &error);
+ g_assert_no_error (error);
+ g_assert_false (g_socket_is_connected (gsock));
+
+ gaddr = g_socket_get_local_address (gsock, &error);
+ g_assert_no_error (error);
+
+ sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
+ SOUP_SOCKET_GSOCKET, gsock,
+ NULL);
+ g_assert_no_error (error);
+ g_assert_nonnull (sock);
+
+ g_object_get (G_OBJECT (sock),
+ SOUP_SOCKET_LOCAL_ADDRESS, &local,
+ SOUP_SOCKET_IS_SERVER, &is_server,
+ NULL);
+ g_assert_cmpint (soup_socket_get_fd (sock), ==, g_socket_get_fd (gsock));
+ g_assert_true (is_server);
+ g_assert_true (soup_socket_is_connected (sock));
+
+ g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1");
+ g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr)));
+ g_object_unref (local);
+ g_object_unref (gaddr);
+
+ g_object_unref (sock);
+
+ /* Closing the SoupSocket should have closed the GSocket */
+ g_assert_true (g_socket_is_closed (gsock));
+
+ g_object_unref (gsock);
+}
+
+static void
+do_socket_from_fd_bad_test (void)
+{
+ GSocket *gsock, *gsock2, *gsockcli;
+ SoupSocket *sock, *sock2;
+ SoupAddress *local, *remote;
+ GSocketAddress *gaddr;
+ gboolean is_server;
+ int fd;
+ GError *error = NULL;
+
+ /* Importing a non-socket fd gives an error */
+ fd = open (g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL), O_RDONLY);
+ g_assert_cmpint (fd, !=, -1);
+
+ sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
+ SOUP_SOCKET_FD, fd,
+ NULL);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
+ g_clear_error (&error);
+ g_assert_null (sock);
+ close (fd);
+
+ /* Importing an unconnected socket gives an error */
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &error);
+ g_assert_no_error (error);
+ g_assert_false (g_socket_is_connected (gsock));
+
+ sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
+ SOUP_SOCKET_FD, g_socket_get_fd (gsock),
+ NULL);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
+ g_clear_error (&error);
+ g_assert_null (sock);
+ g_object_unref (gsock);
+
+ /* Importing a non-listening server-side socket works, but
+ * gives the wrong answer for soup_socket_is_server().
+ */
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &error);
+ g_assert_no_error (error);
+
+ gaddr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
+ g_socket_bind (gsock, gaddr, TRUE, &error);
+ g_object_unref (gaddr);
+ g_assert_no_error (error);
+ g_socket_listen (gsock, &error);
+ g_assert_no_error (error);
+ g_assert_false (g_socket_is_connected (gsock));
+
+ gaddr = g_socket_get_local_address (gsock, &error);
+ g_assert_no_error (error);
+
+ gsockcli = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &error);
+ g_assert_no_error (error);
+
+ g_socket_connect (gsockcli, gaddr, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (g_socket_is_connected (gsockcli));
+
+ gsock2 = g_socket_accept (gsock, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (gsock2);
+
+ sock2 = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
+ SOUP_SOCKET_GSOCKET, gsock2,
+ NULL);
+ g_assert_no_error (error);
+ g_assert_nonnull (sock2);
+
+ g_object_get (G_OBJECT (sock2),
+ SOUP_SOCKET_LOCAL_ADDRESS, &local,
+ SOUP_SOCKET_REMOTE_ADDRESS, &remote,
+ SOUP_SOCKET_IS_SERVER, &is_server,
+ NULL);
+ g_assert_cmpint (soup_socket_get_fd (sock2), ==, g_socket_get_fd (gsock2));
+ g_assert_true (soup_socket_is_connected (sock2));
+ /* This is wrong, but can't be helped. */
+ g_assert_false (is_server);
+
+ g_assert_cmpstr (soup_address_get_physical (local), ==, "127.0.0.1");
+ g_assert_cmpint (soup_address_get_port (local), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr)));
+ g_object_unref (gaddr);
+
+ gaddr = g_socket_get_local_address (gsockcli, &error);
+ g_assert_no_error (error);
+ g_assert_cmpstr (soup_address_get_physical (remote), ==, "127.0.0.1");
+ g_assert_cmpint (soup_address_get_port (remote), ==, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (gaddr)));
+ g_object_unref (gaddr);
+
+ g_object_unref (local);
+ g_object_unref (remote);
+
+ g_object_unref (sock2);
+
+ g_object_unref (gsock);
+ g_object_unref (gsock2);
+ g_object_unref (gsockcli);
+}
+
int
main (int argc, char **argv)
{
@@ -116,6 +346,9 @@ main (int argc, char **argv)
test_init (argc, argv, NULL);
g_test_add_func ("/sockets/unconnected", do_unconnected_socket_test);
+ g_test_add_func ("/sockets/from-fd/client", do_socket_from_fd_client_test);
+ g_test_add_func ("/sockets/from-fd/server", do_socket_from_fd_server_test);
+ g_test_add_func ("/sockets/from-fd/bad", do_socket_from_fd_bad_test);
ret = g_test_run ();
diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml
index b24a7297..9c08d170 100644
--- a/tests/soup-tests.gresource.xml
+++ b/tests/soup-tests.gresource.xml
@@ -13,6 +13,7 @@
<file>resources/mbox.gz</file>
<file>resources/mbox.raw</file>
<file>resources/mbox.zlib</file>
+ <file>resources/misc.xml</file>
<file>resources/ps_binary.ps</file>
<file>resources/rss20.xml</file>
<file>resources/test.aiff</file>
diff --git a/tests/ssl-test.c b/tests/ssl-test.c
index e6bbb615..735ba416 100644
--- a/tests/ssl-test.c
+++ b/tests/ssl-test.c
@@ -2,16 +2,17 @@
#include "test-utils.h"
-static char *uri;
+SoupURI *uri;
+GTlsDatabase *null_tlsdb;
static void
-do_properties_test_for_session (SoupSession *session, const char *uri)
+do_properties_test_for_session (SoupSession *session)
{
SoupMessage *msg;
GTlsCertificate *cert;
GTlsCertificateFlags flags;
- msg = soup_message_new ("GET", uri);
+ msg = soup_message_new_from_uri ("GET", uri);
soup_session_send_message (session, msg);
soup_test_assert_message_status (msg, SOUP_STATUS_OK);
@@ -36,10 +37,10 @@ do_async_properties_tests (void)
session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
g_object_set (G_OBJECT (session),
- SOUP_SESSION_SSL_CA_FILE, "/dev/null",
+ SOUP_SESSION_TLS_DATABASE, null_tlsdb,
SOUP_SESSION_SSL_STRICT, FALSE,
NULL);
- do_properties_test_for_session (session, uri);
+ do_properties_test_for_session (session);
soup_test_session_abort_unref (session);
}
@@ -52,10 +53,10 @@ do_sync_properties_tests (void)
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
g_object_set (G_OBJECT (session),
- SOUP_SESSION_SSL_CA_FILE, "/dev/null",
+ SOUP_SESSION_TLS_DATABASE, null_tlsdb,
SOUP_SESSION_SSL_STRICT, FALSE,
NULL);
- do_properties_test_for_session (session, uri);
+ do_properties_test_for_session (session);
soup_test_session_abort_unref (session);
}
@@ -105,11 +106,11 @@ do_strictness_test (gconstpointer data)
}
if (!test->with_ca_list) {
g_object_set (G_OBJECT (session),
- SOUP_SESSION_SSL_CA_FILE, "/dev/null",
+ SOUP_SESSION_TLS_DATABASE, null_tlsdb,
NULL);
}
- msg = soup_message_new ("GET", uri);
+ msg = soup_message_new_from_uri ("GET", uri);
soup_session_send_message (session, msg);
soup_test_assert_message_status (msg, test->expected_status);
@@ -127,6 +128,7 @@ do_strictness_test (gconstpointer data)
debug_printf (1, " tls error flags: 0x%x\n", flags);
g_object_unref (msg);
+
soup_test_session_abort_unref (session);
}
@@ -146,12 +148,21 @@ do_session_property_tests (void)
GTlsDatabase *tlsdb;
char *ca_file;
SoupSession *session;
+ GParamSpec *pspec;
g_test_bug ("673678");
SOUP_TEST_SKIP_IF_NO_TLS;
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
session = soup_session_async_new ();
+ G_GNUC_END_IGNORE_DEPRECATIONS;
+
+ /* Temporarily undeprecate SOUP_SESSION_SSL_CA_FILE to avoid warnings. */
+ pspec = g_object_class_find_property (g_type_class_peek (SOUP_TYPE_SESSION),
+ SOUP_SESSION_SSL_CA_FILE);
+ pspec->flags &= ~G_PARAM_DEPRECATED;
+
g_signal_connect (session, "notify::ssl-use-system-ca-file",
G_CALLBACK (property_changed), &use_system_changed);
g_signal_connect (session, "notify::tls-database",
@@ -232,6 +243,175 @@ do_session_property_tests (void)
g_assert_true (ca_file_changed);
soup_test_session_abort_unref (session);
+
+ /* Re-deprecate SOUP_SESSION_SSL_CA_FILE */
+ pspec->flags |= G_PARAM_DEPRECATED;
+}
+
+/* GTlsInteraction subclass for do_interaction_test */
+typedef GTlsInteraction TestTlsInteraction;
+typedef GTlsInteractionClass TestTlsInteractionClass;
+
+GType test_tls_interaction_get_type (void);
+
+G_DEFINE_TYPE (TestTlsInteraction, test_tls_interaction, G_TYPE_TLS_INTERACTION);
+
+static void
+test_tls_interaction_init (TestTlsInteraction *interaction)
+{
+
+}
+
+static GTlsInteractionResult
+test_tls_interaction_request_certificate (GTlsInteraction *interaction,
+ GTlsConnection *connection,
+ GTlsCertificateRequestFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsCertificate *cert;
+ const char *ssl_cert_file, *ssl_key_file;
+ GError *my_error = NULL;
+
+ /* Yes, we use the same certificate for the client as for the server. Shrug */
+ ssl_cert_file = g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL);
+ ssl_key_file = g_test_get_filename (G_TEST_DIST, "test-key.pem", NULL);
+ cert = g_tls_certificate_new_from_files (ssl_cert_file,
+ ssl_key_file,
+ &my_error);
+ g_assert_no_error (my_error);
+
+ g_tls_connection_set_certificate (connection, cert);
+ g_object_unref (cert);
+
+ return G_TLS_INTERACTION_HANDLED;
+}
+
+static void
+test_tls_interaction_class_init (TestTlsInteractionClass *klass)
+{
+ GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass);
+
+ interaction_class->request_certificate = test_tls_interaction_request_certificate;
+}
+
+
+#define INTERACTION_TEST_HTTP_RESPONSE "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nOK\r\n"
+
+static gboolean
+accept_client_certificate (GTlsConnection *server,
+ GTlsCertificate *client_cert,
+ GTlsCertificateFlags errors)
+{
+ return TRUE;
+}
+
+static void
+got_connection (GThreadedSocketService *service,
+ GSocketConnection *connection,
+ GObject *source_object)
+{
+ GIOStream *tls;
+ GTlsCertificate *server_cert;
+ GError *error = NULL;
+ const char *ssl_cert_file, *ssl_key_file;
+ GMainContext *thread_context;
+
+ thread_context = g_main_context_new ();
+ g_main_context_push_thread_default (thread_context);
+
+ ssl_cert_file = g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL);
+ ssl_key_file = g_test_get_filename (G_TEST_DIST, "test-key.pem", NULL);
+ server_cert = g_tls_certificate_new_from_files (ssl_cert_file,
+ ssl_key_file,
+ &error);
+ g_assert_no_error (error);
+
+ tls = g_tls_server_connection_new (G_IO_STREAM (connection),
+ server_cert, &error);
+ g_assert_no_error (error);
+ g_object_unref (server_cert);
+
+ g_object_set (G_OBJECT (tls),
+ "authentication-mode", G_TLS_AUTHENTICATION_REQUIRED,
+ NULL);
+ g_signal_connect (tls, "accept-certificate",
+ G_CALLBACK (accept_client_certificate), NULL);
+
+ if (g_tls_connection_handshake (G_TLS_CONNECTION (tls), NULL, &error)) {
+ g_output_stream_write_all (g_io_stream_get_output_stream (tls),
+ INTERACTION_TEST_HTTP_RESPONSE,
+ strlen (INTERACTION_TEST_HTTP_RESPONSE),
+ NULL, NULL, &error);
+ g_assert_no_error (error);
+ } else {
+ g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED);
+ g_clear_error (&error);
+ }
+
+ g_io_stream_close (tls, NULL, &error);
+ g_assert_no_error (error);
+
+ g_object_unref (tls);
+
+ g_main_context_pop_thread_default (thread_context);
+ g_main_context_unref (thread_context);
+}
+
+static void
+do_tls_interaction_test (void)
+{
+ GSocketService *service;
+ GSocketAddress *address, *bound_address;
+ SoupSession *session;
+ SoupMessage *msg;
+ GTlsInteraction *interaction;
+ SoupURI *test_uri;
+ GError *error = NULL;
+
+ SOUP_TEST_SKIP_IF_NO_TLS;
+
+ service = g_threaded_socket_service_new (1);
+ address = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
+ g_socket_listener_add_address (G_SOCKET_LISTENER (service), address,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP,
+ NULL, &bound_address, &error);
+ g_assert_no_error (error);
+ g_object_unref (address);
+ g_signal_connect (service, "run", G_CALLBACK (got_connection), NULL);
+ g_socket_service_start (service);
+
+ test_uri = soup_uri_new ("https://127.0.0.1");
+ soup_uri_set_port (test_uri, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (bound_address)));
+ g_object_unref (bound_address);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+
+ /* Without a GTlsInteraction */
+ msg = soup_message_new_from_uri ("GET", test_uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_SSL_FAILED);
+ g_object_unref (msg);
+
+ interaction = g_object_new (test_tls_interaction_get_type (), NULL);
+ g_object_set (G_OBJECT (session),
+ SOUP_SESSION_TLS_INTERACTION, interaction,
+ NULL);
+ g_object_unref (interaction);
+
+ /* With a GTlsInteraction */
+ msg = soup_message_new_from_uri ("GET", test_uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_assert_true (soup_message_get_https_status (msg, NULL, NULL));
+ g_object_unref (msg);
+
+ soup_uri_free (test_uri);
+ soup_test_session_abort_unref (session);
+
+ g_socket_service_stop (service);
+ g_object_unref (service);
}
static void
@@ -251,21 +431,26 @@ server_handler (SoupServer *server,
int
main (int argc, char **argv)
{
- SoupServer *server;
+ SoupServer *server = NULL;
int i, ret;
+ GError *error = NULL;
test_init (argc, argv, NULL);
if (tls_available) {
- server = soup_test_server_new_ssl (TRUE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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));
- }
+ uri = soup_test_server_get_uri (server, "https", "127.0.0.1");
+
+ null_tlsdb = g_tls_file_database_new ("/dev/null", &error);
+ g_assert_no_error (error);
+ } else
+ uri = NULL;
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);
+ g_test_add_func ("/ssl/tls-interaction", do_tls_interaction_test);
for (i = 0; i < G_N_ELEMENTS (strictness_tests); i++) {
g_test_add_data_func (strictness_tests[i].name,
@@ -276,8 +461,9 @@ main (int argc, char **argv)
ret = g_test_run ();
if (tls_available) {
- g_free (uri);
+ soup_uri_free (uri);
soup_test_server_quit_unref (server);
+ g_object_unref (null_tlsdb);
}
test_cleanup ();
diff --git a/tests/streaming-test.c b/tests/streaming-test.c
index 8d8c02ef..bd4a5194 100644
--- a/tests/streaming-test.c
+++ b/tests/streaming-test.c
@@ -138,7 +138,6 @@ main (int argc, char **argv)
{
GMainLoop *loop;
SoupServer *server;
- guint port;
SoupURI *base_uri;
int ret;
@@ -149,15 +148,13 @@ main (int argc, char **argv)
(guchar *)full_response->data,
full_response->length);
- server = soup_test_server_new (FALSE);
+ server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
soup_server_add_handler (server, NULL,
server_callback, NULL, NULL);
- port = soup_server_get_port (server);
loop = g_main_loop_new (NULL, TRUE);
- base_uri = soup_uri_new ("http://127.0.0.1");
- soup_uri_set_port (base_uri, port);
+ base_uri = soup_test_server_get_uri (server, "http", NULL);
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);
diff --git a/tests/test-cert.pem b/tests/test-cert.pem
index 7f206266..ff863b4d 100644
--- a/tests/test-cert.pem
+++ b/tests/test-cert.pem
@@ -1,17 +1,18 @@
-----BEGIN CERTIFICATE-----
-MIICpDCCAYwCCQC8Suc8hjfgujANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDDAkx
-MjcuMC4wLjEwHhcNMTEwOTE5MTkyMjA1WhcNMjEwOTE2MTkyMjA1WjAUMRIwEAYD
-VQQDDAkxMjcuMC4wLjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCr
-OH7kblu+5zkYTk/ZG21OgbIyltxhLDHPmUpl4yDUFqX5BEtoVfg0Ms4ZuaoeDi4t
-b2LV6Em3UDQwmwPMm2SakfJvRd3nfL6G3UkkBsVqT3V04M9u8fk6YgHPT8PN1Lj7
-5bv9AMRyQRV1QIPondMhbt8JhlmCR6ALbxYtsXkbQF7qzbj7Y2cjvoHzPQSk0QpB
-rEUpj6Schm1NkPen48Z1X1faGL0F3roFHEsf6U1AjP5A4A/UGQsRtq35VzVnKgxW
-N7jumUevEMIvyqLjmvK864AHMIRVCOls9GcIta80bViuVqgtuGgVGM/7SoZfIvPF
-A10jIe7KQoXWAwRi4WclAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAJfihY634dRr
-DeEA4SQ1e0/kB6EF8oeaC+5EuGOJxtoX+yXJfWJsEtmjRwobyOBVV997hdOtdZjo
-mdJOCKerOFKccO9PLNJZ+/l4+NHv9OwOcu4UqvrSsps/pmr/22SIyQswbLLJfPAT
-KjGTDLlj//zrLxzUGsu7lgGsY4s4fVbftFZv7P5AyErpwiFk8qM1BP0NMkn4XWSA
-uSyTeB6O+tWYdh3bA1BeKC2P85sl6xFJI2gxvNTxtdcg9beDqNuEheJ+mEtD3P4w
-HDG1vFaAX0MH1RJSDO/dIoJerN6LTjiTYYYg8yV0lmBxijv25Z/3Gi33OuG9jkdR
-vXDwJpC+/ko=
+MIIC2zCCAcOgAwIBAgIJALRbg2WnuAAqMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
+BAMMCTEyNy4wLjAuMTAeFw0xNzA2MjAxNDI3MzBaFw0yNzA2MTgxNDI3MzBaMBQx
+EjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAKs4fuRuW77nORhOT9kbbU6BsjKW3GEsMc+ZSmXjINQWpfkES2hV+DQyzhm5
+qh4OLi1vYtXoSbdQNDCbA8ybZJqR8m9F3ed8vobdSSQGxWpPdXTgz27x+TpiAc9P
+w83UuPvlu/0AxHJBFXVAg+id0yFu3wmGWYJHoAtvFi2xeRtAXurNuPtjZyO+gfM9
+BKTRCkGsRSmPpJyGbU2Q96fjxnVfV9oYvQXeugUcSx/pTUCM/kDgD9QZCxG2rflX
+NWcqDFY3uO6ZR68Qwi/KouOa8rzrgAcwhFUI6Wz0Zwi1rzRtWK5WqC24aBUYz/tK
+hl8i88UDXSMh7spChdYDBGLhZyUCAwEAAaMwMC4wLAYDVR0RBCUwI4IJbG9jYWxo
+b3N0hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQBj
++U8tebwg5/pof5Rht6TMHqeg6Fcr4OJkL2ph2g+T/AMTS7kEGeFIKJN5AZ+S/qIY
+cdoDKHwc8+bCK/mG6DPmJ4z/2Eamb85YhplOLVrLRwfxRebTK9CtnjcjnflAiU9H
+7vPVwXIvkwebhBSQNKTdkBlPXKaTNWXuygeFG2OVQkPf/KAxSdtg2R+owv/s802Z
+HISk26wY9oFIQz6AiXWdrY1QqNOltZ7rlU5iofAH7X+9ryZlxPWj/gHg2YQRvvLl
+dq6nCF+ED0ke7h0lg5nU0beKEygwli8DlLVbu0JK0PkARFp5t7wUtzC9DCjzvfOc
+gxR44PyZX7/2oaTDm4PS
-----END CERTIFICATE-----
diff --git a/tests/test-utils.c b/tests/test-utils.c
index bc160aea..9c742060 100644
--- a/tests/test-utils.c
+++ b/tests/test-utils.c
@@ -66,6 +66,7 @@ test_init (int argc, char **argv, GOptionEntry *entries)
setlocale (LC_ALL, "");
g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
g_setenv ("GIO_USE_PROXY_RESOLVER", "dummy", TRUE);
+ g_setenv ("GIO_USE_VFS", "local", TRUE);
name = strrchr (argv[0], '/');
if (!name++)
@@ -228,18 +229,31 @@ soup_test_session_new (GType type, ...)
va_list args;
const char *propname;
SoupSession *session;
+ GTlsDatabase *tlsdb;
char *cafile;
+ GError *error = NULL;
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, cafile,
- NULL);
- g_free (cafile);
+ if (tls_available) {
+ cafile = g_test_build_filename (G_TEST_DIST, "test-cert.pem", NULL);
+ tlsdb = g_tls_file_database_new (cafile, &error);
+ g_free (cafile);
+ if (error) {
+ if (g_strcmp0 (g_getenv ("GIO_USE_TLS"), "dummy") == 0)
+ g_clear_error (&error);
+ else
+ g_assert_no_error (error);
+ }
+
+ g_object_set (G_OBJECT (session),
+ SOUP_SESSION_TLS_DATABASE, tlsdb,
+ NULL);
+ g_clear_object (&tlsdb);
+ }
if (http_debug_level && !logger) {
SoupLoggerLogLevel level = MIN ((SoupLoggerLogLevel)http_debug_level, SOUP_LOGGER_LOG_BODY);
@@ -262,79 +276,240 @@ soup_test_session_abort_unref (SoupSession *session)
g_object_unref (session);
}
-static gpointer run_server_thread (gpointer user_data);
+static void
+server_listen (SoupServer *server)
+{
+ GError *error = NULL;
+
+ soup_server_listen_local (server, 0, 0, &error);
+ if (error) {
+ g_printerr ("Unable to create server: %s\n", error->message);
+ exit (1);
+ }
+}
+
+static GMutex server_start_mutex;
+static GCond server_start_cond;
-static SoupServer *
-test_server_new (gboolean in_own_thread, gboolean ssl)
+static gpointer
+run_server_thread (gpointer user_data)
+{
+ SoupServer *server = user_data;
+ SoupTestServerOptions options =
+ GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (server), "options"));
+ GMainContext *context;
+ GMainLoop *loop;
+
+ context = g_main_context_new ();
+ g_main_context_push_thread_default (context);
+ loop = g_main_loop_new (context, FALSE);
+ g_object_set_data (G_OBJECT (server), "GMainLoop", loop);
+
+ if (!(options & SOUP_TEST_SERVER_NO_DEFAULT_LISTENER))
+ server_listen (server);
+
+ g_mutex_lock (&server_start_mutex);
+ g_cond_signal (&server_start_cond);
+ g_mutex_unlock (&server_start_mutex);
+
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ soup_server_disconnect (server);
+
+ g_main_context_pop_thread_default (context);
+ g_main_context_unref (context);
+
+ return NULL;
+}
+
+SoupServer *
+soup_test_server_new (SoupTestServerOptions options)
{
SoupServer *server;
- GMainContext *async_context;
- char *ssl_cert_file, *ssl_key_file;
- SoupAddress *addr;
+ GTlsCertificate *cert = NULL;
+ GError *error = NULL;
- async_context = in_own_thread ? g_main_context_new () : NULL;
+ if (tls_available) {
+ char *ssl_cert_file, *ssl_key_file;
- if (ssl) {
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;
-
- addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT);
- soup_address_resolve_sync (addr, NULL);
+ cert = g_tls_certificate_new_from_files (ssl_cert_file,
+ ssl_key_file,
+ &error);
+ g_free (ssl_cert_file);
+ g_free (ssl_key_file);
+ if (error) {
+ g_printerr ("Unable to create server: %s\n", error->message);
+ exit (1);
+ }
+ }
- server = soup_server_new (SOUP_SERVER_INTERFACE, addr,
- SOUP_SERVER_ASYNC_CONTEXT, async_context,
- SOUP_SERVER_SSL_CERT_FILE, ssl_cert_file,
- SOUP_SERVER_SSL_KEY_FILE, ssl_key_file,
+ server = soup_server_new (SOUP_SERVER_TLS_CERTIFICATE, cert,
NULL);
- 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");
- exit (1);
- }
+ g_clear_object (&cert);
+
+ g_object_set_data (G_OBJECT (server), "options", GUINT_TO_POINTER (options));
- if (in_own_thread) {
+ if (options & SOUP_TEST_SERVER_IN_THREAD) {
GThread *thread;
+ g_mutex_lock (&server_start_mutex);
+
thread = g_thread_new ("server_thread", run_server_thread, server);
+ g_cond_wait (&server_start_cond, &server_start_mutex);
+ g_mutex_unlock (&server_start_mutex);
+
g_object_set_data (G_OBJECT (server), "thread", thread);
- } else
- soup_server_run_async (server);
+ } else if (!(options & SOUP_TEST_SERVER_NO_DEFAULT_LISTENER))
+ server_listen (server);
return server;
}
-SoupServer *
-soup_test_server_new (gboolean in_own_thread)
+static SoupURI *
+find_server_uri (SoupServer *server, const char *scheme, const char *host)
+{
+ GSList *uris, *u;
+ SoupURI *uri, *ret_uri = NULL;
+
+ uris = soup_server_get_uris (server);
+ for (u = uris; u; u = u->next) {
+ uri = u->data;
+
+ if (scheme && strcmp (uri->scheme, scheme) != 0)
+ continue;
+ if (host && strcmp (uri->host, host) != 0)
+ continue;
+
+ ret_uri = soup_uri_copy (uri);
+ break;
+ }
+ g_slist_free_full (uris, (GDestroyNotify)soup_uri_free);
+
+ return ret_uri;
+}
+
+static SoupURI *
+add_listener (SoupServer *server, const char *scheme, const char *host)
{
- return test_server_new (in_own_thread, FALSE);
+ SoupServerListenOptions options = 0;
+ GError *error = NULL;
+
+ if (!g_strcmp0 (scheme, SOUP_URI_SCHEME_HTTPS))
+ options |= SOUP_SERVER_LISTEN_HTTPS;
+ if (!g_strcmp0 (host, "127.0.0.1"))
+ options |= SOUP_SERVER_LISTEN_IPV4_ONLY;
+ else if (!g_strcmp0 (host, "::1"))
+ options |= SOUP_SERVER_LISTEN_IPV6_ONLY;
+
+ soup_server_listen_local (server, 0, options, &error);
+ g_assert_no_error (error);
+
+ return find_server_uri (server, scheme, host);
}
-SoupServer *
-soup_test_server_new_ssl (gboolean in_own_thread)
+typedef struct {
+ GMutex mutex;
+ GCond cond;
+
+ SoupServer *server;
+ const char *scheme;
+ const char *host;
+
+ SoupURI *uri;
+} AddListenerData;
+
+static gboolean
+add_listener_in_thread (gpointer user_data)
{
- return test_server_new (in_own_thread, TRUE);
+ AddListenerData *data = user_data;
+
+ data->uri = add_listener (data->server, data->scheme, data->host);
+ g_mutex_lock (&data->mutex);
+ g_cond_signal (&data->cond);
+ g_mutex_unlock (&data->mutex);
+
+ return FALSE;
}
-static gpointer
-run_server_thread (gpointer user_data)
+SoupURI *
+soup_test_server_get_uri (SoupServer *server,
+ const char *scheme,
+ const char *host)
{
- SoupServer *server = user_data;
+ SoupURI *uri;
+ GMainLoop *loop;
- soup_server_run (server);
- return NULL;
+ uri = find_server_uri (server, scheme, host);
+ if (uri)
+ return uri;
+
+ /* Need to add a new listener */
+ loop = g_object_get_data (G_OBJECT (server), "GMainLoop");
+ if (loop) {
+ GMainContext *context = g_main_loop_get_context (loop);
+ AddListenerData data;
+
+ g_mutex_init (&data.mutex);
+ g_cond_init (&data.cond);
+ data.server = server;
+ data.scheme = scheme;
+ data.host = host;
+ data.uri = NULL;
+
+ g_mutex_lock (&data.mutex);
+ soup_add_completion (context, add_listener_in_thread, &data);
+
+ while (!data.uri)
+ g_cond_wait (&data.cond, &data.mutex);
+
+ g_mutex_unlock (&data.mutex);
+ g_mutex_clear (&data.mutex);
+ g_cond_clear (&data.cond);
+ uri = data.uri;
+ } else
+ uri = add_listener (server, scheme, host);
+
+ return uri;
}
static gboolean
-idle_quit_server (gpointer server)
+done_waiting (gpointer user_data)
{
- soup_server_quit (server);
+ gboolean *done = user_data;
+
+ *done = TRUE;
+ return FALSE;
+}
+
+static void
+disconnect_and_wait (SoupServer *server,
+ GMainContext *context)
+{
+ GSource *source;
+ gboolean done = FALSE;
+
+ source = g_idle_source_new ();
+ g_source_set_priority (source, G_PRIORITY_LOW);
+ g_source_set_callback (source, done_waiting, &done, NULL);
+ g_source_attach (source, context);
+ g_source_unref (source);
+
+ soup_server_disconnect (server);
+ while (!done)
+ g_main_context_iteration (context, TRUE);
+}
+
+static gboolean
+idle_quit_server (gpointer user_data)
+{
+ SoupServer *server = user_data;
+ GMainLoop *loop = g_object_get_data (G_OBJECT (server), "GMainLoop");
+
+ disconnect_and_wait (server, g_main_loop_get_context (loop));
+ g_main_loop_quit (loop);
return FALSE;
}
@@ -345,11 +520,17 @@ soup_test_server_quit_unref (SoupServer *server)
thread = g_object_get_data (G_OBJECT (server), "thread");
if (thread) {
- soup_add_completion (soup_server_get_async_context (server),
- idle_quit_server, server);
+ GMainLoop *loop;
+ GMainContext *context;
+
+ loop = g_object_get_data (G_OBJECT (server), "GMainLoop");
+ context = g_main_loop_get_context (loop);
+ g_main_context_ref (context);
+ soup_add_completion (context, idle_quit_server, server);
+ g_main_context_unref (context);
g_thread_join (thread);
} else
- soup_server_quit (server);
+ disconnect_and_wait (server, NULL);
g_assert_cmpint (G_OBJECT (server)->ref_count, ==, 1);
g_object_unref (server);
@@ -400,7 +581,7 @@ create_cancel_data (SoupRequest *req,
return cancel_data;
}
-static void inline
+inline static void
cancel_message_or_cancellable (CancelData *cancel_data)
{
if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE) {
@@ -461,7 +642,7 @@ soup_test_request_send (SoupRequest *req,
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);
+ cancel_message_or_cancellable (cancel_data);
soup_request_send_async (req, cancellable, async_as_sync_callback, &data);
g_main_loop_run (data.loop);
diff --git a/tests/test-utils.h b/tests/test-utils.h
index 03637dcf..0bc065fc 100644
--- a/tests/test-utils.h
+++ b/tests/test-utils.h
@@ -52,12 +52,25 @@ typedef enum {
SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH = (1 << 5),
} SoupTestRequestFlags;
+#undef SOUP_TYPE_SESSION_ASYNC
+#define SOUP_TYPE_SESSION_ASYNC (_soup_session_async_get_type_undeprecated ())
+#undef SOUP_TYPE_SESSION_SYNC
+#define SOUP_TYPE_SESSION_SYNC (_soup_session_sync_get_type_undeprecated ())
+
SoupSession *soup_test_session_new (GType type, ...);
void soup_test_session_abort_unref (SoupSession *session);
-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);
+typedef enum {
+ SOUP_TEST_SERVER_DEFAULT = 0,
+ SOUP_TEST_SERVER_IN_THREAD = (1 << 0),
+ SOUP_TEST_SERVER_NO_DEFAULT_LISTENER = (1 << 1)
+} SoupTestServerOptions;
+
+SoupServer *soup_test_server_new (SoupTestServerOptions options);
+SoupURI *soup_test_server_get_uri (SoupServer *server,
+ const char *scheme,
+ const char *host);
+void soup_test_server_quit_unref (SoupServer *server);
GInputStream *soup_test_request_send (SoupRequest *req,
GCancellable *cancellable,
diff --git a/tests/timeout-test.c b/tests/timeout-test.c
index 81fb4331..96505e9b 100644
--- a/tests/timeout-test.c
+++ b/tests/timeout-test.c
@@ -22,7 +22,7 @@ request_started_cb (SoupSession *session, SoupMessage *msg,
}
static void
-do_message_to_session (SoupSession *session, const char *uri,
+do_message_to_session (SoupSession *session, SoupURI *uri,
const char *comment, guint expected_status)
{
SoupMessage *msg;
@@ -30,7 +30,7 @@ do_message_to_session (SoupSession *session, const char *uri,
if (comment)
debug_printf (1, " msg %s\n", comment);
- msg = soup_message_new ("GET", uri);
+ msg = soup_message_new_from_uri ("GET", uri);
g_signal_connect (msg, "finished",
G_CALLBACK (message_finished), &finished);
@@ -51,11 +51,11 @@ static void
do_msg_tests_for_session (SoupSession *timeout_session,
SoupSession *idle_session,
SoupSession *plain_session,
- const char *fast_uri,
- const char *slow_uri)
+ SoupURI *fast_uri,
+ SoupURI *slow_uri)
{
- SoupSocket *ret, *idle_first, *idle_second;
- SoupSocket *plain_first, *plain_second;
+ SoupSocket *ret, *idle_first = NULL, *idle_second;
+ SoupSocket *plain_first = NULL, *plain_second;
if (idle_session) {
g_signal_connect (idle_session, "request-started",
@@ -100,7 +100,7 @@ do_msg_tests_for_session (SoupSession *timeout_session,
}
static void
-do_request_to_session (SoupSession *session, const char *uri,
+do_request_to_session (SoupSession *session, SoupURI *uri,
const char *comment, gboolean expect_timeout)
{
SoupRequest *req;
@@ -110,7 +110,7 @@ do_request_to_session (SoupSession *session, const char *uri,
gboolean finished = FALSE;
debug_printf (1, " req %s\n", comment);
- req = soup_session_request (session, uri, NULL);
+ req = soup_session_request_uri (session, uri, NULL);
msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
g_signal_connect (msg, "finished",
@@ -149,11 +149,11 @@ static void
do_req_tests_for_session (SoupSession *timeout_session,
SoupSession *idle_session,
SoupSession *plain_session,
- const char *fast_uri,
- const char *slow_uri)
+ SoupURI *fast_uri,
+ SoupURI *slow_uri)
{
- SoupSocket *ret, *idle_first, *idle_second;
- SoupSocket *plain_first, *plain_second;
+ SoupSocket *ret, *idle_first = NULL, *idle_second;
+ SoupSocket *plain_first = NULL, *plain_second;
if (idle_session) {
g_signal_connect (idle_session, "request-started",
@@ -201,11 +201,11 @@ 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);
+ SoupURI *fast_uri = (SoupURI *)data;
+ SoupURI *slow_uri = soup_uri_new_with_base (fast_uri, "/slow");
gboolean extra_slow;
- if (g_str_has_prefix (fast_uri, "https")) {
+ if (fast_uri->scheme == SOUP_URI_SCHEME_HTTPS) {
SOUP_TEST_SKIP_IF_NO_TLS;
extra_slow = slow_https;
@@ -236,17 +236,19 @@ do_async_timeout_tests (gconstpointer data)
soup_test_session_abort_unref (timeout_session);
soup_test_session_abort_unref (idle_session);
soup_test_session_abort_unref (plain_session);
+
+ soup_uri_free (slow_uri);
}
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);
+ SoupURI *fast_uri = (SoupURI *)data;
+ SoupURI *slow_uri = soup_uri_new_with_base (fast_uri, "/slow");
gboolean extra_slow;
- if (g_str_has_prefix (fast_uri, "https")) {
+ if (fast_uri->scheme == SOUP_URI_SCHEME_HTTPS) {
SOUP_TEST_SKIP_IF_NO_TLS;
extra_slow = slow_https;
@@ -263,6 +265,8 @@ do_sync_timeout_tests (gconstpointer data)
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);
+
+ soup_uri_free (slow_uri);
}
static gboolean
@@ -290,7 +294,7 @@ server_handler (SoupServer *server,
if (!strcmp (path, "/slow")) {
soup_server_pause_message (server, msg);
g_object_set_data (G_OBJECT (msg), "server", server);
- soup_add_timeout (soup_server_get_async_context (server),
+ soup_add_timeout (g_main_context_get_thread_default (),
4000, timeout_finish_message, msg);
}
}
@@ -299,24 +303,22 @@ int
main (int argc, char **argv)
{
SoupServer *server, *https_server = NULL;
- char *uri, *https_uri = NULL;
+ SoupURI *uri, *https_uri = NULL;
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));
+ uri = soup_test_server_get_uri (server, "http", NULL);
if (tls_available) {
SoupSession *test_session;
gint64 start, end;
- https_server = soup_test_server_new_ssl (TRUE);
+ https_server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
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));
+ https_uri = soup_test_server_get_uri (server, "https", "127.0.0.1");
/* The 1-second timeouts are too fast for some machines... */
test_session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
@@ -333,7 +335,7 @@ main (int argc, char **argv)
slow_https = FALSE;
}
} else
- https_uri = g_strdup ("https://fail.");
+ https_uri = soup_uri_new ("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);
@@ -342,8 +344,8 @@ main (int argc, char **argv)
ret = g_test_run ();
- g_free (uri);
- g_free (https_uri);
+ soup_uri_free (uri);
+ soup_uri_free (https_uri);
soup_test_server_quit_unref (server);
if (https_server)
soup_test_server_quit_unref (https_server);
diff --git a/tests/tld-test.c b/tests/tld-test.c
index 4fad8625..31cbb4b8 100644
--- a/tests/tld-test.c
+++ b/tests/tld-test.c
@@ -38,10 +38,10 @@ static struct {
{ "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 },
+ { "bn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "c.bn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
+ { "b.c.bn", "b.c.bn", -1 },
+ { "a.b.c.bn", "b.c.bn", -1 },
/* More complex TLD. */
{ "jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS },
{ "test.jp", "test.jp", -1 },
diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c
index d56b655f..85f09b9e 100644
--- a/tests/uri-parsing.c
+++ b/tests/uri-parsing.c
@@ -151,7 +151,11 @@ static struct {
{ "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 } }
+ { "http", NULL, NULL, "fe80::dead:beef%10", 80, "/", NULL, NULL } },
+
+ /* ".." past top */
+ { "http://example.com/..", "http://example.com/", "785042",
+ { "http", NULL, NULL, "example.com", 80, "/", NULL, NULL } },
};
static int num_abs_tests = G_N_ELEMENTS(abs_tests);
@@ -493,6 +497,72 @@ do_normalization_tests (void)
}
}
+typedef struct {
+ const char *uri;
+ const char *mime_type;
+ const char *body;
+} DataURITest;
+
+static const DataURITest data_tests[] = {
+ { "data:text/plain,foo%20bar",
+ "text/plain",
+ "foo bar" },
+ { "data:text/plain;charset=utf-8,foo%20bar",
+ "text/plain;charset=utf-8",
+ "foo bar" },
+ { "data:text/plain;base64,Zm9vIGJhcg==",
+ "text/plain",
+ "foo bar" },
+ { "data:,foo%20bar",
+ "text/plain;charset=US-ASCII",
+ "foo bar" },
+ { "data:;base64,Zm9vIGJhcg==",
+ "text/plain;charset=US-ASCII",
+ "foo bar" },
+ { "data:,",
+ "text/plain;charset=US-ASCII",
+ "" },
+ { "data:text/plain,",
+ "text/plain",
+ "" }
+};
+
+static void
+do_data_tests (void)
+{
+ SoupSession *session;
+ SoupRequest *req;
+ GInputStream *stream;
+ char buf[128];
+ gsize nread;
+ int i;
+ GError *error = NULL;
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+ for (i = 0; i < G_N_ELEMENTS (data_tests); i++) {
+ req = soup_session_request (session, data_tests[i].uri, &error);
+ g_assert_no_error (error);
+
+ stream = soup_request_send (req, NULL, &error);
+ g_assert_no_error (error);
+
+ g_input_stream_read_all (stream, buf, sizeof (buf), &nread, NULL, &error);
+
+ g_assert_no_error (error);
+ g_assert_cmpint (nread, ==, strlen (data_tests[i].body));
+ buf[nread] = 0;
+ g_assert_cmpstr (buf, ==, data_tests[i].body);
+
+ g_assert_cmpstr (soup_request_get_content_type (req), ==, data_tests[i].mime_type);
+
+ g_input_stream_close (stream, NULL, &error);
+ g_assert_no_error (error);
+ g_object_unref (stream);
+ g_object_unref (req);
+ }
+ soup_test_session_abort_unref (session);
+}
+
int
main (int argc, char **argv)
{
@@ -505,6 +575,7 @@ main (int argc, char **argv)
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);
+ g_test_add_func ("/uri/data", do_data_tests);
ret = g_test_run ();
diff --git a/tests/websocket-test.c b/tests/websocket-test.c
new file mode 100644
index 00000000..722ccbdf
--- /dev/null
+++ b/tests/websocket-test.c
@@ -0,0 +1,971 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This file was originally part of Cockpit.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * Cockpit is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * Cockpit is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "test-utils.h"
+
+typedef struct {
+ GSocket *listener;
+ gushort port;
+
+ SoupSession *session;
+ SoupMessage *msg;
+ SoupWebsocketConnection *client;
+ GError *client_error;
+
+ SoupServer *soup_server;
+ SoupWebsocketConnection *server;
+
+ gboolean no_server;
+ GIOStream *raw_server;
+
+ GMutex mutex;
+} Test;
+
+#define WAIT_UNTIL(cond) \
+ G_STMT_START \
+ while (!(cond)) g_main_context_iteration (NULL, TRUE); \
+ G_STMT_END
+
+static void
+on_error_not_reached (SoupWebsocketConnection *ws,
+ GError *error,
+ gpointer user_data)
+{
+ /* At this point we know this will fail, but is informative */
+ g_assert_no_error (error);
+}
+
+static void
+on_error_copy (SoupWebsocketConnection *ws,
+ GError *error,
+ gpointer user_data)
+{
+ GError **copy = user_data;
+ g_assert (*copy == NULL);
+ *copy = g_error_copy (error);
+}
+
+static void
+setup_listener (Test *test)
+{
+ GSocketAddress *addr;
+ GError *error = NULL;
+
+ test->listener = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP,
+ &error);
+ g_assert_no_error (error);
+
+ addr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
+ g_assert_no_error (error);
+
+ g_socket_bind (test->listener, addr, TRUE, &error);
+ g_assert_no_error (error);
+ g_object_unref (addr);
+
+ addr = g_socket_get_local_address (test->listener, &error);
+ g_assert_no_error (error);
+
+ test->port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
+ g_object_unref (addr);
+
+ g_socket_listen (test->listener, &error);
+ g_assert_no_error (error);
+}
+
+static void
+direct_connection_complete (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ Test *test = user_data;
+ GSocketConnection *conn;
+ SoupURI *uri;
+ GError *error = NULL;
+
+ conn = g_socket_client_connect_to_host_finish (G_SOCKET_CLIENT (object),
+ result, &error);
+ g_assert_no_error (error);
+
+ uri = soup_uri_new ("http://127.0.0.1/");
+ test->client = soup_websocket_connection_new (G_IO_STREAM (conn), uri,
+ SOUP_WEBSOCKET_CONNECTION_CLIENT,
+ NULL, NULL);
+ soup_uri_free (uri);
+ g_object_unref (conn);
+}
+
+static gboolean
+got_connection (GSocket *listener,
+ GIOCondition cond,
+ gpointer user_data)
+{
+ Test *test = user_data;
+ GSocket *sock;
+ GSocketConnection *conn;
+ SoupURI *uri;
+ GError *error = NULL;
+
+ sock = g_socket_accept (listener, NULL, &error);
+ g_assert_no_error (error);
+
+ conn = g_socket_connection_factory_create_connection (sock);
+ g_assert (conn != NULL);
+ g_object_unref (sock);
+
+ if (test->no_server)
+ test->raw_server = G_IO_STREAM (conn);
+ else {
+ uri = soup_uri_new ("http://127.0.0.1/");
+ test->server = soup_websocket_connection_new (G_IO_STREAM (conn), uri,
+ SOUP_WEBSOCKET_CONNECTION_SERVER,
+ NULL, NULL);
+ soup_uri_free (uri);
+ g_object_unref (conn);
+ }
+
+ return FALSE;
+}
+
+static void
+setup_direct_connection (Test *test,
+ gconstpointer data)
+{
+ GSocketClient *client;
+ GSource *listen_source;
+
+ setup_listener (test);
+
+ client = g_socket_client_new ();
+ g_socket_client_connect_to_host_async (client, "127.0.0.1", test->port,
+ NULL, direct_connection_complete, test);
+
+ listen_source = g_socket_create_source (test->listener, G_IO_IN, NULL);
+ g_source_set_callback (listen_source, (GSourceFunc) got_connection, test, NULL);
+ g_source_attach (listen_source, NULL);
+
+ while (test->client == NULL || (test->server == NULL && test->raw_server == NULL))
+ g_main_context_iteration (NULL, TRUE);
+
+ g_source_destroy (listen_source);
+ g_source_unref (listen_source);
+ g_object_unref (client);
+}
+
+static void
+setup_half_direct_connection (Test *test,
+ gconstpointer data)
+{
+ test->no_server = TRUE;
+ setup_direct_connection (test, data);
+}
+
+static void
+teardown_direct_connection (Test *test,
+ gconstpointer data)
+{
+ g_clear_object (&test->listener);
+ g_clear_object (&test->client);
+ g_clear_object (&test->server);
+ g_clear_object (&test->raw_server);
+}
+
+static void
+setup_soup_server (Test *test,
+ const char *origin,
+ const char **protocols,
+ SoupServerWebsocketCallback callback,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ setup_listener (test);
+
+ test->soup_server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
+ soup_server_listen_socket (test->soup_server, test->listener, 0, &error);
+ g_assert_no_error (error);
+
+ soup_server_add_websocket_handler (test->soup_server, "/unix",
+ origin, (char **) protocols,
+ callback, user_data, NULL);
+}
+
+static void
+client_connect (Test *test,
+ const char *origin,
+ const char **protocols,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ char *url;
+
+ if (!test->session)
+ test->session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
+
+ url = g_strdup_printf ("ws://127.0.0.1:%u/unix", test->port);
+ test->msg = soup_message_new ("GET", url);
+ g_free (url);
+
+ soup_session_websocket_connect_async (test->session, test->msg,
+ origin, (char **) protocols,
+ NULL, callback, user_data);
+}
+
+static void
+got_server_connection (SoupServer *server,
+ SoupWebsocketConnection *connection,
+ const char *path,
+ SoupClientContext *client,
+ gpointer user_data)
+{
+ Test *test = user_data;
+
+ test->server = g_object_ref (connection);
+}
+
+static void
+got_client_connection (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ Test *test = user_data;
+
+ test->client = soup_session_websocket_connect_finish (SOUP_SESSION (object),
+ result, &test->client_error);
+}
+
+static void
+setup_soup_connection (Test *test,
+ gconstpointer data)
+{
+ setup_soup_server (test, NULL, NULL, got_server_connection, test);
+ client_connect (test, NULL, NULL, got_client_connection, test);
+ WAIT_UNTIL (test->server != NULL);
+ WAIT_UNTIL (test->client != NULL || test->client_error != NULL);
+ g_assert_no_error (test->client_error);
+}
+
+static void
+teardown_soup_connection (Test *test,
+ gconstpointer data)
+{
+ teardown_direct_connection (test, data);
+
+ g_clear_object (&test->msg);
+ g_clear_error (&test->client_error);
+ g_clear_pointer (&test->session, soup_test_session_abort_unref);
+ g_clear_pointer (&test->soup_server, soup_test_server_quit_unref);
+}
+
+
+static void
+on_text_message (SoupWebsocketConnection *ws,
+ SoupWebsocketDataType type,
+ GBytes *message,
+ gpointer user_data)
+{
+ GBytes **receive = user_data;
+
+ g_assert_cmpint (type, ==, SOUP_WEBSOCKET_DATA_TEXT);
+ g_assert (*receive == NULL);
+ g_assert (message != NULL);
+
+ *receive = g_bytes_ref (message);
+}
+
+static void
+on_close_set_flag (SoupWebsocketConnection *ws,
+ gpointer user_data)
+{
+ gboolean *flag = user_data;
+
+ g_assert (*flag == FALSE);
+
+ *flag = TRUE;
+}
+
+
+static void
+test_handshake (Test *test,
+ gconstpointer data)
+{
+ g_assert_cmpint (soup_websocket_connection_get_state (test->client), ==, SOUP_WEBSOCKET_STATE_OPEN);
+ g_assert_cmpint (soup_websocket_connection_get_state (test->server), ==, SOUP_WEBSOCKET_STATE_OPEN);
+}
+
+#define TEST_STRING "this is a test"
+
+static void
+test_send_client_to_server (Test *test,
+ gconstpointer data)
+{
+ GBytes *received = NULL;
+ const char *contents;
+ gsize len;
+
+ g_signal_connect (test->server, "message", G_CALLBACK (on_text_message), &received);
+
+ soup_websocket_connection_send_text (test->client, TEST_STRING);
+
+ WAIT_UNTIL (received != NULL);
+
+ /* Received messages should be null terminated (outside of len) */
+ contents = g_bytes_get_data (received, &len);
+ g_assert_cmpstr (contents, ==, TEST_STRING);
+ g_assert_cmpint (len, ==, strlen (TEST_STRING));
+
+ g_bytes_unref (received);
+}
+
+static void
+test_send_server_to_client (Test *test,
+ gconstpointer data)
+{
+ GBytes *received = NULL;
+ const char *contents;
+ gsize len;
+
+ g_signal_connect (test->client, "message", G_CALLBACK (on_text_message), &received);
+
+ soup_websocket_connection_send_text (test->server, TEST_STRING);
+
+ WAIT_UNTIL (received != NULL);
+
+ /* Received messages should be null terminated (outside of len) */
+ contents = g_bytes_get_data (received, &len);
+ g_assert_cmpstr (contents, ==, TEST_STRING);
+ g_assert_cmpint (len, ==, strlen (TEST_STRING));
+
+ g_bytes_unref (received);
+}
+
+static void
+test_send_big_packets (Test *test,
+ gconstpointer data)
+{
+ GBytes *sent = NULL;
+ GBytes *received = NULL;
+
+ g_signal_connect (test->client, "message", G_CALLBACK (on_text_message), &received);
+
+ sent = g_bytes_new_take (g_strnfill (400, '!'), 400);
+ soup_websocket_connection_send_text (test->server, g_bytes_get_data (sent, NULL));
+ WAIT_UNTIL (received != NULL);
+ g_assert (g_bytes_equal (sent, received));
+ g_bytes_unref (sent);
+ g_bytes_unref (received);
+ received = NULL;
+
+ sent = g_bytes_new_take (g_strnfill (100 * 1000, '?'), 100 * 1000);
+ soup_websocket_connection_send_text (test->server, g_bytes_get_data (sent, NULL));
+ WAIT_UNTIL (received != NULL);
+ g_assert (g_bytes_equal (sent, received));
+ g_bytes_unref (sent);
+ g_bytes_unref (received);
+ received = NULL;
+
+ soup_websocket_connection_set_max_incoming_payload_size (test->client, 1000 * 1000 + 1);
+ g_assert (soup_websocket_connection_get_max_incoming_payload_size (test->client) == (1000 * 1000 + 1));
+ soup_websocket_connection_set_max_incoming_payload_size (test->server, 1000 * 1000 + 1);
+ g_assert (soup_websocket_connection_get_max_incoming_payload_size (test->server) == (1000 * 1000 + 1));
+
+ sent = g_bytes_new_take (g_strnfill (1000 * 1000, '?'), 1000 * 1000);
+ soup_websocket_connection_send_text (test->server, g_bytes_get_data (sent, NULL));
+ WAIT_UNTIL (received != NULL);
+ g_assert (g_bytes_equal (sent, received));
+ g_bytes_unref (sent);
+ g_bytes_unref (received);
+}
+
+static void
+test_send_bad_data (Test *test,
+ gconstpointer unused)
+{
+ GError *error = NULL;
+ GIOStream *io;
+ gsize written;
+ const char *frame;
+
+ g_signal_handlers_disconnect_by_func (test->server, on_error_not_reached, NULL);
+ g_signal_connect (test->server, "error", G_CALLBACK (on_error_copy), &error);
+
+ io = soup_websocket_connection_get_io_stream (test->client);
+
+ /* Bad UTF-8 frame */
+ frame = "\x81\x04\xEE\xEE\xEE\xEE";
+ if (!g_output_stream_write_all (g_io_stream_get_output_stream (io),
+ frame, 6, &written, NULL, NULL))
+ g_assert_not_reached ();
+ g_assert_cmpuint (written, ==, 6);
+
+ WAIT_UNTIL (error != NULL);
+ g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_CLOSE_BAD_DATA);
+ g_clear_error (&error);
+
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED);
+
+ g_assert_cmpuint (soup_websocket_connection_get_close_code (test->client), ==, SOUP_WEBSOCKET_CLOSE_BAD_DATA);
+}
+
+static const char *negotiate_client_protocols[] = { "bbb", "ccc", NULL };
+static const char *negotiate_server_protocols[] = { "aaa", "bbb", "ccc", NULL };
+static const char *negotiated_protocol = "bbb";
+
+static void
+test_protocol_negotiate_direct (Test *test,
+ gconstpointer unused)
+{
+ SoupMessage *msg;
+ gboolean ok;
+ const char *protocol;
+ GError *error = NULL;
+
+ msg = soup_message_new ("GET", "http://127.0.0.1");
+ soup_websocket_client_prepare_handshake (msg, NULL,
+ (char **) negotiate_client_protocols);
+
+ ok = soup_websocket_server_check_handshake (msg, NULL,
+ (char **) negotiate_server_protocols,
+ &error);
+ g_assert_no_error (error);
+ g_assert_true (ok);
+
+ ok = soup_websocket_server_process_handshake (msg, NULL,
+ (char **) negotiate_server_protocols);
+ g_assert_true (ok);
+
+ protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol");
+ g_assert_cmpstr (protocol, ==, negotiated_protocol);
+
+ ok = soup_websocket_client_verify_handshake (msg, &error);
+ g_assert_no_error (error);
+ g_assert_true (ok);
+
+ g_object_unref (msg);
+}
+
+static void
+test_protocol_negotiate_soup (Test *test,
+ gconstpointer unused)
+{
+ setup_soup_server (test, NULL, negotiate_server_protocols, got_server_connection, test);
+ client_connect (test, NULL, negotiate_client_protocols, got_client_connection, test);
+ WAIT_UNTIL (test->server != NULL);
+ WAIT_UNTIL (test->client != NULL || test->client_error != NULL);
+ g_assert_no_error (test->client_error);
+
+ g_assert_cmpstr (soup_websocket_connection_get_protocol (test->client), ==, negotiated_protocol);
+ g_assert_cmpstr (soup_websocket_connection_get_protocol (test->server), ==, negotiated_protocol);
+}
+
+static const char *mismatch_client_protocols[] = { "ddd", NULL };
+static const char *mismatch_server_protocols[] = { "aaa", "bbb", "ccc", NULL };
+
+static void
+test_protocol_mismatch_direct (Test *test,
+ gconstpointer unused)
+{
+ SoupMessage *msg;
+ gboolean ok;
+ const char *protocol;
+ GError *error = NULL;
+
+ msg = soup_message_new ("GET", "http://127.0.0.1");
+ soup_websocket_client_prepare_handshake (msg, NULL,
+ (char **) mismatch_client_protocols);
+
+ ok = soup_websocket_server_check_handshake (msg, NULL,
+ (char **) mismatch_server_protocols,
+ &error);
+ g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE);
+ g_clear_error (&error);
+ g_assert_false (ok);
+
+ ok = soup_websocket_server_process_handshake (msg, NULL,
+ (char **) mismatch_server_protocols);
+ g_assert_false (ok);
+ soup_test_assert_message_status (msg, SOUP_STATUS_BAD_REQUEST);
+
+ protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol");
+ g_assert_cmpstr (protocol, ==, NULL);
+
+ ok = soup_websocket_client_verify_handshake (msg, &error);
+ g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE);
+ g_clear_error (&error);
+ g_assert_false (ok);
+
+ g_object_unref (msg);
+}
+
+static void
+test_protocol_mismatch_soup (Test *test,
+ gconstpointer unused)
+{
+ setup_soup_server (test, NULL, mismatch_server_protocols, got_server_connection, test);
+ client_connect (test, NULL, mismatch_client_protocols, got_client_connection, test);
+ WAIT_UNTIL (test->client_error != NULL);
+
+ g_assert_error (test->client_error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET);
+}
+
+static const char *all_protocols[] = { "aaa", "bbb", "ccc", NULL };
+
+static void
+test_protocol_server_any_direct (Test *test,
+ gconstpointer unused)
+{
+ SoupMessage *msg;
+ gboolean ok;
+ const char *protocol;
+ GError *error = NULL;
+
+ msg = soup_message_new ("GET", "http://127.0.0.1");
+ soup_websocket_client_prepare_handshake (msg, NULL, (char **) all_protocols);
+
+ ok = soup_websocket_server_check_handshake (msg, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (ok);
+
+ ok = soup_websocket_server_process_handshake (msg, NULL, NULL);
+ g_assert_true (ok);
+
+ protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol");
+ g_assert_cmpstr (protocol, ==, NULL);
+
+ ok = soup_websocket_client_verify_handshake (msg, &error);
+ g_assert_no_error (error);
+ g_assert_true (ok);
+
+ g_object_unref (msg);
+}
+
+static void
+test_protocol_server_any_soup (Test *test,
+ gconstpointer unused)
+{
+ setup_soup_server (test, NULL, NULL, got_server_connection, test);
+ client_connect (test, NULL, all_protocols, got_client_connection, test);
+ WAIT_UNTIL (test->server != NULL);
+ WAIT_UNTIL (test->client != NULL || test->client_error != NULL);
+ g_assert_no_error (test->client_error);
+
+ g_assert_cmpstr (soup_websocket_connection_get_protocol (test->client), ==, NULL);
+ g_assert_cmpstr (soup_websocket_connection_get_protocol (test->server), ==, NULL);
+ g_assert_cmpstr (soup_message_headers_get_one (test->msg->response_headers, "Sec-WebSocket-Protocol"), ==, NULL);
+}
+
+static void
+test_protocol_client_any_direct (Test *test,
+ gconstpointer unused)
+{
+ SoupMessage *msg;
+ gboolean ok;
+ const char *protocol;
+ GError *error = NULL;
+
+ msg = soup_message_new ("GET", "http://127.0.0.1");
+ soup_websocket_client_prepare_handshake (msg, NULL, NULL);
+
+ ok = soup_websocket_server_check_handshake (msg, NULL, (char **) all_protocols, &error);
+ g_assert_no_error (error);
+ g_assert_true (ok);
+
+ ok = soup_websocket_server_process_handshake (msg, NULL, (char **) all_protocols);
+ g_assert_true (ok);
+
+ protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol");
+ g_assert_cmpstr (protocol, ==, NULL);
+
+ ok = soup_websocket_client_verify_handshake (msg, &error);
+ g_assert_no_error (error);
+ g_assert_true (ok);
+
+ g_object_unref (msg);
+}
+
+static void
+test_protocol_client_any_soup (Test *test,
+ gconstpointer unused)
+{
+ setup_soup_server (test, NULL, all_protocols, got_server_connection, test);
+ client_connect (test, NULL, NULL, got_client_connection, test);
+ WAIT_UNTIL (test->server != NULL);
+ WAIT_UNTIL (test->client != NULL || test->client_error != NULL);
+ g_assert_no_error (test->client_error);
+
+ g_assert_cmpstr (soup_websocket_connection_get_protocol (test->client), ==, NULL);
+ g_assert_cmpstr (soup_websocket_connection_get_protocol (test->server), ==, NULL);
+ g_assert_cmpstr (soup_message_headers_get_one (test->msg->response_headers, "Sec-WebSocket-Protocol"), ==, NULL);
+}
+
+static void
+test_close_clean_client (Test *test,
+ gconstpointer data)
+{
+ gboolean close_event_client = FALSE;
+ gboolean close_event_server = FALSE;
+
+ g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event_client);
+ g_signal_connect (test->server, "closed", G_CALLBACK (on_close_set_flag), &close_event_server);
+
+ soup_websocket_connection_close (test->client, SOUP_WEBSOCKET_CLOSE_GOING_AWAY, "give me a reason");
+ g_assert_cmpint (soup_websocket_connection_get_state (test->client), ==, SOUP_WEBSOCKET_STATE_CLOSING);
+
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->server) == SOUP_WEBSOCKET_STATE_CLOSED);
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED);
+
+ g_assert (close_event_client);
+ g_assert (close_event_server);
+
+ g_assert_cmpint (soup_websocket_connection_get_close_code (test->client), ==, SOUP_WEBSOCKET_CLOSE_GOING_AWAY);
+ g_assert_cmpint (soup_websocket_connection_get_close_code (test->server), ==, SOUP_WEBSOCKET_CLOSE_GOING_AWAY);
+ g_assert_cmpstr (soup_websocket_connection_get_close_data (test->server), ==, "give me a reason");
+}
+
+static void
+test_close_clean_server (Test *test,
+ gconstpointer data)
+{
+ gboolean close_event_client = FALSE;
+ gboolean close_event_server = FALSE;
+
+ g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event_client);
+ g_signal_connect (test->server, "closed", G_CALLBACK (on_close_set_flag), &close_event_server);
+
+ soup_websocket_connection_close (test->server, SOUP_WEBSOCKET_CLOSE_GOING_AWAY, "another reason");
+ g_assert_cmpint (soup_websocket_connection_get_state (test->server), ==, SOUP_WEBSOCKET_STATE_CLOSING);
+
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->server) == SOUP_WEBSOCKET_STATE_CLOSED);
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED);
+
+ g_assert (close_event_client);
+ g_assert (close_event_server);
+
+ g_assert_cmpint (soup_websocket_connection_get_close_code (test->server), ==, SOUP_WEBSOCKET_CLOSE_GOING_AWAY);
+ g_assert_cmpint (soup_websocket_connection_get_close_code (test->client), ==, SOUP_WEBSOCKET_CLOSE_GOING_AWAY);
+ g_assert_cmpstr (soup_websocket_connection_get_close_data (test->client), ==, "another reason");
+}
+
+static gboolean
+on_closing_send_message (SoupWebsocketConnection *ws,
+ gpointer data)
+{
+ GBytes *message = data;
+
+ soup_websocket_connection_send_text (ws, g_bytes_get_data (message, NULL));
+ g_signal_handlers_disconnect_by_func (ws, on_closing_send_message, data);
+ return TRUE;
+}
+
+static void
+test_message_after_closing (Test *test,
+ gconstpointer data)
+{
+ gboolean close_event_client = FALSE;
+ gboolean close_event_server = FALSE;
+ GBytes *received = NULL;
+ GBytes *message;
+
+ message = g_bytes_new_static ("another test because", strlen ("another test because"));
+ g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event_client);
+ g_signal_connect (test->client, "message", G_CALLBACK (on_text_message), &received);
+ g_signal_connect (test->server, "closed", G_CALLBACK (on_close_set_flag), &close_event_server);
+ g_signal_connect (test->server, "closing", G_CALLBACK (on_closing_send_message), message);
+
+ soup_websocket_connection_close (test->client, SOUP_WEBSOCKET_CLOSE_GOING_AWAY, "another reason");
+ g_assert_cmpint (soup_websocket_connection_get_state (test->client), ==, SOUP_WEBSOCKET_STATE_CLOSING);
+
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->server) == SOUP_WEBSOCKET_STATE_CLOSED);
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED);
+
+ g_assert (close_event_client);
+ g_assert (close_event_server);
+
+ g_assert (received != NULL);
+ g_assert (g_bytes_equal (message, received));
+
+ g_bytes_unref (received);
+ g_bytes_unref (message);
+}
+
+static gpointer
+timeout_server_thread (gpointer user_data)
+{
+ Test *test = user_data;
+ GError *error = NULL;
+
+ /* don't close until the client has timed out */
+ g_mutex_lock (&test->mutex);
+ g_mutex_unlock (&test->mutex);
+
+ g_io_stream_close (test->raw_server, NULL, &error);
+ g_assert_no_error (error);
+
+ return NULL;
+}
+
+static void
+test_close_after_timeout (Test *test,
+ gconstpointer data)
+{
+ gboolean close_event = FALSE;
+ GThread *thread;
+
+ g_mutex_lock (&test->mutex);
+
+ /* Note that no real server is around in this test, so no close happens */
+ thread = g_thread_new ("timeout-thread", timeout_server_thread, test);
+
+ g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event);
+ g_signal_connect (test->client, "error", G_CALLBACK (on_error_not_reached), NULL);
+
+ /* Now try and close things */
+ soup_websocket_connection_close (test->client, 0, NULL);
+ g_assert_cmpint (soup_websocket_connection_get_state (test->client), ==, SOUP_WEBSOCKET_STATE_CLOSING);
+
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED);
+
+ g_assert (close_event == TRUE);
+
+ /* Now actually close the server side stream */
+ g_mutex_unlock (&test->mutex);
+ g_thread_join (thread);
+}
+
+static gpointer
+send_fragments_server_thread (gpointer user_data)
+{
+ Test *test = user_data;
+ gsize written;
+ const char fragments[] = "\x01\x04""one " /* !fin | opcode */
+ "\x00\x04""two " /* !fin | no opcode */
+ "\x80\x05""three"; /* fin | no opcode */
+ GError *error = NULL;
+
+ g_output_stream_write_all (g_io_stream_get_output_stream (test->raw_server),
+ fragments, sizeof (fragments) -1, &written, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpuint (written, ==, sizeof (fragments) - 1);
+ g_io_stream_close (test->raw_server, NULL, &error);
+ g_assert_no_error (error);
+
+ return NULL;
+}
+
+static void
+test_receive_fragmented (Test *test,
+ gconstpointer data)
+{
+ GThread *thread;
+ GBytes *received = NULL;
+ GBytes *expect;
+
+ thread = g_thread_new ("fragment-thread", send_fragments_server_thread, test);
+
+ g_signal_connect (test->client, "error", G_CALLBACK (on_error_not_reached), NULL);
+ g_signal_connect (test->client, "message", G_CALLBACK (on_text_message), &received);
+
+ WAIT_UNTIL (received != NULL);
+ expect = g_bytes_new ("one two three", 13);
+ g_assert (g_bytes_equal (expect, received));
+ g_bytes_unref (expect);
+ g_bytes_unref (received);
+
+ g_thread_join (thread);
+
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED);
+}
+
+static void
+test_client_context_got_server_connection (SoupServer *server,
+ SoupWebsocketConnection *connection,
+ const char *path,
+ SoupClientContext *client,
+ gpointer user_data)
+{
+ Test *test = user_data;
+ GSocketAddress *addr;
+ GInetAddress *iaddr;
+ char *str;
+ const char *remote_ip;
+
+ addr = soup_client_context_get_local_address (client);
+ iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr));
+ str = g_inet_address_to_string (iaddr);
+ if (g_inet_address_get_family (iaddr) == G_SOCKET_FAMILY_IPV4)
+ g_assert_cmpstr (str, ==, "127.0.0.1");
+ else
+ g_assert_cmpstr (str, ==, "::1");
+ g_free (str);
+
+ addr = soup_client_context_get_remote_address (client);
+ iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr));
+ str = g_inet_address_to_string (iaddr);
+ if (g_inet_address_get_family (iaddr) == G_SOCKET_FAMILY_IPV4)
+ g_assert_cmpstr (str, ==, "127.0.0.1");
+ else
+ g_assert_cmpstr (str, ==, "::1");
+
+ remote_ip = soup_client_context_get_host (client);
+ g_assert_cmpstr (remote_ip, ==, str);
+ g_free (str);
+
+ test->server = g_object_ref (connection);
+}
+
+static void
+test_client_context (Test *test,
+ gconstpointer unused)
+{
+ setup_soup_server (test, NULL, NULL, test_client_context_got_server_connection, test);
+ client_connect (test, NULL, NULL, got_client_connection, test);
+ WAIT_UNTIL (test->server != NULL);
+ WAIT_UNTIL (test->client != NULL || test->client_error != NULL);
+ g_assert_no_error (test->client_error);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ int ret;
+
+ test_init (argc, argv, NULL);
+
+ g_test_add ("/websocket/soup/handshake", Test, NULL,
+ setup_soup_connection,
+ test_handshake,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/send-client-to-server", Test, NULL,
+ setup_direct_connection,
+ test_send_client_to_server,
+ teardown_direct_connection);
+ g_test_add ("/websocket/soup/send-client-to-server", Test, NULL,
+ setup_soup_connection,
+ test_send_client_to_server,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/send-server-to-client", Test, NULL,
+ setup_direct_connection,
+ test_send_server_to_client,
+ teardown_direct_connection);
+ g_test_add ("/websocket/soup/send-server-to-client", Test, NULL,
+ setup_soup_connection,
+ test_send_server_to_client,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/send-big-packets", Test, NULL,
+ setup_direct_connection,
+ test_send_big_packets,
+ teardown_direct_connection);
+ g_test_add ("/websocket/soup/send-big-packets", Test, NULL,
+ setup_soup_connection,
+ test_send_big_packets,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/send-bad-data", Test, NULL,
+ setup_direct_connection,
+ test_send_bad_data,
+ teardown_direct_connection);
+ g_test_add ("/websocket/soup/send-bad-data", Test, NULL,
+ setup_soup_connection,
+ test_send_bad_data,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/close-clean-client", Test, NULL,
+ setup_direct_connection,
+ test_close_clean_client,
+ teardown_direct_connection);
+ g_test_add ("/websocket/soup/close-clean-client", Test, NULL,
+ setup_soup_connection,
+ test_close_clean_client,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/close-clean-server", Test, NULL,
+ setup_direct_connection,
+ test_close_clean_server,
+ teardown_direct_connection);
+ g_test_add ("/websocket/soup/close-clean-server", Test, NULL,
+ setup_soup_connection,
+ test_close_clean_server,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/message-after-closing", Test, NULL,
+ setup_direct_connection,
+ test_message_after_closing,
+ teardown_direct_connection);
+ g_test_add ("/websocket/soup/message-after-closing", Test, NULL,
+ setup_soup_connection,
+ test_message_after_closing,
+ teardown_soup_connection);
+
+
+ g_test_add ("/websocket/direct/protocol-negotiate", Test, NULL, NULL,
+ test_protocol_negotiate_direct,
+ NULL);
+ g_test_add ("/websocket/soup/protocol-negotiate", Test, NULL, NULL,
+ test_protocol_negotiate_soup,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/protocol-mismatch", Test, NULL, NULL,
+ test_protocol_mismatch_direct,
+ NULL);
+ g_test_add ("/websocket/soup/protocol-mismatch", Test, NULL, NULL,
+ test_protocol_mismatch_soup,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/protocol-server-any", Test, NULL, NULL,
+ test_protocol_server_any_direct,
+ NULL);
+ g_test_add ("/websocket/soup/protocol-server-any", Test, NULL, NULL,
+ test_protocol_server_any_soup,
+ teardown_soup_connection);
+
+ g_test_add ("/websocket/direct/protocol-client-any", Test, NULL, NULL,
+ test_protocol_client_any_direct,
+ NULL);
+ g_test_add ("/websocket/soup/protocol-client-any", Test, NULL, NULL,
+ test_protocol_client_any_soup,
+ teardown_soup_connection);
+
+
+ g_test_add ("/websocket/direct/receive-fragmented", Test, NULL,
+ setup_half_direct_connection,
+ test_receive_fragmented,
+ teardown_direct_connection);
+
+ if (g_test_slow ()) {
+ g_test_add ("/websocket/direct/close-after-timeout", Test, NULL,
+ setup_half_direct_connection,
+ test_close_after_timeout,
+ teardown_direct_connection);
+ }
+
+ g_test_add ("/websocket/soup/client-context", Test, NULL, NULL,
+ test_client_context,
+ teardown_soup_connection);
+
+ ret = g_test_run ();
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/xmlrpc-old-server-test.c b/tests/xmlrpc-old-server-test.c
new file mode 100644
index 00000000..a7076b5a
--- /dev/null
+++ b/tests/xmlrpc-old-server-test.c
@@ -0,0 +1,374 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#include "test-utils.h"
+
+static char *uri;
+
+#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+#endif
+
+static void
+type_error (SoupMessage *msg, GType expected, GValueArray *params, int bad_value)
+{
+ soup_xmlrpc_set_fault (msg,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
+ "Bad parameter #%d: expected %s, got %s",
+ bad_value + 1, g_type_name (expected),
+ g_type_name (G_VALUE_TYPE (&params->values[bad_value])));
+}
+
+static void
+args_error (SoupMessage *msg, GValueArray *params, int expected)
+{
+ soup_xmlrpc_set_fault (msg,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
+ "Wrong number of parameters: expected %d, got %d",
+ expected, params->n_values);
+}
+
+static void
+do_sum (SoupMessage *msg, GValueArray *params)
+{
+ int i;
+ double sum = 0.0, val;
+ GValueArray *nums;
+
+ if (params->n_values != 1) {
+ args_error (msg, params, 1);
+ return;
+ }
+ if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &nums)) {
+ type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
+ return;
+ }
+
+ for (i = 0; i < nums->n_values; i++) {
+ if (!soup_value_array_get_nth (nums, i, G_TYPE_DOUBLE, &val)) {
+ type_error (msg, G_TYPE_DOUBLE, nums, i);
+ return;
+ }
+ sum += val;
+ }
+
+ soup_xmlrpc_set_response (msg, G_TYPE_DOUBLE, sum);
+
+}
+
+static void
+do_countBools (SoupMessage *msg, GValueArray *params)
+{
+ int i, trues = 0, falses = 0;
+ GValueArray *bools;
+ GHashTable *ret = soup_value_hash_new ();
+ gboolean val;
+
+ if (params->n_values != 1) {
+ args_error (msg, params, 1);
+ return;
+ }
+ if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &bools)) {
+ type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
+ return;
+ }
+
+ for (i = 0; i < bools->n_values; i++) {
+ if (!soup_value_array_get_nth (bools, i, G_TYPE_BOOLEAN, &val)) {
+ type_error (msg, G_TYPE_BOOLEAN, params, i);
+ return;
+ }
+ if (val)
+ trues++;
+ else
+ falses++;
+ }
+
+ soup_value_hash_insert (ret, "true", G_TYPE_INT, trues);
+ soup_value_hash_insert (ret, "false", G_TYPE_INT, falses);
+ soup_xmlrpc_set_response (msg, G_TYPE_HASH_TABLE, ret);
+ g_hash_table_destroy (ret);
+
+}
+
+static void
+do_md5sum (SoupMessage *msg, GValueArray *params)
+{
+ GChecksum *checksum;
+ GByteArray *data, *digest;
+ gsize digest_len = 16;
+
+ if (params->n_values != 1) {
+ args_error (msg, params, 1);
+ return;
+ }
+
+ if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_BYTE_ARRAY, &data)) {
+ type_error (msg, SOUP_TYPE_BYTE_ARRAY, params, 0);
+ return;
+ }
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+ g_checksum_update (checksum, data->data, data->len);
+ digest = g_byte_array_new ();
+ g_byte_array_set_size (digest, digest_len);
+ g_checksum_get_digest (checksum, digest->data, &digest_len);
+ g_checksum_free (checksum);
+
+ soup_xmlrpc_set_response (msg, SOUP_TYPE_BYTE_ARRAY, digest);
+ g_byte_array_free (digest, TRUE);
+}
+
+
+static void
+do_dateChange (SoupMessage *msg, GValueArray *params)
+{
+ GHashTable *arg;
+ SoupDate *date;
+ int val;
+
+ if (params->n_values != 2) {
+ args_error (msg, params, 2);
+ return;
+ }
+
+ if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_DATE, &date)) {
+ type_error (msg, SOUP_TYPE_DATE, params, 0);
+ return;
+ }
+ if (!soup_value_array_get_nth (params, 1, G_TYPE_HASH_TABLE, &arg)) {
+ type_error (msg, G_TYPE_HASH_TABLE, params, 1);
+ return;
+ }
+
+ if (soup_value_hash_lookup (arg, "tm_year", G_TYPE_INT, &val))
+ date->year = val + 1900;
+ if (soup_value_hash_lookup (arg, "tm_mon", G_TYPE_INT, &val))
+ date->month = val + 1;
+ if (soup_value_hash_lookup (arg, "tm_mday", G_TYPE_INT, &val))
+ date->day = val;
+ if (soup_value_hash_lookup (arg, "tm_hour", G_TYPE_INT, &val))
+ date->hour = val;
+ if (soup_value_hash_lookup (arg, "tm_min", G_TYPE_INT, &val))
+ date->minute = val;
+ if (soup_value_hash_lookup (arg, "tm_sec", G_TYPE_INT, &val))
+ date->second = val;
+
+ soup_xmlrpc_set_response (msg, SOUP_TYPE_DATE, date);
+}
+
+static void
+do_echo (SoupMessage *msg, GValueArray *params)
+{
+ int i;
+ const char *val;
+ GValueArray *in, *out;
+
+ if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &in)) {
+ type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
+ return;
+ }
+
+ out = g_value_array_new (in->n_values);
+ for (i = 0; i < in->n_values; i++) {
+ if (!soup_value_array_get_nth (in, i, G_TYPE_STRING, &val)) {
+ type_error (msg, G_TYPE_STRING, in, i);
+ return;
+ }
+ soup_value_array_append (out, G_TYPE_STRING, val);
+ }
+
+ 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
+server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ char *method_name;
+ GValueArray *params;
+
+ if (msg->method != SOUP_METHOD_POST) {
+ soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+
+ if (!soup_xmlrpc_parse_method_call (msg->request_body->data,
+ msg->request_body->length,
+ &method_name, &params)) {
+ soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED,
+ "Could not parse method call");
+ return;
+ }
+
+ if (!strcmp (method_name, "sum"))
+ do_sum (msg, params);
+ else if (!strcmp (method_name, "countBools"))
+ do_countBools (msg, params);
+ else if (!strcmp (method_name, "md5sum"))
+ do_md5sum (msg, params);
+ else if (!strcmp (method_name, "dateChange"))
+ 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);
+ }
+
+ g_free (method_name);
+ g_value_array_free (params);
+}
+
+static gboolean
+run_xmlrpc_test (char **argv,
+ char **stdout_out,
+ char **stderr_out,
+ GError **error)
+{
+ gboolean ok;
+ int status;
+
+ argv[0] = g_test_build_filename (G_TEST_BUILT, "xmlrpc-old-test", NULL);
+ ok = g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL,
+ stdout_out, stderr_out, &status,
+ error);
+ g_free (argv[0]);
+
+ if (!ok)
+ return FALSE;
+
+ return g_spawn_check_exit_status (status, error);
+}
+
+static void
+do_one_xmlrpc_test (gconstpointer data)
+{
+ const char *path = data;
+ char *argv[12];
+ char *stdout_out, *stderr_out;
+ GError *error = NULL;
+ int arg;
+
+ 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 + 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);
+ }
+
+ 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;
+
+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)
+{
+ SoupServer *server;
+ SoupURI *server_uri;
+ int ret;
+
+ test_init (argc, argv, no_test_entry);
+
+ server = soup_test_server_new (run_tests ? SOUP_TEST_SERVER_IN_THREAD : SOUP_TEST_SERVER_DEFAULT);
+ soup_server_add_handler (server, "/xmlrpc-server.php",
+ server_callback, NULL, NULL);
+ server_uri = soup_test_server_get_uri (server, "http", NULL);
+ soup_uri_set_path (server_uri, "/xmlrpc-server.php");
+ uri = soup_uri_to_string (server_uri, FALSE);
+
+ if (run_tests) {
+ 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-old-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-old/"));
+ path = g_strdup_printf ("/xmlrpc-old-server/%s", tests[i] + strlen ("/xmlrpc-old/"));
+ 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", server_uri->port);
+
+ 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);
+ soup_uri_free (server_uri);
+ g_free (uri);
+ if (run_tests)
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/xmlrpc-old-test.c b/tests/xmlrpc-old-test.c
new file mode 100644
index 00000000..ab7b34d3
--- /dev/null
+++ b/tests/xmlrpc-old-test.c
@@ -0,0 +1,502 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001-2003, Ximian, Inc.
+ */
+
+#include "test-utils.h"
+
+#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+#endif
+
+static SoupSession *session;
+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 gboolean
+send_xmlrpc (const char *body, GValue *retval)
+{
+ SoupMessage *msg;
+ GError *err = NULL;
+
+ msg = soup_message_new ("POST", uri);
+ soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
+ body, strlen (body));
+ soup_session_send_message (session, msg);
+
+ 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) {
+ soup_test_assert (FALSE, "FAULT: %d %s\n", err->code, err->message);
+ g_error_free (err);
+ } else
+ soup_test_assert (FALSE, "ERROR: could not parse response\n");
+ g_object_unref (msg);
+ return FALSE;
+ }
+ g_object_unref (msg);
+
+ return TRUE;
+}
+
+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)) {
+ g_assert_true (G_VALUE_HOLDS (value, type));
+ return FALSE;
+ }
+
+ va_start (args, type);
+ SOUP_VALUE_GETV (value, type, args);
+ va_end (args);
+ return TRUE;
+}
+
+static void
+test_sum (void)
+{
+ GValueArray *dbls;
+ int i;
+ double val, sum, result;
+ GValue retval;
+ gboolean ok;
+
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ debug_printf (2, "sum (array of double -> double): ");
+
+ dbls = g_value_array_new (10);
+ for (i = sum = 0; i < 10; i++) {
+ val = g_random_int_range (0, 400) / 4.0;
+ debug_printf (2, "%s%.2f", i == 0 ? "[" : ", ", val);
+ soup_value_array_append (dbls, G_TYPE_DOUBLE, val);
+ sum += val;
+ }
+ debug_printf (2, "] -> ");
+
+ ok = (do_xmlrpc ("sum", &retval,
+ G_TYPE_VALUE_ARRAY, dbls,
+ G_TYPE_INVALID) &&
+ check_xmlrpc (&retval, G_TYPE_DOUBLE, &result));
+ g_value_array_free (dbls);
+
+ if (!ok)
+ return;
+
+ debug_printf (2, "%.2f\n", result);
+ g_assert_cmpfloat (result, ==, sum);
+}
+
+static void
+test_countBools (void)
+{
+ GValueArray *bools;
+ int i, trues, falses;
+ GValue retval;
+ int ret_trues, ret_falses;
+ gboolean val, ok;
+ GHashTable *result;
+
+ 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++) {
+ val = g_random_boolean ();
+ debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
+ soup_value_array_append (bools, G_TYPE_BOOLEAN, val);
+ if (val)
+ trues++;
+ else
+ falses++;
+ }
+ debug_printf (2, "] -> ");
+
+ ok = (do_xmlrpc ("countBools", &retval,
+ G_TYPE_VALUE_ARRAY, bools,
+ G_TYPE_INVALID) &&
+ check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result));
+ g_value_array_free (bools);
+ if (!ok)
+ 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));
+
+ g_hash_table_destroy (result);
+
+ 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 void
+test_md5sum (void)
+{
+ GByteArray *data, *result;
+ int i;
+ GChecksum *checksum;
+ guchar digest[16];
+ gsize digest_len = sizeof (digest);
+ GValue retval;
+ gboolean ok;
+
+ 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);
+ for (i = 0; i < data->len; i++)
+ data->data[i] = (char)(g_random_int_range (0, 256));
+
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+ g_checksum_update (checksum, data->data, data->len);
+ g_checksum_get_digest (checksum, digest, &digest_len);
+ g_checksum_free (checksum);
+
+ ok = (do_xmlrpc ("md5sum", &retval,
+ SOUP_TYPE_BYTE_ARRAY, data,
+ G_TYPE_INVALID) &&
+ check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result));
+ g_byte_array_free (data, TRUE);
+ if (!ok)
+ return;
+
+ soup_assert_cmpmem (result->data, result->len,
+ digest, digest_len);
+ g_byte_array_free (result, TRUE);
+}
+
+static void
+test_dateChange (void)
+{
+ GHashTable *structval;
+ SoupDate *date, *result;
+ char *timestamp;
+ GValue retval;
+ gboolean ok;
+
+ 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),
+ 1 + g_random_int_range (0, 28),
+ g_random_int_range (0, 24),
+ g_random_int_range (0, 60),
+ g_random_int_range (0, 60));
+ if (debug_level >= 2) {
+ timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
+ debug_printf (2, "date: %s, {", timestamp);
+ g_free (timestamp);
+ }
+
+ structval = soup_value_hash_new ();
+
+#define MAYBE (g_random_int_range (0, 3) != 0)
+
+ if (MAYBE) {
+ date->year = 1970 + (g_random_int_range (0, 50));
+ debug_printf (2, "tm_year: %d, ", date->year - 1900);
+ soup_value_hash_insert (structval, "tm_year",
+ G_TYPE_INT, date->year - 1900);
+ }
+ if (MAYBE) {
+ date->month = 1 + g_random_int_range (0, 12);
+ debug_printf (2, "tm_mon: %d, ", date->month - 1);
+ soup_value_hash_insert (structval, "tm_mon",
+ G_TYPE_INT, date->month - 1);
+ }
+ if (MAYBE) {
+ date->day = 1 + g_random_int_range (0, 28);
+ debug_printf (2, "tm_mday: %d, ", date->day);
+ soup_value_hash_insert (structval, "tm_mday",
+ G_TYPE_INT, date->day);
+ }
+ if (MAYBE) {
+ date->hour = g_random_int_range (0, 24);
+ debug_printf (2, "tm_hour: %d, ", date->hour);
+ soup_value_hash_insert (structval, "tm_hour",
+ G_TYPE_INT, date->hour);
+ }
+ if (MAYBE) {
+ date->minute = g_random_int_range (0, 60);
+ debug_printf (2, "tm_min: %d, ", date->minute);
+ soup_value_hash_insert (structval, "tm_min",
+ G_TYPE_INT, date->minute);
+ }
+ if (MAYBE) {
+ date->second = g_random_int_range (0, 60);
+ debug_printf (2, "tm_sec: %d, ", date->second);
+ soup_value_hash_insert (structval, "tm_sec",
+ G_TYPE_INT, date->second);
+ }
+
+ debug_printf (2, "} -> ");
+
+ ok = (do_xmlrpc ("dateChange", &retval,
+ SOUP_TYPE_DATE, date,
+ G_TYPE_HASH_TABLE, structval,
+ G_TYPE_INVALID) &&
+ check_xmlrpc (&retval, SOUP_TYPE_DATE, &result));
+ g_hash_table_destroy (structval);
+ if (!ok) {
+ soup_date_free (date);
+ return;
+ }
+
+ if (debug_level >= 2) {
+ timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC);
+ debug_printf (2, "%s\n", timestamp);
+ g_free (timestamp);
+ }
+
+ 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);
+}
+
+static const char *const echo_strings[] = {
+ "This is a test",
+ "& so is this",
+ "and so is <this>",
+ "&amp; so is &lt;this&gt;"
+};
+#define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings)
+
+static void
+test_echo (void)
+{
+ GValueArray *originals, *echoes;
+ GValue retval;
+ int i;
+
+ 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++) {
+ soup_value_array_append (originals, G_TYPE_STRING, echo_strings[i]);
+ debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo_strings[i]);
+ }
+ debug_printf (2, "] -> ");
+
+ if (!(do_xmlrpc ("echo", &retval,
+ G_TYPE_VALUE_ARRAY, originals,
+ G_TYPE_INVALID) &&
+ check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) {
+ g_value_array_free (originals);
+ return;
+ }
+ g_value_array_free (originals);
+
+ if (debug_level >= 2) {
+ for (i = 0; i < echoes->n_values; i++) {
+ debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ",
+ g_value_get_string (&echoes->values[i]));
+ }
+ debug_printf (2, "]\n");
+ }
+
+ g_assert_cmpint (echoes->n_values, ==, N_ECHO_STRINGS);
+
+ for (i = 0; i < echoes->n_values; i++)
+ g_assert_cmpstr (echo_strings[i], ==, g_value_get_string (&echoes->values[i]));
+
+ g_value_array_free (echoes);
+}
+
+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;
+ GError *err = NULL;
+ GValue retval;
+
+ msg = soup_message_new ("POST", uri);
+ soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
+ body, strlen (body));
+ soup_session_send_message (session, msg);
+
+ 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 (OK!)\n",
+ err->code, err->message);
+ g_error_free (err);
+ g_object_unref (msg);
+ return;
+ } else
+ soup_test_assert (FALSE, "ERROR: could not parse response\n");
+ } else
+ soup_test_assert (FALSE, "Unexpectedly got successful response!\n");
+
+ g_object_unref (msg);
+}
+
+static void
+test_fault_malformed (void)
+{
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ do_bad_xmlrpc ("<methodCall/>");
+}
+
+static void
+test_fault_method (void)
+{
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
+}
+
+static void
+test_fault_args (void)
+{
+ SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
+
+ 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,
+ "Alternate URI for server", NULL },
+ { "server-test", 'S', 0, G_OPTION_ARG_NONE, &server_test,
+ "If this is being run from xmlrpc-old-server-test", NULL },
+ { NULL }
+};
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+
+ test_init (argc, argv, xmlrpc_entries);
+
+ if (!uri && !server_test) {
+ apache_init ();
+ uri = default_uri;
+ }
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+
+ g_test_add_func ("/xmlrpc-old/sum", test_sum);
+ g_test_add_func ("/xmlrpc-old/countBools", test_countBools);
+ g_test_add_func ("/xmlrpc-old/md5sum", test_md5sum);
+ g_test_add_func ("/xmlrpc-old/dateChange", test_dateChange);
+ g_test_add_func ("/xmlrpc-old/echo", test_echo);
+ g_test_add_data_func ("/xmlrpc-old/ping/empty-params", GINT_TO_POINTER (TRUE), test_ping);
+ g_test_add_data_func ("/xmlrpc-old/ping/no-params", GINT_TO_POINTER (FALSE), test_ping);
+ g_test_add_func ("/xmlrpc-old/fault/malformed", test_fault_malformed);
+ g_test_add_func ("/xmlrpc-old/fault/method", test_fault_method);
+ g_test_add_func ("/xmlrpc-old/fault/args", test_fault_args);
+
+ ret = g_test_run ();
+
+ soup_test_session_abort_unref (session);
+
+ test_cleanup ();
+ return ret;
+}
diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c
index bfeb200a..80f04ea8 100644
--- a/tests/xmlrpc-server-test.c
+++ b/tests/xmlrpc-server-test.c
@@ -1,196 +1,194 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright 2008 Red Hat, Inc.
+ * Copyright 2015, Collabora ltd.
*/
#include "test-utils.h"
static char *uri;
-#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-#endif
-
-static void
-type_error (SoupMessage *msg, GType expected, GValueArray *params, int bad_value)
+static GVariant *
+parse_params (SoupMessage *msg, SoupXMLRPCParams *params, const char *signature)
{
- soup_xmlrpc_set_fault (msg,
- SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
- "Bad parameter #%d: expected %s, got %s",
- bad_value + 1, g_type_name (expected),
- g_type_name (G_VALUE_TYPE (&params->values[bad_value])));
-}
+ GVariant *args;
+ GError *error = NULL;
-static void
-args_error (SoupMessage *msg, GValueArray *params, int expected)
-{
- soup_xmlrpc_set_fault (msg,
- SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
- "Wrong number of parameters: expected %d, got %d",
- expected, params->n_values);
+ args = soup_xmlrpc_params_parse (params, signature, &error);
+ if (!args) {
+ soup_xmlrpc_message_set_fault (msg,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
+ "Wrong method signature: expected %s: %s",
+ signature, error->message);
+ }
+
+ return args;
}
static void
-do_sum (SoupMessage *msg, GValueArray *params)
+do_sum (SoupMessage *msg, SoupXMLRPCParams *params)
{
- int sum = 0, i, val;
- GValueArray *nums;
+ GVariant *args;
+ GVariant *child;
+ GVariantIter iter;
+ double sum = 0.0, val;
- if (params->n_values != 1) {
- args_error (msg, params, 1);
- return;
- }
- if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &nums)) {
- type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
+ if (!(args = parse_params (msg, params, "(ad)")))
return;
- }
- for (i = 0; i < nums->n_values; i++) {
- if (!soup_value_array_get_nth (nums, i, G_TYPE_INT, &val)) {
- type_error (msg, G_TYPE_INT, nums, i);
- return;
- }
+ child = g_variant_get_child_value (args, 0);
+
+ g_variant_iter_init (&iter, child);
+ while (g_variant_iter_loop (&iter, "d", &val))
sum += val;
- }
- soup_xmlrpc_set_response (msg, G_TYPE_INT, sum);
+ soup_xmlrpc_message_set_response (msg, g_variant_new_double (sum), NULL);
+ g_variant_unref (args);
+ g_variant_unref (child);
}
static void
-do_countBools (SoupMessage *msg, GValueArray *params)
+do_countBools (SoupMessage *msg, SoupXMLRPCParams *params)
{
- int i, trues = 0, falses = 0;
- GValueArray *bools;
- GHashTable *ret = soup_value_hash_new ();
+ GVariant *args;
+ GVariant *child;
+ GVariantIter iter;
gboolean val;
+ int trues = 0, falses = 0;
+ GVariantDict dict;
- if (params->n_values != 1) {
- args_error (msg, params, 1);
- return;
- }
- if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &bools)) {
- type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
+ if (!(args = parse_params (msg, params, "(ab)")))
return;
- }
- for (i = 0; i < bools->n_values; i++) {
- if (!soup_value_array_get_nth (bools, i, G_TYPE_BOOLEAN, &val)) {
- type_error (msg, G_TYPE_BOOLEAN, params, i);
- return;
- }
+ child = g_variant_get_child_value (args, 0);
+
+ g_variant_iter_init (&iter, child);
+ while (g_variant_iter_loop (&iter, "b", &val)) {
if (val)
trues++;
else
falses++;
}
- soup_value_hash_insert (ret, "true", G_TYPE_INT, trues);
- soup_value_hash_insert (ret, "false", G_TYPE_INT, falses);
- soup_xmlrpc_set_response (msg, G_TYPE_HASH_TABLE, ret);
- g_hash_table_destroy (ret);
+ g_variant_dict_init (&dict, NULL);
+ g_variant_dict_insert (&dict, "true", "i", trues);
+ g_variant_dict_insert (&dict, "false", "i", falses);
+
+ soup_xmlrpc_message_set_response (msg, g_variant_dict_end (&dict), NULL);
+ g_variant_unref (args);
+ g_variant_unref (child);
}
static void
-do_md5sum (SoupMessage *msg, GValueArray *params)
+do_md5sum (SoupMessage *msg, SoupXMLRPCParams *params)
{
+ GVariant *args;
+ GVariant *child;
GChecksum *checksum;
- GByteArray *data, *digest;
+ GByteArray *digest;
gsize digest_len = 16;
- if (params->n_values != 1) {
- args_error (msg, params, 1);
+ if (!(args = parse_params (msg, params, "(ay)")))
return;
- }
- if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_BYTE_ARRAY, &data)) {
- type_error (msg, SOUP_TYPE_BYTE_ARRAY, params, 0);
- return;
- }
+ child = g_variant_get_child_value (args, 0);
+
checksum = g_checksum_new (G_CHECKSUM_MD5);
- g_checksum_update (checksum, data->data, data->len);
+ g_checksum_update (checksum,
+ g_variant_get_data (child),
+ g_variant_get_size (child));
digest = g_byte_array_new ();
g_byte_array_set_size (digest, digest_len);
g_checksum_get_digest (checksum, digest->data, &digest_len);
g_checksum_free (checksum);
- soup_xmlrpc_set_response (msg, SOUP_TYPE_BYTE_ARRAY, digest);
+ soup_xmlrpc_message_set_response (msg,
+ g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING,
+ digest->data, digest_len,
+ TRUE, NULL, NULL),
+ NULL);
g_byte_array_free (digest, TRUE);
+ g_variant_unref (child);
+ g_variant_unref (args);
}
static void
-do_dateChange (SoupMessage *msg, GValueArray *params)
+do_dateChange (SoupMessage *msg, SoupXMLRPCParams *params)
{
- GHashTable *arg;
+ GVariant *args;
+ GVariant *timestamp;
SoupDate *date;
+ GVariant *arg;
int val;
+ GError *error = NULL;
- if (params->n_values != 2) {
- args_error (msg, params, 2);
+ if (!(args = parse_params (msg, params, "(va{si})")))
return;
- }
- if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_DATE, &date)) {
- type_error (msg, SOUP_TYPE_DATE, params, 0);
- return;
- }
- if (!soup_value_array_get_nth (params, 1, G_TYPE_HASH_TABLE, &arg)) {
- type_error (msg, G_TYPE_HASH_TABLE, params, 1);
- return;
+ g_variant_get (args, "(v@a{si})", &timestamp, &arg);
+
+ date = soup_xmlrpc_variant_get_datetime (timestamp, &error);
+ if (!date) {
+ soup_xmlrpc_message_set_fault (msg,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
+ "%s", error->message);
+ g_clear_error (&error);
+ goto fail;
}
- if (soup_value_hash_lookup (arg, "tm_year", G_TYPE_INT, &val))
+ if (g_variant_lookup (arg, "tm_year", "i", &val))
date->year = val + 1900;
- if (soup_value_hash_lookup (arg, "tm_mon", G_TYPE_INT, &val))
+ if (g_variant_lookup (arg, "tm_mon", "i", &val))
date->month = val + 1;
- if (soup_value_hash_lookup (arg, "tm_mday", G_TYPE_INT, &val))
+ if (g_variant_lookup (arg, "tm_mday", "i", &val))
date->day = val;
- if (soup_value_hash_lookup (arg, "tm_hour", G_TYPE_INT, &val))
+ if (g_variant_lookup (arg, "tm_hour", "i", &val))
date->hour = val;
- if (soup_value_hash_lookup (arg, "tm_min", G_TYPE_INT, &val))
+ if (g_variant_lookup (arg, "tm_min", "i", &val))
date->minute = val;
- if (soup_value_hash_lookup (arg, "tm_sec", G_TYPE_INT, &val))
+ if (g_variant_lookup (arg, "tm_sec", "i", &val))
date->second = val;
- soup_xmlrpc_set_response (msg, SOUP_TYPE_DATE, date);
+ soup_xmlrpc_message_set_response (msg,
+ soup_xmlrpc_variant_new_datetime (date),
+ NULL);
+
+ soup_date_free (date);
+
+fail:
+ g_variant_unref (args);
+ g_variant_unref (arg);
+ g_variant_unref (timestamp);
}
static void
-do_echo (SoupMessage *msg, GValueArray *params)
+do_echo (SoupMessage *msg, SoupXMLRPCParams *params)
{
- int i;
- const char *val;
- GValueArray *in, *out;
+ GVariant *args;
+ GVariant *child;
- if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &in)) {
- type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
+ if (!(args = parse_params (msg, params, "(as)")))
return;
- }
- out = g_value_array_new (in->n_values);
- for (i = 0; i < in->n_values; i++) {
- if (!soup_value_array_get_nth (in, i, G_TYPE_STRING, &val)) {
- type_error (msg, G_TYPE_STRING, in, i);
- return;
- }
- soup_value_array_append (out, G_TYPE_STRING, val);
- }
-
- soup_xmlrpc_set_response (msg, G_TYPE_VALUE_ARRAY, out);
- g_value_array_free (out);
+ child = g_variant_get_child_value (args, 0);
+ soup_xmlrpc_message_set_response (msg, child, NULL);
+ g_variant_unref (args);
+ g_variant_unref (child);
}
static void
-do_ping (SoupMessage *msg, GValueArray *params)
+do_ping (SoupMessage *msg, SoupXMLRPCParams *params)
{
- if (params->n_values) {
- args_error (msg, params, 0);
+ GVariant *args;
+
+ if (!(args = parse_params (msg, params, "()")))
return;
- }
- soup_xmlrpc_set_response (msg, G_TYPE_STRING, "pong");
+ soup_xmlrpc_message_set_response (msg, g_variant_new_string ("pong"), NULL);
+ g_variant_unref (args);
}
static void
@@ -199,7 +197,8 @@ server_callback (SoupServer *server, SoupMessage *msg,
SoupClientContext *context, gpointer data)
{
char *method_name;
- GValueArray *params;
+ SoupXMLRPCParams *params;
+ GError *error = NULL;
if (msg->method != SOUP_METHOD_POST) {
soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
@@ -208,11 +207,13 @@ server_callback (SoupServer *server, SoupMessage *msg,
soup_message_set_status (msg, SOUP_STATUS_OK);
- if (!soup_xmlrpc_parse_method_call (msg->request_body->data,
- msg->request_body->length,
- &method_name, &params)) {
- soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED,
- "Could not parse method call");
+ method_name = soup_xmlrpc_parse_request (msg->request_body->data,
+ msg->request_body->length,
+ &params, &error);
+ if (!method_name) {
+ soup_xmlrpc_message_set_fault (msg, SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED,
+ "Could not parse method call: %s", error->message);
+ g_clear_error (&error);
return;
}
@@ -229,12 +230,12 @@ server_callback (SoupServer *server, SoupMessage *msg,
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,
+ soup_xmlrpc_message_set_fault (msg, SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND,
"Unknown method %s", method_name);
}
g_free (method_name);
- g_value_array_free (params);
+ soup_xmlrpc_params_free (params);
}
static gboolean
@@ -310,15 +311,17 @@ int
main (int argc, char **argv)
{
SoupServer *server;
+ SoupURI *server_uri;
int ret;
test_init (argc, argv, no_test_entry);
- server = soup_test_server_new (run_tests);
+ server = soup_test_server_new (run_tests ? SOUP_TEST_SERVER_IN_THREAD : SOUP_TEST_SERVER_DEFAULT);
soup_server_add_handler (server, "/xmlrpc-server.php",
server_callback, NULL, NULL);
- uri = g_strdup_printf ("http://127.0.0.1:%u/xmlrpc-server.php",
- soup_server_get_port (server));
+ server_uri = soup_test_server_get_uri (server, "http", NULL);
+ soup_uri_set_path (server_uri, "/xmlrpc-server.php");
+ uri = soup_uri_to_string (server_uri, FALSE);
if (run_tests) {
char *out, **tests, *path;
@@ -353,7 +356,7 @@ main (int argc, char **argv)
} else {
GMainLoop *loop;
- g_print ("Listening on port %d\n", soup_server_get_port (server));
+ g_print ("Listening on port %d\n", server_uri->port);
loop = g_main_loop_new (NULL, TRUE);
g_main_loop_run (loop);
@@ -363,6 +366,7 @@ main (int argc, char **argv)
}
soup_test_server_quit_unref (server);
+ soup_uri_free (server_uri);
g_free (uri);
if (run_tests)
test_cleanup ();
diff --git a/tests/xmlrpc-server.php b/tests/xmlrpc-server.php
index 66cb2be7..f315b6d0 100644
--- a/tests/xmlrpc-server.php
+++ b/tests/xmlrpc-server.php
@@ -18,7 +18,7 @@ function sum ($method_name, $params, $app_data)
$sum = 0;
foreach ($params[0] as $val) {
- if (xmlrpc_get_type ($val) != "int")
+ if (xmlrpc_get_type ($val) != "double")
return paramfault();
$sum = $sum + $val;
@@ -71,7 +71,7 @@ function echo_ ($method_name, $params, $app_data)
function ping ($method_name, $params, $app_data)
{
- if (count ($params) == 0)
+ if (is_null ($params) or count ($params) == 0)
return "pong";
else
return paramfault ();
diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c
index f6b20b8f..58d96abc 100644
--- a/tests/xmlrpc-test.c
+++ b/tests/xmlrpc-test.c
@@ -1,14 +1,11 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * Copyright (C) 2001-2003, Ximian, Inc.
+ * Copyright 2001-2003, Ximian, Inc.
+ * Copyright 2015, Collabora ltd.
*/
#include "test-utils.h"
-#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-#endif
-
static SoupSession *session;
static const char *default_uri = "http://127.0.0.1:47524/xmlrpc-server.php";
static const char *uri = NULL;
@@ -26,20 +23,8 @@ static gboolean server_test = FALSE;
} G_STMT_END
#endif
-static const char *const value_type[] = {
- "BAD",
- "int",
- "boolean",
- "string",
- "double",
- "datetime",
- "base64",
- "struct",
- "array"
-};
-
static gboolean
-send_xmlrpc (const char *body, GValue *retval)
+send_xmlrpc (const char *body, const char *signature, GVariant **retval)
{
SoupMessage *msg;
GError *err = NULL;
@@ -51,115 +36,94 @@ send_xmlrpc (const char *body, GValue *retval)
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) {
+ *retval = soup_xmlrpc_parse_response (msg->response_body->data,
+ msg->response_body->length,
+ signature, &err);
+ if (!*retval) {
+ if (err->domain == SOUP_XMLRPC_FAULT)
soup_test_assert (FALSE, "FAULT: %d %s\n", err->code, err->message);
- g_error_free (err);
- } else
- soup_test_assert (FALSE, "ERROR: could not parse response\n");
+ else
+ soup_test_assert (FALSE, "ERROR: %s\n", err->message);
+ g_error_free (err);
g_object_unref (msg);
return FALSE;
}
- g_object_unref (msg);
return TRUE;
}
static gboolean
-do_xmlrpc (const char *method, GValue *retval, ...)
+do_xmlrpc (const char *method, GVariant *args, const char *signature, GVariant **retval)
{
- va_list args;
- GValueArray *params;
- char *body;
gboolean ret;
+ char *body;
+ GError *error = NULL;
- 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);
+ body = soup_xmlrpc_build_request (method, args, &error);
+ g_assert_no_error (error);
if (!body)
return FALSE;
- ret = send_xmlrpc (body, retval);
+ ret = send_xmlrpc (body, signature, retval);
g_free (body);
return ret;
}
-static gboolean
-check_xmlrpc (GValue *value, GType type, ...)
-{
- va_list args;
-
- if (!G_VALUE_HOLDS (value, type)) {
- g_assert_true (G_VALUE_HOLDS (value, type));
- return FALSE;
- }
-
- va_start (args, type);
- SOUP_VALUE_GETV (value, type, args);
- va_end (args);
- return TRUE;
-}
-
static void
test_sum (void)
{
- GValueArray *ints;
- int i, val, sum, result;
- GValue retval;
+ GVariantBuilder builder;
+ int i;
+ double val, sum, result;
+ GVariant *retval;
gboolean ok;
SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
- debug_printf (2, "sum (array of int -> int): ");
+ debug_printf (2, "sum (array of double -> double): ");
- ints = g_value_array_new (10);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad"));
for (i = sum = 0; i < 10; i++) {
- val = g_random_int_range (0, 100);
- debug_printf (2, "%s%d", i == 0 ? "[" : ", ", val);
- soup_value_array_append (ints, G_TYPE_INT, val);
+ val = g_random_int_range (0, 400) / 4.0;
+ debug_printf (2, "%s%.2f", i == 0 ? "[" : ", ", val);
+ g_variant_builder_add (&builder, "d", val);
sum += val;
}
debug_printf (2, "] -> ");
- ok = (do_xmlrpc ("sum", &retval,
- G_TYPE_VALUE_ARRAY, ints,
- G_TYPE_INVALID) &&
- check_xmlrpc (&retval, G_TYPE_INT, &result));
- g_value_array_free (ints);
+ ok = do_xmlrpc ("sum",
+ g_variant_new ("(@ad)", g_variant_builder_end (&builder)),
+ "d", &retval);
if (!ok)
return;
- debug_printf (2, "%d\n", result);
- g_assert_cmpint (result, ==, sum);
+ result = g_variant_get_double (retval);
+ debug_printf (2, "%.2f\n", result);
+ g_assert_cmpfloat (result, ==, sum);
+
+ g_variant_unref (retval);
}
static void
test_countBools (void)
{
- GValueArray *bools;
+ GVariantBuilder builder;
int i, trues, falses;
- GValue retval;
+ GVariant *retval;
int ret_trues, ret_falses;
gboolean val, ok;
- GHashTable *result;
SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
debug_printf (2, "countBools (array of boolean -> struct of ints): ");
- bools = g_value_array_new (10);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("ab"));
for (i = trues = falses = 0; i < 10; i++) {
val = g_random_boolean ();
debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
- soup_value_array_append (bools, G_TYPE_BOOLEAN, val);
+ g_variant_builder_add (&builder, "b", val);
if (val)
trues++;
else
@@ -167,18 +131,16 @@ test_countBools (void)
}
debug_printf (2, "] -> ");
- ok = (do_xmlrpc ("countBools", &retval,
- G_TYPE_VALUE_ARRAY, bools,
- G_TYPE_INVALID) &&
- check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result));
- g_value_array_free (bools);
+ ok = do_xmlrpc ("countBools",
+ g_variant_new ("(@ab)", g_variant_builder_end (&builder)),
+ "a{si}", &retval);
if (!ok)
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));
-
- g_hash_table_destroy (result);
+ g_assert_true (g_variant_lookup (retval, "true", "i", &ret_trues));
+ g_assert_true (g_variant_lookup (retval, "false", "i", &ret_falses));
+ g_assert_cmpint (g_variant_n_children (retval), ==, 2);
+ g_variant_unref (retval);
debug_printf (2, "{ true: %d, false: %d }\n", ret_trues, ret_falses);
g_assert_cmpint (trues, ==, ret_trues);
@@ -188,12 +150,12 @@ test_countBools (void)
static void
test_md5sum (void)
{
- GByteArray *data, *result;
+ GByteArray *data;
int i;
GChecksum *checksum;
guchar digest[16];
gsize digest_len = sizeof (digest);
- GValue retval;
+ GVariant *retval;
gboolean ok;
SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
@@ -210,27 +172,30 @@ test_md5sum (void)
g_checksum_get_digest (checksum, digest, &digest_len);
g_checksum_free (checksum);
- ok = (do_xmlrpc ("md5sum", &retval,
- SOUP_TYPE_BYTE_ARRAY, data,
- G_TYPE_INVALID) &&
- check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result));
+ ok = do_xmlrpc ("md5sum",
+ g_variant_new ("(@ay)",
+ g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING,
+ data->data, data->len,
+ TRUE, NULL, NULL)),
+ "ay", &retval);
g_byte_array_free (data, TRUE);
if (!ok)
return;
- soup_assert_cmpmem (result->data, result->len,
+ soup_assert_cmpmem (g_variant_get_data (retval), g_variant_get_size (retval),
digest, digest_len);
- g_byte_array_free (result, TRUE);
+ g_variant_unref (retval);
}
static void
test_dateChange (void)
{
- GHashTable *structval;
+ GVariantDict structval;
SoupDate *date, *result;
char *timestamp;
- GValue retval;
+ GVariant *retval;
gboolean ok;
+ GError *error = NULL;
SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
@@ -243,65 +208,69 @@ test_dateChange (void)
g_random_int_range (0, 60),
g_random_int_range (0, 60));
if (debug_level >= 2) {
- timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
- debug_printf (2, "date: %s, {", timestamp);
- g_free (timestamp);
+ char *tmp;
+
+ tmp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
+ debug_printf (2, "date: %s, {", tmp);
+ g_free (tmp);
}
- structval = soup_value_hash_new ();
+ g_variant_dict_init (&structval, NULL);
#define MAYBE (g_random_int_range (0, 3) != 0)
if (MAYBE) {
date->year = 1970 + (g_random_int_range (0, 50));
debug_printf (2, "tm_year: %d, ", date->year - 1900);
- soup_value_hash_insert (structval, "tm_year",
- G_TYPE_INT, date->year - 1900);
+ g_variant_dict_insert (&structval, "tm_year",
+ "i", date->year - 1900);
}
if (MAYBE) {
date->month = 1 + g_random_int_range (0, 12);
debug_printf (2, "tm_mon: %d, ", date->month - 1);
- soup_value_hash_insert (structval, "tm_mon",
- G_TYPE_INT, date->month - 1);
+ g_variant_dict_insert (&structval, "tm_mon",
+ "i", date->month - 1);
}
if (MAYBE) {
date->day = 1 + g_random_int_range (0, 28);
debug_printf (2, "tm_mday: %d, ", date->day);
- soup_value_hash_insert (structval, "tm_mday",
- G_TYPE_INT, date->day);
+ g_variant_dict_insert (&structval, "tm_mday",
+ "i", date->day);
}
if (MAYBE) {
date->hour = g_random_int_range (0, 24);
debug_printf (2, "tm_hour: %d, ", date->hour);
- soup_value_hash_insert (structval, "tm_hour",
- G_TYPE_INT, date->hour);
+ g_variant_dict_insert (&structval, "tm_hour",
+ "i", date->hour);
}
if (MAYBE) {
date->minute = g_random_int_range (0, 60);
debug_printf (2, "tm_min: %d, ", date->minute);
- soup_value_hash_insert (structval, "tm_min",
- G_TYPE_INT, date->minute);
+ g_variant_dict_insert (&structval, "tm_min",
+ "i", date->minute);
}
if (MAYBE) {
date->second = g_random_int_range (0, 60);
debug_printf (2, "tm_sec: %d, ", date->second);
- soup_value_hash_insert (structval, "tm_sec",
- G_TYPE_INT, date->second);
+ g_variant_dict_insert (&structval, "tm_sec",
+ "i", date->second);
}
debug_printf (2, "} -> ");
- ok = (do_xmlrpc ("dateChange", &retval,
- SOUP_TYPE_DATE, date,
- G_TYPE_HASH_TABLE, structval,
- G_TYPE_INVALID) &&
- check_xmlrpc (&retval, SOUP_TYPE_DATE, &result));
- g_hash_table_destroy (structval);
+ ok = do_xmlrpc ("dateChange",
+ g_variant_new ("(vv)",
+ soup_xmlrpc_variant_new_datetime (date),
+ g_variant_dict_end (&structval)),
+ NULL, &retval);
if (!ok) {
soup_date_free (date);
return;
}
+ result = soup_xmlrpc_variant_get_datetime (retval, &error);
+ g_assert_no_error (error);
+
if (debug_level >= 2) {
timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC);
debug_printf (2, "%s\n", timestamp);
@@ -317,81 +286,58 @@ test_dateChange (void)
soup_date_free (date);
soup_date_free (result);
+ g_variant_unref (retval);
}
static const char *const echo_strings[] = {
"This is a test",
"& so is this",
"and so is <this>",
- "&amp; so is &lt;this&gt;"
-};
-#define N_ECHO_STRINGS G_N_ELEMENTS (echo_strings)
-
-static const char *const echo_strings_broken[] = {
- "This is a test",
- " so is this",
- "and so is this",
- "amp; so is lt;thisgt;"
+ "&amp; so is &lt;this&gt;",
+ NULL
};
static void
test_echo (void)
{
- GValueArray *originals, *echoes;
- GValue retval;
- int i;
+ GVariant *originals;
+ GVariant *retval;
+ char *str;
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++) {
- soup_value_array_append (originals, G_TYPE_STRING, echo_strings[i]);
- debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", echo_strings[i]);
- }
- debug_printf (2, "] -> ");
+ originals = g_variant_new ("^as", echo_strings);
+ g_variant_ref_sink (originals);
+ str = g_variant_print (originals, TRUE);
+ debug_printf (2, "%s -> ", str);
+ g_free (str);
- if (!(do_xmlrpc ("echo", &retval,
- G_TYPE_VALUE_ARRAY, originals,
- G_TYPE_INVALID) &&
- check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) {
- g_value_array_free (originals);
+ if (!do_xmlrpc ("echo",
+ g_variant_new ("(@as)", originals),
+ "as", &retval)) {
+ g_variant_unref (originals);
return;
}
- g_value_array_free (originals);
- if (debug_level >= 2) {
- for (i = 0; i < echoes->n_values; i++) {
- debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ",
- g_value_get_string (&echoes->values[i]));
- }
- debug_printf (2, "]\n");
- }
+ str = g_variant_print (retval, TRUE);
+ debug_printf (2, "%s\n", str);
+ g_free (str);
- g_assert_cmpint (echoes->n_values, ==, N_ECHO_STRINGS);
+ g_assert_true (g_variant_equal (originals, retval));
- for (i = 0; i < echoes->n_values; i++) {
- 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]));
- }
-
- g_value_array_free (echoes);
+ g_variant_unref (originals);
+ g_variant_unref (retval);
}
static void
test_ping (gconstpointer include_params)
{
- GValueArray *params;
- GValue retval;
+ GVariant *retval;
char *request;
- char *out;
gboolean ret;
+ GError *error = NULL;
g_test_bug ("671661");
@@ -400,10 +346,8 @@ test_ping (gconstpointer include_params)
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);
+ request = soup_xmlrpc_build_request ("ping", g_variant_new ("()"), &error);
+ g_assert_no_error (error);
if (!request)
return;
@@ -419,15 +363,14 @@ test_ping (gconstpointer include_params)
memmove (params, end, strlen (end) + 1);
}
- ret = send_xmlrpc (request, &retval);
+ ret = send_xmlrpc (request, "s", &retval);
g_free (request);
- if (!ret || !check_xmlrpc (&retval, G_TYPE_STRING, &out))
+ if (!ret)
return;
- g_assert_cmpstr (out, ==, "pong");
-
- g_free (out);
+ g_assert_cmpstr (g_variant_get_string (retval, NULL), ==, "pong");
+ g_variant_unref (retval);
}
static void
@@ -435,7 +378,6 @@ do_bad_xmlrpc (const char *body)
{
SoupMessage *msg;
GError *err = NULL;
- GValue retval;
msg = soup_message_new ("POST", uri);
soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
@@ -444,17 +386,17 @@ do_bad_xmlrpc (const char *body)
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) {
+ if (!soup_xmlrpc_parse_response (msg->response_body->data,
+ msg->response_body->length,
+ "()", &err)) {
+ if (err->domain == SOUP_XMLRPC_FAULT) {
debug_printf (1, "FAULT: %d %s (OK!)\n",
err->code, err->message);
g_error_free (err);
g_object_unref (msg);
return;
} else
- soup_test_assert (FALSE, "ERROR: could not parse response\n");
+ soup_test_assert (FALSE, "ERROR: could not parse response: %s\n", err->message);
} else
soup_test_assert (FALSE, "Unexpectedly got successful response!\n");
@@ -485,6 +427,272 @@ test_fault_args (void)
do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
}
+#define BODY_PREFIX \
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" \
+ "<methodCall><methodName>MyMethod</methodName>"
+#define BODY_SUFFIX \
+ "</methodCall>\n"
+
+static void
+verify_serialization (GVariant *value,
+ const char *expected_params)
+{
+ char *debug;
+ char *body;
+ char *params;
+ GError *error = NULL;
+
+ debug = g_variant_print (value, TRUE);
+
+ body = soup_xmlrpc_build_request ("MyMethod", value, &error);
+ g_assert_no_error (error);
+ g_assert (g_str_has_prefix (body, BODY_PREFIX));
+ g_assert (g_str_has_suffix (body, BODY_SUFFIX));
+
+ params = g_strndup (body + strlen (BODY_PREFIX),
+ strlen (body) - strlen (BODY_PREFIX)
+ - strlen (BODY_SUFFIX));
+
+ if (!g_str_equal (params, expected_params))
+ g_error ("Failed to serialize '%s':\n"
+ " expected: %s\n"
+ " got: %s\n",
+ debug, expected_params, params);
+
+ g_free (params);
+ g_free (body);
+ g_free (debug);
+}
+
+static void
+verify_serialization_fail (GVariant *value)
+{
+ char *body;
+ GError *error = NULL;
+
+ body = soup_xmlrpc_build_request ("MyMethod", value, &error);
+ g_assert (body == NULL);
+ g_assert (error != NULL);
+}
+
+static void
+test_serializer (void)
+{
+ SoupDate *date;
+
+ verify_serialization (g_variant_new_parsed ("()"),
+ "<params/>");
+ verify_serialization (g_variant_new_parsed ("(1, 2)"),
+ "<params>"
+ "<param><value><int>1</int></value></param>"
+ "<param><value><int>2</int></value></param>"
+ "</params>");
+ verify_serialization (g_variant_new_parsed ("((1, 2),)"),
+ "<params><param><value><array><data>"
+ "<value><int>1</int></value>"
+ "<value><int>2</int></value>"
+ "</data></array></value></param></params>");
+ verify_serialization (g_variant_new_parsed ("({'one', 1},)"),
+ "<params><param><value><struct>"
+ "<member><name>one</name><value><int>1</int></value></member>"
+ "</struct></value></param></params>");
+ verify_serialization (g_variant_new_parsed ("([{'one', 1},{'two', 2}],)"),
+ "<params><param><value><struct>"
+ "<member><name>one</name><value><int>1</int></value></member>"
+ "<member><name>two</name><value><int>2</int></value></member>"
+ "</struct></value></param></params>");
+ verify_serialization (g_variant_new ("(^ay)", "bytestring"),
+ "<params><param>"
+ "<value><base64>Ynl0ZXN0cmluZwA=</base64></value>"
+ "</param></params>");
+ verify_serialization (g_variant_new ("(y)", 42),
+ "<params>"
+ "<param><value><int>42</int></value></param>"
+ "</params>");
+ date = soup_date_new_from_time_t (1434161309);
+ verify_serialization (g_variant_new ("(v)", soup_xmlrpc_variant_new_datetime (date)),
+ "<params>"
+ "<param><value><dateTime.iso8601>20150613T02:08:29</dateTime.iso8601></value></param>"
+ "</params>");
+ soup_date_free (date);
+ verify_serialization (g_variant_new ("(s)", "<>&"),
+ "<params>"
+ "<param><value><string>&lt;&gt;&amp;</string></value></param>"
+ "</params>");
+ verify_serialization (g_variant_new ("(u)", 0),
+ "<params>"
+ "<param><value><i8>0</i8></value></param>"
+ "</params>");
+
+ verify_serialization_fail (g_variant_new_parsed ("({1, 2},)"));
+ verify_serialization_fail (g_variant_new ("(mi)", NULL));
+ verify_serialization_fail (g_variant_new ("(t)", 0));
+}
+
+static void
+verify_deserialization (GVariant *expected_variant,
+ const char *signature,
+ const char *params)
+{
+ char *body;
+ char *method_name;
+ SoupXMLRPCParams *out_params = NULL;
+ GVariant *variant;
+ GError *error = NULL;
+
+ body = g_strconcat (BODY_PREFIX, params, BODY_SUFFIX, NULL);
+ method_name = soup_xmlrpc_parse_request (body, strlen (body),
+ &out_params,
+ &error);
+ g_assert_no_error (error);
+ g_assert_cmpstr (method_name, ==, "MyMethod");
+
+ variant = soup_xmlrpc_params_parse (out_params, signature, &error);
+ g_assert_no_error (error);
+
+ if (!g_variant_equal (variant, expected_variant)) {
+ char *str1, *str2;
+
+ str1 = g_variant_print (expected_variant, TRUE);
+ str2 = g_variant_print (variant, TRUE);
+ g_error ("Failed to deserialize '%s':\n"
+ " expected: %s\n"
+ " got: %s\n",
+ params, str1, str2);
+ g_free (str1);
+ g_free (str2);
+ }
+
+ soup_xmlrpc_params_free (out_params);
+ g_variant_unref (variant);
+ g_free (method_name);
+ g_free (body);
+}
+
+static void
+verify_deserialization_fail (const char *signature,
+ const char *params)
+{
+ char *body;
+ char *method_name;
+ SoupXMLRPCParams *out_params = NULL;
+ GVariant *variant;
+ GError *error = NULL;
+
+ body = g_strconcat (BODY_PREFIX, params, BODY_SUFFIX, NULL);
+ method_name = soup_xmlrpc_parse_request (body, strlen (body),
+ &out_params,
+ &error);
+ g_assert_no_error (error);
+ g_assert_cmpstr (method_name, ==, "MyMethod");
+
+ variant = soup_xmlrpc_params_parse (out_params, signature, &error);
+ g_assert_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS);
+ g_assert (variant == NULL);
+
+ g_free (body);
+ soup_xmlrpc_params_free (out_params);
+}
+
+static void
+test_deserializer (void)
+{
+ char *tmp;
+ SoupDate *date;
+
+ verify_deserialization (g_variant_new_parsed ("@av []"),
+ NULL,
+ "<params/>");
+ verify_deserialization (g_variant_new_parsed ("()"),
+ "()",
+ "<params/>");
+ verify_deserialization (g_variant_new_parsed ("(@y 1,@n 2)"),
+ "(yn)",
+ "<params>"
+ "<param><value><int>1</int></value></param>"
+ "<param><value><int>2</int></value></param>"
+ "</params>");
+ verify_deserialization (g_variant_new_parsed ("[<[{'one', <1>},{'two', <2>}]>]"),
+ NULL,
+ "<params><param><value><struct>"
+ "<member><name>one</name><value><int>1</int></value></member>"
+ "<member><name>two</name><value><int>2</int></value></member>"
+ "</struct></value></param></params>");
+ verify_deserialization (g_variant_new_parsed ("([{'one', 1},{'two', 2}],)"),
+ "(a{si})",
+ "<params><param><value><struct>"
+ "<member><name>one</name><value><int>1</int></value></member>"
+ "<member><name>two</name><value><int>2</int></value></member>"
+ "</struct></value></param></params>");
+ date = soup_date_new_from_time_t (1434146909);
+ verify_deserialization (g_variant_new_parsed ("[%v]", soup_xmlrpc_variant_new_datetime (date)),
+ NULL,
+ "<params>"
+ "<param><value><dateTime.iso8601>20150612T22:08:29</dateTime.iso8601></value></param>"
+ "</params>");
+ soup_date_free (date);
+ verify_deserialization (g_variant_new_parsed ("[<b'bytestring'>]"),
+ NULL,
+ "<params>"
+ "<param><value><base64>Ynl0ZXN0cmluZwA=</base64></value></param>"
+ "</params>");
+ verify_deserialization (g_variant_new_parsed ("[<1>]"),
+ "av",
+ "<params><param><value><int>1</int></value></param></params>");
+ verify_deserialization (g_variant_new_parsed ("[<%s>]", "<>&"),
+ NULL,
+ "<params>"
+ "<param><value><string>&lt;&gt;&amp;</string></value></param>"
+ "</params>");
+ verify_deserialization (g_variant_new_parsed ("(@y 255,)"),
+ "(y)",
+ "<params>"
+ "<param><value><int>255</int></value></param>"
+ "</params>");
+
+ tmp = g_strdup_printf ("<params>"
+ "<param><value><int>%"G_GUINT64_FORMAT"</int></value></param>"
+ "</params>", G_MAXUINT64);
+ verify_deserialization (g_variant_new ("(t)", G_MAXUINT64),
+ "(t)", tmp);
+ g_free (tmp);
+
+ verify_deserialization_fail (NULL,
+ "<params>"
+ "<param><value><boolean>2</boolean></value></param>"
+ "</params>");
+ verify_deserialization_fail ("(y)",
+ "<params>"
+ "<param><value><int>256</int></value></param>"
+ "</params>");
+ verify_deserialization_fail ("(ii)",
+ "<params>"
+ "<param><value><int>1</int></value></param>"
+ "</params>");
+ verify_deserialization_fail ("(i)",
+ "<params>"
+ "<param><value><int>1</int></value></param>"
+ "<param><value><int>2</int></value></param>"
+ "</params>");
+}
+
+static void
+test_fault (void)
+{
+ char *body;
+ GVariant *reply;
+ GError *error = NULL;
+
+ body = soup_xmlrpc_build_fault (1, "error: %s", "failed");
+ reply = soup_xmlrpc_parse_response (body, strlen (body), NULL, &error);
+ g_assert_error (error, SOUP_XMLRPC_FAULT, 1);
+ g_assert_cmpstr (error->message, ==, "error: failed");
+ g_assert (reply == NULL);
+
+ g_free (body);
+ g_clear_error (&error);
+}
+
static GOptionEntry xmlrpc_entries[] = {
{ "uri", 'U', 0, G_OPTION_ARG_STRING, &uri,
"Alternate URI for server", NULL },
@@ -507,16 +715,19 @@ main (int argc, char **argv)
session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
- 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);
+ g_test_add_func ("/xmlrpc/variant/serializer", test_serializer);
+ g_test_add_func ("/xmlrpc/variant/deserializer", test_deserializer);
+ g_test_add_func ("/xmlrpc/variant/fault", test_fault);
+ g_test_add_func ("/xmlrpc/variant/sum", test_sum);
+ g_test_add_func ("/xmlrpc/variant/countBools", test_countBools);
+ g_test_add_func ("/xmlrpc/variant/md5sum", test_md5sum);
+ g_test_add_func ("/xmlrpc/variant/dateChange", test_dateChange);
+ g_test_add_func ("/xmlrpc/variant/echo", test_echo);
+ g_test_add_data_func ("/xmlrpc/variant/ping/empty-params", GINT_TO_POINTER (TRUE), test_ping);
+ g_test_add_data_func ("/xmlrpc/variant/ping/no-params", GINT_TO_POINTER (FALSE), test_ping);
+ g_test_add_func ("/xmlrpc/variant/fault/malformed", test_fault_malformed);
+ g_test_add_func ("/xmlrpc/variant/fault/method", test_fault_method);
+ g_test_add_func ("/xmlrpc/variant/fault/args", test_fault_args);
ret = g_test_run ();